Powershell: handmade port scanner, -ErrorAction buggy? [duplicate] - powershell

I am writing a script to prepare our laptops before use. It essentially installs certificates and sets the executionpolicy to AllSigned.
It gets executed by right mouse click and "Run with Powershell". This is a windows 10 standard bypass of executionpolicy and lets the script run on unmodified windows 10 machines (That's what it looks like to me at least). So I can execute my script without the need to change the executionpolicy explicitly.
After the script ran the machine is set up. I just get a warning that I want to suppress.
To do this inside the script I elevate the script to administrator rights with a bypass parameter. This works fine except that I get a warning when setting the AllSigned execution policy. It says that I have a policy defined at a more specific scope.
Note: The command worked and the execution policy is set. It just pops up red and looks like an error. If someone else executes the script I don't want to have questions popping up.
--My question:--
As I know that this behavior is intended I don't want the warning from showing up. How can I suppress the message?
I tried various settings with the switches "WarningAction" and "ErrorAction" but it does not work.
Some Details:
ErrorMessage:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy
successfully, but the setting is overridden by a policy defined at a
more specific scope. Due to the override, your shell will retain its
current effective execution policy of Bypass. Type
"Get-ExecutionPolicy -List" to view your execution policy settings.
For more information please see "Get-Help Set-ExecutionPolicy". At
C:\Users\uwe\Desktop\InstallRootCA\InstallRootCertificate.ps1:46
char:5
+ Set-ExecutionPolicy AllSigned -Scope LocalMachine -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
+ FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
Relevant Code parts from powershell script:
Elevating the script prior to execution:
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
exit;
}
Setting the Executionpolicy at the end of the script:
Set-ExecutionPolicy AllSigned -Scope LocalMachine
I tried all kinds of flags
-Force
-WarningAction Ignore|SilentlyContinue
-ErrorAction same
But still the red warning pops up.

You can put this command into a try catch statement. The catch statement will handle the errors and if it is empty, nothing will happen if Set-ExecutionPolicy throws an error.
try{
Set-ExecutionPolicy AllSigned -Scope LocalMachine
}
catch {
#Do Nothing
}
Please test it, let me know if it worked and if it did, please mark the post as the answer :)

Nicicalu's answer is effective; let me add some background information:
What Set-ExecutionPolicy emits in your case is a (statement-)terminating error, which is why it is neither affected by -ErrorAction nor by -WarningAction.
Terminating errors can only be handled via:
try / catch, as shown in Nicicalu's answer.
The - rarely used - trap statement
Confusingly, they can be silenced and ignored by setting preference variable $ErrorActionPreference to 'SilentlyContinue'.
That is confusing, because the seemingly equivalent -ErrorAction common parameter does not work; that is, -ErrorAction SilentlyContinue or -ErrorAction Ignore have no effect, because -ErrorAction is designed to operate on non-terminating errors only.
For a comprehensive overview of PowerShell's complex error handling, see this GitHub docs issue.
Taking a step back: It doesn't make sense for Set-ExecutionPolicy to report an error in this scenario, given that the command still succeeded in principle.
Emitting a warning would be more appropriate, as suggested in GitHub issue #12032.

Related

powershell executionPolicy message

Set-ExecutionPolicy Bypass -File 'E:\Script-Popup\Trigger-Start-Popup.ps1'
Set-ExecutionPolicy Bypass -File 'E:\Script-Popup\Popup-Message - Start.ps1'
powerShell -sta -file 'E:\Script-Popup\Popup-Message - Start.ps1' -Confrim:$true
The script always stops for me here and I want it to run automatically, I tried -Force I tried -Confrim:$true
What else can be done to have it automatically confirm it?
I don't mind putting echo Y and enter, a really stupid solution but I've already tried most of them..
You can't put Set-ExecutionPolicy into a script (obviously) but you can use -Force on it. That will skip the confirmation prompt.
Do note that depending on the Scope you set for Set-ExecutionPolicy the policy you set might not have an effect on new powershell instances such as the one started in the third line.
Use Get-ExecutionPolicy -List to see which scope is set to what policy.
As an aside, you don't usually need to set -Confirm to $True as that is its default value (most of the time). Setting -Confirm to $true obviously won't skip any confirmation boxes; to do that you'd need to set it to $False instead.

Powershell script reports execution-policy error when in a console window from File Explorer

