Powershell Run Bat File in Remote machine - powershell

I modified a function I got from Microsoft forum, it purpose is to run copy a bat file to a remote machine and to run it there. I could see the file being copied over, however it seems not working when I try to call the Invoke-Command to execute the file. Any advice will be appreciated, thank you :)
function Run-BatchFile ($computer, [string]$batLocation)
{
$sessions = New-PSSession -ComputerName $computer -Credential qa\qalab3
Copy-Item -Path $batLocation -Destination "\\$computer\C$\MD5temp" #copy the file locally on the machine where it will be executed
$batfilename = Split-Path -Path $batLocation -Leaf
Invoke-Command -Session $sessions -ScriptBlock {param($batfilename) "cmd.exe /c C:\MD5temp\$batfilename" } -ArgumentList $batfilename -AsJob
$remotejob | Wait-Job #wait for the remote job to complete
Remove-Item -Path "\\$computer\C$\MD5temp\$batfilename" -Force #remove the batch file from the remote machine once job done
Remove-PSSession -Session $sessions #remove the PSSession once it is done
}
Run-BatchFile 192.168.2.207 "D:\MD5Check\test.bat"

You put the commandline you're trying to run in quotes.
Invoke-Command -Session $sessions -ScriptBlock {
param($batfilename)
"cmd.exe /c C:\MD5temp\$batfilename"
} -ArgumentList $batfilename -AsJob
PowerShell will just echo bare strings, not interpret them as command and execute them. You need to use Invoke-Expression for the latter:
Invoke-Command -Session $sessions -ScriptBlock {
param($batfilename)
Invoke-Expression "cmd.exe /c C:\MD5temp\$batfilename"
} -ArgumentList $batfilename -AsJob
or (better) remove the quotes and (optionally) use the call operator:
Invoke-Command -Session $sessions -ScriptBlock {
param($batfilename)
& cmd.exe /c "C:\MD5temp\$batfilename"
} -ArgumentList $batfilename -AsJob

Related

Run console EXE remotely with PowerShell and get its process ID and stdout

I use PowerShell to run a console EXE on a remote server and see its output like this:
Invoke-Command -ComputerName %SERVER_NAME% -ScriptBlock { Set-Location "%EXE_DIR%" ; .\MyExe.exe %EXE_ARGS% }
This works, but gives me no way to kill the process, except connecting to the server via RDP. If I could just save its process ID to a file I should be able to kill it using Stop-Process. I tried this:
Invoke-Command -ComputerName %SERVER_NAME% -ScriptBlock { Start-Process -NoNewWindow -PassThru -Wait -WorkingDirectory "%EXE_DIR%" "%EXE_DIR%\MyExe.exe" "%EXE_ARGS%" }
The process runs, but now I don't see its standard output! When I use Start-Process locally (without Invoke-Command) I see the output.
How can I get both the process ID and the standard output/error?
Use a background job. You can either start a local job to invoke a command on a remote host:
$job = Start-Job -ScriptBlock {
Invoke-Command -ComputerName $computer -ScriptBlock {
Set-Location 'C:\some\folder'
& 'C:\path\to\your.exe' $args
} -ArgumentList $args
} -ArgumentList $argument_list
or open a session to a remote host and start a local job there:
Enter-PSSession -Computer $computer
$job = Start-Job -ScriptBlock {
Set-Location 'C:\some\folder'
& 'C:\path\to\your.exe' $args
} -ArgumentList $argument_list
Exit-PSSession
Job output can be received via Receive-Job:
while ($job.HasMoreData) {
Receive-Job $job
Start-Sleep -Milliseconds 100
}
You can terminate it via its StopJob() method:
$job.StopJob()
Remove-Job removes the job from the job list:
Remove-Job $job

Get output from remote command invocation

I have this simple code to execute a .bat file remotely through PowerShell.
Invoke-Command -ComputerName servername -Credential $credential -ScriptBlock {
Start-Process "\\servername\D$\LocalApp\application\script.bat"
}
The script works fine. The only issue is that I need to be able to see the output in the CMD window while it executes.
Use the call operator (&) instead of Start-Process:
Invoke-Command -ComputerName servername -Credential $credential -ScriptBlock {
& '\\servername\D$\LocalApp\application\script.bat'
}
or run Start-Process with the parameters -NoNewWindow and -Wait:
Invoke-Command -ComputerName servername -Credential $credential -ScriptBlock {
Start-Process '\\servername\D$\LocalApp\application\script.bat' -NoNewWindow -Wait
}

Executing program on remote with Powershell

