[Update] Powershell-Skript mit erhöhten Rechten von einem Netzlaufwerk aus starten
Was sich erstmal nach einer leichten Übung anhört, ein Powershell-Skript von einem Netzlaufwerk aus starten, wird kompliziert, wenn man das Skript mit erhöhten Rechten ausführen will, das Administrator-Konto aber nichts von dem Netzlaufwerk weiß. Der Hintergrund ist folgender: Das Skript liegt für den normalen Benutzer sichtbar auf dem Netzlaufwerk F, das mit dem Share \\Server01\Public
verbunden ist. Damit das Skript sich ausführen lässt, benötigt es die erhöhten Rechte, des Administrationskontos, was mit einem Skript von der c’t geht (eine ausführlichere Version bietet Ben Armstron in seinem Blog).
# Prüfe, ob der User Admin-Rechte hat: $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object System.Security.Principal.WindowsPrincipal($identity) if(!$principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { $powershell = [System.Diagnostics.Process]::GetCurrentProcess() $psi = New-Object System.Diagnostics.ProcessStartInfo $powerShell.Path $script = $MyInvocation.MyCommand.Path $prm = $script foreach($a in $args) { $prm += ' ' + $a } $psi.Arguments = $prm $psi.Verb = "runas" [System.Diagnostics.Process]::Start($psi) | Out-Null return; } # Hier folgt der Code, der die erhöhten Rechte benötigt: $wshshell = new-object -comobject wscript.shell $Answer = $wshshell.popup("Du bist User $env:USERNAME",5,"Der Test hat geklappt!",0) |
Durch die „automatic variable“ $MyInvocation erhält man den vollen Namen des aufrufenden Skripts. Der wird benötigt, damit sich das Skript nochmal selbst aufruft, wenn es beim ersten Durchlauf feststellt, dass der Benutzer, der das Skript gestartet hat, kein Administrator ist. In diesem Fall fordert das Skript erhöhte Rechte an und ruft sich selbst nochmal auf, wenn es sie erhalten hat.
Wenn der Pfad zum Skript auf F:\MyShare
liegt, der für den normalen Benutzer bekannt ist, der Administrator das Laufwerk F: aber nicht kennt, da ihm der Pfad in der Variablen $MyInvocation.MyCommand.Path
fremd ist, läuft das Skript auf einen Fehler. Um diesen Fehler zu vermeiden, gehe ich daher einen Umweg.
[Update] Dabei vermeide ich den alten und unflexiblen Weg, bei dem ich den Laufwerksbuchstaben in das Skript geschrieben habe:
# Der Speicherort F:\MyShare\ ist dem Administrator nicht bekannt, # weshalb ich den Laufwerksnamen durch den UNC-Pfad ersetze: # Anstatt ein einfaches ... # $script = $MyInvocation.MyCommand.Path # ... gehe ich einen Umweg: $path = $($MyInvocation.MyCommand.Path) $script = $path.replace("F:", "\\Server01\Public") |
Mit Hilfe von Peter Kriegel im TechNet-Forum benutze ich jetzt folgende Lösung, nachdem ich mich von Nik aus dem Kommentar ein wenig in die Irre habe führen lassen. Der Lösungsweg mit net share
war doch zu umständlich. Stattdessen benutze ich ein WMI-Objekt mit Hilfe des Get-WmiObject
Cmdlets:
# Prüfe, ob der User Admin-Rechte hat: $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object System.Security.Principal.WindowsPrincipal($identity) if(!$principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { $powershell = [System.Diagnostics.Process]::GetCurrentProcess() $psi = New-Object System.Diagnostics.ProcessStartInfo $powerShell.Path $script = $MyInvocation.MyCommand.Path <# Hier wird es problematisch, wenn das Skript auf einem Netz- laufwerk liegt, das dem Administrationskonto nicht bekannt ist, wie z.B. Laufwerk F:\. #> Get-WmiObject Win32_LogicalDisk | ForEach { # Prüfe, ob das Skript auf einem Netzlaufwerk liegt: if ($script.contains($_.DeviceID)){ # Wenn ja, ersetze den Laufwerksbuchstaben durch den UNC-Pfad: $script = $script.replace($_.DeviceID,$_.ProviderName) } } $prm = $script foreach($a in $args) { $prm += ' ' + $a } $psi.Arguments = $prm $psi.Verb = "runas" [System.Diagnostics.Process]::Start($psi) | Out-Null return; } # Hier folgt der Code, der die erhöhten Rechte benötigt: $wshshell = new-object -comobject wscript.shell $Answer = $wshshell.popup("Du bist User $env:USERNAME",5,"Der Test hat geklappt!",0) |
Geschrieben in Powershell, Windows