Powershell-Script: wie Leerzeichen im aufzurufenden Programmpfad umgehen?

mux

Lt. Junior Grade
Registriert
Apr. 2011
Beiträge
306
Guten Abend!
Könntet Ihr mir bitte mal helfen? Ich beschäftige mich gerade zum ersten Mal etwas näher mit Powershell. Bin da leider überhaupt nicht firm drin!

Die Aufgabe die ich ausführen lassen möchte ist rel. einfach: Ich möchte, dass beim Anklicken der Verknüpfung zum Script "RunAfterburnerElevated.ps1" die UAC aufploppt, ich das Admin-PW eingebe und der MSI Afterburner + RivaTuner mit erweiterten Rechten startet. Ich bin mit einen User-Account eingeloggt und da funktioniert der automatische Start der Programme nicht.

Problem ist (mMn) dass in den Programmpfaden Leerzeichen enthalten sind und ich weiß (noch) nicht, wie ich damit umzugehen habe :confused_alt:. Bei Programmen ohne Leerzeichen im Pfad (zB. Rainmeter und HWiNFO) funktioniert mein Script so wie es soll, welches dann so aussieht:

PowerShell:
#
# this Powershell script runs Rainmeter and HWiNFO as elevated processes, prompting for elevation if
# needed
#
If (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
  # relaunch as an elevated process
  Start-Process powershell.exe "-File ",('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs
  Exit
}

# run HWiNFO
& "$($Env:ProgramFiles)\HWiNFO64\HWiNFO64.exe"

# run Rainmeter
& "$($Env:ProgramFiles)\Rainmeter\Rainmeter.exe"

Passe ich nun selbiges an und schreibe ins neue Script für MSI Afterburner+RivaTuner:

PowerShell:
#
# this Powershell script runs MSI Afterburner and RivaTuner Statistics Server as elevated processes, prompting for elevation if
# needed
#
If (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
  # relaunch as an elevated process
  Start-Process powershell.exe "-File ",('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs
  Exit
}

# run Afterburner
& "${$Env:ProgramFiles(86)}\MSI Afterburner\MSIAfterburner.exe"

# run RivaTuner
& "${$Env:ProgramFiles(86)}\RivaTuner Statistics Server\RTSS.exe"

passiert nichts.

Habe im Netz rumgelesen und u.a. hier gefunden, wie ich den Pfad zu C:\Program Files (86) anpassen kann. Nichts, oder für mich nur Unverständliches habe ich aber dazu gefunden, wie ich die Ordnernamen anpassen kann. Glaubt mir, ich habe 20 und mehr Varianten ausprobiert, es führte jedoch keine zum Ziel.

Könnte mir bitte jemand helfen und sagen, wie ich die beiden Programme im Script (dem unteren) korrekt ausführen lassen kann?

Danke!
 
Zuletzt bearbeitet:
Du solltest die richtige Environment-Variable nehmen (da fehlt das 'x' vor dem '86'), und dann kannst du das so verpacken:

PowerShell:
# run Afterburner
& "$(${Env:ProgramFiles(x86)})\MSI Afterburner\MSIAfterburner.exe"

# run RivaTuner
& "$(${Env:ProgramFiles(x86)})\RivaTuner Statistics Server\RTSS.exe"

Du hättest aber auch einfach den Pfad angeben können, wo die Files liegen, ohne die Programmpfade mit Env zu ermitteln - wäre wohl hier am einfachsten gewesen.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: mux
Ey Alter, ich könnte mich grad mehrmals vor die Stirn kloppen, aber dann kann ich so schlecht schlafen :freak:
Das mit dem x tut ja fast weh! Danke für den Hinweis!! So funktionierts, aber warum die zusätzlichen Klammern? Da muss ich wohl noch ein wenig lernen...
Gibt es eine Empfehlung für Tutorials/Literatur usw.? Wo hast du deine Kenntnisse her, wenn ich fragen darf?
Aber erstmal: ne gute Nacht und großen Dank! :n8:
 
Ist schon spät ;-) - du brauchst natürllich nur eine Klammer - die muss aber geschweift sein, weil er sonst mit dem "(x86)" nicht zurecht kommt, was im Variablennamen mit drinsteckt. So tut es natürlich genauso:
PowerShell:
& "${Env:ProgramFiles(x86)}\MSI Afterburner\MSIAfterburner.exe"
 
  • Gefällt mir
Reaktionen: mux, kartoffelpü und Poati
DarkAngel2401 schrieb:
& "${Env:programFiles(x86)}\MSI Afterburner\MSIAfterburner.exe"

Das kann so nicht funktionieren. Ich bekomme bei dieser Eingabe eine Fehlermeldung.
Da muss ein Leerzeichen zwischen "ProgramFiles" und "(x86)"

PowerShell:
& "${Env:ProgramFiles (x86)}\MSI Afterburner\MSIAfterburner.exe"

Darf es auch eine GUI sein mit Auswahl?

PowerShell:
$HideConsoleWindow = '[DllImport("user32.dll")]public static extern bool ShowWindow(IntPtr handle, int state);'
Add-Type -Name WPS -Member $HideConsoleWindow -Namespace CNS -ReferencedAssemblies System.Drawing,System.Windows.Forms –PassThru -ErrorAction SilentlyContinue
[VOID][CNS.WPS]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)

