Get exitcode from powershell invoke-command from linux - windows

/usr/bin/pwsh -command Invoke-Command -Hostname PC -UserName boss -FilePath ./check.ps1 -ArgumentList "A","25","10"
So I am running this command from Ubuntu with bash shell. The invoke-command is connecting with ssh. The last line of check.ps1 is "Exit 2". But exit code alway return 0. Any suggestions to get the correct exit code? I would like to use this command as Nagios check.

Unfortunately, as of PowerShell 7.2, any out-of-runspace code, notably including remoting calls, does not relay script / process exit codes.
Therefore, your script's exit 2 command has no effect on the exit code reported by the /usr/bin/pwsh process.
Even inside the PowerShell session this exit code isn't available for out-of-runspace calls[1], so - unfortunately - your only option is to make your script output the desired exit code, make the PowerShell session capture it, and relay with an exit call that is a direct part of the PowerShell code passed to the CLI's -command parameter.
In the simplest case, if you modify your script to output the desired exit code and assuming that that exit code is the script's only output, you can use:
/usr/bin/pwsh -command 'exit (Invoke-Command -Hostname PC -UserName boss -FilePath ./check.ps1 -ArgumentList A, 25, 10)'
[1] For in-runspace calls, the exit code set by scripts that use exit as well as by external programs (processes) is reflected in the automatic $LASTEXITCODE variable.

For what it's worth, I believe if your script has an exception, the exit code will be non-zero. For example, my check.ps1 just has "get-childitem foo" where foo doesn't exist. This is from cmd, but I believe the effect is the same.
pwsh -command Invoke-Command -computername localhost check.ps1 -args A,25,10
Get-ChildItem: Cannot find path 'C:\Users\js\Documents\foo' because it does not exist.
echo %errorlevel%
1

Related

Powershell equivalent of Perl's $CHILD_ERROR

I essentially require a functionality in Powershell that executes the given string (it can be a CMD/Powershell command, a perl/python/powershell with arguments or an exe with arguments, etc) captures its exit value.
In perl I would pass the string to 'system()' and use the '$CHILD_ERROR' perlval and shift it to access the exit code.
In powershell I am clueless.
I tried using Invoke-Expression, but even if the expression passed to Invoke-Expression fails, the Invoke-Expression call itself will have succeeded.
You can use $LASTEXITCODE to get the exit code from an external program or the Boolean $? to check if the last operation succeeded or failed. Run Get-Help about_Automatic_Variables -ShowWindow from a PowerShell console to see more details.
You may want to check out the & (call) command as an alternative to Invoke-Expression when running external programs. Run Get-Help about_Automatic_Variables -ShowWindow from a PowerShell console for details.
Also remember you may be able to just call the external program without using one of the commands above. See the example below:
param($Hostname="127.0.0.1", $Tries=1, $Wait=1000)
$output = ping.exe $Hostname -n $Tries -w $Wait # captures anything written to stdout
$output|? {$_ -match 'Request timed out'}|Write-Warning
$LASTEXITCODE # returns the exit code from ping.exe
You can copy it to a test.ps1 file and run it from a PowerShell console window (.\test.ps1 8.8.8.8 for instance) to see how it works.

Autologon.exe via command line and get result

Is there a way I can execute sysinternals Autologon.exe from command line (Powershell) and get the result, i.e. know if the credentials entered were correct?
If I use the GUI and not the command line then I do get message with this info..
Thanks.
You can run any Windows .exe/cmd/bat/vbs from PoSH, as long as you call it correctly.
PowerShell: Running Executables
https://social.technet.microsoft.com/wiki/contents/articles/7703.powershell-running-executables.aspx
There are several different methods for running executables as well as invoking code. How do you know which one to use for the job? Here is an outline of the methods with examples and general use.
Regarding ---
"If I use the GUI and not the command line then I do get message with this info.."
This is because Autologon.exe is doing this work and returning the result. SO, it's Autologon. PoSH will not get in Autologon's way / process, but you can get the exit code from external tools as long as you know what they are. I've not tried to this with Autologon. Yet, in most cases, it's a Boolean response: success or failure, 0 or 1, or 1 or 2. The Start-Process cmdlet allows you to trap error / exit code from a process, using the -PassThru parameter. Often that is use in concert with the -wait parameter as well.
Something like:
$AutologExitCode = Start-Process -FilePath = Autologon.exe -ArgumentList $SomeArguments -NoNewWindow -Wait -PassThru
"The error/exit code from AutoLogon is $($AutologonExitCode.ExitCode)"
Full disclosure: We do not allow Autologon in our environment. So, I've spent no time using Autologon, but the above premise would be the same as other exe's.

Batch one liner append second command after powershell call

