Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Warten auf Ende einer Shell Anweisung

Forumthread: Warten auf Ende einer Shell Anweisung

Warten auf Ende einer Shell Anweisung
13.08.2015 10:23:24
Hannes
Huhu liebe Herber Gemeinde,
ich bäuchte mal eure kompetente Hilfe :S
Ich entpacke mit Hilfe 7zip eine Datei über ein Shell Aufruf.
Klappt Wunderbar! ABER:
Wird danach die entpackte Datei direkt wetierverarbeitet, demnach muss ich mein Makro so lange pausiweren bis 7 Zip fertig mit entpacken ist. Eine Zwischenlösung ist hier Application.Wait (Now + TimeValue("0:00:05")). Allerdings ist das nicht optimal bei einer Laufzeit kleiner 5s und führt zum Fehler wenn die zu entpackende Datei mal größer ist als normal, also Laufzeit über 5s.
Wie kann ich Excel auf Beendung der Sehll Answeisung warten lassen?
Danke im Vorraus!
Hier mein CODE:

Dim fso As Object
'ausgewählte Datei entpacken mit 7-Zip
str7zipProgramm = "C:\Program Files\7-Zip\7z.exe" 'Pfad zur 7zip .exe
str7zipArchiv = GZDATEIPFAD  'Pfad zu entpackender Datei
str7zipOrdner = "D:\TEMP"  'pfad zielordner
Set fso = CreateObject("Scripting.FileSystemObject")
str7zipProgramm = fso.GetFile(str7zipProgramm).ShortPath
str7zipArchiv = fso.GetFile(str7zipArchiv).ShortPath
str7zipOrdner = fso.GetFolder(str7zipOrdner).ShortPath
Shell str7zipProgramm & " x " & str7zipArchiv & " -o" & str7zipOrdner, vbMinimizedNoFocus
'5s warten auf 7zip beendet
Application.Wait (Now + TimeValue("0:00:05"))

Anzeige

2
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Warten auf Ende einer Shell Anweisung
13.08.2015 10:35:26
Nepumuk
Hallo,
ein Beispiel zum basteln:
Option Explicit

Private Declare Function OpenProcess Lib "kernel32.dll" ( _
    ByVal dwDesiredAccess As Long, _
    ByVal bInheritHandle As Long, _
    ByVal dwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" ( _
    ByVal hObject As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" ( _
    ByVal hHandle As Long, _
    ByVal dwMilliseconds As Long) As Long

Private Const PROCESS_QUERY_INFORMATION = &H400
Private Const SYNCHRONIZE = &H100000
Private Const INFINITE As Long = &HFFFFFFFF

Public Sub ShellAndWait()
    Dim lngTaskID As Long, lngProcID As Long, lngExitCode As Long
    lngTaskID = Shell("C:\Windows\NOTEPAD.EXE D:\test.txt", vbNormalFocus)
    lngProcID = OpenProcess(SYNCHRONIZE + PROCESS_QUERY_INFORMATION, 0&, lngTaskID)
    Call WaitForSingleObject(lngProcID, INFINITE)
    Call CloseHandle(lngProcID)
    AppActivate Application.Caption, True
    MsgBox "Jetzt geht's weiter"
End Sub

Gruß
Nepumuk

Anzeige
AW: Warten auf Ende einer Shell Anweisung
13.08.2015 11:32:48
Hannes
Es hat bestens geklappt! Konnte es auf meine Shell ummodeln und funktioniert wie gewüsncht. DANKE!
;
Anzeige
Anzeige

Infobox / Tutorial

Warten auf das Ende einer Shell-Anweisung in Excel VBA


Schritt-für-Schritt-Anleitung