My script runs fine in ISE however not in a PowerShell console window.
I have tried to replace any " with ' (just in case it was an encoding error but I am not sure).
EDIT: The script works when copy and pasted into the console but not when opened with the console.
Here is the script, ZAOCC.ps1:
$path = '\\auisasvc2k801\safe\Information Technology\Support\Powershell\ZAOCC\Excel'
$path2 = '\\auisasvc2k801\safe\Information Technology\Support\Powershell\ZAOCC\PDF'
$xlFixedFormat = 'Microsoft.Office.Interop.Excel.xlFixedFormatType' -as [type]
$excelFiles = Get-ChildItem -Path $path -include *.xls, *.xlsx -recurse
$objExcel = New-Object -ComObject excel.application
$objExcel.visible = $false
$date = Get-Date -Format 'dd.MM.yyyy'
foreach($workbook in $excelFiles)
{
$filepath = Join-Path -Path $path2 -ChildPath ('Mine Control Record - ' + $date + '.pdf')
$workbook = $objExcel.workbooks.open($workbook.fullname, 3)
$workbook.Saved = $true
'Saving $filepath'
$workbook.ExportAsFixedFormat($xlFixedFormat::xlTypePDF, $filepath)
$objExcel.Workbooks.close()
}
$objExcel.Quit()
Here is the error message:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by
a policy defined at a more specific scope. Due to the override, your shell will retain its current effective
execution policy of RemoteSigned. Type "Get-ExecutionPolicy -List" to view your execution policy settings. For more
information please see "Get-Help Set-ExecutionPolicy".
At line:1 char:46
+ ... -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & "\ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
+ FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
The error message suggests that you're running your script from File Explorer, using the shortcut menu's Run with PowerShell command (which uses Windows PowerShell; note that PowerShell [Core] (v6+) no longer offers this command - see middle section).
Note that doing so will automatically close the console window that is opened to run the script when the script exits.
To avoid that, open a Windows PowerShell console window first, and then run your script from there - this will also make your problem go away.
(Another option is to modify the shortcut-menu command definition, as shown below.)
The reason for the error is that your execution policy is set by either a machine-level or a user-level Group Policy, which takes precedence over the attempt to set the execution policy at the process level.
In fact, you cannot override an execution policy set via Group Policy from user code, neither with a Set-ExecutionPolicy call nor via the -ExecutionPolicy CLI parameter.
The attempt to set the execution at the process level - Set-ExecutionPolicy -Scope Process Bypass - is part of the command line that is used by the shortcut-menu command definition, and it is it - not your script - that triggers the error.
Therefore, the error message will appear on any system where the execution policy is defined via Group Policy, every time a script is directly invoked from File Explorer.
Note that the error message is confusing in this case, claiming that the command "updated your execution policy successfully", when in reality it had no effect.
Also note that the error is a statement-terminating error[1], which means that overall execution still continues and your script is invoked, despite the error - assuming that the Group Policy-set execution policy allows it.
In general, especially given that the console window automatically closes when the script terminates (for whatever reason), consider not using this direct-invocation feature.
In fact, PowerShell [Core] (v6+) doesn't even offer this shortcut-menu command anymore and instead offers commands at the directory / drive level to open an interactive session there.
If you still want to invoke your script via File Explorer and want to avoid the error message, you can modify the shortcut-menu command definition in the registry by simply removing the attempt to set the execution policy.
The definition is at HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0\Command and modifying it requires elevation (running as admin); however, it is possible to create a user-level definition as well.
The following command redefines the shortcut-menu command definition so that Set-ExecutionPolicy is no longer called:
# NOTE: Requires elevation:
Set-ItemProperty registry::HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\0\Command '(default)' #'
powershell.exe -NoLogo -File "%1"
'#
If you also want to keep the window open, add -NoExit as the first parameter.
[1] Generally speaking, the message shouldn't be an error at all; it should be a warning, as suggested in this GitHub issue. However, in the interest of backward compatibility it was decided to keep the current behavior.

How to suppress warning message from script when calling Set-ExecutionPolicy

