Question Powershell - Elevation perd son répertoire actuel


Un problème mène à un autre! L'aide de l'utilisateur a simplement corrigé un problème, ce qui a conduit à un autre problème alors que je continuais à travailler sur ce script. Mon script exécute une vérification pour voir si l'utilisateur actuel est un administrateur comme suit:

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
}

L'argument de $ loc est un paramètre qui a été transmis à l'origine via un fichier de commandes, comme suit:

@setlocal enableextensions
@cd /d "%~dp0"
SET current="%~dp0
START /WAIT powershell.exe -ExecutionPolicy Bypass -File "JavaInstall.ps1" -loc %current%

En haut du fichier Powershell, nous avons:

param(
[string]$loc
)

Cela fonctionne sous deux conditions:

1) L’utilisateur est déjà administrateur.
2) Le dossier à partir duquel il est exécuté n’a pas d’espace.

Lorsqu'il est exécuté à partir d'un dossier tel que: C: \ Users \ User \ Desktop \ Java Test, il échoue soudainement. Si j'écris Host en cours de route, je peux voir que la variable $ loc est correcte jusqu'à l'altitude. Après qu'il se soit élevé, rien après l'espace est perdu. Si je l'exécute directement en tant qu'administrateur, il contourne évidemment l'altitude et fonctionne même avec des espaces dans les dossiers, mais je ne souhaite pas exiger un scénario d'exécution avec un clic droit. Des idées sur ce qui pourrait causer la perte de texte après l'espace pendant l'élévation?


3
2018-04-28 20:17


origine


Pour le problème des chemins avec des espaces, c'est peut-être parce que vous manquez une citation de clôture sur cette ligne SET current="%~dp0 - Ƭᴇcʜιᴇ007
Ce qui est étrange, c'est que tout sauf une seule citation à cet endroit provoque la coupure avec des espaces, même avant l’élévation. J'utilise peut-être mal cette commande pour commencer, car cela semble étrange. - Tim P.
Peut-être juste abandonner les guillemets sur cette ligne, et plutôt envelopper %current% avec eux (dans le START ligne du lot). - Ƭᴇcʜιᴇ007
Pourquoi lancez-vous le script batch en premier lieu? Ne pouvez-vous pas appeler directement Powershell avec les autorisations appropriées? - Zoredache
J'ai pensé à exécuter un script Powershell sur un autre ordinateur, il était nécessaire de définir ExecutionPolicy, étant donné que nous n'avons pas les certifications en place et que le comportement par défaut de Powershell est utilisé. - Tim P.


Réponses:


Vous avez affaire à l'analyse de plusieurs lignes de commande ici, c'est pourquoi il est difficile de le faire fonctionner correctement. Vous devez avoir des citations autour de votre chemin avec des espaces quand il a passé à le PowerShell (à partir du fichier bat) et quand il est passé de le Powershell (à l'applet de commande Start-Process). Cela signifie une fuite sérieuse:

  1. Supprimez la barre oblique inverse du %~dp0, ou il va gâcher avec échapper à P.2
  2. Échapper aux guillemets avec une barre oblique inverse (\) pour le START commande à cause de le fonctionnement de l'analyseur de ligne de commande C:

    Un guillemet double précédé d'une barre oblique inverse, \ ",
      est interprété comme un guillemet double littéral (").

  3. Les guillemets d'échappement dans le PowerShell lors de l'utilisation Start-Process applet de commande

    1. Pour le -File paramètre:

      "`"$($MyInvocation.MyCommand.Path)`""
      
    2. Pour le $Loc argument:

      "\`"$Loc\`""
      

L'exemple ci-dessous fonctionne pour moi et maintient le chemin avec des espaces intacts tout en s'élevant.

Lanceur de chauve-souris:

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%\""

Code d'élévation 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
}

0
2018-02-24 14:56