I am trying to write a Powershell script to automate general tasks on a new computer including installing software. ExecutionPolicy has been the bane of my existence when it comes to blocking me from running automated scripts that I have been writing.
One of my PS scripts requires elevated Admin privileges, so I have a batch file where I am calling to launch PS as Administrator but I am still getting stuck with the script instantly closing/failing due to ExecutionPolicy. Ideally, I would like a way to bypass the ExecutionPolicy on a per script basis instead of completely changing it and then changing it back.
I have looked up different Set-ExecutionPolicy methods but they don't seem to work.
I need a generic command in a .bat file to launch a specified powershell script as Admin AND bypassing the current ExecutionPolicy.
The key is to use the
-ExecutionPolicyCLI parameter (which only the innerpowershellcall below needs; the sole purpose of the outer one is to launch the target session with elevation (as admin), which itself doesn't involve execution of a script file):-ExecutionPolicyCLI parameter, nor in-session withSet-ExecutionPolicy- the solution below won't work. See this answer for details.Also - unrelated to execution policies - additional work is required in order to preserve the caller's working directory, because elevated sessions default to the SYSTEM32 directory. Therefore, the command below incorporates an explicit
Set-Locationcall to set the working directory. Note that in order to call a script located in that directory you need to prefix its name with.\(e.g.,.\script.ps1instead of justscript.ps1):-noexitkeeps the elevated session open after the specified.ps1script terminates; remove it, if you want the session and thereby its window to close automatically.-noprofilesuppresses loading of the profile scripts; in the secondpowershellcall, that isn't strictly necessary, but still advisable for a predictable execution environment.Note:
In order to avoid
"-related escaping hell, the above solution uses'...'strings only, as understood by PowerShell in the context of a-c(-Command) CLI call, which, however, assumes the following:The script file name / path itself and the pass-through arguments mustn't contain
'chars. - if they do, they must be enclosed in''....''and the embedded'must be escaped as''''(sic).Set-Locationcall above, this is handled automatically by usingcmd.exe's string-replacement technique on its%CD%variable (%CD:'=''''%).If the script file path or pass-through arguments contain spaces, there mustn't be runs of multiple spaces - if so (which would be very unusual in the case of paths),
"-quoting would have to be used. Otherwise, values with spaces must be enclosed in''...'', as shown with thefoo 1argument above.Since the script file is invoked via
-c(-Command) rather than via-f(-File), the interpretation of arguments passed to it may situationally differ - see this answer.[1] There is a limited workaround: Execution policies only relate to script files, so reading a script file's content into memory and executing that - be it via constructing a script block first or by passing it directly to the usually-to-be-avoided
Invoke-Expression- is a way to bypass the active execution policy. A simplified example:powershell -noprofile -c "Invoke-Expression (Get-Content -Raw c:\path\to\foo.ps1)". That said, the technique won't work if the code executed this way calls other script files, which may also happen implicitly when modules are auto-imported.