I have a batch file structured like below:
cd "C:\my\scripts\directory
powershell -f myPowershellSCript.ps1
exit %errorlevel%
This batch file is being sent through an in house remote shell application (which is mostly a black box to me) in a non-interactive way to another machine to be run. I can execute the application and watch it's output on the terminal locally. The script is completing the powershell script and then just dropping back to the remote shell on the test machine without ever running the last line in the batch file. I see the cmd.exe shell drop back to a prompt at C:\my\scripts\directory on the remote machine and just wait. Because it's non-interactive the script never completes.
I'd like to tag that last exit line onto the end of the line that calls powershell, but everything I've tried (below) has not worked. I fear that powershell is taking everything as input instead of batch interpreting them as two separate commands.
powershell -f SecurePaymentsTestLauncher.ps1 && exit 1
powershell -nonInteractive -f SecurePaymentsTestLauncher.ps1 && exit 1
powershell -nonInteractive -command "& 'SecurePaymentsTestLauncher.ps1'" && exit 1
powershell -nonInteractive -command "& 'SecurePaymentsTestLauncher.ps1'" ; exit 1
powershell -nonInteractive -f SecurePaymentsTestLauncher.ps1 ; exit 1
still produces the same result. No return from the remote execution.
How do I append a second command to a batch file line when the first command is a call to powershell?
Is your PowerShell process exiting status 0? The && conditional operator only executes the command it precedes when the command it follows exits 0. If you want to exit 1 regardless of whether PowerShell exits zero or non-zero, use a single &.
In your powershell command, you might also need to call the .ps1 script name as .\SecurePaymentsTestLauncher.ps1 and add the -ExecutionPolicy RemoteSigned arguments.
Try
cd "C:\my\scripts\directory"
start powershell -f myPowershellSCript.ps1
exit %errorlevel%
Using 'start' in front of powershell instantiates a separate powershell host outside of the batch script host, which will allow your ps1 file to do its thing while your batch script goes straight to 'exit %errorlevel%'

How to debug hidden powershell scripts?

I'm writing a script that normally will get called by another application (VMware vCenter Server). From that application I trigger a batch file (redirect.bat) and pass a variable which is the powershell script name (TestMe.ps1).
The script is placed on a Windows Server and when I go into the command prompt of the Windows Server and call the redirect script, I see that my PowerShell script runs as expected. However when I trigger it from the app the Powershell script is not run or doesn't produce output. I have confirmation that the redirect.bat is run, because the redirect.bat writes a line in a log file.
The vCenter Server app is running under Local System account. Could it be a permissions error? Is LocalSystem allowed to run Powershell scripts?
I now have no clue if the Powershell script even starts, because it (of course) is not visible in my console when running. The batch file always returns errorlevel = 0.
Any tips on how to insert debugging info in the script that should always give output? Tips on how to troubleshoot this?
redirect.bat:
set POWERSHELL=C:\WINDOWS\system32\windowspowershell\v1.0\powershell.exe -nologo -noprofile -noninteractive
SET ERRORLEVEL =
echo %1 > G:\DataStoreAlarms\Log\Redirect-batch.txt
start %POWERSHELL% -command "&"%1""
echo Error level: %ERRORLEVEL% >> G:\DataStoreAlarms\Log\Redirect-batch.txt
I call redirect.bat from the command line and from the app like this:
redirect.bat G:\DataStoreAlarms\Scripts\TestGabrie.ps1
TestGabrie.ps1:
$String = "This is a test"
$String | Out-File -FilePath "G:\DataStoreAlarms\Log\Powershell.txt" -Append
Regards
Gabrie
Problem seemed to be the START command:
start %POWERSHELL% -command "&"%1""
After changing it to this, it worked:
%POWERSHELL% -command "&"%1""
Thanks for all your help.

Powershell Git Hook Exit Code

I have the following in my .git/hooks/pre-commit file
#!/bin/sh
exec c:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy RemoteSigned -Command " Get-Location | % { '$_\pre-commit-hook.ps1'} | % { & $_ }"
exit
This successfully executes the code in the pre-commit-hook.ps1 file in the same directory, but does not capture the exit code. According to tldp.org the last exit code will be returned if only exit is specified. Git hooks will fail if the exit code is non-zero, but even though my powershell script returns a status code of 1, it always succeeds. What can I do to capture the exit code from the powershell script so the hook will function correctly?
Keep the invocation of the ps1 script simple and you should have it working. The following works for me:
#!/bin/sh
echo
exec powershell.exe -ExecutionPolicy RemoteSigned -File '.\.git\hooks\pre-commit-hook.ps1'
exit
The ps1 script just had an exit 1 and the commit did not happen.
When you are doing stuff like -command, Powershell is not known to work properly and you might have to do something like -command {& .\test.ps1; exit $lastexitcode}

Resources