I'm having trouble executing a program on a remote server. This is my command
$appCommand = "`"c:\SIDApps\{0}\{1}.exe`"" -f $destinationDirectory, $processToKill
Invoke-Command -ComputerName $remoteComputer -Credential $credentials -ScriptBlock { $args[0] } -ArgumentList $appCommand
That prints out "c:\SIDApps\FFMBC_Drone\GCUKTransCodeServiceFFMBCApp.exe" (Including the quotes) in the output window, but does not actually execute the program
If you only output $args[0] in the ScriptBlock it will only display the path not run the command.
Have you tried this ?
$appCommand = "c:\SIDApps\{0}\{1}.exe" -f $destinationDirectory, $processToKill
Invoke-Command -ComputerName $remoteComputer -Credential $credentials -ScriptBlock { Start-Process $args[0] } -ArgumentList $appCommand

PSSession will not change the working directory

I have a script I'm trying to implement. If I run each line seperately, it works just fine. But if I place it in a function, or run with PowerGUI or Powershell ISE, it errors out. The problem is the script isn't changing the working directory, therefore the file that Invoke-Command is calling isn't found.
$DLUpdate = New-PSSession -ComputerName msmsgex10wprd03 -Credential $DLUpdateCred -Name DLUpdate
Enter-PSSession -Session $DLUpdate
$UpdateDLPath = 'c:\users\mascott2\Desktop\Distrolist\Updates\'
Set-Location $UpdateDLPath
Invoke-Command -ScriptBlock {cmd.exe "/c updatedls.bat"}
Exit-PSSession
Remove-PSSession -Name DLUpdate
You shouldn't be using Enter-PSSession in a script like that. Put all the commands you want into the scriptblock you use with Invoke-Command and run it against your session:
$DLUpdate = New-PSSession -ComputerName msmsgex10wprd03 -Credential $DLUpdateCred -Name DLUpdate
Invoke-Command -Session $DLUPdate -ScriptBlock {
$UpdateDLPath = 'c:\users\mascott2\Desktop\Distrolist\Updates\'
Set-Location $UpdateDLPath
cmd.exe "/c updatedls.bat"
}
Remove-PSSession -Name DLUpdate

Running Batch Script on remote Server via PowerShell

I need to connect to some remote servers from a client (same domain as the servers) once connected, I need to run a batch file:
I've done so with this code:
$Username = 'USER'
$Password = 'PASSWORD'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
try {
Invoke-Command -ComputerName "SERVER1" -Credential $Cred -ScriptBlock -ErrorAction Stop {
Start-Process "C:\Users\nithi.sundar\Desktop\Test.bat"
}
} catch {
Write-Host "error"
}
This script does not give any errors, but it doesn't seem to be executing the batch script.
any input on this would be greatly appreciated.
Try replacing
invoke-command -computername "SERVER1" -credential $Cred -ScriptBlock -ErrorAction stop { Start-Process "C:\Users\nithi.sundar\Desktop\Test.bat" }
with
Invoke-Command -ComputerName "Server1" -credential $cred -ErrorAction Stop -ScriptBlock {Invoke-Expression -Command:"cmd.exe /c 'C:\Users\nithi.sund
ar\Desktop\Test.bat'"}
It's not possible that the code you posted ran without errors, because you messed up the order of the argument to Invoke-Command. This:
Invoke-Command ... -ScriptBlock -ErrorAction Stop { ... }
should actually look like this:
Invoke-Command ... -ErrorAction Stop -ScriptBlock { ... }
Also, DO NOT use Invoke-Expression for this. It's practically always the wrong tool for whatever you need to accomplish. You also don't need Start-Process since PowerShell can run batch scripts directly:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
C:\Users\nithi.sundar\Desktop\Test.bat
} -Credential $Cred -ErrorAction Stop
If the command is a string rather than a bare word you need to use the call operator, though:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
& "C:\Users\nithi.sundar\Desktop\Test.bat"
} -Credential $Cred -ErrorAction Stop
You could also invoke the batch file with cmd.exe:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
cmd /c "C:\Users\nithi.sundar\Desktop\Test.bat"
} -Credential $Cred -ErrorAction Stop
If for some reason you must use Start-Process you should add the parameters -NoNewWindow and -Wait.
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
Start-Process 'C:\Users\nithi.sundar\Desktop\Test.bat' -NoNewWindow -Wait
} -Credential $Cred -ErrorAction Stop
By default Start-Process runs the invoked process asynchronously (i.e. the call returns immediately) and in a separate window. That is most likely the reason why your code didn't work as intended.