Erstellen eines Datenbankdumps



  • Es wird, wie ich oben schon vorgeschlagen habe, ein WaitHandle dafür benutzt (hier ein ProcessWaitHandle mit Callback), s. Process.EnsureWatchingForExit.



  • @Th69
    Ahjo, wir haben etwas aneinander vorbeigeredet. Ich dachte, du meinst, dass das Exited Ereignis immer ausgelöst wird und ich dachte, dass ohne weitere Funktionsaufrufe eine Message Queue benötigt wird. Auf jeden Fall wird in WaitForExit das Ereignis ausgelöst, wenn der Prozess innerhalb der Wartefrist endet, egal ob mit oder ohne Message Queue.



  • @DocShoe / Th69

    ...so ganz habe ich zwar nicht alles verstanden, außer dass WaitForExit funktionieren sollte.
    Wenn ich das so einfüge wie von Dir, DocShoe, beschrieben, also zwei verschiedene Prozesse starte und nach jedem ein WaitForExit() bzw WaitForExit(500)einbaue, dann wird nur der erste Prozess proc_dump ausgeführt. proc_archive und std::remove(...) wird nicht mehr ausgeführt.
    Leider habe ich das mit dem Debuggen noch nicht hinbekommen, werde mich aber nochmals damit beschäftigen...



  • @uvbey
    ...also, ich habe das Programm Windows-Debug-Modus gestartet. Ohne WaitForExitläuft das ohne eine Meldung durch, mit dem WaitForExitwird eine Exception in Process.cs ausgelöst:

    private void EnsureState(State state)
    {
             ...
    	if ((state & State.Associated) != 0 && !Associated)
    	{
    		throw new InvalidOperationException(SR.GetString("NoAssociatedProcess"));
    	}
            ...
    

    --> Diesem Objekt ist kein Prozess zugeordnet ... Das verstehe ich jetzt nicht, wenn ich doch proc_dump->WaitForExit(500); angebe...

    Nachtrag: Die gleiche Exception wird geworfen bei der Abfrage von proc_dump->HasExited.
    Nachtrag 2: Auch wenn ich backup_database() aus dem laufenden Programm mittels Tastendruck aufrufe, erscheint der identische Fehler : NoAssociatedProcess



  • Da bist du jetzt auf eine Besonderheit bei C++ reingefallen, die bei C# sofort zu einem Compilerfehler geführt hätte: Start ist eine statische Methode der Klasse Process und du rufst sie über ein Objekt auf, anstatt den Rückgabewert zu benutzen:

    Process^ proc_dump = Process::Start( "mysqldump" ); // in C# benutzt man Process.Start(...)
    proc_dump->WaitForExit();
    

    Edit:
    Jetzt ist auch klar, warum StartInfo->CreateNoWindow = true; bei dir nicht funktioniert, da du es auf dem falschen Process-Objekt anwendest: du mußt die Überladung Start(ProcessStartInfo) benutzen...

    Alternativ gibt es noch die (eine) nicht-statische Start()-Methode ohne Parameter (schau dir das Beispiel an).

    PS:
    Du kannst in der .NET-Doku auch die Sprache (oben in der Titelzeile über eine ComboBox) von C# auf C++ stellen, um die Beispiele in C++/CLI angezeigt zu bekommen.



  • Dafür kann uvbey nichts, das habe ich verbockt.
    Mea culpa 😞



  • @DocShoe
    ..und ich hab's einfach übernommen - die Verantwortung liegt also bei mir 😉

    @Th69
    ...und wieder bestätigt sich die alte Entwicklerweisheit: Kaum macht man alles richtig, schon geht's!

    Das ist jetzt mein funktionierender Code:

    void backup_database(void)
    {
            ...
    
            Process^ proc_dump = gcnew Process();
    	ProcessStartInfo^ startInfoDump = gcnew ProcessStartInfo("mysqldump");
    	startInfoDump->WindowStyle = ProcessWindowStyle::Hidden;
    	startInfoDump->Arguments = mysqldump_arguments;
    	proc_dump = Process::Start(startInfoDump);
    	proc_dump->WaitForExit(1000);
    
    	Process^ proc_archive = gcnew Process();
    	ProcessStartInfo^ startInfoArchive = gcnew ProcessStartInfo("7z");
    	startInfoArchive->WindowStyle = ProcessWindowStyle::Hidden;
    	startInfoArchive->Arguments = zip_arguments;
    	proc_archive = Process::Start(startInfoArchive);
    	proc_archive->WaitForExit(1000);
    
    	std::remove(dump_filename.c_str());
            return;
    }
    

    Das Cmd-Fenster ist nun nicht mehr sichtbar, und alles funktioniert bestens!

    Vielen herzlichen Dank euch beiden - ich war schon am verzweifeln... Und auch der Hinweis mit der Umstellung auf C++ bei.NET hat mit geholfen und wird mir in Zukunft noch mehr helfen.

    Schönen Tag noch, und dann ein schönes Wochenende

    Viktor



  • Ich vermute mal vorsichtig, dass man die Zeilen 5 und 12 nicht mehr braucht, da Process::Start neue Instanzen anlegt und zurückgibt.
    Und auch das WaitForExit( 1000 ) ist seeeehr optimistisch, du gehst davon aus, dass sowohl der db-dump als auch das Einpacken der Datei nicht länger als 1 Sekunde dauern, bevor du mit dem nächsten Schritt weitermachst. Ich würde als Reserve da Minuten vorsehen.
    Oder du machst das, wie in einem der Links, die Th69 vorgeschlagen hat, über eine Schleife und machst erst dann weiter, wenn HasExited true ist.

    while( !proc->HasExited )
    {
       proc->WaitForExit( 1000 );
       if( !proc->HasExited )
       {
          // Timeout beim Warten auf Prozessende, was nu? Meldung? 
       }
    }
    


  • @DocShoe

    Natürlich hats Du Recht, Zeile 5 und 12 benötige ich nicht mehr. Dann muss ich das Process^in Zeile 9 und 16 davorstellen:

    Process^ proc_dump = Process::Start(startInfoDump);
    

    Ich habe jetzt eine Abfrage if( !proc->HasExited ) eingefügt und gebe im Fehlerfall eine Meldung aus, dass das Programm neu gestartet und wieder geschlossen werden soll. Länger wie 10 Sekunden kann ich aber nicht warten, da ich davon ausgehe, dass dann bereits der Rechner heruntergefahren wird. Am Ende eines Trainingsabends hat es die Aufsicht schon immer eilig, ebenfalls an die Theke zu kommen... 😉
    Ich werde das aber weiter beobachten. Im Bedarfsfall kann ich da noch Funktionalität einfügen (eigenes Fenster mit "Bitte Warten...", mehrere automatisierte Versuche etc.). Jetzt muss das erst einmal genügen.
    Nochmals Danke für eure Hilfe!!



  • @uvbey sagte in Erstellen eines Datenbankdumps:

    Länger wie 10 Sekunden kann ich aber nicht warten, da ich davon ausgehe, dass dann bereits der Rechner heruntergefahren wird. Am Ende eines Trainingsabends hat es die Aufsicht schon immer eilig, ebenfalls an die Theke zu kommen... 😉

    Dann kann man nur hoffen dass nie die Datenmengen in der Datenbank so groß werden, dass ein Dump länger als die 10s brauchen 😉



  • @uvbey sagte in Erstellen eines Datenbankdumps:

    Ich habe jetzt eine Abfrage if( !proc->HasExited ) eingefügt und gebe im Fehlerfall eine Meldung aus, dass das Programm neu gestartet und wieder geschlossen werden soll. Länger wie 10 Sekunden kann ich aber nicht warten, da ich davon ausgehe, dass dann bereits der Rechner heruntergefahren wird.

    Wurgs 😱
    Mit dem Herunterfahren sollte man sich schon so lange Zeit lassen, bis das Backup durch ist, ansonsten brauchste auch kein Backup.

    Dann schalte da doch ein Formular vor, dass dem Benutzer sagt, dass gerade ein Backup gemacht wird, dann sieht er wenigstens, dass er den Rechner nicht runterfahren darf.



  • @firefly sagte in Erstellen eines Datenbankdumps:

    Dann kann man nur hoffen dass nie die Datenmengen in der Datenbank so groß werden, dass ein Dump länger als die 10s brauchen

    Aktuell habe ich Daten seit dem 01.01.2023 drin - und das Backup dauert um die 200ms. Da habe ich schon noch Luft nach oben 😉
    @DocShoe: Das mit dem Formular habe ich mir auch schon überlegt. Ich werde das mal in Angriff nehmen. Ganz so kritisch ist das aber nicht - bislang haben wir das Backup noch nie gebraucht, und selbst wenn mal eines verloren geht, ist das auch nicht die Welt... Obwohl, nach Murphys Gesetz...🤔


Anmelden zum Antworten