Fenster in den Vordergrund holen und Tasteneingabe/n übergeben - PowerShell


Status
Dieses Thema wurde gelöst! Zur Lösung gehen…
#1
Hallo Forumsmitglieder,

erstmal Respekt und Robustheit.

Dann meine PowerShell Zeilen:
---
Code:
# PowerShell ausführung erlauben
    Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -Force
# Biende Klassen mit ein
    add-type -AssemblyName microsoft.VisualBasic
    add-type -AssemblyName System.Windows.Forms
# Starte Prozess an den die Tasteneingaben übergeben werden sollen
    Start-Process -WindowStyle Maximized -FilePath "C:\Program Files (x86)\Acronis\TrueImage2014\TrueImageHome\TrueImageTools.exe" -ArgumentList /system_cleanup -LoadUserProfile
Ist ein Test-Prozess der sich nach dem erssten Prozess öffnen soll um den ersten Prozess dann in den Vordergrund zu holen
    Start-Process -WindowStyle Maximized -FilePath "C:\Program Files\Notepad++\notepad++.exe"
# Räumt den Prozessen Zeit ein sich zu Starten
    Start-Sleep -Seconds 5

#############################
# Lege Variable an die den Prozess identifiziert
    $TrueImageTools = get-process * | ?{$_.WindowTitle -like '*Systembereinigung*'}    # Gibt den richtigen Prozess aus, wenn ich ihn über die Variable "$TrueImageTools"abfrage

#############################

# Prozess in den Vordergrund holen
    [Microsoft.VisualBasic.Interaction]::AppActivate(“$TrueImageTools”)    # An dem Punkt hängt es. Das Fenster kommt nicht in den Vordergrund.

# Der untenstehede Kommentierteblock funktioniert zumindest in Notepad. Hier werden die Tasten als Eingabe wiedergegeben.
<#
    [System.Windows.Forms.SendKeys]::SendWait(“Test”)
Wait-Event -Timeout 3
[Microsoft.VisualBasic.Interaction]::AppActivate(“notepad”)
    [System.Windows.Forms.SendKeys]::SendWait("{TAB}Z1")
Wait-Event -Timeout 3
[Microsoft.VisualBasic.Interaction]::AppActivate(“notepad”)
    [System.Windows.Forms.SendKeys]::SendWait("{DOWN}D1")
Wait-Event -Timeout 3
[Microsoft.VisualBasic.Interaction]::AppActivate(“notepad”)
    [System.Windows.Forms.SendKeys]::SendWait("{UP}U2")
Wait-Event -Timeout 3
[Microsoft.VisualBasic.Interaction]::AppActivate(“notepad”)
    [System.Windows.Forms.SendKeys]::SendWait("{LEFT}L1")
Wait-Event -Timeout 3
[Microsoft.VisualBasic.Interaction]::AppActivate(“notepad”)
    [System.Windows.Forms.SendKeys]::SendWait("{ENTER}E2")#>
---
Jetzt mein Anliegen:
Die Variable die ich Anlege zwischen den Rautezeilen [lCODE]$TrueImageTools[/ICODE] erkennt den Prozess richtig. Tehoretisch könnte ich mir die ID und den Namen des Prozesses geben lassen, was ich aber praktisch nicht in der Zeile [lCODE][Microsoft.VisualBasic.Interaction]::AppActivate(“$TrueImageTools”)[/ICODE] anstelle des roten Textes verarbeiten kann. Im Fehlerbericht seitens der Powershell heist es dazu:
Code:
[Microsoft.VisualBasic.Interaction]::AppActivate(“TrueImageTools”)
Ausnahme beim Aufrufen von "AppActivate" mit 1 Argument(en):  "Der Prozess TrueImageTools wurde nicht gefunden."
Was ich bisher versucht habe:
Den Fenstertitel anstelle der Variablen einzutragen. Doch der offensichtliche funktiniert nicht. Dann den nicht ganz so offensichtlichen versucht nämlich "system_cleanup", "System_Cleanup", "SystemCleanup", "Systemcleanup", "systemcleanup".

