Here is a simple test function called RegistryBoundParams.ps1
:
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$Target,
[Parameter(Mandatory = $false)]
[switch]
$MySwitch
)
if(!(Test-IsAdmin)){
Request-AdminRights -NoExit
Exit
}
if($MySwitch){
"Do something" | Out-Host
}else {
"Do something else" | Out-Host
}
Show-AllArguments
If I call it via the PS terminal, everything works as expected:
Exact call: C:\Tools\scripts> .\RegistryBoundParams.ps1 -Target "C:\Test\" -MySwitch
If I call it through the registry (adding the command to a context menu), I get:
pwsh -noexit -file "C:\Tools\scripts\RegistryBoundParams.ps1" -Target "C:\Program Files\Python39\python.exe" -MySwitch
Plaintext of the error: RegistryBoundParams.ps1: A positional parameter cannot be found that accepts argument '$null'.
Here's a reg file that shows exactly what I added in the registry:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\1_TestRegistry]
@="Test Powershell Script from Registry"
"Icon"="C:\\Tools\\icons\\apps\\Powershell 1.ico,0"
"NeverDefault"=""
[HKEY_CLASSES_ROOT\*\shell\1_TestRegistry\command]
@="pwsh -noexit -file \"C:\\Tools\\scripts\\RegistryBoundParams.ps1\" -Target \"C:\\Program Files\\Python39\\python.exe\""
So somewhere along the lines $Null is being passed to the script, and I have no Idea why.
I could really, really use some help here.
Thanks so much for any guidance.
Edit:
I found that if I add a new string variable called $catchall, the script works. I suspect that when being called from the registry it's appending a null value for some reason. Which is why the script works when I define an additional "catch all" variable.
This is definitely not an ideal solution at all, so I am still looking for a solution here. Really appreciate any help!
Edit2:
It turns out that the Request-AdminRights
script I was using that mklement0 authored had a bug that has now been fixed. Anyone who wants one-line self elevation with bound/unbound parameter support that's cross-platform... go get it!
CodePudding user response:
The problem was a (since-fixed) bug in the code that you based your self-elevating function Request-AdminRights
on:
The bug was that in the case of an advanced script such as yours, $args
- which is never bound in advanced scripts - was mistakenly serialized as $null
instead of translated to @()
, resulting in that $null
getting passed as an extra argument on re-invocation.
If you redefine your Request-AdminRights
function based on the now updated body of the Ensure-Elevated
function in the original answer, your problem should go away - no need to modify the enclosing script.