Programm automatisch laufen lassen

Steusi

Nasenbär
Hallo, ich möchte mittels VB ein Programm ausführen, jedoch werden beim start des Programms 2 Abfragen gestartet.
Das erste aufpopende Fenster kann einfach mit ENTER bestätigt werden, sobald das gesehen ist öffnet sich ein 2. Fenster, wo 2mal TAB gedrückt werden muss und dann ENTER.
Ich dachte es wäre kein großes Problem, doch der Programmcode arbeitet zu "schnell", deshalb müsste ich eine kleine Pause von 1 Sekunde einbauen, in der Zeit würde das 2. Fenster aufpopen können oder?

Kann VB auch ein aktives Fenster erkennen?

Mein Code:
Code:
Public Class Form1
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      Dim strEXE As String

            strEXE = "PFAD_zum_Programm"

            Shell(strEXE)


            My.Computer.Keyboard.SendKeys("{ENTER}")


            'Sleep(1000)
            My.Computer.Keyboard.SendKeys("{TAB}")
            My.Computer.Keyboard.SendKeys("{TAB}")
            My.Computer.Keyboard.SendKeys("{ENTER}")
            

            'My.Computer.Keyboard.SendKeys("%{F4}")

    End Sub
End Class
Das erste ENTER klicken funktioniert wurderbar, aber Sleep klappt nicht! Dann bleibt das Programm immer hängen.

Das Programm, welches ich ausführe erzeugt Excel-Tabellen, sobald es fertig ist soll das Programm wieder geschlossen werden wie realisiere ich das? Ich muss nicht unbedingt gucken, ob der Prozess wirklich beendet ist, würde auch wieder ein Timer von 2 Sekunden reichen, mich interessiert nur wie ich dem aktiven Porgramm sage, dass es geschlossen werden soll!


//Ich hoffe es ist nicht schlimm, dass ich diesen Beitrag nochmal geschrieben habe, bitte löscht den alten Beitrag, welcher HIER zufinden ist.
 
Hallo, hier ein Beispiel:
Code:
Imports System.Threading

Public Class Form1
    Private Declare Sub keybd_event Lib "user32" (ByVal _
        bVk As Byte, ByVal bScan As Byte, ByVal dwFlags _
        As Int32, ByVal dwExtraInfo As Int32)

    Private Const VK_TAB = &H9
    Private Const VK_RETURN = &HD
    Private Const KEYEVENTF_KEYUP = &H2

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim ExterneAnwendung As New System.Diagnostics.Process()
        ExterneAnwendung.StartInfo.FileName = "Excel.exe"
        ExterneAnwendung.Start()

        Dim localByName As Process() = Process.GetProcessesByName("Excel")

        Thread.Sleep(1000)

        keybd_event(VK_RETURN, 0, 0, 0)
        keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0)

        Thread.Sleep(1000)

        keybd_event(VK_TAB, 0, 0, 0)
        keybd_event(VK_TAB, 0, KEYEVENTF_KEYUP, 0)

        Thread.Sleep(1000)

        keybd_event(VK_TAB, 0, 0, 0)
        keybd_event(VK_TAB, 0, KEYEVENTF_KEYUP, 0)

        Thread.Sleep(1000)

        keybd_event(VK_RETURN, 0, 0, 0)
        keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0)

        Thread.Sleep(1000)

        localByName(0).CloseMainWindow()

        ExterneAnwendung.WaitForExit()
        MsgBox("Excel wurde beendet")
    End Sub
End Class
 
Aha, man muss mit keybd_event arbeiten, werde mir den Befehl einmal ganz genau anschauen.
Ich habe deinen Code erstmal so übernommen, jedoch tritt bei mir folgender Fehler auf.
Code:
localByName(0).CloseMainWindow()
Bei dieser Codezeile sagt er mir folgendes:
IndexOutOfRangeException:
Der Index war außerhalb des Arraybereichs.

Wofür steht die 0 (Null)? Das Programm, welches ich ausführe, startet selbstständig im Hintergrund noch eine .cmd Datei und danach öffnet es die erstellte Excel-Datei.

Oder muss ich folgendes anpassen:
Code:
Dim localByName As Process() = Process.GetProcessesByName("Excel")
 
Du musst das ganze natürlich für dein gestartetes Programm anpassen.
Da wo in meinem Beispiel "Excel" steht muss dein Programmname rein.

Wenn das gestartete Programm im Hintergrund läuft, hast du ein Problem.
Die keybd_event werden an das Fenster gesendet das den Fokus hat.

Ansonsten informiere dich mal über die API sendmessage oder postmessage.

Kannst du die Excel Tabellen nicht aus deiner Anwendung heraus erzeugen?
 
Das Programm erzeugt meine Datein schon automatisch, nur ich bekomme es eben nicht geschlossen.
Zum Ende bleibt die .CMD und die EXCEL Datei offen. Ich habe immer das Gefühl, das VB EXCEL beenden will, bevor es überhaupt geöffnet wird.
Kann man das noch vorher überprüfen, ob EXCEL offen ist, sprich der Prozess EXCEL existiert.

Ich habe mir mal API angeguckt, wie du gesagt hast, siehe HIER:
http://www.vbarchiv.net/tipps/details.php?id=572

