Ab zweitem Drucken unter Win11 friert Anwendung ein



  • Hallo zusammen,

    mein altes Programm, das bisher unter allen Windosen brav gedruckt hat, bleibt nun hängen,
    sobald man das Drucken zum zweiten Mal aufruft.
    Das Problem hat zwar schon jemand geschildert, jedoch ohne hilfreiche Antwort.

      CDC	dcPrinter;
      DOCINFO	strDocInfo;
      DEVMODE*		pDevMode = NULL;
    ...
      CPrintDialogEx dlgDrucken(PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS | PD_HIDEPRINTTOFILE | PD_NOSELECTION | PD_NOCURRENTPAGE, &m_pFrame->m_wndView);
    	if (dlgDrucken.DoModal()!= S_OK)
                 return;
    	if((pDevMode =  dlgDrucken.GetDevMode()) == NULL)
    			return;
    	pDevMode->dmFields		|= DM_ORIENTATION; // Wird geändert
    	pDevMode->dmOrientation	 = DMORIENT_LANDSCAPE;//DMORIENT_PORTRAIT;
    	strDocInfo.lpszDocName   = cAnlagenNamen.GetBuffer(); cAnlagenNamen.ReleaseBuffer();
        if(!dcPrinter.CreateDC(dlgDrucken.GetDriverName(), dlgDrucken.GetDeviceName(), dlgDrucken.GetPortName(), pDevMode))
    	   return;
    	if(dcPrinter.StartDoc(&strDocInfo) <= 0) {
    		dcPrinter.DeleteDC();
    		return;
    	}
    ...
    ...
    	dcPrinter.EndDoc();
    	dcPrinter.DeleteDC();
    	
    	if(pDevMode){
    		GlobalUnlock(pDevMode);
    		GlobalFree(pDevMode);
    	}
    

    Es genügt, dass das Programm einmal den Druck-Dialog angezeigt hat,
    und schon bleibt es beim nächsten Versuch hängen.
    Sobald man dann das Programm abschiesst, kommt der neue, unbedienbare Druck-Dialog dann zum Vorschein.

    Kann da jemand bitte helfen?



  • Aus dem Bauch,
    pDevMode ist ja ein Pointer auf ein Objekt welches von dlgDrucken.GetDevMode() geliefert wird.
    Ist das nur eine Referenz, oder muss dieses wieder zerstört werden?
    Anscheinend wohl mit GlobalFree(pDevMode);.
    Ich sehe in Deinem Code einige return;, was passiert mit pDevMode?
    Kann es sein, dass Windows 11 etwas anders mit Objekten im Speicher umgeht?



  • @Helmut-Jakoby
    OK, vielen Dank, Jakoby.
    Mit den "returns" hast Du sicher recht. Werd ich nacharbeiten müssen.
    Ehrlichgesagt hatten in diesem Programmteil zuvor sogar noch ein paar "DeleteDC()" gefehlt, und das "Global..()" komplett.
    Die "returns" werden eigentlich auch nicht angesprochen, da es ja funktioniert (das erste Mal).

    Es ist alter Code von meinem Vorgänger, der damit seit fast 20 Jahren funktioniert hat!
    Und nun, unter Win11 gehts schief.

    Dann habe ich eben genauer nachgelesen.
    Das "DeleteDC()" wird schon öfter genannt, in Foren. Aber das "Global..()" Zeugs habe ich nur an einer Stelle gesehen.
    Microsoft selbst gibt da keine genaue Vorschrift. Das sollten die für die Erklärung ihrer "Create..()"-Methoden auch gleich dazuschreiben.

    Ich habe es halt damit probiert.
    Leider ohne Erfolg

    Bisher hat das ja alles funktioniert!



  • Bei CPrintDialogEx::GetDevMode steht aber nur etwas von GlobalUnlock, nicht von GlobalFree.



  • Wo bleibt das Programm denn stehen, wenn du mit dem Debugger im Einzelschrittmodus durchläufst?



  • @Th69 Hallo Th69
    ich hab das so irgendwo gesehen und einfach ergänzt.
    Mein Eindruck ist, dass Microsoft selbst nicht weiss, was zu tun ist.
    .. oder es eben nicht sagt.



  • @DocShoe Hallo DocShoe
    Ich weiss es leider nicht!
    Ich arbeite unter Win10!
    Und das passiert unter Win11! Da hab ich keine Entwicklungsumgebung.
    Aber wie schon gesagt, es versucht den Dialog wieder zu öffnen, bleibt aber da auf (halbem Weg?) stehen.
    Also nachdem man schon mal erfolgreich gedruckt hat.
    Erst wenn das Programm gekillt wird, geht der Dialog auf. Davor ist es eingefroren.
    Aber Drucken ist dann natürlich auch nichts mehr.



  • @elmut19 sagte in Ab zweitem Drucken unter Win11 friert Anwendung ein:

    Und das passiert unter Win11!

    Hast du denn keinen Win11 Rechner zur Hand?

    Sofern Remote Debugging für dich nicht in Frage kommt, würde ich mal die Debug Fassung kompilieren, auf dem Win11 Rechner laufen lassen, beim Absturz einen Crash Dump machen, und diesen dann mittels WinDbg debuggen.



  • @Quiche-Lorraine
    Hallo Quiche-Lorraine,

    inzwischen haben wir ein Notebook mit Win11 da, noch ohne VStudio.
    Hab das Remote-Debugging bisher nur auf einem Win6 Panel machen müssen. Aber werd mal gucken, was einfacher ist.

    Vermutung wäre (gemäss Verhalten), dass es beim "DoModal()" des Druck-Dialogs hängen bleibt.

    Aber wie ist das mit der 32Bit-Emulation auf dem neuen Windows?
    Könnte darin der Grund liegen?

    Ich habe z.B. folgenden Beitrag gefunden:
    https://learn.microsoft.com/en-us/answers/questions/1319494/new-print-dialog-box-just-let-me-print-once-(c-)
    oder
    https://stackoverflow.com/questions/57020201/c-gdi-printing-causes-system-to-freeze

    Man kann über einen Registry Eintrag das Win11 zwingen, den alten Dialog zu verwenden.
    Ansonsten wird ein neuer Dialog verwendet.
    Mit dem alten funktioniert das Drucken dann wieder.



  • @elmut19 sagte in Ab zweitem Drucken unter Win11 friert Anwendung ein:

    Aber wie ist das mit der 32Bit-Emulation auf dem neuen Windows?
    Könnte darin der Grund liegen?

    Langsam, mein Bauch sagt mir erst einmal dass man hier nach undefiniertem Verhalten suchen sollte. Es wäre nicht das erste Problem dieser Art.

    Als Vorlauf würde ich mal den Application Verifier ausprobieren. Danach würde ich mal den Code Schritt für Schritt debuggen und alle Parameter mittels der MSDN überprüfen.

    BTW: Überprüfe mal ob etwas im Device Context selektiert wurde. Die Art und Weise des Selektierens ist leider fehleranfällig. Ich habe mir da selbst einige Handles ins Nirwana befördert, bevor Dr. Memory mir den Fehler zeigte.



  • @Quiche-Lorraine
    Folgende Methoden habe ich noch auf dem Device Context gefunden.

    m_pDC->SelectObject(&cPenNormal);
    m_pDC->SetTextColor(..);
    m_pDC->FillRect(..);
    m_pDC->DrawText(..);
    ..MoveTo, ..LineTo, ..EndPage(), ..IsPrinting()

    Also ein "CBrush" oder "CPen", "CFont" kommt über ein "SelectObject(..)" rein.
    Sonst habe ich nichts gefunden. Und die funktionieren schon lange so.
    Das mit dem Application Verifier muss ich dann noch anschieben.



  • @elmut19 sagte in Ab zweitem Drucken unter Win11 friert Anwendung ein:

    Und die funktionieren schon lange so.

    Ja das ist halt das Wesen von undefiniertem Verhalten. Es funktioniert halt solange eine Bedingung erfüllt ist.

    Frage: Achtest du auf den Rückgabewert von SelectObject()?



  • @Quiche-Lorraine
    Nein! Also manchmal wird die Rückgabe einem Old-Obj zugewiesen.
    Aber oft ohne Zuweisung.
    Beim Überfliegen habe ich gerade nicht drauf geachtet, ob es sich dabei um den DC des Druckers handelt.
    Aber der ist sicher auch betroffen.

    ... "An application should always replace a new object with the original, default object after it has finished drawing with the new object."

    Es könnte also sein, dass das ursprüngliche Object nicht wieder zurückgeschrieben wird.

    Aber es heisst auch, dass diese Objekte dann über eine "OnIdle(..)"-Fktn, über das System verwaltet werden.

    Aber ich finde auch, z.B. in meiner "DrawLine(..)" ein "ding.DeleteObject();"
    ... Also insgesamt viele solcher "xxx.DeleteObject()".
    Das für den Print-Vorgang nachzuverfolgen dauert natürlich einige Zeit.



  • @elmut19 sagte in Ab zweitem Drucken unter Win11 friert Anwendung ein:

    Nein! Also manchmal wird die Rückgabe einem Old-Obj zugewiesen.

    Dann probiere doch mal folgendes. Jedes SelectObject liefert das zuvor selektierte Objekt zurück. Also würde ich den Device Context so wiederherstellen, wie ich ihn vorfand.

    // Sorry WinAPI Code 
    PrevSelectedBitmap = SelectObject(dcTrans, MyBitmap);
    // 
    // Do stuff...
    // 
    SelectObject(dcTrans, PrevSelectedBitmap);
    

    https://devblogs.microsoft.com/oldnewthing/20130306-00/?p=5043



  • @Quiche-Lorraine
    Bin mal einen Druck-Vorgang durchgegangen.
    Am Anfang wird ein Object, aber lokal in der Methode, gesichert.
    Die Sicherung erfolgt auf Pen und Font Objekte.
    Danach werden dies Objekte zig mal getauscht, ohne das vorherige in ein "Old" zu sichern.
    Im Abschluss werden erzeugte Objekte durch "DeleteObject()" auch wieder gelöscht.
    Zwischedurch wird auch wieder ein "OldFont" zurückgeschrieben.

    Im Grossen Ganzen sollte das eigentlich nicht so schlecht sein.
    Visuell aber schwer zu 100% einzuschätzen.



  • @elmut19
    Inzwischen sehe ich den "neuen" Druck-Dialog von Win11als Bug von Microsoft an.
    Es ist nirgends eine Programmiervorschrift für das Din zu finden.
    Das Einzige, was es gibt, ist ein Registry Patch, der den alten Druck-Dialog wieder einschaltet.
    https://answers.microsoft.com/de-de/windows/forum/all/windows-11-modernen-drucken-dialog-ohne-maus/729b38f0-536b-4a06-b014-950f83ccd557



  • @elmut19 sagte in Ab zweitem Drucken unter Win11 friert Anwendung ein:

    Inzwischen sehe ich den "neuen" Druck-Dialog von Win11als Bug von Microsoft an.

    Hast du dir schon das Problem auf Win11 unter dem Debugger angeschaut?



  • @Quiche-Lorraine
    Ich werd erstmal einen Testrechner mit Win11 beantragen.
    Der Rechner, auf dem wir das kurz probiert haben, ist leider nicht meiner.
    Das ist mir da doch zu umständlich.
    Aber jedenfalls vielen Dank für Deine Hinweise.
    ... Und ich werd noch weitersuchen ...



  • @elmut19 Warum nicht einfach ne VM nutzen?



  • @Tyrdal
    Danke Tyrdal.
    Werd ich jedanfalls auch beantragen.
    Hab ich nicht dran gedacht, da ich eh unbedingt noch ein Notebook fürs Homeoffice möchte.
    Mal sehn, was Lizenztechnisch besser ist.
    Bisher kann ich nur sehen, dass auf dem "normalen" Druckweg meine Objekte, so wie ich es bei Microsoft nachlesen kann, auch wieder abgebaut werden.
    Vorerst bleibt leider die einzige Möglichkeit, den Registry Patch anzuwenden.
    Programmiertechnisch wird es da keine Möglichkeit geben, da der neue Druck-Dialog ja neuer ist, als meine Programmierumgebung (und deren Doku).


Log in to reply