I have around 5000 folders each containing a dos executable and required files.
Currently I am using a for loop to call the below code. it takes a long time to execute one by one as each execution takes around 5 seconds.
Is there an option where I can execute all the exe files at the same time ?
Any ideas?
Thanks
I tried using
start "" 1/ddd.exe input.dat
start "" 2/ddd.exe input.dat
start "" 3/ddd.exe input.dat
.
.
.
in a batch file. input.dat has the arguments to pass on to the exe. but the exe opens up a new window and its not taking the arguments. first argument is "2" run to certain part of the exe and second any number to exit the program after it has finished.
You tried
for /D %%a in (*) do (
echo processing: %%a
start /B "Name" cmd.exe "cd %%a & ddy.exe < parameters.txt"
)
I would prefer start /D "%%a" /min "Name" cmd.exe /c "ddy.exe < parameters.txt". /B causes them to use the same console and they may block each other. /D sets the working folder (no need for cd), /min minimizes the windows to keep your screen clean.
And don't forget /c with the cmd command (without, you get no parallel processes).
As a whole:
for /D %%a in (*) do (
echo processing: %%a
start /D "%%a" /min "Name" cmd.exe /c "ddy.exe < parameters.txt"
)
This is a -very- minimalistic script to run N commands at a time from a list. If you are on a supported Windows system, it will have PowerShell.
There is no error checking or proper help information. It writes stdout to the specified log file, but does nothing with the exit code from the command. If something fails, it would need to be identified from the log file.
To use this, put the following code into the file Invoke-JobList.ps1
Create a .csv file with the commands you want to run and a different log file name for each command. The log file name cannot be the same for multiple commands. If you have 5000 commands to process, you will probably need to write a script/program to produce it.
I provided a sample .csv file and a batch file that I used for testing. You do not need to use to.bat.
=== Get-Content .\Invoke-JobList.ps1
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true)]
[string[]]$jobFile
,[Parameter(Mandatory=$false)]
[int]$nConcurrent = 2
)
$jobs = Import-Csv -Path $jobFile
$jobHash = #{}
$nJobsRunning = 0
foreach ($job in $jobs) {
if ($nJobsRunning -lt $nConcurrent) {
Write-Verbose -Message "starting command $($job.command)"
$j = Start-Job -ScriptBlock ([ScriptBlock]::Create($job.command))
$jobHash[$j] = $job.logfile
$nJobsRunning++
}
while ($nJobsRunning -ge $nConcurrent) {
# wait for one or more jobs to state Completed
$jobsRunning = Get-Job
foreach ($jobRun in $jobsRunning) {
if (($null -ne $jobHash[$jobRun]) -and ($jobRun.State -eq 'Completed')) {
Receive-Job -Job $jobRun | Out-File -FilePath $jobHash[$jobRun]
Remove-Job -Job $jobRun
$jobHash.Remove($jobRun)
$nJobsRunning--
}
}
}
}
Write-Verbose -Message $($nJobsRunning.ToString() + " remaining jobs")
# Wait for all remaining jobs to complete
while ($nJobsRunning -gt 0) {
$jobsRunning = Get-Job
foreach ($jobRun in $jobsRunning) {
if (($null -ne $jobHash[$jobRun]) -and ($jobRun.State -eq 'Completed')) {
Receive-Job -Job $jobRun | Out-File -FilePath $jobHash[$jobRun]
Remove-Job -Job $jobRun
$jobHash.Remove($jobRun)
$nJobsRunning--
}
}
}
=== Get-Content .\joblist3.csv
command,logfile
C:\src\jobs\to.bat 10,ss-001.txt
C:\src\jobs\to.bat 10,ss-002.txt
C:\src\jobs\to.bat 10,ss-003.txt
C:\src\jobs\to.bat 10,ss-004.txt
C:\src\jobs\to.bat 10,ss-005.txt
C:\src\jobs\to.bat 10,ss-006.txt
C:\src\jobs\to.bat 10,ss-007.txt
=== Get-Content .\to.bat
#ECHO OFF
SET "TO=%1"
IF "%TO%" == "" (SET "TO=5")
REM Cannot use TIMEOUT command
ping -n %TO% localhost
EXIT /B 0
Invoke it with parameters.
.\Invoke-JobList.ps1 -jobFile joblist3.csv -nConcurrent 3 -Verbose
Related
I have a folder on a shared network drive with a large number of text files. I am required to list the file name, size and number of lines/ rows in each file. I am able to use command prompt to get the output separately but I cannot seem to combine.
This works perfectly to list the file name and size:
DIR /s “files location*.txt” > Directory.txt
This works to for the line count:
for %f in ("files location*.txt" ) do find /v /c "" "%f"
I tried the following to combine but the output was empty and the command prompt window showed the full file location and name but without the line count
DIR /s “files location*.txt” | for %f in (“files location*.txt”) do find /v /c "" "%f" > Directory.txt
I think this question has been here before. Put these two (2) files into the same directory. The directory should be in the PATH variable. Many things could be done to make this more flexible using parameters. If you are on a supported Windows system, PowerShell will be available. If you have PowerShell 6 or higher, change powershell to pwsh.
=== Get-FileLineCount.bat
#ECHO OFF
powershell -NoLogo -NoProfile -File "%~dp0Get-FileListCount.ps1"
EXIT /B
=== Get-FileLineCount.ps1
Get-ChildItem -File -Path 'C:\src\t' -Filter '*.txt' |
ForEach-Object {
[PSCustomObject]#{
LastWriteTime = $_.LastWriteTime
Length = $_.Length
LineCount = (Get-Content -Path $_.FullName | Measure-Object).Count
FileName = $_.FullName
}
}
This produces the following output.
LastWriteTime Length LineCount FileName
------------- ------ --------- --------
2021-04-08 08:14:59 3 1 C:\src\t\abc.txt
2021-04-08 08:16:39 8 1 C:\src\t\abc-utf-8.txt
2019-07-08 11:38:36 30 1 C:\src\t\append.txt
2019-07-08 11:38:36 36 12 C:\src\t\appendtemp.txt
2020-03-06 09:48:51 104 25 C:\src\t\Combined.txt
Update2:
Now, when I know, that x32 is the problem I debugged into the script using powershell_ise_x32 and found out, that $Word.Documents is null.
So Powershell-API for Word has a different behaviour in x32 PowerShell, then in 64bit.
Update:
The error occurs, when using PowerShell x32 and occurs NOT on PowerShell 64bit. That was really it. Powershell x32 was executed because I started it from the Total Commander 32bit.
The question is now - why 32bit and 64bit PowerShell have different behaviour?
Initial Question:
I wrote a powershell script, to convert my WordDocuments and merge them to one.
I wrote a Batch script, to start this powershell script.
When I execute the script directly in "Powershell ISE" the script works fine.
When I execute the batch script as Administrator via context menu, the script reports errors. In this case the C:\WINDOWS\SysWOW64\cmd.exe is executed.
When I execute another cmd.exe found on my system as Administrator - everything works fine:
"C:\Windows\WinSxS\amd64_microsoft-windows-commandprompt_31bf3856ad364e35_10.0.15063.0_none_9c209ff6532b42d7\cmd.exe"
Why do I have different behaviour in different cmd.exe? What are those different cmd.exe?
Batch Script:
cd /d "%~dp0"
powershell.exe -noprofile -executionpolicy bypass -file "%~dp0%DocxToPdf.ps1"
pause
Powershell Script
$FilePath = $PSScriptRoot
$Pdfsam = "D:\Programme\PDFsam\bin\run-console.bat"
$Files = Get-ChildItem "$FilePath\*.docx"
$Word = New-Object -ComObject Word.Application
if(-not $?){
throw "Failed to open Word"
}
# Convert all docx files to pdf
Foreach ($File in $Files) {
Write-Host "Word Object: " $Word
Write-Host "File Object: " $Word $File
Write-Host "FullName prop:" $File.FullName
# open a Word document, filename from the directory
$Doc = $Word.Documents.Open($File.FullName)
# Swap out DOCX with PDF in the Filename
$Name=($Doc.FullName).Replace("docx","pdf")
# Save this File as a PDF in Word 2010/2013
$Doc.SaveAs([ref] $Name, [ref] 17)
$Doc.Close()
}
# check errors
if(-not $?){
Write-Host("Stop because an error occurred")
pause
exit 0
}
# wait until the conversion is done
Start-Sleep -s 15
# Now concat all pdfs to one single pdf
$Files = Get-ChildItem "$FilePath\*.pdf" | Sort-Object
Write-Host $Files.Count
if ($Files.Count -gt 0) {
$command = ""
Foreach ($File in $Files) {
$command += " -f "
$command += "`"" + $File.FullName + "`""
}
$command += " -o `"$FilePath\Letter of application.pdf`" -overwrite concat"
$command = $Pdfsam + $command
echo $command
$path = Split-Path -Path $Pdfsam -Parent
cd $path
cmd /c $command
}else{
Write-Host "No PDFs found for concatenation"
}
Write-Host -NoNewLine "Press any key to continue...";
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown");
I've found $PSScriptRoot to be unreliable.
$FilePath = $PSScriptRoot;
$CurLocation = Get-Location;
$ScriptLocation = Split-Path $MyInvocation.MyCommand.Path
Write-Host "FilePath = [$FilePath]";
Write-Host "CurLocation = [$CurLocation]";
Write-Host "ScriptLocation = [$ScriptLocation]";
Results:
O:\Data>powershell ..\Script\t.ps1
FilePath = []
CurLocation = [O:\Data]
ScriptLocation = [O:\Script]
As to the differences between the various cmd.exe implementations, I can't really answer that. I should have thought they'd be functionally identical, but maybe there's 32/64-bit differences that matter.
The error occurs, when using PowerShell x32 and occurs NOT on PowerShell 64bit.
I debugged into the script using powershell_ise_x32 and found out, that $Word.Documents is null.
This is because on my system Word 64bit is installed.
My batch script in DOS is processing way to slow, so someone recomended I use powershell. I'm running it now for my first time on windows, but I've never used it before today. I hear it's similar to batch scripting, so I'm currently converting my batch script into a powershell script. Below is my script so far half way through conversion:
# ask user for network share and file that they would like to search
$textFilePath = Read-Host Please enter filesystem location of "filenames.txt". Include drive letter or // at start of path
$uncPath = Read-Host Please enter the UNC path you would like to search. Include // at start of path.
# REM check if network path is available. If it is, search network directory for files with same name as the strings in filenames.txt
IF (Test-Path %uncPath%) {
echo Network Path Exists. Searching %uncPath% for files with same name and extension as filenames in the filenames.txt file
for (/r %uncPath% %%G IN (*)) {for (/F "tokens=*" %%i in (%textFilePath%)) {if (%%~nxG==%%i) {echo %%~nxG,%%~fG >> filenamesOutput.txt}}}
pause
}
IF (!(Test-Path exist %uncPath%)) {
echo File not found
GOTO:userInput
}
I'm currently learning the powershell commands as I go and changing the batch command to powershell. Help with conversion would be appreciated.
AFter Edit:
Here's my original batch script:
#echo off
echo Please enter filesystem location of "filenames.txt". (Include Drive letter or // at start of path)
set /p textFilePath=Enter The Value:%=%
:userInput
REM ask user for network share and file that they would like to search
echo Please enter the UNC path you would like to search. (Include // at start of path)
set /p uncPath=Enter The Value:%=%
REM check if network path is available. If it is, search network directory for files with same name as the strings in filenames.txt
IF exist %uncPath% (
echo Network Path Exists. Searching %uncPath% for files with same name and extension as filenames in the filenames.txt file
for /r %uncPath% %%G IN (*) DO for /F "tokens=*" %%i in (%textFilePath%) DO if %%~nxG==%%i echo %%~nxG,%%~fG >> filenamesOutput.txt
pause
)
IF NOT exist %uncPath% (
echo File not found
GOTO:userInput
)
After 2nd Edit:
$VerbosePreference = "continue"
# ask user for network share and file that they would like to search
$textFilePath = Read-Host Please enter filesystem location of "filenames.txt". Include drive letter or // at start of path
$uncPath = Read-Host Please enter the UNC path you would like to search. Include // at start of path.
# check if network path is available. If it is, search network directory for files with same name as the strings in filenames.txt
IF (Test-Path $uncPath){
echo "Network Path Exists. Searching $uncPath for files with same name and extension as filenames in the filenames.txt file"
foreach($file in Get-ChildItem $uncPath -Recurse) {
# Get-Content reads in a file, line by line
foreach($line in Get-Content $_.FullName) {
# if goes in here
if($file.Name -eq $line){
echo $file.Name
"{0},{1}" -f $file.Name,$file.FullName | Out-File filenamesOutput2.txt -Append
}
}
}
Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
}
IF (!(Test-Path $uncPath)){
echo "UNC path not found"
Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
}
Variables:
In PowerShell, variable references are always prefixed with $ (much like in PHP or Perl).
So any variable you would assign and dereference in cmd/batch as:
set /p varname= somevalue
echo %varname%
Would in PowerShell be treated as (notice no difference between assigning and dereferencing):
$varname = "varvalue"
Write-Host $varname
So your exists/Test-Path statements should be:
if(Test-Path $uncPath){
# Loops in here
# "#" starts is a single-line comment btw
}
For loop:
In cmd, the for loop construct behaves different depending on the first switch:
for /r roughly means "loop recursively through filesystem tree"
for /f roughly means "loop through tokens in a file"
it should be noted that cmd for loops use parameters, denoted by the prefix %% (like %%G or %%i in your example)
PowerShell doesn't have this concept and just uses variables in loops. Thus, your for /r and for /f loops become:
# Get-ChildItem is equivalent to the "dir" command
# The -Recurse is pretty self-explanatory ( = /S)
foreach($file in Get-ChildItem $uncPath -Recurse) {
# Get-Content reads in a file, line by line
foreach($line in Get-Content $textFilePath) {
# if goes in here
}
}
Parameter modifiers:
In cmd, a parameter (like %%G) can be modified using a tilde (~) followed by a sequence of modifier characters.
%%~nG means "treat %%G as a path, return the name without extension"
%%~xG means "treat %%G as a path, return the file extension"
so %%~nxG naturally means "return filename WITH extension".
In PowerShell, everything is a .NET object, and in the case of $file, it's a FileInfo object. From the FileInfo object, the filename (WITH the extension) is stored in the Name property, so your if statement:
if %%~nxG==%%i
becomes:
if($file.Name -eq $line){
# echo and output goes in here
}
%%~fG means "treat %%G as a path, give me the full rooted path"
Again, the fact that $file is a FileInfo object comes in handy, the full path can be accessed from the FullName property:
"{0},{1}" -f $file.Name,$file.FullName | Out-File filenamesOutput.txt -Append
The -f operator is a simplified syntactic shortcut to String.Format, .NET's version of sprintf if you will.
Ultimately resulting in something like:
# ask user for network share and file that they would like to search
$textFilePath = Read-Host 'Please enter filesystem location of "filenames.txt". Include drive letter or \\ at start of path'
$uncPath = Read-Host 'Please enter the UNC path you would like to search. Include \\ at start of path.'
# check if network path is available. If it is, search network directory for files with same name as the strings in filenames.txt
if (Test-Path $uncPath) {
Write-Host "Network Path Exists. Searching $uncPath for files with same name and extension as filenames in the filenames.txt file"
foreach($file in Get-ChildItem $uncPath) {
foreach($line in Get-Content $textFilePath) {
if($file.Name -eq $line){
'"{0}","{1}"' -f $file.Name,$file.FullName | Out-File filenamesOutput.txt -Append
}
}
}
pause
} else {
Write-Host "File not found"
}
Some time ago, #Magoo was nice enough to help me in working out a FOR /F command to archive files into 7-zip:
Using FOR or FORFILES batch command to individually archive specific files
Since then I've expanded it somewhat and want to do more elaborate things with it. However, to keep this question simple, I've included the basics to try and get this working, which I haven't had much success at.
I'm rather new to PowerShell and I have some specific reasons to use this instead of batch files, moving forward.
I understand that some more experienced users may note that I will have a reduction in performance by using such statements in PowerShell, but it isn't an important issue for me.
$env:Path += ";C:\Program Files\7-Zip"
$sourcedir = read-host "Enter the directory to archive: "
foreach ($aname in {
'cmd /c dir /s/b /a-d "$sourcedir\*.iso" '
'cmd /c dir /s/b /a-d "$sourcedir\*.daa" '
'cmd /c dir /s/b /a-d "$sourcedir\*.nrg" '
'cmd /c dir /s/b /a-d "$sourcedir\*.flp" '}
) {
IF NOT EXIST $aname.7z (
echo 7z a -t7z "$aname.7z" "$aname" -mx9 -mmt >> Z:\test\7z-log.txt
ECHO "$aname" archived.
) ELSE (
ECHO "$aname" archive file already exists.
)
}
I got into some trouble with the IF EXIST statement and even when I removed the IF and had a one-line ECHO just to simplify it even more, but I couldn't get it to output what I wanted.
So, I tried a different approach:
$env:Path += ";C:\Program Files\7-Zip"
$sourcedir = read-host "Enter the directory to archive: "
$dir_iso = ForEach-Object { cmd /c dir /s/b /a-d "$sourcedir\*.iso" }
$dir_daa = ForEach-Object { cmd /c dir /s/b /a-d "$sourcedir\*.daa" }
$dir_nrg = ForEach-Object { cmd /c dir /s/b /a-d "$sourcedir\*.nrg" }
$dir_flp = ForEach-Object { cmd /c dir /s/b /a-d "$sourcedir\*.flp" }
foreach ($aname in $dir_iso,$dir_daa,$dir_nrg,$dir_flp) {
ECHO "$aname" archived.
}
But what this did, is clumped each item of each type together, then appended "archived" to that set. Something like:
C:\folder1\iso1.iso C:\folder1\iso2.iso C:\folder1\iso3.iso archived.
C:\folder2\image.nrg archived.
C:\folder3\app1.flp C:\folder3\app2.flp archived.
instead of:
C:\folder1\iso1.iso archived.
C:\folder1\iso2.iso archived.
C:\folder1\iso3.iso archived.
C:\folder2\image.nrg archived.
C:\folder3\app1.flp archived.
C:\folder3\app2.flp archived.
I'm having a real hard time with getting this to work. Can anyone help?
Thanks.
The first thing I see here is you are using this to get file information from the filesystem
$dir_iso = ForEach-Object { cmd /c dir /s/b /a-d "$sourcedir\*.iso" }
More specifically cmd /c dir /s/b /a-d "$sourcedir\*.iso". This would translate easily to Get-ChildItem
$dir_iso = Get-ChildItem -Path $sourcedir -Filter "*.iso" -Recurse -File | Select-Object -ExpandProperty FullName
Path is the file path of the folder you are checking
Filter you want only files ending with .iso
Recurse all subdirectories are checked
File returns only files and not directories (PowerShell 3.0 or higher!. There is a simple equivalent if this is an issue. )
Select-Object -ExpandProperty FullName would just return the full path of the files found in an array.
IF EXIST could be replaced by Test-Path
If(Test-Path "$aname.7z"){
Do stuff...
}
As for the ForEach loop foreach ($aname in $dir_iso,$dir_daa,$dir_nrg,$dir_flp) there are a couple good approaches with this but the simplest transistion would be
$dir_iso + $dir_daa + $dir_nrg + $dir_flp | ForEach-Object{
Do Stuff
}
I would probably build the file collection in one variable to begin with to avoid the to concat the arrays together
$files = Get-ChildItem -Path $sourcedir -Recurse -File | Where-Object{$_.Extension -match "(iso|daa|nrg|flp)$" } | Select-Object -ExpandProperty FullName
$files | ForEach-Object{
Write-Host "$_"
}
Use write-host instead of echo.
Multidimensional array, so you'll need an inner loop.
foreach ($aname in $dir_iso,$dir_daa,$dir_nrg,$dir_flp) {
foreach ($bname in $aname) {
write-host "$bname" archived.
}
}
Another possibility; this pipes the commands together rather than storing each in a separate variable.
Get-Item $sourcedir\* |
Where {$_.Extension -like ".iso" -or $_.Extension -like ".daa" -or $_.Extension -like ".nrg" -or $_.Extension -like ".flp"} |
Foreach-Object {
if (-Not (Test-Path "$_.BaseName.7z"))
{
Write-Host $_.FullName not yet archived.
}
else
{
Write-Host $_.FullName already archived.
}
}
Based on How can I auto-elevate my batch file, so that it requests from UAC administrator rights if required? I'm trying to make an RunElevated.bat (see code below) that accepts a command-line (batch file name and parameters) as arguments.
The RunElevated.bat works fine when the target batch file path has no spaces in them. But it fails as soon as that path has spaces: no matter how I quote things, either PowerShell barfs, or the parameters are not passed correctly from PowerShell to the batch file.
I tried:
escaping with "" (as suggested by many sources)
escaping with \" (as suggested by Escaping quotes in powershell.exe -command via command prompt)
adding --% (as suggested by PowerShell and external commands done right and Easier Reuse of Command Lines From Cmd.exe)
surrounding with ' (as suggested by CB.).
So:
Is what I want to do possible at all?
If so: how?
RunElevated.bat:
:checkParameters
echo [%*]
if [%1]==[] ( goto :help ) else ( goto :checkPrivileges )
:help
echo Syntax:
echo %0 CmdLine
echo Where CmdLine is executed with UAC privileges.
goto :exit
:checkPrivileges
net file 1>nul 2>nul
if '%errorlevel%' == '0' ( goto :gotPrivileges ) else ( goto :getPrivileges )
:getPrivileges
PowerShell "Start-Process -FilePath \"%0\" -Verb RunAs -ArgumentList \"%*\""
goto :exit
:gotPrivileges
%*
pause
:exit
pause
exit /b
echo-cd.bat which I stored in both D:\tools\echo-cd.bat and "D:\to ols\echo-cd.bat":
echo Current Directory: [%CD%]
echo Parameters: [%*]
pause
This runs fine:
D:\tools\RunElevated.bat D:\tools\echo-cd.bat foo
These fail:
D:\tools\RunElevated.bat "D:\to ols\echo-cd.bat" foo
First failure is at the %*:
C:\Windows\system32>D:\to ols\echo-cd.bat foo
'D:\to' is not recognized as an internal or external command,
operable program or batch file.
This is because PowerShell removed the quotes around the batch file name:
C:\Windows\system32>echo [D:\to ols\echo-cd.bat foo]
[D:\to ols\echo-cd.bat foo]
I expected D:\to ols\echo-cd.bat to have double quotes around it, and foo not.
D:\tools\RunElevated.bat \"D:\to ols\echo-cd.bat\" foo
Second failure is at the PowerShell level:
D:\>PowerShell "Start-Process -FilePath \"D:\tools\RunElevated.bat\" -Verb RunAs -ArgumentList \"\"D:\to ols\echo-cd.bat\" foo\""
Start-Process : Cannot validate argument on parameter 'ArgumentList'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At line:1 char:77
+ Start-Process -FilePath "D:\tools\RunElevated.bat" -Verb RunAs -ArgumentList <<<< ""D:\to ols\echo-cd.bat" foo"
This is because escaping twice will end up with an empty string for ArgumentList.
D:\tools\RunElevated.bat --% "D:\to ols\echo-cd.bat" foo
Third failure is also at the %*:
C:\Windows\system32>--% D:\to ols\echo-cd.bat foo
'--%' is not recognized as an internal or external command,
operable program or batch file.
This too is because PowerShell removed the quotes around the batch file name:
C:\Windows\system32>echo [--% D:\to ols\echo-cd.bat foo]
[--% D:\to ols\echo-cd.bat foo]
I expected --% to be absent, D:\to ols\echo-cd.bat to have double quotes around it, and foo not.
D:\tools\RunElevated.bat '"D:\to ols\echo-cd.bat"' foo
Again a failure is at the %*:
C:\Windows\system32>'D:\to ols\echo-cd.bat' foo
The filename, directory name, or volume label syntax is incorrect.
This is because PowerShell removed the double quotes (and left the single quotes) around the batch file name:
C:\Windows\system32>echo ['D:\to ols\echo-cd.bat' foo]
['D:\to ols\echo-cd.bat' foo]
C:\Windows\system32>if ['D:\to] == [] (goto :help ) else (goto :checkPrivileges )
I recall using the following approach for this:
start "" %systemroot%\System32\windowspowerShell\v1.0\powershell.exe -exec bypass -noprofile -command "&{ start-process powershell -verb RunAs -ArgumentList '-noprofile -exec bypass -file \"c:\temp\test folder\elevatedpowershell.ps1\"'}"
You can replace \"c:\temp\test folder\elevatedpowershell.ps1\" with \"$0\" like you did there.
I also found the solution from Keith Hill on self elevating PowerShell to be useful if I need the person to be admin. I do not have the link now but it goes like this:
function IsAdministrator
{
$Identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$Principal = New-Object System.Security.Principal.WindowsPrincipal($Identity)
$Principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
}
function IsUacEnabled
{
(Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System).EnableLua -ne 0
}
if (!(IsAdministrator))
{
if (IsUacEnabled)
{
[string[]]$argList = #('-NoProfile', '-File', ('"' + $MyInvocation.MyCommand.Path + '"'))
$argList += $MyInvocation.BoundParameters.GetEnumerator() | Foreach {"-$($_.Key)", "$($_.Value)"}
$argList += $MyInvocation.UnboundArguments
Start-Process "$env:Windir\System32\WindowsPowerShell\v1.0\PowerShell.exe" -Verb Runas -WorkingDirectory $pwd -WindowStyle Hidden -ArgumentList $argList
return
}
else
{
throw "You must be administrator to run this script"
}
}
Assuming, you want to have elevated PowerShell script, you can have that at the top of your PowerShell script.
Ugly but it can do the job.
Use single quotes (or any character of your choice) and insert this in your code:
:gotPrivileges
cd "%~p0"
set arg=%*
set arg=%arg:'="%
%arg%
:: %*
pause
If you have 8.3 file names enabled you can try this:
:getPrivileges
setlocal enabledelayedexpansion
set Args=%*
for %%a in (%*) do if exist %%a (
set Args=!Args:%%a="%%~sa"!
)
PowerShell "Start-Process -FilePath \"%0\" -Verb RunAs -ArgumentList \"%Args%\"" 2>nul
goto :exit
However, if you pass an argument that happens to be the name of a file or folder (that exists relative to RunElevated.bat) it can get altered.