Set-PSReadlineOption -HistorySaveStyle SaveNothing

Get-Process | Where-Object -FilterScript {$_.ProcessName -Eq "powershell" -And $_.Id -Ne $PID} | Stop-Process -Force

$ErrorActionPreference = "SilentlyContinue"

Function GenWinForm
{
    $WinForm = New-Object System.Windows.Forms.Form -Property @{
        ClientSize = '235,220'
        StartPosition = 'CenterScreen'
        FormBorderStyle = 'None'
        BackColor = '255,30,30,30'
        MinimizeBox = $False
        MaximizeBox = $False
        ControlBox = $False
        Topmost = $True
        ShowInTaskbar = $False
    }
  
    $RadioBttn1 = New-Object System.Windows.Forms.RadioButton -Property @{
        Location = '25,25'
        Size = '115,25'
        AutoSize = $False
        ForeColor = 'White'
        Cursor = 'Hand'
        Font = 'Verdena,9'
        TextAlign = 'MiddleLeft'
        Text = "HWiNFO64"
        Add_CheckedChanged = {
            If ($RadioBttn1.Checked -Eq $True)
            {
                $RadioBttn1.Checked
                $Script:Prog = "$Env:ProgramFiles (x86)\HWiNFO64\HWiNFO64.exe"
                $OkButton.Enabled = $True
            }
        }
    }
  
    $RadioBttn2 = New-Object System.Windows.Forms.RadioButton -Property @{
        Location = '25,60'
        Size = '115,25'
        AutoSize = $False
        ForeColor = 'White'
        Cursor = 'Hand'
        Font = 'Verdena,9'
        TextAlign = 'MiddleLeft'
        Text = "Rainmeter"
        Add_CheckedChanged = {
            If ($RadioBttn2.Checked -Eq $True)
            {
                $RadioBttn2.Checked
                $Script:Prog = "$Env:ProgramFiles (x86)\Rainmeter\Rainmeter.exe"
                $OkButton.Enabled = $True
            }
        }
    }
  
    $RadioBttn3 = New-Object System.Windows.Forms.RadioButton -Property @{
        Location = '25,95'
        Size = '115,25'
        AutoSize = $False
        ForeColor = 'White'
        Cursor = 'Hand'
        Font = 'Verdena,9'
        TextAlign = 'MiddleLeft'
        Text = "MSIAfterburner"
        Add_CheckedChanged = {
            If ($RadioBttn3.Checked -Eq $True)
            {
                $RadioBttn3.Checked
                $Script:Prog = "$Env:ProgramFiles (x86)\MSI Afterburner\MSIAfterburner.exe"
                $OkButton.Enabled = $True
            }
        }
    }
  
    $RadioBttn4 = New-Object System.Windows.Forms.RadioButton -Property @{
        Location = '25,130'
        Size = '115,25'
        AutoSize = $False
        ForeColor = 'White'
        Cursor = 'Hand'
        Font = 'Verdena,9'
        TextAlign = 'MiddleLeft'
        Text = "RivaTunerSTS"
        Add_CheckedChanged = {
            If ($RadioBttn4.Checked -Eq $True)
            {
                $RadioBttn4.Checked
                $Script:Prog = "$Env:ProgramFiles (x86)\RivaTuner Statistics Server\RTSS.exe"
                $OkButton.Enabled = $True
            }
        }
    }
  
    $OkButton = New-Object System.Windows.Forms.Button -Property @{
        Location = '25,170'
        Size = '80,25'
        AutoSize = $False
        BackColor = '255,30,30,30'
        ForeColor = 'Lime'
        Cursor = 'Hand'
        Add_MouseHover = {$OkButton.ForeColor = [System.Drawing.Color]::White}
        Add_MouseLeave = {$OkButton.ForeColor = [System.Drawing.Color]::Lime}
        Font = 'Verdena,10'
        TextAlign = 'MiddleCenter'
        Text = 'Ausführen'
        Enabled = $False
        Add_Click = {
            $WinForm.Close()
            & $Prog
        }
    }
  
    $ExButton = New-Object System.Windows.Forms.Button -Property @{
        Location = '140,170'
        Size = '80,25'
        AutoSize = $False
        BackColor = '255,30,30,30'
        ForeColor = 'Orange'
        Cursor = 'Hand'
        Add_MouseHover = {$ExButton.ForeColor = [System.Drawing.Color]::White}
        Add_MouseLeave = {$ExButton.ForeColor = [System.Drawing.Color]::Orange}
        Font = 'Verdena,10'
        TextAlign = 'MiddleCenter'
        Text = 'Abbrechen'
        Add_Click = {
            $WinForm.Hide()
            [System.Environment]::Exit(0)
        }
    }
  
    [Void]$WinForm.Controls.AddRange(@(
    $RadioBttn1,
    $RadioBttn2,
    $RadioBttn3,
    $RadioBttn4,
    $ExButton,
    $OkButton))
  
    [Void]$WinForm.ShowDialog()
}

$CurrentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
If ($CurrentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator))
{
    GenWinForm
}
Else
{
    $ElevatedProcess = New-Object System.Diagnostics.ProcessStartInfo "powershell.exe";
    $ElevatedProcess.Arguments = "& '" + $Script:MyInvocation.MyCommand.Path + "'"
    $ElevatedProcess.Verb = "runas"
    [System.Diagnostics.Process]::Start($ElevatedProcess)
    [System.Environment]::Exit(0)
}

Screenshot.png
 

Anhänge

Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: mux
NotNerdNotDau schrieb:
Das kann so nicht funktionieren. Ich bekomme bei dieser Eingabe eine Fehlermeldung.
Da muss ein Leerzeichen zwischen "ProgramFiles" und "(x86)"

PowerShell:
& "${Env:ProgramFiles (x86)}\MSI Afterburner\MSIAfterburner.exe"
Nein, es muss ohne Leerzeichen sein (er hat ja auch schon geschrieben das es so läuft).
1685426064575.png
 
Korben2206 schrieb:
Wenn ich den Code so wie du eingebe, dann muss es tatsächlich ohne Leerzeichen sein.
Gebe ich den Code so, wie im folgenden Bild zu sehen, ein:
Screenshot2.png
 
Das was du machst, ist die Environment-Variable "ProgramFiles" evaluieren und dann ein " (x86)" hinhängen (mit Space davor), und das dann per Full Name referenzieren. Deswegen funktioniert das dann eben im ersten Beispiel nicht, weil "C:\Program Files(x86)" (ohne Space) nicht exisiert.
Die Variable heißt aber nun mal "ProgramFiles(x86)" - und da gehört einfach ne geschweifte Klammer drum herum, damit die runden Klammern mit zum Variablennamen zugeordnet werden.
 
  • Gefällt mir
Reaktionen: Maviapril2
Ja gut, das ist wieder so eine Sache, die ich nicht logisch nachvollziehen kann.
Aber Variable hin oder her, entscheidend ist doch wohl, dass der Pfad zur Datei tatsächlich existiert.

Wie das nachfolgende Beispiel mit "Test-Path" zeigt:

Screenshot.png


Auf jeden Fall funktioniert alles mit dem Code in dem von mir oben eingestellten Skript.
 
Es funktioniert bei mir mit der Scriptzeile aus Post #2 von DarkAngel2401.
Das mit dem Auswahlfenster ist nett, aber mir wäre das zuviel Klickerei. Aber vllt. für den ein oder anderen ja nützlich. Danke!
Ich habe mir nun die Verknüpfung zum Script in den Autostart gelegt: klappt.
Wenn es nun noch die Möglichkeit gäbe das Admin-PW zu übergeben, so dass ich es für den Programmstart nicht mehr händisch eingeben müsste... Ich habe jedoch keine Ahnung, ob das überhaupt möglich ist.
 
Nee, möchte ich nicht ;)
Das mit dem Berechtigungsnachweis gucke ich mir mal an. Interessant.
 
mux schrieb:
Das mit dem Auswahlfenster ist nett, aber mir wäre das zuviel Klickerei.
Na ja, das wären dann zwei Klicks.
Aber gut, wenn es denn auch auf andere Weise funktioniert und diese Methode favorisiert wird, dann ist das Ziel erreicht.

Zum Abschluss nur noch eine Verständnisfrage @DarkAngel2401 :

DarkAngel2401 schrieb:
Die Variable heißt aber nun mal "ProgramFiles(x86)" - und da gehört einfach ne geschweifte Klammer drum herum, damit die runden Klammern mit zum Variablennamen zugeordnet werden.
Diesen Effekt erreicht man auch, indem man die Codezeile mit doppelten An- und Abführungszeichen "..." versieht.

Wird mit ${......} nicht eine Array generiert? Das wäre, nach meinem Verständnis, in diesem Fall vollkommen unnötig, da es sich nur um ein Objekt und nicht um mehrere Objekte handelt.
Arrays verursachen, je nach Komplexität des Skripts, eine sehr hohe Auslastung und wenn man keine Array benötigt, dann sollte man eben darauf verzichten.
 
Wie bereits erwähnt, erreicht man den Zugriff auch mit "".
Damit werden in den Pfadangaben, falls vorhanden, auch Leerzeichen und die meisten Sonderzeichen korrekt in die Variable integriert.
Ich halte das für "wasserfester" als die Variante mit den geschweiften Klammern und dem $ davor.

Arrays können nicht nur mit Verwendung des Klammeraffen @ erzeugt werden, sondern auch auf diese Weise:
$Test = $("Test1","Test2,"Test3")
In dem Fall muss man allerdings die runden Klammern verwenden.

Aber okay, das ist im vorliegenden Fall nicht entscheidend und soll nur der Information dienen.
 
Zurück
Oben