Um Excel VBA dazu zu bringen, auf das Ende einer Shell-Anweisung zu warten, kannst du die OpenProcess- und WaitForSingleObject-Funktionen aus der kernel32.dll nutzen. Hier ist eine Schritt-für-Schritt-Anleitung:

  1. Deklariere die benötigten Funktionen: Füge die folgenden Deklarationen am Anfang Deines Moduls hinzu:

    Private Declare Function OpenProcess Lib "kernel32.dll" ( _
       ByVal dwDesiredAccess As Long, _
       ByVal bInheritHandle As Long, _
       ByVal dwProcessId As Long) As Long
    
    Private Declare Function WaitForSingleObject Lib "kernel32.dll" ( _
       ByVal hHandle As Long, _
       ByVal dwMilliseconds As Long) As Long
    
    Private Declare Function CloseHandle Lib "kernel32.dll" ( _
       ByVal hObject As Long) As Long
    
    Private Const PROCESS_QUERY_INFORMATION = &H400
    Private Const SYNCHRONIZE = &H100000
    Private Const INFINITE As Long = &HFFFFFFFF
  2. Erstelle die Subroutine für das Warten: Erstelle eine Subroutine, die die Shell-Anweisung ausführt und wartet, bis sie abgeschlossen ist:

    Public Sub ShellAndWait()
       Dim lngTaskID As Long
       Dim lngProcID As Long
    
       ' Beispiel für einen Shell-Befehl
       lngTaskID = Shell("C:\Windows\NOTEPAD.EXE D:\test.txt", vbNormalFocus)
       lngProcID = OpenProcess(SYNCHRONIZE + PROCESS_QUERY_INFORMATION, 0, lngTaskID)
    
       ' Warten, bis der Prozess abgeschlossen ist
       Call WaitForSingleObject(lngProcID, INFINITE)
       Call CloseHandle(lngProcID)
    
       MsgBox "Jetzt geht's weiter"
    End Sub
  3. Ersetze den Shell-Befehl: Ersetze den Shell-Befehl durch Deinen eigenen, z.B. um 7-Zip zu nutzen.


Häufige Fehler und Lösungen

  • Fehler: "Zugriffsverletzung"
    Stelle sicher, dass Du die richtigen Berechtigungen hast, um den Prozess zu öffnen. Überprüfe die dwDesiredAccess-Parameter in der OpenProcess-Funktion.

  • Fehler: "Shell gibt -1 zurück"
    Dies deutet darauf hin, dass die Shell-Anweisung nicht korrekt ist. Überprüfe den Pfad und die Argumente.


Alternative Methoden

Wenn Du die OpenProcess- und WaitForSingleObject-Funktionen nicht verwenden möchtest, kannst Du auch die Application.Wait-Methode in Kombination mit einer Schleife nutzen. Beachte jedoch, dass dies weniger effizient ist:

Dim start As Double
start = Timer
Do While Timer < start + 5 ' Warten für 5 Sekunden
    DoEvents ' Erlaubt es Excel, andere Tasks zu verarbeiten
Loop

Praktische Beispiele

Hier ist ein Beispiel, wie Du 7-Zip verwenden kannst, um eine Datei zu entpacken und auf das Ende des Prozesses zu warten:

Public Sub UnzipAndWait()
    Dim fso As Object
    Dim lngTaskID As Long
    Dim lngProcID As Long
    Dim str7zipProgramm As String
    Dim str7zipArchiv As String
    Dim str7zipOrdner As String

    str7zipProgramm = "C:\Program Files\7-Zip\7z.exe" ' Pfad zur 7zip .exe
    str7zipArchiv = "D:\TEMP\deinArchiv.zip" ' Pfad zur zu entpackenden Datei
    str7zipOrdner = "D:\TEMP" ' Zielordner

    Set fso = CreateObject("Scripting.FileSystemObject")
    lngTaskID = Shell(str7zipProgramm & " x " & str7zipArchiv & " -o" & str7zipOrdner, vbNormalFocus)
    lngProcID = OpenProcess(SYNCHRONIZE + PROCESS_QUERY_INFORMATION, 0, lngTaskID)

    Call WaitForSingleObject(lngProcID, INFINITE)
    Call CloseHandle(lngProcID)

    MsgBox "Entpacken abgeschlossen!"
End Sub

Tipps für Profis

  • Verwende vbMinimizedNoFocus, um die Shell-Anwendung im Hintergrund zu minimieren, ohne den Fokus zu verlieren.
  • Teste Deine Shell-Befehle zuerst in der Eingabeaufforderung, um sicherzustellen, dass sie korrekt sind.
  • Wenn Du regelmäßig mit externen Programmen arbeitest, erstelle eine Utility-Funktion, um die Wiederverwendbarkeit zu erhöhen.

FAQ: Häufige Fragen

1. Wie kann ich mehrere Prozesse gleichzeitig warten lassen?
Du kannst eine Schleife verwenden, die alle Prozess-IDs speichert und für jede WaitForSingleObject aufruft.

2. Funktioniert dies auch in Excel 365?
Ja, die beschriebenen Methoden funktionieren in allen modernen Excel-Versionen, die VBA unterstützen.

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Entdecke mehr
Finde genau, was du suchst

Die erweiterte Suchfunktion hilft dir, gezielt die besten Antworten zu finden

Suche nach den besten Antworten
Unsere beliebtesten Threads

Entdecke unsere meistgeklickten Beiträge in der Google Suche

Top 100 Threads jetzt ansehen
Anzeige