Start an executable on a remote station - powershell

I have a executable that resides on a remote station that I am trying to run from a central server, but running into issues. I am able to stop the Process on the remote station from the server using
Invoke-Command -ComputerName $name {Stop-Process -Name "ProcessName"
But when I try and run the executable, using
Invoke-Command -ComputerName $Args Start-Process "C:\Process\Process.exe"
it returns an error
This command cannot be run due to the error: The system cannot find the file
I have tried many variations of Invoke-Command, Start-Process, along with specifying the UNC path using the $name variable, but it will not run the executable stored on the remote computer.

You should run it like this:
Invoke-Command -ComputerName $name -ScriptBlock {
Set-Location c:\path\to\exe
FileName.exe /switch 1 /switch 2
}
You don’t need to use Start-Process. Just call the file and it should start execution.

Related

Powershell : I am trying to run a script on a remote server. The script is for gathering info of that remote and other servers in the same domain

Editing to be clear with the issue
I am running the below code from a local computer which should run the script Test.ps1 placed on $server at C:\Temp to collect data from $server and other servers.
When i perform this, the script runs but i only get data for the $server and not the others. While if i run the C:\Temp\Test.ps1 script sitting on the $server, i get the desired output for all servers.
I am using this code
$s = New-PSSession -ComputerName $server -Credential $credential
Invoke-Command -Session $s -Command {C:\Temp\Test.ps1}
I am getting the output for the remote server on which the code is placed (localhost for the script), buti am not getting any output for the other servers.
While if I run the script locally on the remote server i get output from all the servers
The script does not have to be on the remote host. PowerShell allows you to run local PS1 scripts on remote computers.
Running Remote Commands
https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/running-remote-commands?view=powershell-7.1
Run a Script
To run a script on one or many remote computers, use the FilePath
parameter of the Invoke-Command cmdlet. The script must be on or
accessible to your local computer. The results are returned to your
local computer.
For example, the following command runs the DiskCollect.ps1 script on
the remote computers, Server01 and Server02.
Invoke-Command -ComputerName Server01, Server02 -FilePath 'c:\Scripts\DiskCollect.ps1'
As for this...
'My requirement is to run that script from the remote host per
security protocols'
... just use a script block as shown via the same MS Docs link
Run a Remote Command
To run a command on one or more computers, use the Invoke-Command
cmdlet. For example, to run a Get-UICulture command on the Server01
and Server02 remote computers, type:
Invoke-Command -ComputerName Server01, Server02 -ScriptBlock {& .c:\Scripts\DiskCollect.ps1}
Of course, I just removed Get-UICulture cmdlet in the docs command, with a script to use.
It depends on how your remote script uses credentials to access other servers. This should classify as a double hop issue.
If you cannot use CredSPP, you can use Resource-Based Kerberos Constrained Delegation
or use credentials inside the Invoke-Command scriptblock i.e. you can define a credential object on the local computer to be used in the -credentials parameter, and refer to it with $using:cred in your scriptblock.
The article does a good job of summarizing all your options.

Start-process: both positional parameter and can't locate file specified

Ok, So I am working on the powershell remote deployment of software to ADUsers.
I have remote access to the computer and all, no problems there.
Right now I am at the point where I have a exe file from Ninite to just install 7zip onto the client pc just to see when it works so i can start deploying some bigger programs to it.
The guide I have found to help me deploy out the software for now looks like this:
Invoke-Command -ComputerName *REDACTED* -Scriptblock {
Start-Process C:\Users\Administrator\Documents\ninite_7_zip\Ninite 7Zip Installer.exe '/silent' -wait
}
When I do run this code, I get the error:
A positional parameter cannot be found that accepts argument 'Installer.exe'.
So I thought to myself, that it might be because of the spaces in the name. So therefore I changed it to:
Invoke-Command -ComputerName *REDACTED* -Scriptblock {
Start-Process C:\Users\Administrator\Documents\ninite_7_zip\Ninite_7Zip_Installer.exe '/silent' -wait
}
And ofcourse also changed it's name within the folder to match the "newly made" code.
But the error now changed into:
This command cannot be run due to the error: The system cannot find the file specified
Even though I use Powershell ISE, and I used it's guideboxes when writing, to enter the folder and find it, when I wrote the directory.
My only goal in this, is that I want to remotely run and complete this installer on the client PC when deployed from the DC upon which the file lies.
Anybody got a qualified guess? Or maybe even so, a solution.
Thanks in advance for your kind answers.
When I do run this code, I get the error:
A positional parameter cannot be found that accepts argument 'Installer.exe'.
You'll want to use quotation marks to qualify path names with spaces in them:
Start-Process 'C:\Users\Administrator\Documents\ninite_7_zip\Ninite 7Zip Installer.exe' '/silent' -wait
But the error now changed into:
This command cannot be run due to the error: The system cannot find the file specified
Even though I use Powershell ISE, and I used it's guideboxes when writing, to enter the folder and find it, when I wrote the directory.
ISE is not smart enough to realize that the scriptblock is to be executed on a remote computer, so it completes the path based on your local file system.
You still need to copy the executable to the remote machine in order to execute it:
# first copy the installer to remote file system
$remoteSession = New-PSSession -ComputerName $computerName
$localInstaller = 'C:\Users\Administrator\Documents\ninite_7_zip\Ninite 7Zip Installer.exe'
$remotePath = Invoke-Command -Session $remoteSession -ScriptBlock { $env:TEMP }
Copy-Item $localInstaller -Destination (Join-Path $remotePath "7zInstaller.exe") -ToSession $remoteSession
# now we can invoke the executable on the remote machine (re-using the same remoting session)
Invoke-Command -Session $remoteSession -ScriptBlock {
Start-Process (Join-Path $env:TEMP "7zInstaller.exe") '/silent' -Wait
}
# clean up
$remoteSession |Remove-PSSession |Out-Null

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.

Launch exe/bat on remote server with PowerShell (not copy content to my server)

I found the Invoke-Command cmdlet in PowerShell that supposedly is invoking a command on another server but this doesn't quite work. Instead what I get is the print of what the bat/exe. My exe is a console app and the bat was a test I did that launches the exe with start "" "myexe.exe".
This is the command I'm trying to do:
Invoke-Command -ComputerName 10.10.10.10 -ScriptBlock {
'C:\Program Files\program.exe'
}
or
Invoke-Command -ComputerName 10.10.10.10 -ScriptBlock {
'C:\Program Files\batch.bat'
}
In both cases instead of the command getting invoked on the other server I get the print on the server I call from.
Did I miss an argument somewhere? I want to launch the exe/bat on the remote server, not on the server I'm on.
EDIT
I made it work with this:
$command = "PathtoExe.exe"
$process = [WMICLASS]"\\10.10.10.10\ROOT\CIMV2:win32_process"
$result = $process.Create($command)
But now the exe is not displayed, it's like running in the background.
Your problem is how you're trying to call the executable. In PowerShell, everything is an object. What you're doing is printing the String to the console instead of executing. To invoke the string, you need to use the call operator: &
Invoke-Command -ComputerName 10.10.10.10 -ScriptBlock {
& 'C:\Program Files\batch.bat'
}
This will cause it to use the default program for that extension.
I had the same pain trying to run "netsh.exe" on a remote host. Eventually got it working with the following code:
Invoke-Command -ComputerName 10.10.10.10 -ScriptBlock {Invoke-Expression "C:\Program Files\program.exe"}

Powershell Remoting: Load local script inside script

I launch a local script on a remote computer with:
Invoke-Command -ComputerName RemoteServer -FilePath C:\myFolder\Script1.ps1
This script dot-sources another script (Script2), which also is located on my local computer in "C:\myFolder". This fails because Script1 trys to load the Script2 from the remote computer.
Is there a way to load Script2 from my local computer inside Script1 inside the remoting session?
[Workaround]
Create a session to the remote server
Use the session to load the script2
use the same session to run the script1.
eg:- $Session = New-PSSession -ComputerName $Server
Invoke-command -Session $Session -FilePath <script2> this should load functions
Invoke-command -Session $Session -FilePath <script1>
here the functions in script2 will be available for script1 to consume, so no need to refer and dot source script2 .
I don't think this can work the way you outlined it since code running on the remote machine cannot find a file that is relative to the local machine.
The only way to achieve this is to share your script and include it as with a UNC path, or an administrative share, like \\localmachine\c$\users\test\script\a.ps1.
But there's a chance you'll run into authentication issues (double hop).
The (easiest) solution: copy all your scripts to the remote machine first and make sure that the paths used in the scripts will work.