Manchmal muss ein Skript halt mit erhöhten Rechten laufen. Das erreicht man in der Regel entweder damit, dass man den Aufrufenden mit
1 |
#Requires -RunAsAdministrator |
vor den Kopf stößt, oder man macht das Skript „Self-Elevating“:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[CmdletBinding()] Param( [Parameter(Mandatory=$false)] [switch]$RunElevated ) function Test-Admin { $currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent()) $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) } if ((Test-Admin) -eq $false) { if ($RunElevated) { Write-Warning 'We tried to elevate and failed' } else { try { Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -nologo -noexit -file "{0}" -RunElevated' -f ($myinvocation.MyCommand.Definition)) -EA Stop } catch { Write-Warning ('Error trying to self-elevate: {0}' -f $_.Exception.Message) } exit } } Write-Host "Hello elevated world!" # Code that needs elevation |
Doch was ist, wenn das Skript möglichst kurz gehalten werden möchte oder man einen Shortcut auf dem Desktop erstellen muss, der für die Elevation sorgt, anstatt diese Logik im Skript selbst zu verbauen?
In diesem Fall wird der PowerShell-Befehl mit -Verb RunAs aus einer CMD-Shell heraus aufgerufen, und man bekommt mit den verschachtelten Anführungszeichen zu tun, die CMD anders als PowerShell verarbeitet:
1 |
powershell.exe -nologo -noprofile -WindowStyle Hidden -Command "& {Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -nologo -noexit -ExecutionPolicy Bypass -file ""c:\temp\folder with spaces\SomeScript.ps1"""')}" |
Man beachte die Anführungszeichen um den Pfad herum: davor sind zwei notwendig, dahinter jedoch drei!
Sind die Skriptpfade etwas länger, wird man beim Erstellen eines Shortcuts auf die Längenbeschränkung auf 215 Zeichen stoßen. Zum Glück gilt diese Beschränkung nicht für die Shortcut-Dateien als Solche, sondern lediglich für den Wizard im Explorer. Mit der PowerShell kann ein Shortcut mit beliebiger Pfadlänge erstellt werden:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[CmdletBinding()] Param( [Parameter(Mandatory=$true)] [string]$ShortCutName, [Parameter(Mandatory=$true)] [string]$ScriptLiteralPath ) $shortCutFullName = Join-Path -Path ([Environment]::GetFolderPath('Desktop')) -ChildPath ('{0}.lnk' -f $ShortCutName) $WshShell = New-Object -comObject WScript.Shell $Shortcut = $WshShell.CreateShortcut($shortCutFullName) $Shortcut.TargetPath = 'powershell.exe' $Shortcut.Arguments = '-nologo -noprofile -Command "& {{Start-Process powershell.exe -Verb RunAs -ArgumentList (''-noprofile -nologo -noexit -ExecutionPolicy Bypass -file ""{0}"""'')}}"' -f $ScriptLiteralPath $Shortcut.WindowStyle = 7 $Shortcut.Save() |
Happy Shortcutting!