Unable to run the parametrized batch file on remote machine using PowerShell - powershell

Execute the remote server parametrized batch file from PowerShell.
Doesn't throw an error nor executed command on remote machine.
$path = "D:\run\test-5.2.bat";
Invoke-Command -ComputerName testserver -Scriptblock { "$path" }
Script inside the bat file is msiexec with parameters, which shall execute through Command Prompt only.

Based on this msdn link, you can run a ps1 script file on remote computers. So if it is possible to "port" the content of the bat file in a ps1 it should work. Here is the msdn example:
Example 11: Run a script on all the computers listed in a text file
PS C:\> Invoke-Command -ComputerName (Get-Content Servers.txt) -FilePath C:\Scripts\Sample.ps1 -ArgumentList Process, Service
This example uses the Invoke-Command cmdlet to run the Sample.ps1 script on all of the computers listed in the Servers.txt file. The command uses the FilePath parameter to specify the script file. This command lets you run the script on the remote computers, even if the script file is not accessible to the remote computers.
When you submit the command, the content of the Sample.ps1 file is copied into a script block and the script block is run on each of the remote computers. This procedure is equivalent to using the ScriptBlock parameter to submit the contents of the script.
Hope that helps

$path is a string. PowerShell simply echoes bare strings instead of executing them, unlike CMD or bash. Use the call operator (&):
& "$path"
or Start-Process:
Start-Process cmd.exe -ArgumentList '/c', $path -NoNewWindow -Wait
to have PowerShell execute a string as a command. Since you say you're running msiexec.exe from the batch script using the latter may be required.
On top of that you have a scope issue. The variable $path inside the scriptblock is not the same as the one in the global scope. You can mitigate that via the using: scope qualifier:
Invoke-Command -Computer testserver -Scriptblock { & "$using:path" }
or by passing $path as an argument to the scriptblock:
Invoke-Command -Computer testserver -Scriptblock { & "$($args[0])" } -ArgumentList $path

Related

Remotely running Acrobat Distller via powershell command line

I have a task to remotely run Acrobat Distller (AD) remotely.
I was able to locally run AD in the command prompt:
"C:\Program Files (x86)\Adobe\Acrobat DC\Acrobat\acrodist.exe" /O $OutputFolder $InputFolder\test.ps
I tried invoking the same command using powershell:
powershell.exe -NoExit -Command Invoke-Command -ComputerName $server -ScriptBlock {'"C:\Program Files (x86)\Adobe\Acrobat DC\Acrobat\acrodist.exe" /O $OutputFolder $InputFolder\test.ps'}
When ran, the powershell command did prompt any error BUT it did not generate the expected PDF output as well.
Can I get some assistance on what I am doing wrong here?
Thanks
You probably need to use $using:OutputFolder and $using:InputFolder.
Normally, powershell variables are only set for your session and don't carry over to remote servers. The $Using: format allows you to do this with Invoke-Command.

Powershell start-process can't find file

I am trying to upgrade a server with a particular application from a client by PowerShell remote:
Invoke-Command -ComputerName $server -Credential $mycreds {Start-Process -FilePath "C:\temp\xxx.exe" -ArgumentList "-default", "-acceptEULA" -wait }
Whatever I try, I get messages like "Can't find the file specified..." what do I do wrong?
FilePath is on the local (client) computer.
Your C:\temp\xxx.exe executable must be present on the server (the remote machine) for your command to work, because that is where your script block ({ ... }) executes.
Note: By contrast, if you use Invoke-Command with the -FilePath parameter in order to run a locally present script file (.ps1) remotely, PowerShell automatically copies it to the remote machine; from the docs: "When you use this parameter, PowerShell converts the contents of the specified script file to a script block, transmits the script block to the remote computer, and runs it on the remote computer."
To copy the executable there from your local (client-side) machine, you need a 4-step approach (PSv5+, due to use of Copy-Item -ToSession[1]):
Create a remoting session to $server explicitly, using New-PSSession
Copy the local (client-side) executable to that session (the remote computer) with Copy-Item and its -ToSession parameter
Run your Invoke-Command command with the -Session parameter (rather than -ComputerName) in order to run in the explicitly created session (this isn't strictly necessary, but there's no need to create another (ad hoc) session).
Run Remove-PSSession to close the remote session.
Important: In a PowerShell remoting session, you cannot run external programs that require interactive user input:
While you can launch GUI applications, they invariably run invisibly.
Similarly, interactive console applications aren't supported (although output from console applications is received by the client).
However, interactive prompts from PowerShell commands are supported.
To put it all together:
# Specify the target server(s)
$server = 'w764' # '.'
# Establish a remoting session with the target server(s).
$session = New-PSSession -ComputerName $server
# Copy the local executable to the remote machine.
# Note: Make sure that the target directory exists on the remote machine.
Copy-Item C:\temp\xxx.exe -ToSession $session -Destination C:\temp
# Now invoke the excutable on the remote machine.
Invoke-Command -Session $session {
# Invoke *synchronously*, with -Wait.
# Note: If the program is a *console* application,
# you can just invoke it *directly* - no need for Start-Process.
Start-Process -Wait -FilePath C:\temp\xxx.exe -ArgumentList "-default", "-acceptEULA"
}
# Close the remote session.
# Note: This will terminate any programs that still
# run in the remote session, if any.
Remove-PSSession $session
[1] If you're running Powershell v4 or below, consider downloading psexec.