Wie kann ich den richtigen Fenstertitel ermitteln?

Kann mir dazu bitte jemand ein Besipiel in Codezeilen geben?

Wie bekomme ich es hin, dass TrueImageTools in den Vordergrund kommt?

Was eine Lösung sein könnte, wäre das ich versuche die Prozess-ID an eine oder mehrere C#-Zeilen zu übergeben. Allerdings bekomme ich das ohne hilfe nicht hin. Da ich keine C# kenntnisse habe und auch PowerShell-Technisch mich eher als Anfänger sehe. Meine Inspiration habe ich was C# angeht von Microsoft.
Ich habe keine Ahnung wie ich C#-Klassen in die Powershell einbinden kann.

Hat jemand Rat und Besipiele wie ich das machen kann?
 
Zuletzt bearbeitet:

ComFreek

Mod | @comfreek
Moderator
#2
Ich sehe mehrmals in deinem Code typographische Anführungszeichen (“...”) anstelle normaler Anführungszeichen ("..."). Im Code solltest du nur die Letzteren verwenden. Mich wundert es, dass du keinen Syntaxfehler beim Ausführen des Skripts bekommst. Oder sind die typographischen Anführungszeichen beim Reinkopieren ins Forum passiert?

[Microsoft.VisualBasic.Interaction]::AppActivate(“notepad”)
Das funktioniert übrigens bei nur, wenn ich statt "notepad" den String "Editor" nehme.

Ich hab ein bisschen gegoogelt und ein PS Skript gefunden, das direkt auf dem Process-Objekt aufgerfuden werden kann.
Die Quelle ist Bringing Window in the Foreground.
Code:
#Requires -Version 2
# ^^^ Put this at the top of the containing *.ps1 script file!

<#
  Copied almost verbatim from: https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/bringing-window-in-the-foreground

  License: Unknown! So beware under fair use.

  Changes:
    - changed function name