I am writing a script to prepare our laptops before use. It essentially installs certificates and sets the executionpolicy to AllSigned.
It gets executed by right mouse click and "Run with Powershell". This is a windows 10 standard bypass of executionpolicy and lets the script run on unmodified windows 10 machines (That's what it looks like to me at least). So I can execute my script without the need to change the executionpolicy explicitly.
After the script ran the machine is set up. I just get a warning that I want to suppress.
To do this inside the script I elevate the script to administrator rights with a bypass parameter. This works fine except that I get a warning when setting the AllSigned execution policy. It says that I have a policy defined at a more specific scope.
Note: The command worked and the execution policy is set. It just pops up red and looks like an error. If someone else executes the script I don't want to have questions popping up.
--My question:--
As I know that this behavior is intended I don't want the warning from showing up. How can I suppress the message?
I tried various settings with the switches "WarningAction" and "ErrorAction" but it does not work.
Some Details:
ErrorMessage:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy
successfully, but the setting is overridden by a policy defined at a
more specific scope. Due to the override, your shell will retain its
current effective execution policy of Bypass. Type
"Get-ExecutionPolicy -List" to view your execution policy settings.
For more information please see "Get-Help Set-ExecutionPolicy". At
C:\Users\uwe\Desktop\InstallRootCA\InstallRootCertificate.ps1:46
char:5
+ Set-ExecutionPolicy AllSigned -Scope LocalMachine -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
+ FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
Relevant Code parts from powershell script:
Elevating the script prior to execution:
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
exit;
}
Setting the Executionpolicy at the end of the script:
Set-ExecutionPolicy AllSigned -Scope LocalMachine
I tried all kinds of flags
-Force
-WarningAction Ignore|SilentlyContinue
-ErrorAction same
But still the red warning pops up.
You can put this command into a try catch statement. The catch statement will handle the errors and if it is empty, nothing will happen if Set-ExecutionPolicy throws an error.
try{
Set-ExecutionPolicy AllSigned -Scope LocalMachine
}
catch {
#Do Nothing
}
Please test it, let me know if it worked and if it did, please mark the post as the answer :)
Nicicalu's answer is effective; let me add some background information:
What Set-ExecutionPolicy emits in your case is a (statement-)terminating error, which is why it is neither affected by -ErrorAction nor by -WarningAction.
Terminating errors can only be handled via:
try / catch, as shown in Nicicalu's answer.
The - rarely used - trap statement
Confusingly, they can be silenced and ignored by setting preference variable $ErrorActionPreference to 'SilentlyContinue'.
That is confusing, because the seemingly equivalent -ErrorAction common parameter does not work; that is, -ErrorAction SilentlyContinue or -ErrorAction Ignore have no effect, because -ErrorAction is designed to operate on non-terminating errors only.
For a comprehensive overview of PowerShell's complex error handling, see this GitHub docs issue.
Taking a step back: It doesn't make sense for Set-ExecutionPolicy to report an error in this scenario, given that the command still succeeded in principle.
Emitting a warning would be more appropriate, as suggested in GitHub issue #12032.

Silence / Redirect PowerShell error stream: what am I missing?

I have a Powershell script to loosen the execution policy on a machine, essentially running:
Set-ExecutionPolicy Unrestricted -Force
Since ExecutionPolicy is restriced on the machine, I need to launch the .ps1 script using .bat file which bypasses the execution policy like this:
PowerShell.exe -ExecutionPolicy Bypass -File ./psscripts/myScript.ps1
By using this trick, I get the following error:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by
a policy defined at a more specific scope. Due to the override, your shell will retain its current effective
execution policy of Bypass.
The error is trying to tell me that policy scope of the current process (launched with -Bypass) overrides the one I just set, but I don´t really care anyway, so I would like to simply hide this error.
I have tried using the -ErrorAction SilentlyContinue:
Set-ExecutionPolicy Unrestricted -Force -ErrorAction SilentlyContinue
But the error still displays. So I tried to redirect the error stream to &NULL like this:
Set-ExecutionPolicy Unrestricted -Force 2> $NULL
...but even like this, the error still pops up on the terminal.
I have successfully managed to silence the error using a try-catch like this:
try{Set-ExecutionPolicy Unrestricted -Force} catch {}
However, I would still like to understand why the two other approaches won´t work?
Trying to redirect the error stream (or any stream) to a variable, the variable turns out empty, so I assume I am somehow trying to redirect the stream from the wrong process?
Does this have something to do with launching Powershell from the .bat file?
Can anyone help me out here?
Redirecting PowerShell's error output stream with 2> only works for non-terminating errors.
Note: The -ErrorAction common parameter operates exclusively on non-terminating errors as well - unlike the seemingly equivalent ErrorActionPreference preference variable, however, which - surprisingly - also applies to terminating errors - see the link to the GitHub docs issue below.
Set-ExecutionPolicy emits a terminating error, which only try / catch can handle (and the rarely used trap statement).
See also:
A description of PowerShell's fundamental error types in the context of guidance for command authors on when to emit a terminating vs. a non-terminating error: this answer.
A comprehensive overview of PowerShell's surprisingly complex error handling: this GitHub docs issue.

Set-ExecutionPolicy Error when not being called

When I run any script from a .ps1 file on my server I receive an error about the Set-ExcutionPolicy being successful but being overridden by a higher scope.
However none of the code I am running has anything to do with execution policies or changing them. Any Idea why I'm getting this error?
This is on a Windows 2012 R2 server where execution policy for all levels is set to remote signed. I'm running on PowerShell V4.0
If I open PowerShell or the ISE and type in the command it completes without showing the error it only occurs when I try and run a script from a .ps1 file.
This is the error:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy
successfully, but the setting is overridden by a policy defined at a more
specific scope. Due to the override, your shell will retain its current
effective execution policy of RemoteSigned. Type "Get-ExecutionPolicy -List"
to view your execution policy settings. For more information please see
"Get-Help Set-ExecutionPolicy".
At line:1 char:46
+ if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
+ FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
The "Run with PowerShell" context menu entry for .ps1 files invokes the following commandline:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & '%1'"
It's stored in the registry key HKCU\Microsoft.PowerShellScript.1\Shell\0\Command. Since you have the execution policy defined via Group Policy, setting a conflicting execution policy in the Process scope whenever you're running a PowerShell script via its context menu causes the error you observed.
Change the commandline in the registry to something like this:
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -File "%L"
and the error will disappear.