开发者

How to return an exit code from a Powershell script only when run non-interactively

开发者 https://www.devze.com 2023-01-29 19:08 出处:网络
I have a lot of scripts that are running as scheduled tasks. So they do a $host.setshouldexit(1) on any failure, which shows up in the task scheduler as the return code.

I have a lot of scripts that are running as scheduled tasks. So they do a $host.setshouldexit(1) on any failure, which shows up in the task scheduler as the return code.

I also want to be able to run these scripts interactively while debugging and testing. So the $host.setshouldexit()开发者_开发百科 kills my powershell or ISE session.

My question is: how can I detect if a script is running non-interactively? If it is, then I'll use setshouldexit, otherwise it will print the error code or something nondestructive. (Note that I don't want to use [environment]::userinteractive because these scripts are not always running in what the OS thinks is a non-interactive session.)

There is a -noninteractive switch that I'm using for the scheduled tasks. Is there some way I can query that from powershell?


The $Host.SetShouldExit method should not be necessary, and is actually inconsistent, depending on how you are calling your scripts. Using the keyword exit should get you your exit status.

Using powershell -F script.ps1:

  • exit - works
  • SetShouldExit - ignored

Using powershell -c '.\script.ps1':

  • exit - status reduced to 0 or 1, for success or failure of the script, respectively.
  • SetShouldExit - exits with correct status, but remaining lines in script are still run.

Using powershell -c '.\script.ps1; exit $LASTEXITCODE' [1]:

  • exit - works
  • SetShouldExit - exits with status == 0, and remaining lines in script are still run.

Calling directly from powershell (> .\script.ps1):

  • exit - works
  • SetShouldExit - terminates calling powershell host with given exit status


Why not just have it take a parameter "testing" which sets the right behavior during your tests? You have a history buffer so it will be hardly any more typing to run.


I had the same issue. The following works for me:

# Exit with Return Code when NOT using PowerShell ISE
if ($psise -eq $Null)
{
    $host.SetShouldExit(1)
}


Upon finding your question I have taken the issue a bit further and found $MyInvocation.MyCommand.Name. This is False in both the command interpreter and the ISE command interpreter. And when a script (mine is jest.ps1) containing just the line: Write-Host $MyInvocation.MyCommand.Name is run from cmd.exe call to powershell.exe as:

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe  -ExecutionPolicy RemoteSigned -NoExit -NonInteractive -NoProfile -File "M:\WindowsPowerShell\Jest.ps1"

Output is simply:

Jest.ps1


Check $Host.Name. If your script is running outside of an IDE, it will return a value of ConsoleHost. Otherwise it will return a reference to the IDE such as Windows PowerShell ISE Host or PowerGUIScriptEditorHost.

I have to use SetShouldExit because the scheduler that runs my scripts usually ignores other methods of indicating a failure. I add a function to allow SetShouldExit when $Host.Name is ConsoleHost. It saves a lot of IDE crashes during testing.


This directly answers the question poster had about whether or not you can query if the powershell console was launched with -NonInteractive switch.

Function Test-IsPowerShellConsoleNonInteractive { [Boolean]([Environment]::GetCommandLineArgs() -Match '-NonInteractive') }
$IsPSConsoleNonInteractive = Test-IsPowerShellConsoleNonInteractive
If ($IsPSConsoleNonInteractive) { $Host.SetShouldExit(2) }
0

精彩评论

暂无评论...
验证码 换一张
取 消