Powershell Git Hook Exit Code - windows

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}

Related

Get exitcode from powershell invoke-command from linux

/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

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.

Returning the correct return code

I am running the following commandline in a SCCM Task Sequence:
%WinDir%\system32\windowsPowershell\v1.0\Powershell.exe -ExecutionPolicy Bypass -Command "& {.\SAS9.4_Frv1.ps1 Install -Perso:Base}"
I tried returning from my script different exit code: -1 1618, etc... And everytime I get a return code of 0.
How may I make my script returning the correct exit code?
from my script, I am returning Exit -1 or Exit 1618.

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%'

Using Ruby to execute Powershell command in Git Hooks

I am using Git on Windows and trying to include unit testing in the workflow. If the commit message contain a keyword. The commit-msg hook will trigger Powershell command to run some Nunit tests.
This is my ruby code in the hook
#!/usr/bin/env ruby
message_file = ARGV[0]
message = File.read(message_file)
puts "The commit message is " + message
$regex = /(#runtest)/
if $regex.match(message)
exec 'powershell.exe -ExecutionPolicy RemoteSigned -Command {RunNunitTestCase}'
end
However when I commit a changes, the result is like below. The exec line was run but do nothing.
PS D:\testfolder> git commit -am '#runtest'
The commit message is #runtest
[authorupdate b14878d] 123
1 files changed, 1 insertions(+), 0 deletions(-)
I am new to ruby and powershell. Feel free to comment if this workflow is feasible or you have a better approach.
Thank you.
The curly bracket needs to be escaped.
exec "powershell.exe -ExecutionPolicy RemoteSigned -Command & \{RunNunitTestCase\}
I tried the exact script with the exec line being:
exec 'powershell.exe -ExecutionPolicy RemoteSigned -Command gps'
and it did print out the output of gps when I did git commit -m "#runtest"
So it does run the command and it does work.
Make sure that whatever you are executing does work. Grab the powershell line and try it out on commandline directly.

Resources