一个问题导致另一个问题!用户帮助刚刚修复了一个问题,当我继续处理此脚本时,又引发了另一个问题。我的脚本运行检查以查看当前用户是否是管理员,如下所示:
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" + $myinvocation.mycommand.definition + "'" + $loc
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}
$loc 的参数是一个最初通过批处理文件传递的参数,如下所示:
@setlocal enableextensions
@cd /d "%~dp0"
SET current="%~dp0
START /WAIT powershell.exe -ExecutionPolicy Bypass -File "JavaInstall.ps1" -loc %current%
在 Powershell 文件的顶部,我们有:
param(
[string]$loc
)
这在两种条件下有效:
1) 用户已经是管理员。2
) 在遍历过程中任何时候运行此命令的文件夹都没有空格。
当从文件夹(例如:C:\Users\User\Desktop\Java Test)运行此程序时,它会突然失败。如果我沿途执行 Write-Host,我可以看到 $loc 变量在提升后才是正确的。提升后,空格后的所有内容都会丢失。如果我以管理员身份直接运行此程序,它当然会绕过提升,即使文件夹中有空格也能正常工作,但我不想要求右键单击运行方案。有什么想法可能导致提升期间空格后的文本丢失?
答案1
您在这里处理多个命令行解析,这就是为什么很难让它正常工作。您必须在路径经过时用引号括起来,并在路径之间留空格到PowerShell(来自 bat 文件)以及它何时通过从Powershell(到 Start-Process cmdlet)。这意味着一些严重的转义:
- 从 中删除尾随的反斜杠
%~dp0
,否则它会与 中的转义混淆第 2 页 - 使用反斜杠 (
\
)转义START
命令中的引号,因为C 命令行解析器的工作方式:前面带有反斜杠的双引号 \"
被解释为文字双引号 (")。 Start-Process
使用cmdlet时在 PowerShell 中转义引号对于
-File
参数:"`"$($MyInvocation.MyCommand.Path)`""
对于
$Loc
论点:"\`"$Loc\`""
下面的示例对我来说是有效的,并且在自我提升的同时保持带有空间的路径完好无损。
蝙蝠发射器:
SETLOCAL EnableExtensions
:: Get current directory
SET current=%~dp0
:: Does "current" variable have a trailing slash? If so, remove it
IF %current:~-1%==\ SET current=%current:~,-1%
cd /d %current%
START /WAIT powershell.exe -ExecutionPolicy Bypass -File "JavaInstall.ps1" -Loc \""%current%\""
PowerShell 提升代码:
Param(
[string]$Loc
)
$Delay = 5
Write-Host "`$Loc argument: $Loc"
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
[Security.Principal.WindowsBuiltInRole] 'Administrator')
)
{
Write-Host "Not elevated, restarting in $Delay seconds ..."
Start-Sleep -Seconds $Delay
$Arguments = @(
'-NoProfile',
'-NoExit',
'-File',
"`"$($MyInvocation.MyCommand.Path)`"",
"\`"$Loc\`""
)
Start-Process -FilePath PowerShell.exe -Verb RunAs -ArgumentList $Arguments
Break
}
else
{
Write-Host "Already elevated, exiting in $Delay seconds..."
Start-Sleep -Seconds $Delay
}