Volatile Clipboard für CTRL-C

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Peter329.

    Volatile Clipboard für CTRL-C

    Hi,

    ich muss ein bissl weiter ausholen, um mein Anliegen verständlich zu machen:

    Mit dem Windows Clipboard, kann man bequem Daten aus einer Anwendung in eine andere Anwendung übertragen.

    Daran stört mich aber, dass der Inhalt des Clipboards nicht "von selbst" verschwindet ... sondern im dümmsten Fall bis zum Shutdown erhalten bleibt. Wenn man sensitive Daten eingestellt hat, dann fallen die im Handumdrehen einem Hacker in die Hand ... denn wenn die zum Zug kommen, dann prüfen die meist sofort, was im Clipboard steht !

    Die Idee ist ein "volatile Clipboard" ... also ein Verfahren, dass dafür sorgt, dass sich der Inhalt des Clipboards nach sagen wir mal drei Sekunden verflüchtig.

    Wenn man das Clipboard mit Button-Click oder Feld-DoubleClick befüllt, dann ist das sehr einfach mit einem Delete Timer zu regeln. HIer ein Sample:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    3. Timer1.Interval = 3000 'Autoclear delay is 3 seconds
    4. TextBox1.Text = "hello baby" 'Insert test content
    5. Label1.Text = "" 'Initialize message field
    6. End Sub
    7. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    8. ClipboardSet(TextBox1.Text) 'Set clipboard using button
    9. End Sub
    10. Private Sub TextBox1_DoubleClick(sender As Object, e As EventArgs) Handles TextBox1.DoubleClick
    11. ClipboardSet(TextBox1.Text) 'Set clipboard using double click
    12. End Sub
    13. Private Sub ClipboardSet(strText As String)
    14. Timer1.Enabled = False 'Stop autoclear timer
    15. Clipboard.SetText(strText) 'Fill clipboard
    16. Label1.Text = "OK, Clipboard set."
    17. Timer1.Enabled = True 'Start autoclear timer
    18. End Sub
    19. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    20. Timer1.Enabled = False 'Stop autoclear timer
    21. Dim strClipboard As String = Clipboard.GetText() 'Get clipboard
    22. Clipboard.Clear() 'Remove text from clipboard
    23. If strClipboard.Trim = "" Then 'Display message
    24. Label1.Text = "*** Clipboard is empty."
    25. Else
    26. Label1.Text = "OK, clipboard retrieved."
    27. MessageBox.Show(strClipboard)
    28. End If
    29. End Sub
    30. Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    31. Timer1.Enabled = False 'Stop autoclear timer
    32. Label1.Text = "Clipboard autocleared."
    33. Clipboard.Clear() 'Remove text from clipboard
    34. End Sub
    35. End Class


    So far so good !

    Aber oft befülle ich das Clipboard mit der Tasten Kombination CTRL-C

    Jetzt würde ich gern dafür sorgen, dass auch in diesen Fällen mein Delete-Timer zuschlägt. MIt anderen Worten, wie bringe ich CTRL-C dazu, nicht nur das Clipboard mit dem ausgewählten Text zu befüllen, sondern auch noch den Befehl Timer1.Enabled = True abzusetzen.

    Ich habe zunächst an GetAsyncKeyState gedacht:

    VB.NET-Quellcode

    1. <DllImport("user32.dll")>
    2. Public Shared Function GetAsyncKeyState(ByVal vKey As Keys) As Int16
    3. End Function


    Aber diese Funktion müsste ich ja mit einem Button Click aufrufen ... und dann kann ich gleich den Timer selber starten, ohne den Umweg über GetAsyncKeyState .

    Ich suche also eine Möglichkeit DIREKT auf CTRL-C zu reagieren.

    Ich hoffe, ich habe mein nicht so ganz triviales Anliegen verständlich machen können.

    LG
    Peter

    Dieser Beitrag wurde bereits 15 mal editiert, zuletzt von „Peter329“ ()

    Danke erst mal für die Beiträge.


    @asusdk

    Klar,man kann etwa alle drei Sekunden nachfragen, ob das Clipboard etwas enthält. Dann werden aber auch Eingaben gelöscht, die nicht von meinem Programm eingestellt wurden. Und das scheint mir ein bissl sehr rabiat zu sein.

    Außerdem könnte es sein, dass der Timer gerade abläuft, nachdem ich Daten eingestellt habe ... und dann sind die sofort weg !

    Schade, aber so einfach geht das leider nicht.

    @EpagneulBreton

    Wenn man GetAsyncKeyState ständig prüft, dann mag das ja für eine Anwendung ganz in Ordnung sein ... aber als allgemeingültige Lösung ist das halt nicht ganz so ideal, weil dadurch ein ziemlicher Systemoverhead ausgelöst wird.

    Und auch hier könnte der Timer gerade dann ablaufen, nachdem die Daten eingestellt wurden.

    LG
    Peter

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Peter329“ ()

    Außerdem könnte es sein, dass der Timer gerade abläuft, nachdem ich Daten eingestellt habe ... und dann sind die sofort weg !


    hätte es mir was dies angeht auch etwas anders vorgestellt:

    TimerCheck, mit Interval 100 Prüft ob das Clipboard leer ist, wenn nein, startet es den TimerClear der dann je nach dem wie lange die Daten vorhanden bleiben sollen als Intervall hat, ist dieses dann erreicht, Clipboard.Clear

    Dann werden aber auch Eingaben gelöscht, die nicht von meinem Programm eingestellt wurden. Und das scheint mir ein bissl sehr rabiat zu sein.


    man könnte den TimerClear ausschließlich dann starten wenn bei einer änderung dessen was das Clipboard enthält dein Programm den Focus hatte

    aber soweit auch nur als gedankenspiel ^^
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Na gut, danke erst mal für deine Anregungen.

    Trotzdem, die Idee eine asynchrone Prüfroutine zu starten birgt schon eine Menge Probleme.

    Aber das ist ja auch nicht mein Ziel. Die Frage ist, ob man DIREKT auf das "Ereignis" CTRL-C in MEINER Anwendung reagieren kann. Ich hab mit KEYPRESS und Konsorten herum experimentiert ... aber meine Versuche scheitern alle aus verschiedenen Gründen.

    Dass dies nicht trivial ist, ist mir schon klar. Aber vielleicht hat jemand ja eine zündende Idee.

    LG
    Peter

    P.S.:

    Es gibt natürlich die Möglichkeit den Keyboard Buffer alle paar Millisekunden abzutesten. Damit kriegt man CTRL-C schon zu fassen ... aber das ist halt eine ILLEGALE Lösung. Denn so arbeiten Keyboard Logger Viren. Und damit ist das nichts, was ich einsetzen möche !

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()

    Hallo Peter,
    Keine Lösung, aber als Denkanstoß:
    In einer meiner Anwendungen reagiere ich auf ALT+F12:

    VB.NET-Quellcode

    1. Private Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifier As Integer, ByVal vk As Integer) As Integer
    2. Private Declare Sub UnregisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer)
    3. Private Const Key_NONE As Integer = &H0
    4. Private Const Key_ALT As Integer = &H1
    5. Private Const WM_HOTKEY As Integer = &H312

    Form Load:

    VB.NET-Quellcode

    1. RegisterHotKey(Me.Handle, 1, Key_ALT, Keys.F12)

    Form Closing:

    VB.NET-Quellcode

    1. UnregisterHotKey(Me.Handle, 1)

    und die WndProc muss überschrieben werden:

    VB.NET-Quellcode

    1. Protected Overrides Sub WndProc(ByRef m As Message)
    2. If m.Msg = WM_HOTKEY Then
    3. 'hier dann Text in Zwischenablge
    4. End If
    5. MyBase.WndProc(m)
    6. End Sub


    Die Bezeichnung für Strg findest bestimmt im Netz
    "Hier könnte Ihre Werbung stehen..."

    VB.NET-Quellcode

    1. Private Sub Form_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    2. If e.Control And e.KeyCode = System.Windows.Forms.Keys.C Then
    3. MessageBox.Show("Strg+C wurde gedrückt")
    4. Timer1.enabled = True
    5. End If
    6. End Sub


    damits in der ganzen Form funktioniert halt im Load-Event noch

    VB.NET-Quellcode

    1. Me.KeyPreview = True
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    setzt aber voraus, das die Form den Focus hat, sonst klappt es nicht und wenn ich Peter richtig verstehe, will er wann immer auch Ctrl+C gedrückt wird reagieren und dazu brauchst halt den globalen HotKey
    "Hier könnte Ihre Werbung stehen..."
    setzt aber voraus, das die Form den Focus hat, sonst klappt es nicht und wenn ich Peter richtig verstehe, will er wann immer auch Ctrl+C gedrückt wird reagieren und dazu brauchst halt den globalen HotKey


    @MichaHo naja soweit ich diesen Satz richtig deute:



    Aber das ist ja auch nicht mein Ziel. Die Frage ist, ob man DIREKT auf das "Ereignis" CTRL-C
    in MEINER Anwendung reagieren kann. Ich hab mit KEYPRESS und Konsorten
    herum experimentiert ... aber meine Versuche scheitern alle aus
    verschiedenen Gründen.


    soll es nur in seiner Anwendung so sein, und eben nicht Global, evtl. hab ichs auch falsch interpretiert ^^
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Da habt ihr jetzt recht!

    Man muss natürlich entscheiden, ob man CTRL-C nur lokal oder global abfangen will.

    Mit der Technik von @aususdk haben wir eine lokale Lösung:

    VB.NET-Quellcode

    1. Private Sub Form_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    2. If e.Control And e.KeyCode = Keys.C Then 'CTRL+C depressed
    3. Label1.Text = "Ok, Clipboard set."
    4. Timer1.Enabled = True
    5. End If
    6. End Sub


    Das funktioniert dann auch für die Anwendung hervorragend.

    Mit dem Vorschlag von @MichaHo haben wir einen globalen Ansatz. Ich starte per Autostart ein Programm, dass mir CTRL+F12 als Hotkey einrichtet ... und schon kann ich entscheiden, wie ich das Clipboard befüllen will. Mit CTRL+C nicht-volatil, mit CTRL+F12 volatil.

    Das mit dem "Hotkey" klappt auch prima. Nur weiß ich jetzt nicht, wie ich beim Hotkey Interrupt an die markierten Daten herankomme. Ich muss ja die markierten Daten der Form abrufen, die gerade den Fokus hat. Da komme ich jetzt nicht weiter ....

    LG
    Peter
    @Peter329 So ein Standardwerkzeug gegen die üblichen Benutzergewohnheiten zu programmieren ist unsauber.
    Besser ist es, wie bei Word und Co zu fragen, ob das Clippboard gelöscht werden soll.
    Ich denke mal, dass Du zwischedn zwei Programmen Daten transferieren willst.
    Wenn Du von beiden die Quellen hast, nimm ggf. TCP zur Datenübertragung.
    Wenn Du vom Empfänger die Quellen hast, lösch das Clipboard nach Empfang der Daten.
    Wenn Du vom Sender die Quellen hast, mach was beim Befüllen des Clipboard.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    so jetzt hab ich doch fast einen Tag mit dem "volatilen Clipboard" zugebracht. Hier die Ergebnisse:

    1. RFG hat natürlich Recht, dass man nicht Funktionen des native Windows verfälschen sollte. Zumal es nicht so einfach geht. Die Idee, das Clipboard zu überwachen ist nicht so gut, weil man ja das Clipboard auch mit CTRL-X befüllen kann. Und da sollte sich der Inhalt wohl besser nicht verflüchtigen. Und zum anderen ist es wohl sehr schwierig, den markierten Text aus dem fokussierten Window zu holen ... das sieht mir also eher nach einer Sackgasse aus.

    2. Ich hab dann versucht, die Idee mit dem Hotkey zu verfolgen. Der Hotkey LÖSCHT das Clipboard und gibt eine Meldung aus ... Das ist zwar nicht so ganz das was ich mir unter einem "volatilen Clipboard" vorstelle, aber besser als gar nix.

    Das Coding ist recht einfach ... im Load Event den Hotkey registrieren ... im Closing Event das Dingens deregistrieren ... und in der WinProc das Clipboard löschen und eine Meldung ausgeben. Das klappt auch recht gut aber ....

    ... aber es gibt einige mir unerklärliche Effekte: Der Close der Anwendung dauert jetzt extrem lang (bis zu 30 Sekunden) ... und auch andere triviale Anwendungen (wie etwa notepad.exe) starten auf einmal mit 20 - 30 Sekunden Zeitverzögerung. Woran das liegt, da hab ich keine Ahnung. Ich vermute mal, dass der Bursche (trotz deregister) irgendwo in der WinProc rotiert ... Wie auch immer, so richtig happy bin ich damit natürlich nicht !

    3. Ich hab die Idee mit dem "volatilen Clipboard" jetzt erst mal auf Eis gelegt ... ich schreib mir in einen "Button" der das vermaledeite Clipboard löscht und gut isses ... Mit schönen Ideen ist es halt so wie mit schönen Frauen ... man sollte ihnen nicht hinterher laufen ! :)

    Danke für eure vielen Ratschläge !

    LG
    Peter

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Peter329“ ()