PowerShell Invoke-Command using Start-Process is not creating log file - powershell

I have a command line exe on a remote server which I need to execute remotely (running on the remote server). This exe connects to the DB, and writes a log file.
I have enabled WinRM by executing these PowerShell commands:
netsh http add iplisten localip {add local ip here}
netsh http add iplisten 127.0.0.1
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*" -Force
Enable-PSRemoting -Force
This works and I was able to test by executing
Test-WSMan {computername}
I am now trying to execute the command line exe via Invoke-Command and expecting a log file entry to be created with this script.
Invoke-Command –ComputerName MyServer –ScriptBlock {
Start-Process "C:\TheRemotePath\ToTheExe.exe"
}
PowerShell does not display any errors. However, no log file is generated. I have full rights to the directory of the exe as well as the log file directory. I am able to successfully run the exe via Windows Explorer (navigate to the remote exe and double click to run).
Any idea why this does not seem to work or what tools I can use to try and diagnose?

I would try testing the path and switching to the call operator as Ansgar mentioned, i.e.:
Invoke-Command –ComputerName MyServer –ScriptBlock {
$path = "C:\TheRemotePath\ToTheExe.exe"
if (Test-Path $path) {
Write-Host -ForegroundColor Green "Confirmed access to $path!"
& $path
}
else {
Write-Host -ForegroundColor Yellow "Unable to reach $path!"
}
}
Doing those will help you diagnose where it's getting tripped up. Depending on the EXE, I've had to use different methods of starting the process from Powershell.

Change the working directory to the location of your executable before running it. I would also recommend using the call operator (&) instead of Start-Process, unless you have reason to use the latter.
Invoke-Command –ComputerName MyServer –ScriptBlock {
Set-Location 'C:\MyDirectory'
& 'MyApp.Console.exe'
}

Related

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.

Using Powershell to check proxy setting on remote machine

So i know I can't use Netsh because WinRM is disabled/access denied on my network.
I cant invoke etc.
So I'm trying to figure out a way to take a list of computer names and get the proxy from the machines.
So, my idea is to take the list I have on a \share, and foreach ($pc in $list) I would copy over a .cmd file from the same share. that .cmd file just runs a powershell script from the share, on that remote machine.
So copy a cmd to remote machine. Run cmd on remote machine, that cmd just runs the powershell script that gets the proxy from the registry, and then writes the machine name and the proxy to a file on the share.
But,
I'm getting a blank output tho. So, weird.
Here's the script that runs on the remote machine:
Set-ExecutionPolicy Unrestricted -Force
$proxy = (Get-ItemProperty
'Registry::HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings') | Select-Object AutoConfigURL
"$env:computername $proxy" |
Out-file -filepath "\share\Proxy\IEproxylistResolved.csv"
The problem is that I get empty file in IEproxylistResolved.csv its 3am and I'm prob just half dead in the head but could use a fresh perspective.
Have you tried this:
Import-Module PSRemoteRegistry
Get-RegValue -ComputerName $Computer1 -Key
"Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Value AutoConfigURL
Source

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 Passing Local Parameters to a Remote Script via Invoke-Command

Using PowerShell 4.0. I'm trying to run a script remotely that resides on the remote server. I need to pass a variable from my local script to the remote script. I've gone over dozens of posts and tried at least 10 variations but none seem to work. My initial command was:
Invoke-Command -ComputerName $ServerList -FilePath $piDeployScript -ArgumentList $SDFEnvironment
Where $piDeployScript is the full UNC path to the script on the remote server and $SDFEnvironment is a simple string parameter passed into my script. It looks like the parameter is not getting passed to the script. Is there a simple way to do this? How far off am I?
Update: I don't write the remote scripts, they're written by other groups in the company. The only thing I know is what field(s) need to be passed and they're all positional. I don't know the actual parameter names in the remote scripts. I could get them but I'm trying to write something that will work regardless of the parameters on the remote script. I get passed a list of parameter values (in this case 1 parameter) and send that list of strings to the remote script.
Update: Per #dugas this is the test script I'm running on my own server to test the functionality
Param
(
# SDF Environment
[Parameter(Position=0)]
[string]$SDFEnvironment
)
if ($PSBoundParameters.ContainsKey('SDFEnvironment'))
{
"Script Ran Env $SDFEnvironment"|Out-File -FilePath .\$SDFEnvironment"_LogFile.txt" -Encoding ascii -Force
}
else
{
"Environment Parameter missing"|Out-File -FilePath .\"ERR_LogFile.txt" -Encoding ascii -Force
}
Update: Below is the entire section of my local script that runs the Invoke-Command:
# Run the specifed script on all computers
Write-Output ("Running command ""{0}"" on server(s) ""{1}"" for Environment ""{2}"" " -f $piDeployScript,$SDFServerList,$SDFEnvironment)
try
{
if (Test-Connection -ComputerName $SDFServerList -Quiet)
{
Invoke-Command -ComputerName $SDFServerList -FilePath $piDeployScript -ArgumentList $SDFEnvironment
}
else
{
Write-Error "Remoting not enabled on one or more of ""$SDFServerList"" "
exit 1
}
}
catch
{
Write-Error ("Error running script {0} on server(s) {1}. Check log for more detail." -f $piServerScript,$SDFServerList)
exit 1
}
and here's the output from that code:
Running command "D:\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1" on server(s) "ad1hfdahp802" for Environment "INT"
D:\a5\RWS_pi_exceed_presentation\Content_Deploy\trunk\deploy\Deploy-Content.ps1
: Error running script pi_exceed_presentation_deploy.ps1 on server(s)ad1hfdahp802. Check log for more detail.
My bad on the $piDeployScript variable. It's not the UNC to the script, it's the local file system address on the remote server. Is that the problem? Is it looking for the script on my local D: drive? Did I just answer my question?
Just to test my questions above I ran this code in PowerShell from my desktop:
$s="ad1hfdahp802"
$SDFEnvironment="INT"
$fp="\\ad1hfdahp802\D$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1"
try
{
Invoke-Command -ComputerName $s -FilePath $fp -ArgumentList $SDFEnvironment
}
catch
{
write-output "error running $fp on $s for $SDFEnvironment"
}
The code returned with no error, but the remote script didn't run. I logged into the remote server via RDC and ran the remote script locally in PowerShell with and without a parameter and it worked as expected. Now I'm really stumped.
Local script:
$server='ad1hfdahp802'
$remotepath='\\ad1hfdahp802\d$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
$scriptPath='d:\AHP\pi_exceed_presentation\'
$SDFEnvironment='INT'
Invoke-Command -ComputerName $server -FilePath $remotepath -ArgumentList($SDFEnvironment,$scriptPath)
Remote Script:
Param
(
# SDF Environment
[Parameter(Position=0)]
[string]$SDFEnvironment,
[Parameter(Position=1)]
[string]$scriptPath
)
Write-Output "Running Script - $SDFEnvironment"
Write-Output "Path: $scriptPath"
$outpath=("{0}\{1}_LogFile.txt" -f $scriptPath,$SDFEnvironment)
"Script Ran Env $SDFEnvironment"|Out-File -FilePath $outpath -Encoding ascii -Force
Write-Output "Script Complete"
This combination works. Originally the remote script used $PSCommandPath (also tried $PSScriptRoot) to determine the output path but that doesn't work on scripts run remotely. The actual path has to be passed in if you want deterministic placement of output files.