Using PowerShell to execute a remote script that calls a batch file

I am having an issue with running a batch file that is located on a remote server.
I have a batch file located on a remote server that i want to run that kicks off an automated Selenium test. For simplicity, let's say the name of my batch file is mybatch.bat
I have the following code in a Powershell script located on the server:
$BatchFile = "mybatch.bat"
Start-Process -FilePath $BatchFile -Wait -Verb RunAs
If I run this PowerShell script locally on the server in ISE then it runs fine and it kicks off the selenium test which takes a couple minutes to run.
Now I want to try to execute this test from another machine by using PowerShell remoting. Let's assume that remoting is already configured on the servers.
I have a PowerShell script located on another server which has the following code segment. Assume that all of the session variables have the correct information set:
$CMD = "D:\mybatch.bat"
$TargetSession = New-PSSession -ComputerName $FullComputerName -Credential $myCreds -ConfigurationName RemoteExecution
$command = "powershell.exe -File $CMD -Wait"
Invoke-Command -Session $TargetSession -ScriptBlock { $command }
When this script runs, it does connect to the remote machine and create a remote session. It does look like it kicks off the batch file because PowerShell does not give me an error. But it does not wait for the full 3 or 4 minutes for the Selenium test to finish. It seems like it just times out. Also if I am logged onto the other machine, I don't see any Selenium web test running. No Selenium log files or results files are created on remote server as should be expected.
I was wondering what I could be doing wrong with my code.
Also, it seems that the server always returns the echo outputs of the batch file to my local machine. I see these random blinking white screen on ISE which looks like output from the batch file
$command = "powershell.exe -File $CMD -Wait"
Invoke-Command -Session $TargetSession -ScriptBlock { $command }
There are 2 issues with the above code:
$command inside the scriptblock and $command outside the scriptblock are different variables due to different scopes. The variable inside the scriptblock is thus undefined and the scriptblock will simply echo an emtpy value.
Even if $command weren't undefined, the scriptblock would still just echo its value, since it's defined as a string. PowerShell does not execute strings unless you're using something like Invoke-Expression (which you shouldn't).
This should do what you want:
$CMD = "D:\mybatch.bat"
$TargetSession = New-PSSession -ComputerName $FullComputerName -Credential $myCreds -ConfigurationName RemoteExecution
Invoke-Command -Session $TargetSession -ScriptBlock { & $using:CMD }
If you would like execute a bat file from another machine by using PowerShell Remote Session, simply enter dot and then follow by a whitespace, then enter the exact path of bat file located on that remote machine.
Example
Invoke-Command -ComputerName RemoteComputerName -Credential $credential -ScriptBlock {. "D:\Temp\Install_Something.bat"}

Run .bat file with Administrative rights

My PowerShell script runs a .bat file to install an .msu file. But I need to run this .bat file with Administrator rights.
The .bat file is:
WUSA C:\temp\Win8.1AndW2K12R2-KB3191564-x64.msu /quiet /norestart
I have Domain Controller and a lot of clients. With PowerShell PS session I interactively connect to every client. I need to use this bat file with Domain Admin credentials, how can I do this?
You could use Invoke-Command
You could save the servers in list in a text file and then use the Get-Content command to save the array in a variable:
$clients = Get-Content C:\ExampleClientList.txt
Then use the variable for the ComputerName parameter of Invoke-Command. Then in the scriptblock parameter is where you run the command, since you can run executables in PowerShell there isn't any need for the bat file. Last the Credential parameter will allow you run this as the Local administrator.
Invoke-Command -Computername $clients -ScriptBlock {WUSA C:\temp\Win8.1AndW2K12R2-KB3191564-x64.msu /quiet /norestart} -Credential (Get-Credential)
I am not sure i understand your question.
To start batch file from powershell you can use start-proccess command:
powershell start-process <path to your file> -verb RunAs

Trouble Executing a .cmd file during a PS-Session

Im trying to execute a .bat file remotely in a powershell script. The code in my script file looks something like this:
$server
$cred
# Both of these methods are strings pointing to the location of the scripts on the
# remote server ie. C:\Scripts\remoteMethod.cmd
$method1
$method2
$scriptArg
Enter-PSSession $server -Credential $cred
Invoke-Command {&$method1}
if($?)
{
Invoke-Command {&$method2 $args} -ArgumentList $scriptArg
}
Exit-PSSession
But whenever I run it I get
The term 'C:\Scripts\remoteMethod.cmd' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
This happens even if i switch around the order the methods are called in.
I found this question Using Powershell's Invoke-Command to call a batch file with arguments and have tried the accepted answers to no avail.
I wouldn't have expected the $method1 and $method2 variables to be available inside the scriptblock for Invoke-Command. Usually you would have to pass those in via the -ArgumentList parameter e.g.:
Invoke-Command {param($method, $arg) &$method $arg} -Arg $method2 $scriptArg
But it seems in your case the path to the CMD file is making it across the remote connection. Try this to see if the problem is related to a modified ComSpec environment variable on the remote machine:
Invoke-Command {param($method, $arg) cmd.exe /c $method $arg} -Arg $method2, $scriptArg