GetClipboardData crashed Dll



  • Hallo! Ich verzweifel langsam.

    Folgendes Problem:

    Ich möchte gerne etwas in die zwischenablage für ca 250 Millisekunden Tuen dies dann an ein Fenster mit STRG + V senden und dann den alten inhalt wieder ins Clipboard tuen. Das problem ist nun das das ganze ist eine Dll compiliere ich es als Consolen App funtz es 1a doch so steht beim dll aufruf: das programm hat aufgehört zu arbeiten.. CODE:

    static string GetClipData()
    {
        char * buffer = NULL;
    //open the clipboard
    
        string fromClipboard;
        if ( OpenClipboard(NULL))
        {
            HANDLE hData = ::GetClipboardData( CF_TEXT );
            char * buffer = (char*)GlobalLock( hData );
            fromClipboard = buffer;
            GlobalUnlock( hData );
            CloseClipboard();
        }
    
        if(!buffer)
        {
            return "";
        }
        else
        {
            return fromClipboard;
        }
    }
    
    static string CopyToClipboard(string str)
    {
    	HGLOBAL hText;
    	char *pText;
    	hText = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE, 280);
    	pText = (char*)GlobalLock(hText);
    	strcpy(pText, str.c_str());
    	GlobalUnlock(hText);
    
    	string textit = GetClipData();
    
            OpenClipboard(NULL);
    	EmptyClipboard();
    	SetClipboardData(CF_TEXT, hText);
    	CloseClipboard();
    
    	return textit;
    }
    

  • Mod

    Und was ist, wenn CF_TEXT nicht in der Zwischenablge ist?
    Dann knallt es doch.

    Du solltest schon prüfen was GetClipboardData liefert.

    Anders gesagt: Dein Code würde eine Bitmap nicht in die Zwischenablge zurück bringen.



  • bitmaps usw wäre egal es geht rein um den text^^



  • @hamburger:
    Du hast nicht richtig verstanden, was Martin Richter geschrieben hat.
    Er meinte, Du mußt bei jeder Funktion die mögliche Fehlermeldung auswerten!

    Am Beispiel von GetClipboardData() sähe es so aus:

    HANDLE hData = ::GetClipboardData( CF_TEXT );
    if( hData != NULL )
    {
      // GetClipboardData() ist erfolgreich.
      ...
    }
    

    Das gleiche Prinzip auch auf andere Funktionen wie z.B. GlobalLock(), GetClipData(), ... anwenden.
    Du darfst niemals davon ausgehen, daß es immer klappt!

    fromClipboard = buffer;
    

    Du bist Dir hoffentlich im Klaren, daß hier kein String kopiert wird?

    Des weiteren gibst Du einen Pointer auf eine lokale Variable zurück, d.h. der Inhalt auf den fromClipboard zeigt ist ungültig, da Lebensdauer nur innerhalb der Funktion!

    string fromClipboard;
    
    ...
    
    return fromClipboard;
    

    HTH,
    Martin



  • hamburger schrieb:

    bitmaps usw wäre egal es geht rein um den text^^

    Es geht ja nicht um ein Bitmap, das du in der Zwischenablage parken willst - es geht um die Daten, die vor deinem Aufruf dort standen 😉 (und das kann alles mögliche sein)


  • Mod

    Zudem würde ich in der heutigen Zeit CF_TEXT vergessen und nur noch CF_UNICODETEXT verwenden.



  • Mmacher schrieb:

    fromClipboard = buffer;
    

    Du bist Dir hoffentlich im Klaren, daß hier kein String kopiert wird?

    Und wieso nicht?



  • Erstmal danke für eure vielen Antworten. Mein Hauptproblem bezog sich nicht dadrauf wenn bitmaps usw in der ablage wären und es dann crashed sondern das es IMMER CRASHED!Als test hatte ich den string TEST in der ablage. Als ich es versuchte auszuführen crashte die App. Ich versuchte das gleich mit 1 zu 1 der selben funktion in einer Consolen Application und dort hat es auf anhieb geklappt. Was mein eigentliches problem ist, ist warum crashed die DLL beim aufruf der funktion und die Consolen app nicht! Mehr wollte ich in der hinsicht nicht wissen! Danke 🙂



  • Und Du wunderst Dich?

    Na klasse, wieso schreiben wir Dir Tipps als Hilfen, wenn Du sie nicht mal ausprobierst?

    Nochmal als Klartext: Bitte werte sämtliche Rückgabewerte von Funktionen auf Plausibilität bzw. Fehler aus!

    Das ist ELEMENTARES BESTANDTEIL der sauberen Programmierung!

    Und hast schon mal mit dem Debugger analysiert?
    Martin

    P.S.: Daß Deine Konsolen-App nicht abstürzt ist höchstwahrscheinlich purer Zufall!



  • yahendrik schrieb:

    Mmacher schrieb:

    fromClipboard = buffer;
    

    Du bist Dir hoffentlich im Klaren, daß hier kein String kopiert wird?

    Und wieso nicht?

    Guck mal in der MSDN Doku zu GetClipboardData(): http://msdn.microsoft.com/en-us/library/ms649039(VS.85).aspx
    Dort ist zu lesen:

    The application should copy the data immediately.

    Dort ist auch ein Link zu einem Beispielprogramm zu finden, in dem genau das Kopieren eines Strings demonstriert wird.

    Gruß
    Martin



  • Mich haben nur deine Aussagegen irritiert.

    Mmacher schrieb:

    Des weiteren gibst Du einen Pointer auf eine lokale Variable zurück, d.h. der Inhalt auf den fromClipboard zeigt ist ungültig, da Lebensdauer nur innerhalb der Funktion!

    string fromClipboard;
    ...
    return fromClipboard;
    

    Es handelt sich hierbei um einen std::string und wo jetzt deiner Meinung nach ein Zeiger zurück gegeben wird, sehe ich auch nicht. Das ist eine wohl definierte Operation, sofern sie nicht über Modulgrenzen hinweggeht.
    Und da sehe ich auch das Problem bei der Sache: Die Benutzung von STL-Objekten zwischen exe und dll, also die Allokation von Speicher im dll-Code und Freigabe in der Anwendung. Dass es klappt, hängt meiner Meinung nach von zu vielen Faktoren ab, erstmal natürlich der gleiche Compiler, vermutlich die gleiche Version (Release/Debug), gleiche Codeerzeugung etc..
    Deshalb würde ich auch davon abraten und nur eingebaute Typen im Dll-Interface verwenden (intern kann selbstverständlich auf beiden Seiten die STL verwendet werden).
    Also aus

    static string GetClipData();
    

    Nun die Version

    size_t GetClipData(char* buf, size_t buflen);
    

    Falls für buf NULL angegeben wurde, wird die Länge des Clipboardinhalts geliefert, andernfalls war die Operation bei einem Wert ungleich 0 erfolgreich.
    Anwender können die Funktion dann so benutzen:

    size_t len = GetClipData(NULL, 0);
    if(len)
    {
      std::vector<char> buf(len+1);
      if(GetClipData(&buf[0], len+1))
      {
        string s = &buf[0];
        ...
      }
    }
    

    Mit einem kommenden C++0x-Compiler kann der Umweg über den vector ausgelassen werden, noch ist aber nicht garantiert, dass der Buffer eines Strings an einem Stück im Speicher liegt.

    Natürlich müssen die Rückgabewerte der Funktionen überprüft werden und vor allen Dingen, wie schon mehrfach geschrieben, geschaut werden, ob das passende Format in der Zwischenablage ist, aber wenn dies der Fall ist, finde ich die Aussage

    MMacher schrieb:

    Daß Deine Konsolen-App nicht abstürzt ist höchstwahrscheinlich purer Zufall!

    etwas weit hergeholt.


Anmelden zum Antworten