#>
function Show-ProcessInForeground($Process, [Switch]$Maximize)
{
 $sig = '
  [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
  [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
 '
 
 if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
 $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
 $hwnd = $process.MainWindowHandle
 $null = $type::ShowWindowAsync($hwnd, $Mode)
 $null = $type::SetForegroundWindow($hwnd) 
}
In deinem Code müsstest du die Funktion dann wie folgt aufrufen:
Code:
$TrueImageTools = Get-Process * | ? {
  $_.WindowTitle -like '*Systembereinigung*'
} | Select -First 1    # We only want the first such process!

Show-ProcessInForeground $TrueImageTools
 
#3
Ich sehe mehrmals in deinem Code typographische Anführungszeichen (“...”) anstelle normaler Anführungszeichen ("..."). Im Code solltest du nur die Letzteren verwenden. Mich wundert es, dass du keinen Syntaxfehler beim Ausführen des Skripts bekommst. Oder sind die typographischen Anführungszeichen beim Reinkopieren ins Forum passiert?
Nun wen ich die Anführungszeichen in die ISE so über Umschlt + 2 eingebe, dann erscheinen die so.
Siehe Bild 1:
10-03__10-22-26__Administrator_ Windows PowerShell ISE.png
Bild 1

Ich habe das bei mehreren Scripten so gemacht, siehe folgendes script:
Code:
Set-ExecutionPolicy Unrestricted -Scope LocalMachine -Force
    #Powershell berechtigungen erteilen
#-----------------------------------------------------------
# Variabelen anlegen
    # Variable für die zu deaktivierenden Prozesse
        $dProcesses = "SearchUI"
    # Variable für die zu deaktivierenden Services
        $dServices = "afcdpsrv","syncagentsrv","DiagTrack","RetailDemo","MapsBroker","TermService","SensorDataService","SensorService","SensrSvc","diagnosticshub.standardcollector.service","wercplsupport","WerSvc","WpnService","wmiApSrv","XboxGipSvc","XblAuthManager","XboxNetApiSvc","XblGameSave","SEMgrSvc","KtmRm","LanmanServer","CscService","SessionEnv","FDResPub","fdPHost","DPS","UmRdpService","lmhosts","upnphost","WebClient"
    # Variable für die zu deaktivierenden Tasks
        $dTasks = "Microsoft Compatibility Appraiser","Proxy","Consolidator","UsbCeip","Microsoft-Windows-DiskDiagnosticDataCollector","WakeUpAndContinueUpdates","WakeUpAndScanForUpdates","Property Definition Sync","XblGameSaveTask"
#Auszuführende Operationen
    # Starttyp ändern von ...
        # ...Services
            Get-Service -Name $dServices | Set-Service -StartUpType Manual -Status Stopped -Force
                Wait-Event -Timeout 3
    #Stoppen von...
        # ...Prozessen
            Get-Process -name $dProcesses | Stop-Process -Force
                  Wait-Event -Timeout 3
        # ...Services
            Get-Service -Name $dServices | Stop-Service -Force
                Wait-Event -Timeout 3
        # ...Tasks
            Get-ScheduledTask -TaskName $dTasks | Stop-ScheduledTask
                Wait-Event -Timeout 3
    #deaktivieren von...
        # ...Tasks
            Get-ScheduledTask -TaskName $dTasks | Disable-ScheduledTask
                Wait-Event -Timeout 3
# Powershell berechtigungen entziehen
   Set-ExecutionPolicy Restricted -Scope LocalMachine -Force
Das funktioniert.

Das funktioniert übrigens bei nur, wenn ich statt "notepad" den String "Editor" nehme.
Ich habe an der stelle meinen Fehler gefunden. Wenn ich versuche wie folgt Notepad zu starten: Start-Prozess -Name notepad funktioniert es nicht. Wenn ich aber stattdessen nur notepad eingebe, funktioniert der Start des Editors über den Namen notepad. Es kann sein, dass ich vor dem Post hier noch andere Sachen probiert habe und dann die Situation falsch wiedergegeben habe.
An der stelle sorry.

Ich hab ein bisschen gegoogelt und ein PS Skript gefunden, das direkt auf dem Process-Objekt aufgerfuden werden kann.
Die Quelle ist Bringing Window in the Foreground.
Code:
#Requires -Version 2
# ^^^ Put this at the top of the containing *.ps1 script file!

<#
  Copied almost verbatim from: https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/bringing-window-in-the-foreground

  License: Unknown! So beware under fair use.

  Changes:
    - changed function name
#>
function Show-ProcessInForeground($Process, [Switch]$Maximize)
{
$sig = '
  [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
  [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
'

if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
$type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
$hwnd = $process.MainWindowHandle
$null = $type::ShowWindowAsync($hwnd, $Mode)
$null = $type::SetForegroundWindow($hwnd)
}
In deinem Code müsstest du die Funktion dann wie folgt aufrufen:
Code:
$TrueImageTools = Get-Process * | ? {
  $_.WindowTitle -like '*Systembereinigung*'
} | Select -First 1    # We only want the first such process!

Show-ProcessInForeground $TrueImageTools
Das werde ich gegen Später mal ausprobieren. Ich versuche mich auf deinen Vorschlag, spätestens morgen zu melden und ein feedback zu geben. Ich weis nur nie wann ich Zeit habe.
 
#4
Guten Abend Forum,

vielen Dank zuerst an alle die interesse gezeigt hatten.

@ComFreek
Besonderen Dank an dich. Du hast dir sogar die Mühe gemachten mir auf die Sprünge zu helfen.
Nach dem ich nun noch ein wenig rum geforscht habe, habe ich die für mich praktikabelste Lösung gefunden.

Code:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine -Force
###############################################################################
#Binde Klassen ein
    add-type -AssemblyName microsoft.VisualBasic
    add-type -AssemblyName System.Windows.Forms
###############################################################################
#Funktion um geöffnete Fenster in den Fordergrund zu holen
#Quelle:
#   https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/bringing-window-in-the-foreground
function Show-Process($Process, [Switch]$Maximize)
{
  $sig = '
    [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
  '
 
  if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
  $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
  $hwnd = $process.MainWindowHandle
  $null = $type::ShowWindowAsync($hwnd, $Mode)
  $null = $type::SetForegroundWindow($hwnd)
}
###############################################################################
#Starte den Prozess und schreibe den Vorgang in eine Variable
    $RunSysClean = Start-Process -FilePath "C:\Program Files (x86)\Acronis\TrueImage2014\TrueImageHome\TrueImageTools.exe" -ArgumentList /system_cleanup -LoadUserProfile -WindowStyle Minimized -PassThru
###############################################################################
#Warte bis der Prozess gestattet hat.
    start-sleep -Seconds 13
###############################################################################
#Hole das Fenster mit dem Process in den Fordergrund
    Show-Process -Process $RunSysClean -Normal
###############################################################################
#Warte 0,3 Millisekunden
    Wait-Event -Timeout 0.3
###############################################################################
#Füre den ersten Tastendruck aus
    [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
###############################################################################
#Warte 120 Sekunden um die Laufwerke zu analysieren.
    Wait-Event -Timeout 120
###############################################################################
#Lege zweite Variable RunSysClean an.
    $RunSysClean2 = $RunSysClean
###############################################################################
#Hole das Fenster mit dem Process in den Fordergrund
    Show-Process -Process $RunSysClean2
#Warte 0,3 Millisekunden
    Wait-Event -Timeout 0.3
###############################################################################
#Füre den ersten Tastendruck mit analysierten Laufwerken aus
    [System.Windows.Forms.SendKeys]::SendWait("{LEFT}")
###############################################################################
#Füre den zweiten Tastendruck mit analysierten Laufwerken aus
    [System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
###############################################################################
#Entzieht der PowerShell die ausführungsberechtigung
    Set-ExecutionPolicy -ExecutionPolicy Restricted -Scope LocalMachine -Force
Diese Script habe ich in eine Aufgabenplanug gepackt und wird jetzt wöchentlich ausgefürht.

Da ich eher einen Struckturierten Code brauche, um Ihn für mich sinnvoll verwerten zu können, habe ich auf das oben erwähnte Pferd gesetzt. Mein Code davor war das blanke Kaos. Jetzt ist es für mich zu Hundertprozent nachfollzehbar.

Es funktioniert. Es läuft derzeit auf meinem System durch.

Einen schönen Abend und nochmals vielen Dank!

PS: Kann man den Beitrag als gelöst markieren?
 

ComFreek

Mod | @comfreek
Moderator
#5
Super, dass es jetzt funktioniert :)

Show-Process -Process $RunSysClean -Normal
Wo kommt denn der Normal-Switch her? In der Funktionsdefinition sehe ich davon nichts. Ich glaube, es tut einfach nichts? (Ich hätte gedacht, PowerShell wirft einen Fehler, wenn man ein Switch angibt, das nicht existiert. Das ist wohl nur bei Built-Ins standardmäßig der Fall?)
 
#6
Super, dass es jetzt funktioniert :)


Wo kommt denn der Normal-Switch her? In der Funktionsdefinition sehe ich davon nichts. Ich glaube, es tut einfach nichts? (Ich hätte gedacht, PowerShell wirft einen Fehler, wenn man ein Switch angibt, das nicht existiert. Das ist wohl nur bei Built-Ins standardmäßig der Fall?)
@com Freek
Du hast vollkommen recht, dass hat keinen einfluss auf das Script. Ich hatte mal einen versuch laufen... :)
Auch wenn ich schon einiges mit der PowerShell gemacht habe, so deutet denke ich vieles darauf hin, dass ich noch sehr am lernen bin. Ich versuche daher gerne was und schaue wie es sich wo auswirkt.

Sorry, dass ich den Code nicht genauer unter die lupe genommen hatte.
 
Status
Dieses Thema wurde gelöst! Zur Lösung gehen…

Neue Beiträge