Run cmd from a given folder inside PowerShell script - powershell

Is there any possibility to run a cmd command from a different folder then the script home location (e.g. C:\ScriptHome)?
I mean e.g.
Cmd /C "C:\Test\test.exe"
but this exe should be called from e.g. "C:\RunTestExeHere"
Basically, it can be done in pure cmd, like cd "C:\RunTestExeHere" and after
C:\RunTestExeHere>C:\Test\test.exe
but can it be done in powershell?
Thank you!

Your best bet is to sandwich your external command between Push-Location and Pop-Location commands.
A simple example:
Push-Location -EA Stop C:\ # You'd use C:\RunTestExeHere instead
cmd /c dir # You'd use & "C:\Test\test.exe" instead
Pop-Location
Another option (the invocation syntax is less convenient):
Start-Process -Wait -NoNewWindow cmd -ArgumentList /c, dir -WorkingDirectory C:\

Related

PowerShell - Set working directory on ELEVATED Start-Process command [duplicate]

When I enter the command
Start-Process powershell -WorkingDirectory "D:\folder"
it opens new PowerShell window with D:\folder location set.
But when I enter the command
Start-Process powershell -WorkingDirectory "D:\folder" -Verb RunAs
it opens new PowerShell window with admin rights but with C:\Windows\system32 location set.
How can I open new PowerShell window with admin rights and my own location determined?
I also had the same problem and solved it with this command:
Start-Process powershell.exe -verb runAs -ArgumentList '-NoExit', '-Command', 'cd D:\folder'
Once you run the above command, Windows will launch with admin authority and the specified directory.
Here's another example which can be used for opening CMD from PowerShell as an administrator into the current folder:
Start-Process cmd -ArgumentList ("/k cd {0}" -f (Get-Location).path) -Verb RunAs
if used within a script you can use
Start-Process cmd -ArgumentList ("/k cd {0}" -f $PSScriptRoot) -Verb RunAs
If you want to open a new elevated PowerShell session from the current one which is not elevated you can use:
Start-Process powershell.exe -ArgumentList ("-NoExit",("cd {0}" -f (Get-Location).path)) -Verb RunAs
or
Start-Process powershell.exe -ArgumentList ("-NoExit",("cd {0}" -f $PSScriptRoot)) -Verb RunAs
when used inside scripts
When using Start-Process with -Verb RunAs, a -WorkingDirectory argument is honored if the target executable is a .NET executable; examples:
pwsh.exe (the PowerShell (Core) CLI) does honor it.
cmd.exe and, curiously, powershell.exe (the Windows PowerShell CLI) do not, and invariably use C:\Windows\System32.
The problem exists at the level of the .NET API that PowerShell uses behind the scenes (see System.Diagnostics.ProcessStartInfo), as of this writing (.NET 6.0.0-preview.4.21253.7).
Unless you know that you're invoking a .NET executable, a workaround that changes to the desired working folder in the new process is therefore required; to offer a more robust alternative to ふゆな's helpful answer:
$dir = $PWD.ProviderPath # use the current dir.
Start-Process -Verb RunAs powershell.exe #"
-noexit -c Set-Location -LiteralPath "$dir"
"#
The embedded "..." quoting around $dir ensures that paths with spaces are also handled correctly. (To use the current directory without an intermediate variable, replace "dir" with "$($PWD.ProviderPath)".
Using a here-string (#"<newline>...<newline>"#) isn't strictly necessary, but simplifies the embedded quoting; with a regular expandable string ("..."), the embedded " must be escaped as `" (or "").
Using $PWD's .ProviderPath property ensures that a file-system-native path is used (based on drive letters also seen in cmd.exe, for instance), given that the calling session's current location may be based on a PowerShell-only drive (see New-PSDrive) that the elevated process may not have defined (at all or not based on the same root location).
Caveat: If the native path is on a mapped network drive, this won't work, because elevated processes do not see the same drive mappings; in that event, pass the underlying UNC path.
Workaround for launching a GUI application elevated from a given working directory:
Since changing to the working directory must happen in the new, elevated process, a helper shell process is needed to perform this operation, which is best done via cmd.exe (for better performance):
$exeToLaunch = 'Notepad.exe' # may include arguments
$dir = $PWD.ProviderPath # use the current dir.
Start-Process -Verb RunAs -WindowStyle Hidden cmd.exe #"
/c cd "$dir" & $exeToLaunch
"#
Once you run Powershell as administrator;
user the push-location command like so:
Push-Location -Path C:\
or put it into your script and run the script from the elevated Powershell prompt.
I just ran your code example and it opened correctly for me at the WorkingDirectory location. Ensure the directory exists before you run the command. I tested against a drive on C and secondary drive as well and both worked.

generate a war file using Powershell

I am new to Powershell.I am trying to generate a war file in the location of jar.exe , any inputs highly appreciated.
I have tried to generate the war file using Start Process, But it is not generating the war file
$wargen=Start-Process -FilePath "cmd.exe" -ArgumentList "/K cd /d D:\Temp\ws\9.0\base\java\8.0\bin\jar.exe -cvf foo.war" -Verb "runas" -Verbose
You don't need to try so hard. It's not necessary to invoke Start-Process or cmd.exe to run a command. PowerShell is a shell; it can run commands. Just type the command at the PowerShell prompt and press Enter.
PS C:\> D:\Temp\ws\9.0\base\java\8.0\bin\jar.exe -cvf foo.war
I am wondering about why your example uses the runas shell verb to run the command as an elevated process; my guess is that this is unnecessary.

Installing an MSI file on a remote machine with PowerShell

I'm working on a utility to automate some processes and one task is to install a .msi file on a remote machine. The file is found in C:\Users\username on the remote machine and for simplicity's sake, the filename is file.msi. The command I'm using is:
Invoke-Command -ComputerName $remoteMachine -ScriptBlock{cmd /c start /wait msiexec /i $installPath /quiet}
When I execute this on my local dev machine, it doesn't show any errors, but doesn't install the file.
However, when I copy the exact command inside the brackets and run it in a PowerShell script on the remote machine, it installs successfully. I know my $remoteMachine is correct because I use it extensively throughout the rest of the script.
I know the $installPath variable also isn't the issue because for testing purposes I hardcoded the full path and it still doesn't install.
I also have proper permissions on the remote machine because earlier in the script I copy and paste the .msi from one machine to another without a problem.
I've tried a combination of commands and have been stuck here for a while, so any help would be greatly appreciated!
Ideally, this should work.
Invoke-Command -ComputerName $remoteMachine -ScriptBlock{msiexec /i $installPath /quiet}
The reason it is failing is coz you are not passing the $installPath as argumentlist. Modify it like this.
Invoke-Command -ComputerName $remoteMachine -ScriptBlock{
param(
[Parameter(Mandatory=$true,
Position=0)]
$installPath
)
cmd /c start /wait msiexec /i $installPath /quiet
} -ArgumentList $installPath
But if it isn't working, here is a workaround that I used a while ago.
Create a .bat file with the command msiexec /i $installPath /quiet and push it to the location just like you pushed the msi file.
Now from the invoke scriptblock, simply call the bat file instead.
Invoke-Command -ComputerName $remoteMachine -ScriptBlock{C:\Users\Username\Install.bat}
where Install.bat is the name of your bat file.
Note: You might want to use the /norestart switch as well if you are not looking to cause a reboot. Depends on what you are trying to install.
Beginning in PowerShell 3.0, you can use the Using scope modifier to identify a local variable in a remote command.
syntax of Using :- $Using:<VariableName>
In your case :
Invoke-Command -ComputerName $remoteMachine -ScriptBlock{cmd /c start /wait msiexec /i $Using:installPath /quiet}
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_variables?view=powershell-7.2#using-local-variables

Start-Process -WorkingDirectory as administrator does not set location

When I enter the command
Start-Process powershell -WorkingDirectory "D:\folder"
it opens new PowerShell window with D:\folder location set.
But when I enter the command
Start-Process powershell -WorkingDirectory "D:\folder" -Verb RunAs
it opens new PowerShell window with admin rights but with C:\Windows\system32 location set.
How can I open new PowerShell window with admin rights and my own location determined?
I also had the same problem and solved it with this command:
Start-Process powershell.exe -verb runAs -ArgumentList '-NoExit', '-Command', 'cd D:\folder'
Once you run the above command, Windows will launch with admin authority and the specified directory.
Here's another example which can be used for opening CMD from PowerShell as an administrator into the current folder:
Start-Process cmd -ArgumentList ("/k cd {0}" -f (Get-Location).path) -Verb RunAs
if used within a script you can use
Start-Process cmd -ArgumentList ("/k cd {0}" -f $PSScriptRoot) -Verb RunAs
If you want to open a new elevated PowerShell session from the current one which is not elevated you can use:
Start-Process powershell.exe -ArgumentList ("-NoExit",("cd {0}" -f (Get-Location).path)) -Verb RunAs
or
Start-Process powershell.exe -ArgumentList ("-NoExit",("cd {0}" -f $PSScriptRoot)) -Verb RunAs
when used inside scripts
When using Start-Process with -Verb RunAs, a -WorkingDirectory argument is honored if the target executable is a .NET executable; examples:
pwsh.exe (the PowerShell (Core) CLI) does honor it.
cmd.exe and, curiously, powershell.exe (the Windows PowerShell CLI) do not, and invariably use C:\Windows\System32.
The problem exists at the level of the .NET API that PowerShell uses behind the scenes (see System.Diagnostics.ProcessStartInfo), as of this writing (.NET 6.0.0-preview.4.21253.7).
Unless you know that you're invoking a .NET executable, a workaround that changes to the desired working folder in the new process is therefore required; to offer a more robust alternative to ふゆな's helpful answer:
$dir = $PWD.ProviderPath # use the current dir.
Start-Process -Verb RunAs powershell.exe #"
-noexit -c Set-Location -LiteralPath "$dir"
"#
The embedded "..." quoting around $dir ensures that paths with spaces are also handled correctly. (To use the current directory without an intermediate variable, replace "dir" with "$($PWD.ProviderPath)".
Using a here-string (#"<newline>...<newline>"#) isn't strictly necessary, but simplifies the embedded quoting; with a regular expandable string ("..."), the embedded " must be escaped as `" (or "").
Using $PWD's .ProviderPath property ensures that a file-system-native path is used (based on drive letters also seen in cmd.exe, for instance), given that the calling session's current location may be based on a PowerShell-only drive (see New-PSDrive) that the elevated process may not have defined (at all or not based on the same root location).
Caveat: If the native path is on a mapped network drive, this won't work, because elevated processes do not see the same drive mappings; in that event, pass the underlying UNC path.
Workaround for launching a GUI application elevated from a given working directory:
Since changing to the working directory must happen in the new, elevated process, a helper shell process is needed to perform this operation, which is best done via cmd.exe (for better performance):
$exeToLaunch = 'Notepad.exe' # may include arguments
$dir = $PWD.ProviderPath # use the current dir.
Start-Process -Verb RunAs -WindowStyle Hidden cmd.exe #"
/c cd "$dir" & $exeToLaunch
"#
Once you run Powershell as administrator;
user the push-location command like so:
Push-Location -Path C:\
or put it into your script and run the script from the elevated Powershell prompt.
I just ran your code example and it opened correctly for me at the WorkingDirectory location. Ensure the directory exists before you run the command. I tested against a drive on C and secondary drive as well and both worked.

How to call .cmd file as administrator?

Please let me know how to call .cmd file as administrator from PowerShell script:
The second line below should open as Administrator from a PowerShell script:
Set-Location "C:\client\service"
Invoke-Item "C:\client\service\_install.cmd"
Then the command prompt should wait after execution. This needs to handle in PowerShell script not possible to write in _install.cmd file.
Batch-scripts runs in CMD.exe, so you need to start a CMD.exe process as admin.
Start-Process -FilePath "C:\Windows\System32\cmd.exe" -ArgumentList "/k","C:\client\service\_install.cmd" -Verb RunAs -Wait
Start-Process is the cmdlet to start a process
-FilePath "C:\Windows\System32\cmd.exe" starts cmd.exe process
-ArgumentList "/k","C:\client\service\_install.cmd" tells cmd to leave the console open after running the script (is this what you wanted? if not, replace with /c so the cmd-window will close when done). The second argument is your script.
-Verb RunAs tells Start-Process to start the process as admin (you will recieve a UAC-window if enabled)
-Wait tells Start-Process to wait until the process is finished. With cmd /k this means after you exited the command prompt. If you've changed that to cmd /c, then it waits until the script is done.
If you need to change the working directory inside the cmd-file, then you need to modify the .cmd, or write a wrapper-script, like:
#echo off
cd /d C:\client\service
C:\client\service\_install.cmd