Announcement

Collapse
No announcement yet.

CreateProcess

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • CreateProcess

    Ich kann mit CreateProcess wunderbar z.b. daß <br>
    MS-Notepad starten. Wenn ich das Notepad beende <br>
    läuft meine Anwendung weiter. <br>
    Wenn ich aber statt dem Notepad die Setup.exe vom Installsield <br>
    aufrufe bleibt meine Anwendung stehen und reagiert nicht mehr. <br>
    Wenn ich dann meine Anwendung zurück setze wird der Installshield <br>
    ausgeführt. <br>
    Wie kann ich den Installshield ausführen und meine Anwendung <br>
    darauf warten lassen bis dieser beendet ist (wie es mit Notepad ja <br>
    funktioniert!!!??? ) ? <br>

    Schon jetzt vielen Dank!!

    Alex Weth

  • #2
    Hallo,

    Windows ist ein botschaftsgesteuertes Betriebssystem. Bei der Fehlerbeschreibung gehe ich davon aus, das im Programm nach dem Start des InstallSHIELD-Setupprogramms gewartet wird, ohne die eigene Botschaftswarteschlange auszulesen. Win32 toleriert dieses Verhalten, obwohl es nicht ganz korrekt ist, wenn sich dieser Zustand über einen längeren Zeitpunkt hinzieht - und weil es so bequem ist, mache ich das auch von Zeit so Zeit in meinen Beispielen ;-)

    Allerdings überzeugt sich der InstallSHIELD vom Systemzustand, indem er eine Broadcast-Botschaft an alle Top-Level-Fenster schickt und auf die Beantwortung <b>wartet</b>. Wenn nun das eigene Programm die eigene Botschaftswarteschlange <b>nicht</b> regelmässig ausliest, kann sie diese Botschaft auf nicht beantworten, so dass der InstallSHIELD wartet und wartet und wartet....

    Man kann das Problem nur beseitigen, indem während der Wartezeit auf das Ende des gestarteten Prozesses auch die eigene Botschaftswarteschlange ausgelesen wird:
    <pre>
    procedure TFormMain.Button1Click(Sender: TObject);
    begin
    WaitExecute('calc.exe');
    end;

    {
    Das Programm startet eine andere Win32-Anwendung und wartet auf deren
    Ende. Allerdings soll die eigene Anwendung während dieser Zeit immer
    noch auf Benutzeraktionen und Windows-Botschaften reagieren. Der
    Benutzer kann das Fenster verschieben, als Icon ablegen und wieder
    von der Taskleiste herstellen. Dazu ist es notwendig, das die Win32-
    API-Funktion MsgWaitForMultipleObjects nicht nur beim Ende des gestarteten
    Prozesses zurückkehrt, sondern immer dann, wenn eine neue Botschaft von
    Windows zugestellt wurde. Aus diesem Grund verwendet die API-Funktion
    MsgWaitForMultipleObjects die Konstante QS_ALLINPUT, somit kehrt die
    Funktion bei jeder neuen Botschaft zurück. Über den anschliessenden
    Aufruf von ProcessMessages werden die neuen Botschaften als bearbeitet
    markiert, so dass sich MsgWaitForMultipleObjects wieder für neue
    Botschaften auf Lauer legt, solange der gestartet Prozess noch läuft.
    }

    procedure TFormMain.WaitExecute(sEXE: String);
    var
    aTSI : TStartupInfo;
    aTPI : TProcessInformation;
    iRet : Integer;
    begin
    FillChar(aTSI, SizeOf(aTSI), #0);
    FillChar(aTPI, SizeOf(aTPI), #0);
    aTSI.CB := SizeOf(aTSI);
    if not CreateProcess(nil, PChar(sEXE), nil, nil, False,
    NORMAL_PRIORITY_CLASS,
    nil, nil, aTSI, aTPI) then
    RaiseLastWin32Error;
    StatusBar1.SimpleText := 'Externer Prozess ist aktiv.';
    repeat
    iRet := MsgWaitForMultipleObjects(1, aTPI.hProcess, False, INFINITE,
    (QS_ALLINPUT));
    if iRet <> (WAIT_OBJECT_0) then
    begin
    // aktustische Rückmeldung zur Demonstration
    MessageBeep($FFFFFFFF);
    Application.ProcessMessages;
    end;
    until iRet = (WAIT_OBJECT_0);
    CloseHandle(aTPI.hProcess);
    StatusBar1.SimpleText := 'Externer Prozess wurde beendet.';
    end;
    </pre>

    P.S: Das Beispiel stammt aus meinem neuen (demnächst erscheinenden) Buch <b>Delphi Win32-Lösungen</b>

    Comment


    • #3
      Danke Herr Kosch,
      aber es funktioniert nicht.
      Jetzt wartet meine Anwendung nicht mehr bis der Installshield
      beendet wurde, sondern läuft weiter.
      Ich greife als nächstes (nach Aufruf von Installshield) auf
      Tabellen zu die erst vom Installshield installiert werden
      -> Fehlermeldung Datei nicht vorhanden.
      Haben Sie noch eine Idee??? Ich bräuchte nämlich dringen diese Funktion!
      Vielen Dank!

      Ale

      Comment


      • #4
        Hallo zusammen,
        <br>
        ich habe das gleiche Problem, auch - leider - noch keine Lösung.
        <br>
        Ich nehme an, dass es sich um InstallShield-Express (bei Delphi xx)
        <br>
        handelt: Die erzeugte Setup.Exe ist keine 32-bit-Applikation,
        <br>
        sondern 16-bittig, jedenfalls startet NT sie in einer NTVDM.
        <br>
        Der Effekt, dass die Setup-Exe nach 100% (Vorbereitung) stehenbleibt,
        <br>
        tritt bei mir auch dann auf, wenn Outlook 2000 läuft.
        <br>
        Beendet man Outlook, geht's sofort weiter!
        <br>
        Vielleicht hilft das ja ein bisschen weiter..
        <br>
        MfG
        <br>
        Ma

        Comment


        • #5
          Der WinZip Self-Extractor hat die Fähigkeit Install-Shield zu starten und solange zu warten bis Install-Shield beendet ist.<br>
          Dazu muß im WinZip Self-Extractor ein Feld >Warte auf< gesetzt werden.
          In der Hilfe zu WinZip Self-Extractor habe ich folgende Einträge gefunden:<br>
          "Das Feld >Warte auf< wird normalerweise nicht verwendet, jedoch starten einige Setup-Programme - unter ihnen auch das von Sterling Software's verwendete InstallShield, andere Programme um die Installation abzuwickeln und werden dann plötzlich wieder geschlossen. In solchen Fällen brauchen Sie das Feld >Warte auf< um dem selbstextrahierenden ZIP-Archiv mitzuteilen, daß es auf das Beenden eines bestimmten Moduls warten soll, bevor die Dateien im temporären Verzeichnis wieder gelöscht werden sollen.
          Normalerweise wird in das >Feld Warte< auf automatisch ein Wert eingetragen. Dieser Wert sollte _DELIS sein, wenn Sie ein 16-Bit selbstextrahierendes ZIP-Archiv erstellen möchten, bei einem 32-Bit selbstextrahierenden ZIP-Archiv sollte dieser Wert _ISDEL sein."<br&gt

          Comment


          • #6
            Ich habe soeben die repeat-Schleife in der procedure TFormMain.WaitExecute(sEXE: String); von Herrn Kosch folgendermassen erweitert:<br>
            <b>until (iRet = (WAIT_OBJECT_0)) and (FindWindow(nil, 'Setup') = 0);</b><br>
            Dies scheint zu funktionieren

            Comment


            • #7
              Hallo,

              die Win32-API-Funktion <b>MsgWaitForMultipleObjects</b> wartet auf das Prozess-Handle (aTPI.hProcess) des über CreateProcess gestarteten Prozesses. In dem Beispiel mit dem Windows-Taschenrechner (CALC.EXE) kann dies gut nachverfolgt werden. Wird beim Aufruf von MsgWaitForMultipleObjects auch tatsächlich das Prozess-Handle des Setup-Programms übergeben? Wenn ja, sollte geprüft werden, ob der InstallSHIELD nicht einen sogenannten <i>Bootstrap-Loader</i> verwendet: Ein "Hilfsprogramm" packt das komprimierte Setup-Programm aus und startet dieses als 2. Anwendung und beendet sich selbst sofort wieder. In diesem Fall reicht das einfache Warten auf das Prozess-Handle in der Tat nicht aus.

              In meinem neuen Buch <b>Delphi Win32-Lösungen</b> (das demnächste erscheint) stelle ich eine elegante Möglichkeit vor, wie man eigene Programme und Funktionen <b>während</b> eines InstallSHIELD Express-Setupprogramms aufrufen kann. Zwar kann dies die kleine InstallSHIELD Express-Version offiziell nicht, es gibt aber dennoch einen Weg, eigene DLL-Funktionen und sogar eigene EXEs während des Installationsvorgangs in definierbarer Reihenfolge aufzurufen.

              Zur Frage: "<i>Der Effekt, dass die Setup-Exe nach 100% (Vorbereitung) stehenbleibt, tritt bei mir auch dann auf, wenn Outlook 2000 läuft. </i>". <br>
              Das Programm Outlook ist berüchtigt dafür, ebenfalls nicht immer "pünktlich" auf Windows-Broadcasts zu antworten. Dieser Effekt wird auf den Web-Seiten vom InstallSHIELD beschrieben. Nicht ohne Grund wird beim Starten des Setups empfohlen, alle (!) anderen Anwendungen zu schliessen

              Comment


              • #8
                <prep>
                Die Kombination aus den Vorschlägen von A.Kosch und D.Elsässer funktioniert bei mir ebenfalls.
                NT-Taskmanager zeigt, dass zunächst SETUP.EXE (vom aufrufenden
                Programm per Create-Process) gestartet wird und nach ca. 44% das Programm _ISDEL.EXE startet, dann wird Setup.EXE nach 100% Vorbereitung beendet.
                _ISDEL.EXE erzeugt ein Fenster Namens 'Setup'.
                Man muss also wirklich nach Beenden der gestarteten Task
                auf das Verschwinden des Fensters 'Setup' warten.
                Soweit mein Stand der Dinge.

                Dank an alle
                Max
                </prep&gt

                Comment


                • #9
                  Hallo,<br>
                  wie kann ich über das Processhandle an des Handle des Top-Level-Fenster der Anwendung kommen?<br>:-) Jens Schuman

                  Comment

                  Working...
                  X