Nur klappt der Code nicht so, wie er dort steht, es fehlt sicher noch ein Verweis auf eine Library oder?
 
Zuletzt bearbeitet:
Prüfen kannst du so:
Code:
        Dim localByName() As Process = Process.GetProcessesByName("Excel")

        If localByName.Length = 0 Then
            MsgBox("Excel nicht offen")
        Else
            MsgBox("Excel ist offen")
        End If
 
Excel ist offen und es erscheint die Meldung:
"Excel nicht offen" Wie geht das.
Ich habe einen Verdacht. Was macht
Code:
Thread.Sleep(1000)
genau?
Wird damit VB zum warten gezwungen, leider nicht oder? Sondern nur das aktive Fenster.
Dann habe ich es auch einmal nur mit Sleep versucht und zwar folgendermaßen:
Code:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sleep(1000)
Das klappt aber auch nicht.
Sobald das 2. mal ENTER "gedrückt" wurde wird eine .CMD Datei aufgerufen.
Diese CMD Datei kann ich aber nicht auslesen, dieser wurde von einem Fremden programmiert. In der CMD-Datei ist hinterlegt, dass die Excel-Datei erzeugt werden soll.

Durch das Sleep wird also nur die CMD Datei zum warten gezwungen, ist das Richtig?

Excel-Datei ist erzeugt und wird durch die CMD-Datei auch automatisch ausgeführt.
Ich will sie gleich wieder schließen, danach verschiede ich die erstellte Excel-Datei in einen anderen Ordner.

Im Moment ist es aber der Fall, dass die Excel-Datei erstellt wird. Mein Code eingreift und die erstellte Datei verschiebt. Beim ausführen der Excel-Datei (von der CMD-Datei aus) kommt schon die Fehlermeldung, das die Datei nicht existiert. Ist ja klar, schließlich habe ich die Datei schon verschoben.

Deshalb brauche ich einen Befehl, damit VB nicht so schnell arbeitet, es soll mal eine kleine Pause einlegen und alle anderen Prozessen laufen lassen.

Falls es sowas nicht gibt, bräuchte ich eine Befehl, der VB erst weiter machen lässt, wenn keine Excel-Datei mehr geöffnet ist. Also reicht es nicht, dass VB einmal guckt, ob eine Excel-Datein offen ist, sonder VB soll diese Zeile solange prüfen bis keine Excel-Datei mehr geöffnet ist!

Ich hoffe Ihr versteht mein Vorhaben und habt einen guten Ratschlag für mich!
 
Thread.Sleep(1000)

Lässt VB warten, nicht die cmd.

Ich habe Excel mal per Hand geöffnet und mit folgendem Code geprüft ob Excel läuft.
Code:
 Dim localByName As Process() = Process.GetProcessesByName("Excel")

        If localByName.Length = 0 Then
            MsgBox("Excel nicht offen")
        Else
            MsgBox("Excel ist offen")
        End If

Das Ergebnis ist: Excel ist offen.

Wenn die cmd die Excel Mappen erstellt kannst du dann nicht die cmd von deinem Programm aus starten?
 
Wenn du die cmd von deinem Prog aus starten könntest:
Code:
        Dim ExterneAnwendung As New System.Diagnostics.Process()
        ExterneAnwendung.StartInfo.FileName = "DieCmdDatei"
        ' falls Argumente übergeben werden müssen
        ExterneAnwendung.StartInfo.Arguments = "/a /c u.s.w."
        ExterneAnwendung.Start()

        ' warten bis cmd fertig
        ExterneAnwendung.WaitForExit()

        ' Excel schliessen
        Dim localByName As Process() = Process.GetProcessesByName("Excel")
        localByName(0).CloseMainWindow()
 
Wenn ich Excel manuell öffne und dann das Programm starte kommt bei mir auch "Excel ist offen"
An die CMD Datei komme ich leider nicht ran, diese ist in eine .exe mitverschachtelt, leider!

Ab diesem ENTER wird die CMD-Datei aus der EXE heraus gestartet.
no.1
Code:
        keybd_event(VK_RETURN, 0, 0, 0)
        keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0)


        If localByName.Length = 0 Then
            MsgBox("Excel nicht offen")
        Else
            MsgBox("Excel ist offen")
        End If
Ergebnis in der Reihenfolge:
ENTER
CMD-Fenster erschein kurz
Meldung: Excel nicht offen (im Hintergrund)
Excel-Datei geöffnet

no2.
Code:
        keybd_event(VK_RETURN, 0, 0, 0)
        keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0)

       Thread.Sleep(5000)

        If localByName.Length = 0 Then
            MsgBox("Excel nicht offen")
        Else
            MsgBox("Excel ist offen")
        End If
Ergebnis in der Reihenfolge:
ENTER
CMD-Fenster erschein 5 Sekunden
Meldung: Excel nicht offen (im Hintergrund)
Excel-Datei geöffnet

Es ist leider so, ich kann es mir auch nicht erklären. Warum klappt folgende "Endlos-Schleife" nicht?

Code:
        Dim x As Integer
        x = 0
        Dim localByName As Process() = Process.GetProcessesByName("Excel")
        MsgBox(x)

        Do While x < 1
            If localByName.Length = 0 Then
                x = 0
            Else
                x = 1
            End If
        Loop
        MsgBox(x)
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück