Force ErrorActionPreference when running PowerShell? - powershell

We use PowerShell for some of our automated build scripts. Unfortunately, by default, PowerShell continues after an error.
Ordinarily, I can change this behaviour by setting $ErrorActionPreference = Stop.
I can't see a corresponding command line switch for PowerShell.exe, and we (deliberately) run the commands with -noprofile, so I can't put it in there.
How do I do this for a build script?

Put it at the top of the script you're running?
$ErrorActionPreference = 'Stop'
Alternatively, you can also get similar control at the cmdlet level using the ErrorAction parameter.

There doesn't seem to be a way to set:
powershell -erroractionpreference stop ...
The following would work:
powershell -command { $ErrorActionPreference = "stop"; .\test.ps1 } -noprofile
There is of course nothing to stop the script (re)setting ErrorActionPreference.

Related

How to run Multiple command in Windows Powershell sequentially like second executes if first is passed?

To execute multiple commands in PowerShell we use ; . But there is a flaw in it it executes all the commands even if one fails in between.
Is there any substitute for && in Windows Powershell ?
But there is a flaw in it it executes all the commands even if one fails in between.
Try setting the appropriate preference variable - it defaults to Continue in powershell.exe:
$ErrorActionPreference = 'Stop'
Some-Command
Some-CommandThatMightFail
Some-OtherCommand
Now, if Some-CommandThatMightFail throws an error, execution of the containing script or function will stop and return to the caller immediately.
See the about_Preference_Variables topic in the documentation on more information about controlling error handling behavior with $ErrorActionPreference
Beware that the $ErrorActionPreference = 'Stop' assignment only affects the current scope - overwriting it will only affect the error action preference in the script/function/scriptblock where that assignment was executed:
PS C:\> $ErrorActionPreference
Continue
PS C:\> &{
$ErrorActionPreference = 'Stop'
# preference only changes inside this scriptblock
$ErrorActionPreference
}
Stop
PS C:\> $ErrorActionPreference # still Continue in parent scope
Continue

ErrorAction Stop by default in PowerShell scripts

How can I set in a PowerShell script that all the actions have the property ErrorAction set to Stop?
P.S.: Powershell 2.0
Set the $ErrorActionPreference for the script to stop:
$ErrorActionPreference = "Stop"
edit: As ivan-mirchev pointed out, of course this change is not permanet and only active in the runspace where the code is executed. When you open a new Powershell session it will have the default value of $ErrorAction = 'Continue'

How do I run powershell scripts without admin rights?

If I try to change the execution policy, I get a message that says I can't modify the registry because I'm not an administrator.
It seems like this should be possible, since I can run batch files and other .exe and .com programs.
If your domain administrator hasn't forbidden it, you can do this:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser
This changes the default execution policy for PowerShell sessions run under the current user, rather than setting it for all users on the machine.
If you instead want to change the execution policy for just the current PowerShell session, you can use this command:
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
However, if your domain administrator is using the "Turn on Script Execution" group policy, you will not be able to change your execution policy at all. The group policy setting makes the Set-ExecutionPolicy cmdlet ineffective.
You can try and set the policy of the process itself.
powershell.exe -ExecutionPolicy bypass
if you want to have an easy way to run a script myscript.ps1 from the windows shell then all you need is a bat Runmyscript.bat with the following contents:
type myscript.ps1 | powershell -
So simple it makes me wonder why you can't just run the ps1 in the first place, but there we go.
A generic version that prompts for userinput to type the name of the script would be:
set /p filename="Type name of script here: "
type %filename% | powershell -
I suppose if you wanted to, you could also write a generic vbscript script that opens any file in powershell using a dialogue box using this http://todayguesswhat.blogspot.co.uk/2012/08/windows-7-replacement-for.html
how about
$script = Get-Content .\test.ps1
Invoke-Expression $script
This works for me. Try this: cmd /min /C "set __COMPAT_LAYER=RUNASINVOKER && start "" %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
The third technique I've found elsewhere on the internet is to use
powershell.exe -EncodedCommand XXXXXXX
where XXXXXXX is the result of
$code = {
#powershell script goes here.
}
}
[convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($code))
Ref:
http://dmitrysotnikov.wordpress.com/2008/06/27/powershell-script-in-a-bat-file/

Custom powershell prompt is clearing $lastexitcode

My powershell profile has a custom powershell prompt that unfortunately causes $lastexitcode values to be lost. For instance, given a powershell script "fail.ps1" with contents "exit 123", when I run the script, $? is $false while $lastexitcode is 0. If I instead run powershell without loading my profile with the custom prompt, after running fail.ps1 then $lastexitcode is 123.
Has anyone seen this problem before? Is there a way to preserve $lastexitcode as the prompt is generated?
I ran into this when using Posh-git, https://github.com/dahlbyk/posh-git, a nice powershell prompt for git.
Issue can be resolved by capturing $LASTEXITCODE at the start of the prompt and restoring it at the end:
function prompt {
$realLASTEXITCODE = $LASTEXITCODE
# ...
$LASTEXITCODE = $realLASTEXITCODE
}
You need to do this to make it work:
function prompt {
$realLASTEXITCODE = $global:LASTEXITCODE
# ...
$global:LASTEXITCODE = $realLASTEXITCODE
# cleanup
Remove-Variable realLASTEXITCODE
}

PowerShell 2.0 - Running scripts for the command line call vs. from the ISE

After writing deployment scripts from within the ISE, we need our continuous integration (CI) server to be able to run them automatically, i.e. from the command line or via a batch file.
I have noticed some significant differences between the following calls:
powershell.exe -File Script.ps1
powershell.exe -Command "& '.\Script.ps1'"
powershell.exe .\Script.ps1
Some simple examples:
When using -File, errors are handled in the exact same way as the ISE.
The other two calls seem to ignore the $ErrorActionPreference variable, and do not catch Write-Error in try/catch blocks.
When using pSake:
The last two calls work perfectly
Using the ISE or the -File parameter will fail with the following error:
The variable '$script:context' cannot be retrieved because it has not been set
What are the implications of each syntax, and why they are behaving differently? I would ideally like to find a syntax that works all the time and behaves like the ISE.
Not an answer, just a note.
I searched for explanation of -file parameter. Most sources say only "Execute a script file.". At http://technet.microsoft.com/en-us/library/dd315276.aspx I read
Runs the specified script in the local scope ("dot-sourced"), so that the functions
and variables that the script creates are available in the current session. Enter
the script file path and any parameters.
After that I tried to call this:
powershell -command ". c:\temp\aa\script.ps1"
powershell -file c:\temp\aa\script.ps1
powershell -command "& c:\temp\aa\script.ps1"
Note that first two stop after Get-Foo, but the last one doesn't.
The problem I describe above is related to modules -- if you define Get-Foo inside script.ps1, all the 3 calls I described stop after call to Get-Foo.
Just try to define it inside the script.ps1 or dotsource the file with Get-Foo and check it. There is a chance it will work :)
Here is a concrete example of the behaviour I described.
MyModule.psm1
function Get-Foo
{
Write-Error 'Failed'
}
Script.ps1
$ErrorActionPreference = 'Stop'
$currentFolder = (Split-Path $MyInvocation.MyCommand.Path)
Import-Module $currentFolder\MyModule.psm1
try
{
Get-Foo
Write-Host "Success"
}
catch
{
"Error occurred"
}
Running Script.ps1:
From the ISE, or with the -File parameter
will output "Error occurred" and stop
From the command line without the -File parameter
will output "Failed" followed by "Success" (i.e. not caught)