点源脚本
我有一个自言自语的摘要,所以我决定,而不是在每个需要运行的脚本的顶部复制它,以将其移至一个单独的.ps1:
function Switch-ToAdmin {
# Self-elevate the script if required
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$Cmd = @(
"-Command Set-Location `"$(Get-Location)`"; & `"$PSCommandPath`""
"-$($PSBoundParameters.Keys)"
)
$ProcArgs = @{
FilePath = 'PowerShell.exe'
Verb = 'RunAs'
ArgumentList = $Cmd
}
Start-Process @ProcArgs
Exit
}
}
}
因此,对于每个需要高程的脚本,我都会预先
. "$PSScriptRoot\self-elevate.ps1"
Switch-ToAdmin
# rest of script
执行以上成功成功地执行了UAC提示,但其余的脚本不会被执行。 这是不允许的吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
darin 和已经提供了关键的指针:
darin指出 自动
$ pscommandpath
accoviableswitch> switch toadmin
function中的变量该函数称为的脚本的完整路径,但即使该脚本的定义是直接加载了 定义的脚本的完整路径通过。
进入主脚本的范围#点源操作员 - “ rel =“ nofollow noreferrer”>点源操作员。$ psscriptroot
变量,它反映了定义脚本的完整目录路径。 path。此外,更一般地,自动
$ PSBOUNDPARAMETERS
变量在函数内部反映 该函数的绑定参数,而不是其封闭 script 'S。铁指出 cmdlet 可用于获取有关脚本的呼叫者 的信息,从索引
开始代码>;返回的第一个对象 - 索引
0
,当get -pscallstack
输出在数组中捕获,表示 current 命令。索引1
因此,请参考即时呼叫者,从点来源的脚本的角度来看是您的主要脚本。因此:
替换
$ pscommandpath
用$ myinvocation.pscommandpath
,通过自动 $ myInvocation.psCommandPath 真正反映了呼叫者的完整脚本路径,无论定义了所谓的函数。(get-pscallstack)[1] .scriptName
,尽管属性名称建议的是,但也返回了调用脚本的完整路径。 /li>替换
$ psboundParameters
(get-pscallstack)[1] .invocationinfo.boundparameters
(get-pscallstack)[1] .arguments
,但它似乎仅包含一个 string ,其中包含所有参数的表示形式仅半结构化,因此不允许重新构建单个参数。顺便说一句:
即使
$ psboundParameters
包含预期的信息,“ - $($ psboundparameters.keys)”
只有在您的脚本定义的情况下,才能成功地传递绑定参数仅一个参数,如果该参数为[switch]
参数,并且在每个调用中实际传递。在这种情况下,通过鲁棒通过参数很难做到,并且具有固有的局限性 - 参见此答案对于 - 复杂 - 尝试使其尽可能地工作。
Darin and iRon have provided the crucial pointers:
Darin points out that the automatic
$PSCommandPath
variable variable in yourSwitch-ToAdmin
function does not contain the full path of the script from which the function is called, but that of the script in which the function is defined, even if that script's definitions are loaded directly into the scope of your main script via.
, the dot-sourcing operator.$PSScriptRoot
variable, which reflects the defining script's full directory path.Also, more generally, the automatic
$PSBoundParameters
variable inside a function reflects that function's bound parameters, not its enclosing script's.iRon points out that the
Get-PSCallStack
cmdlet can be used to get information about a script's callers, starting at index1
; the first object returned - index0
, whenGet-PSCallStack
output is captured in an array, represents the current command. Index1
therefore refers to the immediate caller, which from the perspective of your dot-sourced script is your main script.Therefore:
Replace
$PSCommandPath
with$MyInvocation.PSCommandPath
, via the automatic$MyInvocation
variable.$MyInvocation.PSCommandPath
truly reflects the caller's full script path, irrespective of where the called function was defined.(Get-PSCallStack)[1].ScriptName
, which despite what the property name suggests, returns the full path of the calling script too.Replace
$PSBoundParameters
with(Get-PSCallStack)[1].InvocationInfo.BoundParameters
(Get-PSCallStack)[1].Arguments
, but it seems to contain a single string only, containing a representation of all arguments that is only semi-structured and therefore doesn't allow robust reconstruction of the individual parameters.As an aside:
Even if
$PSBoundParameters
contained the intended information,"-$($PSBoundParameters.Keys)"
would only succeed in passing the bound parameters through if your script defines only one parameter, if that parameter is a[switch]
parameter, and if it is actually passed in every invocation.Passing arguments through robustly in this context is hard to do, and has inherent limitations - see this answer for a - complex - attempt to make it work as well as possible.