Powershell-提升丢失当前目录

Powershell-提升丢失当前目录

一个问题导致另一个问题!用户帮助刚刚修复了一个问题,当我继续处理此脚本时,又引发了另一个问题。我的脚本运行检查以查看当前用户是否是管理员,如下所示:

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)。这意味着一些严重的转义:

  1. 从 中删除尾随的反斜杠%~dp0,否则它会与 中的转义混淆第 2 页
  2. 使用反斜杠 ( \)转义START命令中的引号,因为C 命令行解析器的工作方式

    前面带有反斜杠的双引号 \"
    被解释为文字双引号 (")。

  3. Start-Process使用cmdlet时在 PowerShell 中转义引号

    1. 对于-File参数:

      "`"$($MyInvocation.MyCommand.Path)`""
      
    2. 对于$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
}

相关内容