Änderungsverlauf (Erstfassung, veröffentlicht am 21. Aug 2026)
- Erstveröffentlichung
Diesen Artikel zitieren(DOI (registriertes Archiv): 10.5281/zenodo.22176593)
Die folgenden DOIs verweisen auf bereits archivierte Versionen, die vom aktuellen Text abweichen können. Verwenden Sie die URL dieser Seite, um auf den aktuellen Text zu verweisen.
Go Komura (2026). Wie Zwischenablage und Drag-and-Drop funktionieren — OLE-Datenübertragung in Geschäftsanwendungen richtig behandeln. KomuraSoft LLC. https://comcomponent.com/de/blog/windows-clipboard-drag-drop-ole-data-transfer/
- DOI (registriertes Archiv)
- 10.5281/zenodo.22176593
- DOI (zuletzt registrierte Version)
- 10.5281/zenodo.22176594
„Wenn wir eine Tabelle aus Excel einfügen, fällt die Formatierung auseinander.“ „Inhalt, den wir in unserer App kopieren, kommt in Word nicht so an, wie wir es wollen.“ „Wir wollen Dateien per Drag-and-Drop aufnehmen.“ — Solche Anfragen kommen bei der Überarbeitung von Geschäftsanwendungen häufig.
Alles das sind alltägliche Vorgänge. Denkt man die Zwischenablage aber als „Kiste für ein Datenstück“, liest man den Mechanismus falsch. Tatsächlich legt sie denselben Inhalt gleichzeitig in mehreren Formaten ab, und die Einfügeseite wählt das Format, das sie versteht. Deshalb erzeugt dieselbe Kopie je nach Einfügeziel verschiedene Ergebnisse.
Dass Einfügen nach dem Schließen der Quelle fehlschlägt, hängt mit „verzögertem Rendering“ zusammen: Die Daten entstehen erst, wenn sie gebraucht werden. Und OLE-Drag-and-Drop (D&D) übergibt IDataObject — dieselbe Datendarstellung wie die OLE-Zwischenablage — über COM-Schnittstellen. Kopieren und Einfügen und D&D sind verwandte Funktionen: Sie teilen das Datenformat und unterscheiden sich in der Art des Transports.
Dieser Artikel richtet sich an IT-Verantwortliche in kleinen und mittleren Unternehmen und an Entwickler von Windows-Apps. Zuerst geht es um die Formate, dann um die Umsetzung auf Einfüge-, Kopier- und Überwachungsseite, danach um die Verwaltung von Verlauf, Synchronisierung und RDP sowie um die Fallstricke von OLE-D&D.
1. Zuerst das Fazit
Drei Achsen sollte man im Blick behalten.
- Die Kopierseite bietet mehrere Formate an, die Einfügeseite wählt daraus. Grundlegend sind
CF_UNICODETEXTfür Text,CF_HDROPfür eine Liste von Dateipfaden und das registrierte Format „HTML Format“ für formatierten Text.1234 - Entwerfen Sie nicht nur das Format der Daten, sondern auch Prüfung und Lebensdauer. Behandeln Sie eingefügte Daten als nicht vertrauenswürdige externe Eingabe. Eine Kopierseite mit verzögertem Rendering setzt auch die Materialisierung beim Beenden um. Überwachen Sie mit
AddClipboardFormatListenerundWM_CLIPBOARDUPDATE, und fangen Sie Lesekonflikte mit erneuten Versuchen ab.5678 - Machen Sie klar, wie weit die Daten reisen und was nach der Übergabe geschieht. Verlauf, Cloud-Synchronisierung und RDP-Umleitung sind Verwaltungsgegenstände. OLE-D&D verlangt STA-Initialisierung durch
OleInitialize, und ein Ablegen von gewöhnlichen Rechten auf eine erhöhte App blockiert UIPI. Außerdem istMoveein Vertrag, unter dem die Originaldaten verschwinden.910111213
Wer nach Ziel lesen will, beginnt beim folgenden Kapitel.
| Problem oder Ziel | Zuerst prüfen | Kapitel |
|---|---|---|
| Eine eingefügte Excel-Tabelle fällt auseinander | Die Formate, die die Kopierseite anbietet, und das Format, das die Einfügeseite wählt | Kapitel 2–4 |
| Eine Kopie aus unserer App auch in anderen Apps nutzbar machen | Mehrere Formate anbieten und die Daten nach dem Beenden behalten | Kapitel 5 |
| Eine Kopie erkennen und automatisch aufnehmen | Listener-Registrierung und erneute Leseversuche | Kapitel 6 |
| Geheimnisse aus Verlauf, Synchronisierung und RDP heraushalten | Ausschlussformate auf der App-Seite und organisatorische Richtlinie | Abschnitt 6.3, Kapitel 7 |
| D&D umsetzen; es scheitert nur im erhöhten Zustand | OLE-Initialisierung, die Rechtegrenze, Effekte und Pfadprüfung | Kapitel 8–9 |
In der Abbildung kennzeichnet eine durchgezogene Linie eine stets geltende Beziehung und eine gestrichelte Linie eine bedingte (die Bedingungen stehen bei jeder Beziehung auf der Detailseite). Die vollständige Liste der Beziehungen (20 insgesamt, mit Beleg und Sicherheitsgrad) und die Definitionen der wichtigsten Konzepte sind auf der Detailseite der Wissenskarte (auf Japanisch) zusammengestellt. Daten: JSON-LD / Turtle
2. Was die Zwischenablage wirklich ist — nicht „ein Datenstück“, sondern „derselbe Inhalt in mehreren Formaten“
Die Zwischenablage ist ein Mechanismus zum Teilen von Daten zwischen Apps. Apps auf demselben Desktop können sie nutzen, aber die genaue Einheit des Teilens ist die Fensterstation. Eine andere Benutzersitzung oder RDP-Sitzung hat jeweils eine eigene Zwischenablage. Dass Kopieren und Einfügen über RDP funktioniert, liegt daran, dass die Umleitung die beiden verbindet (Kapitel 7).
Das übergeordnete Prinzip ist, dass die Nutzung vom Benutzer ausgeht. Die offizielle Entwurfsposition ist, Daten nicht ohne Wissen des Benutzers hinein- oder herauszulegen.1
Nach dem Leeren der Zwischenablage legt die Kopierseite denselben Inhalt in mehreren Formaten ab, vom ausdrucksstärksten abwärts.6 Das Kopieren einer Tabelle in einer Tabellenkalkulation sieht begrifflich so aus.
| Rang | Format | Inhalt |
|---|---|---|
| 1 | Privates App-Format | Vollständige interne Darstellung einschließlich Formeln und Formatierung (zum Einfügen in dieselbe App) |
| 2 | HTML Format | Ein HTML-Fragment, das Tabellenstruktur und Formatierung behält |
| 3 | CSV | Zellgetrennter Text |
| 4 | CF_UNICODETEXT | Tabulatorgetrennter einfacher Text |
| 5 | Bildformat | Ein Bitmap davon, wie die Tabelle aussieht |
Was die Einfügeseite herausholt, ist das Format, das sie versteht, aus dieser Liste. Word erhält eine formatierte Tabelle und der Editor tabulatorgetrennten Text, weil die beiden verschiedene Formate gewählt haben.
Mit anderen Worten: „Das Ergebnis hängt vom Einfügeziel ab“ ist für sich kein Fehler. Man muss Angebot der Kopierseite und Wahl der Einfügeseite zusammen betrachten.
flowchart TB
accTitle: Wie dieselbe Kopie je nach Einfügeziel verschiedene Ergebnisse erzeugt
accDescr: Die Kopierseite legt denselben Inhalt in mehreren Formaten auf die Zwischenablage, und die Einfügeseite wählt das Format, das sie versteht; Word erhält daher eine formatierte Tabelle und der Editor tabulatorgetrennten Text
copy["Kopierseite: Tabellenkalkulation"] --> cb["Zwischenablage (derselbe Inhalt in mehreren Formaten)"]
cb --> f1["Privates App-Format"]
cb --> f2["HTML Format"]
cb --> f3["CSV"]
cb --> f4["CF_UNICODETEXT"]
f2 -->|"Word wählt dieses"| word["Formatierte Tabelle"]
f4 -->|"Editor wählt dieses"| notepad["Tabulatorgetrennter Text"]
Umgekehrt lassen sich die Eingangsklagen — „die Formatierung fällt auseinander“, „es wird etwas Seltsames eingefügt“ — fast alle auf die Wahl oder das Angebot der Formate auf einer der beiden Seiten zurückführen. Kapitel 4 behandelt die Einfügeseite, Kapitel 5 die Kopierseite.
3. Standardformate und registrierte Formate — CF_UNICODETEXT, CF_HDROP, HTML Format
3.1. Standardformate — für Text die Unicode-Seite nutzen
Formate, die das Betriebssystem im Voraus definiert, heißen Standardformate. In Geschäftsanwendungen tauchen vor allem die folgenden auf.2
| Format | Wert | Inhalt |
|---|---|---|
| CF_TEXT | 1 | ANSI-Text (codepageabhängig) |
| CF_UNICODETEXT | 13 | Unicode-Text. Das kanonische Format für Text ist dieses |
| CF_HDROP | 15 | Eine Liste von Dateipfaden (ein HDROP-Handle) |
| CF_DIB | 8 | Ein geräteunabhängiges Bitmap |
| CF_LOCALE | 16 | Die dem Text zugeordnete Gebietsschema-Kennung |
CF_TEXT und CF_UNICODETEXT sind „synthetisierte Formate“, zwischen denen das System implizit umwandelt. Die Umwandlung nutzt die CF_LOCALE zugeordnete Codepage.2
Zeichen, die ANSI nicht darstellen kann, gehen bei der Umwandlung jedoch verloren. Bei Unicode-eigenen Symbolen, kombinierenden Zeichen und Ähnlichem führt das Überlassen an die Umwandlung zu Zeichensalat. Die Regel lautet: Lesen und Schreiben der App auf CF_UNICODETEXT vereinheitlichen, in .NET auf DataFormats.UnicodeText.
flowchart LR
accTitle: Implizite Umwandlung zwischen CF_UNICODETEXT und CF_TEXT
accDescr: Die App liest und schreibt nur CF_UNICODETEXT; das System synthetisiert CF_TEXT durch implizite Umwandlung mit der Codepage von CF_LOCALE. Zeichen, die ANSI nicht darstellen kann, fallen bei dieser Umwandlung weg
apprw["Lesen und Schreiben der App"] --> uni["CF_UNICODETEXT (kanonisch)"]
uni <-->|"System wandelt implizit um (Codepage von CF_LOCALE)"| ansi["CF_TEXT (ANSI, codepageabhängig)"]
ansi -.-> loss["Nicht darstellbare Zeichen fallen bei der Umwandlung weg (Nährboden für Zeichensalat)"]
3.2. CF_HDROP — Dateien reisen als „Liste von Pfaden“
CF_HDROP ist das, was der Datei-Explorer für Dateikopien und D&D nutzt. Zuerst merken: Was reist, ist eine Liste vollständiger Pfade, nicht die Dateien selbst.
Am Anfang des Speicherblocks steht eine DROPFILES-Struktur, danach Pfadzeichenfolgen, getrennt durch NUL-Zeichen. Am Ende steht eine leere Zeichenfolge, der Block endet also mit einem „doppelten NUL“. Im Header ist pFiles der Startversatz der Pfadliste und fWide gibt an, ob die Zeichenfolgen Unicode sind.3
[DROPFILES header: pFiles=start offset of the path list, fWide=1 (Unicode)]
C:\data\a.txt(NUL)C:\data\b.txt(NUL)(NUL)
Im nativen Code holt man sie einzeln mit DragQueryFile; in .NET kommen sie als string[] über DataFormats.FileDrop. Dass „nur Pfade reisen, nicht die Dateien selbst“, wirkt in Kapitel 8 und 9 beim D&D erneut.
flowchart TB
accTitle: Speicherblockstruktur von CF_HDROP
accDescr: Am Anfang des globalen Speichers steht eine DROPFILES-Struktur; pFiles gibt den Startversatz der Pfadliste an und fWide, ob Unicode vorliegt. Danach folgen NUL-getrennte vollständige Pfade, abgeschlossen durch eine leere Zeichenfolge als doppeltes NUL. Es reisen nur Pfade, nicht die Dateien selbst
hdr["DROPFILES-Struktur (pFiles = Startversatz der Liste / fWide = 1)"] --> p1["C:\\data\\a.txt + NUL"]
p1 --> p2["C:\\data\\b.txt + NUL"]
p2 --> tail["Abschließende leere Zeichenfolge (doppeltes NUL)"]
hdr -.-> note["Es reisen nur Pfade, nicht die Dateien selbst"]
3.3. Registrierte Formate — RegisterClipboardFormat und „HTML Format“
Daten, die Standardformate nicht ausdrücken können, lassen sich unter einem selbst gewählten Namen als registriertes Format teilen. Man übergibt einen Namen an RegisterClipboardFormat und erhält eine Format-ID. Dieselbe Namensregistrierung in einer anderen App liefert dieselbe ID, die Verständigung über den Namen ist also der Kontaktpunkt zwischen Apps.1
Beim Austausch strukturierter Daten in der eigenen App-Familie nimmt man einen Namen, der nicht kollidiert, etwa KomuraSoft.Report.RowData.
HTML Format ist „UTF-8 mit Header“
Das repräsentative registrierte Format ist „HTML Format“, ein Format für formatierten Text neben RTF. Der Rumpf ist UTF-8-Text, vorn hängt jedoch ein Header mit Byteversätzen.4
Version:0.9
StartHTML:<byte position where the whole HTML starts>
EndHTML:<byte position where the whole HTML ends>
StartFragment:<byte position where the fragment starts>
EndFragment:<byte position where the fragment ends>
<html><body>
<!--StartFragment--><b>Fett</b> Fragmenttext<!--EndFragment-->
</body></html>
Jeder Versatz wird vom Anfang der Daten einschließlich des Headers selbst gemessen. StartHTML / EndHTML zeigen auf das gesamte HTML, StartFragment / EndFragment auf Anfang und Ende des vom Benutzer gewählten Fragments. Die Einheit ist Bytes, nicht Zeichen.
Beim Erzeugen setzt man es in dieser Reihenfolge zusammen.
- Die Versatzfelder in fester Breite reservieren (zum Beispiel 10 Stellen).
- Den HTML-Rumpf bauen und als UTF-8 kodieren.
- Die Bytepositionen nach der Kodierung messen und in den Header zurückschreiben.
In UTF-8 mit japanischen Zeichen stimmen Zeichenzahl und Bytezahl nicht überein. Vertauscht man das, fehlt beim Einfügen in eine andere App der Anfang oder das Ende.4
flowchart TB
accTitle: Wie der Header von HTML Format zu den Versätzen steht
accDescr: Im Header zeigen StartHTML und EndHTML auf das gesamte HTML und StartFragment und EndFragment auf das vom Benutzer gewählte Fragment, jeweils als Bytepositionen vom Anfang der Daten. Weil Zeichenzahl und Bytezahl in UTF-8 auseinanderlaufen, füllt man sie mit Bytepositionen, die nach der Kodierung gemessen werden
header["Header (Version / StartHTML / EndHTML / StartFragment / EndFragment)"] --> html["Gesamtes HTML (StartHTML bis EndHTML)"]
html --> frag["Gewähltes Fragment (StartFragment bis EndFragment)"]
header -.-> byte["Jeder Versatz = Byteposition vom Anfang der Daten (nach UTF-8-Kodierung gemessen und zurückgeschrieben)"]
Daneben wird für tabellarische Daten häufig CSV (DataFormats.CommaSeparatedValue in .NET) genutzt. Für die Zusammenarbeit mit Excel funktioniert das gleichzeitige Anbieten von HTML Format (formatiert), CSV (nur Werte) und CF_UNICODETEXT (tabulatorgetrennt) unabhängig vom Einfügeziel.
4. Praktiken auf der Einfügeseite — Formatpriorität und Prüfung
4.1. Von den reichen Formaten abwärts suchen
Die Einfügeseite sucht unter den Formaten, die sie verarbeiten kann, vom informationsreichsten an. Man kann die Reihenfolge nutzen, in der die Kopierseite die Formate vom ausdrucksstärksten abwärts abgelegt hat, oder eine eigene Prioritätsliste angeben.6
| Win32-API | Art der Wahl |
|---|---|
EnumClipboardFormats |
Zählt in der Ablagereihenfolge der Kopierseite auf; das erste erkannte Format verwenden |
GetPriorityClipboardFormat |
Wählt ein verfügbares Format aus der Prioritätsliste, die die Einfügeseite übergibt |
In .NET sieht die Verzweigung so aus.
// Tabelleneinfügen: von reich nach einfach suchen
var data = Clipboard.GetDataObject();
if (data is null) return;
// Ein beworbenes Format garantiert nicht, dass die Nutzlast ein string ist. Diesen
// Zweig nur nutzen, wenn auch der Typ stimmt; sonst zum nächsten Kandidaten fallen
if (data.GetDataPresent(DataFormats.Html)
&& data.GetData(DataFormats.Html) is string html)
{
// Header von HTML Format prüfen, dann als Tabelle aufnehmen
}
else if (data.GetDataPresent(DataFormats.CommaSeparatedValue))
{
// Als CSV aufnehmen
}
else if (data.GetDataPresent(DataFormats.UnicodeText))
{
// Als tabulatorgetrennten Text aufnehmen
}
Das ist die Antwort auf die Eingangsklage, eine eingefügte Excel-Tabelle falle auseinander. Tabellenstruktur erreicht eine App nie, die nur einfachen Text liest. Wie weit man die Formate akzeptiert, ist eine Entwurfsentscheidung der Einfügeseite.
flowchart TB
accTitle: Einfügeverzweigung, die von reichen Formaten abwärts sucht
accDescr: Ist HTML Format vorhanden und die Nutzlast ein string, als Tabelle aufnehmen; sonst CSV; fehlt auch das, tabulatorgetrennter Text, vom ausdrucksstärksten Format abwärts. Ist kein Kandidat da, ablehnen
startsel["Einfügen beginnen"] --> h{"HTML Format vorhanden und Nutzlast ein string?"}
h -->|"Ja"| useh["Header prüfen und als Tabelle aufnehmen"]
h -->|"Nein"| c{"CSV vorhanden?"}
c -->|"Ja"| usec["Als CSV aufnehmen"]
c -->|"Nein"| t{"UnicodeText vorhanden?"}
t -->|"Ja"| uset["Als tabulatorgetrennten Text aufnehmen"]
t -->|"Nein"| giveup["Ablehnen"]
4.2. Eingefügte Daten sind externe Eingabe
Das wird leicht übersehen, aber der Inhalt der Zwischenablage ist externen Ursprungs, und man weiß nicht, welche App ihn abgelegt hat. Microsoft selbst warnt in der Dokumentation zur OLE-Zwischenablage, Zwischenablagedaten seien nicht vertrauenswürdig und vor der Nutzung in der App sorgfältig zu parsen.5
Dass ein Format vorhanden ist, sagt noch nicht, dass sich die Daten aufnehmen lassen. Prüfen Sie auch den Typ der eigentlichen Nutzlast und führen Sie die folgenden Prüfungen aus.
| Was zu prüfen ist | Was zu kontrollieren ist |
|---|---|
| Der Header von HTML Format | Ob die Versätze außerhalb des Bereichs zeigen. Manche Apps erzeugen kaputte Header |
| Werte wie Zahlen, Daten und Codes | Ob sie dieselbe Validierung bestehen wie eine Eingabe am Bildschirm |
| Die Größe der Daten | Ob sie die Annahmegrenze überschreiten, etwa bei Bildern von Hunderten Megabyte oder Text mit Millionen Zeilen |
Beachten, dass die Materialisierung beginnt, bevor sich die Größe prüfen lässt
Bei Abwehr gegen riesige Daten unterscheidet man, welche Last welcher Stufe sich verhindern lässt. GetData in .NET löst beim Aufruf auch verzögertes Rendering aus und materialisiert Text bis zu einer verwalteten Zeichenfolge. Eine Größenprüfung erst nach dem Abruf verhindert die Last dieser Materialisierung nicht.
Prüft man das von Win32-GetClipboardData zurückgegebene HGLOBAL mit GlobalSize, lässt sich abwehren, dass riesige Daten in die Umwandlung in eine verwaltete Zeichenfolge und ins Parsen weitergeschoben werden. Bei Formaten mit verzögertem Rendering löst GetClipboardData selbst jedoch das Rendern aus. Dass die Kopierquelle die Daten selbst materialisiert, lässt sich nicht verhindern.
Damit die Oberfläche nicht einfriert, verlegt man den Abruf vom UI-Thread weg und lehnt Daten über der Grenze ab. Auch dann verlangt Clipboard in .NET STA. Nutzen Sie einen eigenen Thread, der auf STA gesetzt ist, nicht den Threadpool (MTA) von Task.Run (Abschnitt 5.1).
Der Gedanke, dass „ein Wert von außen vor der Nutzung geprüft wird, unabhängig vom Weg“, ist derselbe wie in „Verwenden Sie den ausgelesenen Wert eines QR-Codes nie ungeprüft“. Die Annahme, Einfügen sei sicher, weil es eine Benutzerhandlung ist, ist der Weg in den Unfall.
flowchart LR
accTitle: Eingefügte Daten prüfen, bevor man sie nutzt
accDescr: Daten aus der Zwischenablage durchlaufen nacheinander Prüfungen auf Vorhandensein des Formats, Typ der Nutzlast, Größengrenze und Inhalt; scheitert eine Prüfung, ablehnen oder zum nächsten Kandidatenformat fallen
present["Vorhandensein des Formats prüfen (GetDataPresent)"] --> type["Typ der Nutzlast prüfen (is string / string[])"]
type --> size["Größengrenze prüfen"]
size --> content["Inhalt prüfen (Header, Pfade, Werte)"]
content --> ok["Aufnehmen"]
type -.->|"Falscher Typ"| rej["Ablehnen / nächstes Kandidatenformat"]
size -.->|"Zu groß"| rej
content -.->|"Ungültig"| rej
5. Praktiken auf der Kopierseite — mehrere Formate gleichzeitig anbieten und verzögertes Rendering
5.1. Mehrere Formate gleichzeitig ablegen
Die Praxis der Kopierseite ist das Spiegelbild von 4.1: ein reiches Format und ein einfaches Format gleichzeitig anbieten. Mit dem DataObject von WinForms/WPF sind es wenige Zeilen.14
// WinForms (System.Windows.Forms). WPF hat dieselbe Form mit DataObject/Clipboard in System.Windows
var data = new DataObject();
data.SetData(DataFormats.Html, htmlFormatText); // HTML-Format-Zeichenfolge mit Header
data.SetData(DataFormats.CommaSeparatedValue, csv); // CSV
data.SetData(DataFormats.UnicodeText, plainText); // Einfacher Text
Clipboard.SetDataObject(data, copy: true); // copy:true = nach dem Beenden der App behalten
Hier trennen wir die Thread-Bedingung und die Lebensdauer nach dem Beenden.
Thread-Bedingung: Die Clipboard-Klasse in .NET lässt sich nur von einem STA-Thread nutzen.14 Der UI-Thread von WinForms/WPF ist durch [STAThread] STA, das ist also normalerweise kein Problem; von einem Hintergrundthread, der nicht STA ist, geht es nicht. Den Hintergrund erklärt „Grundlagenwissen zu COM STA/MTA“.
Lebensdauer nach dem Beenden: copy: true bedeutet „nach dem Beenden der App behalten“. Zusammen mit dem folgenden verzögerten Rendering wird klar, warum diese Angabe nötig ist.
5.2. Verzögertes Rendering — warum „schließen und nicht mehr einfügen“
Alle Formate bei jedem Kopieren zu erzeugen heißt, auch für Formate zu arbeiten, die nie genutzt werden. Der Mechanismus, der das vermeidet, ist verzögertes Rendering (delayed rendering).6
Zur Kopierzeit übergibt man NULL als Datenhandle an SetClipboardData und registriert nicht die Daten selbst, sondern das Versprechen, sie „auf Anfrage zu erzeugen“. Wird das Format angefordert, kommt WM_RENDERFORMAT bei der Kopierquelle an, und erst dann entstehen die Daten.
Beim Beenden das „Versprechen“ in Daten verwandeln
Beendet sich die Kopierquelle mit noch nicht gerenderten Formaten, kann die Einfügeseite diese Daten nicht mehr empfangen. Das ist das Problem „Quelle schließen und nicht mehr einfügen“.
Vor dem Beenden ist die Kopierquelle dafür verantwortlich, auf WM_RENDERALLFORMATS zu antworten und jedes noch nicht gerenderte Format zu materialisieren. Formate, die nicht materialisiert wurden, gehen mit dem Beenden der Kopierquelle verloren.6
flowchart TB
accTitle: Ablauf des verzögerten Renderings und „schließen und nicht mehr einfügen“
accDescr: Die Kopierquelle registriert mit einem NULL-Handle nur ein Versprechen und materialisiert die Daten bei Anfrage mit WM_RENDERFORMAT. Beim Beenden muss sie jedes Format mit WM_RENDERALLFORMATS materialisieren; unterbleibt das, geht das Format verloren
promise["Kopierquelle: nur ein Versprechen mit SetClipboardData(format, NULL) registrieren"] --> req["Einfügeseite fordert dieses Format an"]
req --> render["WM_RENDERFORMAT → Daten an Ort und Stelle erzeugen"]
promise --> quit["Kopierquelle steht kurz vor dem Beenden"]
quit -->|"Mit WM_RENDERALLFORMATS materialisieren"| ok["Einfügen funktioniert nach dem Beenden weiter"]
quit -->|"Materialisierung unterlassen"| lost["Dieses Format geht verloren (schließen und nicht mehr einfügen)"]
Auf der OLE-Zwischenablage legt man ein IDataObject mit OleSetClipboard ab. Was die Zwischenablage dann hält, ist ein Zeiger auf das Datenobjekt.
Der Aufruf von OleFlushClipboard beim Beenden materialisiert die Daten auf der Zwischenablage, sodass Einfügen nach dem Beenden weiter funktioniert.7 Clipboard.SetDataObject(data, copy: true) in .NET legt genau dieses „nach dem Beenden behalten“ fest.
Wenn Sie in Excel einen großen Bereich kopieren und dann beenden, ist die Frage, ob die große Information auf der Zwischenablage behalten werden soll, die Bestätigung, ob diese Materialisierung (der Flush) ausgeführt wird. Auch in der eigenen App entwirft man verzögertes Rendering und die Materialisierung beim Beenden als Satz.
Verzögern garantiert nicht, dass die Oberfläche reagiert bleibt
Verzögertes Rendering ist eine Leistungsoptimierung, aber das Erzeugen der angeforderten Daten läuft synchron in der Nachrichtenverarbeitung. Der Kompromiss ist, dass die Oberfläche einfriert, wenn das Erzeugen lange dauert.6
6. Praktiken für die Überwachung der Zwischenablage — Listener, erneuter Versuch und Ausschluss aus dem Verlauf
6.1. AddClipboardFormatListener nutzen
Anforderungen wie „den Wert eines Barcodelesers oder eine Kopie aus dem Kernsystem erkennen und automatisch aufnehmen“ verlangen die Überwachung von Änderungen der Zwischenablage. Historisch gibt es drei Methoden, heute eine richtige Antwort.8
| Methode | Bewertung |
|---|---|
| Periodisch per Timer lesen (Polling) | Verschwenderisch und kann Änderungen verpassen. Nicht nutzen |
| SetClipboardViewer (Viewer-Kette) | Ein Fehler in einer App der Kette zerstört die ganze Kette. Nur aus Abwärtskompatibilität behalten |
| AddClipboardFormatListener | Empfohlen. WM_CLIPBOARDUPDATE wird an das registrierte Fenster zugestellt |
flowchart LR
accTitle: Ablauf der Zwischenablageüberwachung
accDescr: Bei Handle-Erzeugung mit AddClipboardFormatListener registrieren, und WM_CLIPBOARDUPDATE kommt, welche App auch kopiert. Mit erneuten Versuchen lesen und beim Zerstören des Handles symmetrisch mit RemoveClipboardFormatListener abmelden
created["OnHandleCreated: AddClipboardFormatListener"] --> wait["Warten"]
anyapp["Irgendeine App kopiert"] --> notify["WM_CLIPBOARDUPDATE trifft ein"]
wait --> notify
notify --> readtry["Mit erneuten Versuchen lesen (Abschnitt 6.2)"]
readtry --> wait
destroyed["OnHandleDestroyed: RemoveClipboardFormatListener"] -.->|"Symmetrisch abmelden"| created
// Minimale WinForms-Umsetzung
public partial class MainForm : Form
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
const int WM_CLIPBOARDUPDATE = 0x031D;
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
AddClipboardFormatListener(Handle);
}
protected override void OnHandleDestroyed(EventArgs e)
{
// Symmetrisch abmelden, passend zu Zerstörung und Neuaufbau des Handles
RemoveClipboardFormatListener(Handle);
base.OnHandleDestroyed(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_CLIPBOARDUPDATE)
{
// Hier Clipboard.GetDataObject() lesen und aufnehmen, wenn das Format gebraucht wird
}
base.WndProc(ref m);
}
}
6.2. Erneut versuchen, wenn sich die Zwischenablage nicht öffnen lässt
Nur ein Fenster zur Zeit kann die Zwischenablage öffnen. Solange ein anderer Prozess sie offen hat, schlägt OpenClipboard fehl.6
Direkt nach WM_CLIPBOARDUPDATE kann die Kopierquelle oder eine andere überwachende App noch damit arbeiten. Ein vorübergehender Lesefehler ist ein normales Ereignis; man baut Logik ein, die einige Dutzend Millisekunden wartet und einige Male erneut versucht.
In .NET gibt es Überladungen mit Wiederholungszahl und Abstand nur auf der Schreibseite, SetDataObject. Die Leseseite, GetDataObject und Ähnliches, hat keine.
| Leseseite | Umgang mit Konkurrenz |
|---|---|
| WinForms | ExternalException fangen, warten und erneut versuchen |
| WPF | COMException fangen, warten und erneut versuchen |
Warten und erneuter Versuch beim Lesen werden auf der App-Seite umgesetzt.
flowchart LR
accTitle: Ablauf erneuter Leseversuche auf der Zwischenablage
accDescr: Nur ein Fenster zur Zeit kann die Zwischenablage öffnen, daher kann ein Lesen direkt nach der Änderungsbenachrichtigung durch Konkurrenz mit einem anderen Prozess fehlschlagen. Bei einer Ausnahme einige Dutzend Millisekunden warten und erneut versuchen; ist die Grenze erreicht, diesmal aufgeben und beim nächsten Update aufnehmen
upd["WM_CLIPBOARDUPDATE"] --> tryread["Lesen versuchen"]
tryread -->|"Erfolg"| useok["Aufnehmen (Prüfung in Kapitel 4)"]
tryread -->|"Fehler (ein anderes Fenster nutzt sie)"| waitretry["Einige Dutzend Millisekunden warten"]
waitretry -->|"Einige Male erneut versuchen"| tryread
waitretry -->|"Grenze erreicht"| giveup2["Diesmal aufgeben (beim nächsten Update aufnehmen)"]
6.3. Aus Verlauf und Synchronisierung heraushalten — Rücksicht bei Kopierfunktionen, die Geheimnisse tragen
Windows hat Zwischenablageverlauf (Win+V) und geräteübergreifende Synchronisierung (Cloud-Zwischenablage), und Daten, die eine App ablegt, unterliegen standardmäßig beidem. Eine App, deren Kopierfunktion Geheimnisse wie Kennwörter oder Kontonummern trägt, legt zusätzlich ein registriertes Format ab, das die Daten aus Verlauf und Synchronisierung ausschließt.1
| Registriertes Format | Was es unterdrückt |
|---|---|
ExcludeClipboardContentFromMonitorProcessing |
Schließt den gesamten kopierten Inhalt aus Verlauf und geräteübergreifender Synchronisierung aus |
CanIncludeInClipboardHistory (DWORD 0) |
Nur Verlauf |
CanUploadToCloudClipboard (DWORD 0) |
Nur geräteübergreifende Synchronisierung |
Kennwortmanager halten kopierte Kennwörter mit diesem Mechanismus aus Win+V heraus. Es genügt, den Namen an RegisterClipboardFormat zu übergeben, eine Format-ID zu erhalten und sie neben die gewöhnlichen Daten zu setzen; in Geschäftsanwendungen, die Geheimnisse behandeln, lohnt sich die Umsetzung.
7. Die Zwischenablage aus IT-Sicht — Verlauf, Cloud-Synchronisierung und RDP steuern
Was die App mit kopiertem Inhalt tut und was die Organisation insgesamt zulässt, sind getrennte Fragen. Ein Administrator betrachtet drei Dinge: Verlauf, Cloud-Synchronisierung und RDP-Umleitung.
Der Zwischenablageverlauf sammelt kürzlich kopierten Inhalt. Die Cloud-Zwischenablage synchronisiert ihn zwischen Geräten, die mit demselben Microsoft-Konto oder Microsoft-Entra-Konto angemeldet sind.10
So praktisch das ist, entstehen Rückstände und Übertritt: Personenbezogene Daten aus dem Kernsystem bleiben im Verlauf, oder auf dem Dienst-PC kopierter Inhalt synchronisiert auf einen privaten PC.
7.1. Verlauf und geräteübergreifende Synchronisierung steuern
Die zwei Richtlinien für die organisatorische Steuerung sind diese.
| Was gesteuert wird | GPO (Computerkonfiguration > Administrative Vorlagen > System > Betriebssystemrichtlinien) | Policy CSP (Intune) | Vorgabe |
|---|---|---|---|
| Zwischenablageverlauf | Zwischenablageverlauf zulassen | Experience/AllowClipboardHistory | Zugelassen |
| Geräteübergreifende Synchronisierung | Zwischenablagesynchronisierung zwischen Geräten zulassen | Privacy/AllowCrossDeviceClipboard | Zugelassen |
Beide sind ab Windows 10 Version 1809 verfügbar; bei Deaktivierung werden die entsprechenden Einträge in der Einstellungen-App ausgegraut, und die Richtlinie greift sofort.910
7.2. Übertragung zwischen RDP-Sitzungen steuern
Die Zwischenablageumleitung von RDP (Remotedesktop) verbindet den lokalen PC und die Remote-Sitzung. Weil Kopieren und Einfügen standardmäßig funktioniert, kann das auch ein Weg werden, Geheimnisse von einem Server wegzutragen.
Die Einstellung, die beide Richtungen blockiert, ist die Richtlinie „Zwischenablageumleitung nicht zulassen“ (Registrierungswert fDisableClip).11
Neuere Windows-Server- und Windows-11-Versionen haben außerdem Richtlinien für feinere Steuerung ergänzt, etwa die Begrenzung nur der Richtung Server zu Client auf Text. Ob man es ganz verbietet oder Richtung und Format stufenweise einschränkt, ist eine Abwägung zwischen Betrieb und Sicherheit.
flowchart LR
accTitle: Wege, auf denen Zwischenablageinhalt sich ausbreitet, und die Steuerpunkte
accDescr: Kopierter Inhalt unterliegt standardmäßig Verlauf und Cloud-Synchronisierung, und über RDP gelangt er durch Umleitung in eine andere Sitzung. Jedes lässt sich per Richtlinie steuern, und die App-Seite kann Inhalt mit den Ausschlussformaten aus Verlauf und Synchronisierung heraushalten
cb["Zwischenablage"] --> hist["Verlauf (Win+V)"]
cb --> cloud["Cloud-Synchronisierung → anderes Gerät"]
cb --> rdp["RDP-Umleitung → andere Sitzung"]
hist -.-> p1["Steuerung: AllowClipboardHistory"]
cloud -.-> p2["Steuerung: AllowCrossDeviceClipboard"]
rdp -.-> p3["Steuerung: fDisableClip"]
cb -.-> p4["App-Seite: mit ExcludeClipboardContentFromMonitorProcessing und Ähnlichem ausschließen (Abschnitt 6.3)"]
8. Drag-and-Drop ist COM — IDataObject + IDropSource + IDropTarget
8.1. Dieselben Daten wie die Zwischenablage, anders getragen
OLE-Drag-and-Drop läuft über die folgenden drei Rollen.15
| Rolle | Umgesetzt von | Aufgabe |
|---|---|---|
| IDataObject | Ziehquelle | Die getragenen Daten. Dasselbe mehrformatige Datenobjekt wie die Zwischenablage |
| IDropSource | Ziehquelle | Entscheiden, ob das Ziehen weitergeht oder abgebrochen wird, und Cursor-Rückmeldung |
| IDropTarget | Ablegeziel | Annahme erklären und die Daten in DragEnter/DragOver/DragLeave/Drop entgegennehmen |
Der Ablauf ist wie folgt.
- Die Ziehquelle ruft
DoDragDropauf und startet die Ziehschleife. - Tritt die Maus in ein Ablegeziel-Fenster, wird
IDropTargetbenachrichtigt. - Das Ablegeziel erklärt, ob es annimmt, und holt beim Ablegen das benötigte Format aus dem
IDataObject.
Die offizielle Dokumentation erklärt auch, dass D&D dieselbe Funktion wie Kopieren und Einfügen der Zwischenablage bereitstellt und eine App, die Kopieren und Einfügen bereits umsetzt, nur eine kleine Ergänzung braucht.15 Mit anderen Worten: Das mehrformatige DataObject aus den Kapiteln 2 bis 5 ist auch die Fracht von D&D.
flowchart LR
accTitle: Ablauf von OLE-Drag-and-Drop
accDescr: Die Ziehquelle ruft DoDragDrop mit einem IDataObject als Fracht auf und die Ziehschleife beginnt; das IDropTarget des Ablegeziels erklärt die Annahme in DragEnter und DragOver und holt beim Drop ein Format aus dem IDataObject
src["Ziehquelle: IDataObject + IDropSource"] -->|"DoDragDrop"| loop["Ziehschleife"]
loop -->|"Maus tritt ins Fenster"| enter["IDropTarget.DragEnter/DragOver (den Effect jedes Mal erklären)"]
enter -->|"Taste losgelassen"| drop["IDropTarget.Drop"]
drop --> data["Ein Format aus dem IDataObject wählen und holen"]
8.2. OleInitialize (STA) ist erforderlich
Ein Ablegeziel-Fenster wird mit RegisterDragDrop registriert. Als Voraussetzungen prüft man zwei Dinge: OLE-Initialisierung und Nachrichtenverarbeitung.
Für die Initialisierung OleInitialize nutzen. Nutzt man stattdessen CoInitialize / CoInitializeEx, schlägt RegisterDragDrop mit E_OUTOFMEMORY fehl. OleInitialize initialisiert COM als STA.12
Der registrierende Thread muss eine Nachrichtenpumpe ausführen. OLE-D&D wurzelt in Fenstern und Nachrichtenverarbeitung; unterbleibt das, hängen andere Apps während eines Ziehvorgangs.12 Der Hintergrund ist dasselbe Threadmodell wie in „Grundlagenwissen zu COM STA/MTA“.
In WinForms/WPF über Ereignisse empfangen
In WinForms/WPF übernimmt das Framework OLE-Initialisierung und die Schnittstellenumsetzungen. Der Entwickler schreibt die Annahmeerklärung und die eigentliche Aufnahme in Ereignisse.
// WinForms: abgelegte Dateien annehmen
listView1.AllowDrop = true;
listView1.DragEnter += (s, e) =>
{
// Auch prüfen, dass die Quelle Copy zulässt (manche Quellen lassen nur Move/Link zu)
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop)
&& (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy
? DragDropEffects.Copy // Annehmen: als Kopie entgegennehmen
: DragDropEffects.None; // Nicht annehmen
};
listView1.DragDrop += (s, e) =>
{
// Ziehdaten sind ebenfalls externe Eingabe. Auch wenn FileDrop beworben wird, kann die
// Nutzlast null oder ein anderer Typ sein, und der Abruf selbst kann fehlschlagen
object data;
try { data = e.Data.GetData(DataFormats.FileDrop); }
catch (COMException) { return; }
if (data is not string[] paths) return;
foreach (var path in paths)
{
// Den Pfad prüfen, bevor aufgenommen wird (Abschnitt 9.3)
}
};
In WPF ist das Bild dasselbe. Empfangen mit AllowDrop="True" am Element und den Ereignissen DragOver / Drop, und das Pfadarray mit e.Data.GetData(DataFormats.FileDrop) holen.
Die Annahme (den Effect) jedes Mal zu erklären in DragEnter / DragOver ist die Konvention von IDropTarget. Lässt man das weg, bleibt der Cursor auf „nicht erlaubt“. Prüfen Sie nicht nur, ob das Format vorhanden ist, sondern wie im Codebeispiel auch, ob die Ziehquelle Copy zulässt.
9. Fallstricke von D&D — Erhöhung, Move und Pfadprüfung
9.1. Auf eine als Administrator erhöhte App lässt sich nicht ablegen
Eine Datei aus dem Datei-Explorer auf eine mit „Als Administrator ausführen“ gestartete App ablegen und nichts passiert — das ist kein Umsetzungsfehler, sondern Betriebssystementwurf. UIPI (User Interface Privilege Isolation) blockiert standardmäßig Nachrichten von einem Prozess niedrigerer Integrität an ein Fenster höherer Integrität, daher erreichen Ablegebenachrichtigungen vom Datei-Explorer mit gewöhnlichen Rechten (mittlere Integrität) eine erhöhte App nie.13
flowchart LR
accTitle: Wie UIPI ein Ablegen auf eine erhöhte App blockiert
accDescr: UIPI blockiert standardmäßig die Ablegebenachrichtigung vom Datei-Explorer mittlerer Integrität an eine erhöhte App hoher Integrität, daher kommt sie nie an. Die Oberfläche bei gewöhnlichen Rechten belassen und privilegierte Arbeit isolieren, und das Ablegen kommt an
explorer["Datei-Explorer (mittlere Integrität)"] -->|"Ablegebenachrichtigung"| uipi{"UIPI"}
uipi -->|"Blockiert (Vorgabe)"| elevated["Erhöhte App (hohe Integrität): keine Reaktion"]
uipi -->|"Durchlass"| normal["Oberfläche bei gewöhnlichen Rechten: das Ablegen kommt an"]
normal -.->|"Nur privilegierte Arbeit übergeben"| broker["Eigener Prozess, der die Arbeit isoliert, die Erhöhung braucht"]
Es gibt auch einen Workaround, der WM_DROPFILES und ähnliche Nachrichten einzeln mit ChangeWindowMessageFilterEx zulässt.13 Das ist jedoch eine Gegenmaßnahme für die ältere Ablegebenachrichtigung über WM_DROPFILES und löst OLE-D&D insgesamt nicht.
Die grundlegende Leitlinie ist, die App nicht dauerhaft erhöht laufen zu lassen. Isoliert man nur die Arbeit, die Erhöhung braucht, in einen eigenen Prozess, kann die Oberfläche selbst bei gewöhnlichen Rechten bleiben und D&D annehmen. Den Isolierungsentwurf beschreibt ausführlich „Administratorrechte und Broker-Prozesse in Windows-Apps“.
9.2. Was DragDropEffects bedeutet — Move ist ein Vertrag, dass „das Original verschwindet“
Copy / Move / Link in DragDropEffects sind keine Cursordekoration; sie sind ein Vertrag zwischen Ziehquelle und Ablegeziel.
Die Ziehquelle erklärt in DoDragDrop die Menge der zulässigen Effekte, das Ablegeziel wählt den tatsächlichen Effekt. Nach Konvention löscht die Ziehquelle die Daten (die Datei), wenn Move vereinbart ist.
Gibt die Empfangsseite unüberlegt Move zurück, landet man bei „ich habe abgelegt und die Originaldatei ist weg“. Für die Aufnahme in Geschäftsanwendungen macht man das ausdrückliche Copy der Empfangsseite zur sicheren Vorgabe.
flowchart LR
accTitle: Der Vertrag von DragDropEffects — bei Move verschwindet das Original
accDescr: Die Ziehquelle erklärt in DoDragDrop die Menge der zulässigen Effekte, das Ablegeziel wählt den tatsächlichen Effekt. Weil die Konvention ist, dass die Ziehquelle die Datei löscht, wenn Move vereinbart ist, sollte eine Empfangsseite, die aufnimmt, Copy ausdrücklich angeben
srcdecl["Ziehquelle: zulässige Effekte erklären (Copy | Move | Link)"] --> tgtsel["Ablegeziel: den tatsächlichen Effekt wählen"]
tgtsel -->|"Copy"| copyok["Originaldatei bleibt (die sichere Seite für Aufnahme)"]
tgtsel -->|"Move"| moveact["Ziehquelle löscht die Datei — woher „das Original ist weg“ kommt"]
9.3. Abgelegte Pfade prüfen
Was in CF_HDROP/FileDrop reist, sind nur Pfade (Abschnitt 3.2). Vor der Aufnahme führt man sie durch dieselbe Prüfung wie externe Eingabe, genau wie beim Einfügen.
- Datei oder Ordner: Als Spezifikation festlegen, was geschieht, wenn ein ganzer Ordner abgelegt wird (rekursiv aufnehmen oder ablehnen).
- OneDrive-Platzhalter: Existiert der Pfad, der Dateirumpf aber nicht lokal — eine Datei bei Bedarf —, startet beim Öffnen ein Download und scheitert offline. Verhalten und Gegenmaßnahmen beschreibt OneDrive „Dateien bei Bedarf“ und Business-Apps.
- Lange und besondere Pfade: Pfade jenseits von MAX_PATH, Netzwerkpfade (UNC) und Pfade auf Wechselmedien erst annehmen, nachdem bestätigt ist, dass die nachfolgende Verarbeitung sie bewältigt.
- Anzahl und Gesamtgröße: Damit das Ablegen von Tausenden Dateien die Oberfläche nicht einfriert, die Aufnahme asynchron machen und eine Grenze sowie eine Fortschrittsanzeige vorsehen.
10. Zusammenfassung
- Die Zwischenablage ist ein Mechanismus, der denselben Inhalt gleichzeitig in mehreren Formaten in einem einzelnen Bereich ablegt, der innerhalb desselben Desktops (Fensterstation) geteilt wird. Weil das Einfügeziel das Format wählt, erzeugt dieselbe Kopie verschiedene Ergebnisse.
- Text ist CF_UNICODETEXT, Dateien sind CF_HDROP, und formatierter Text ist das registrierte Format HTML Format (Header mit Byteversätzen + UTF-8).
- Die Einfügeseite sucht Formate von reich nach einfach und prüft den Inhalt als externe Eingabe. Die Kopierseite bietet mehrere Formate gleichzeitig an und setzt bei verzögertem Rendering auch die Materialisierung beim Beenden um (WM_RENDERALLFORMATS / OleFlushClipboard).
- Überwachung ist AddClipboardFormatListener + WM_CLIPBOARDUPDATE. Auf Konkurrenz um OpenClipboard mit erneuten Versuchen vorbereiten und Geheimnisse mit ExcludeClipboardContentFromMonitorProcessing und Ähnlichem aus Verlauf und Synchronisierung ausschließen.
- Die IT kann Zwischenablageverlauf, Cloud-Synchronisierung und RDP-Umleitung über GPO/Intune steuern. Alles ist standardmäßig zugelassen, in Umgebungen mit Geheimnissen also bewusst entscheiden.
- D&D ist COM: IDropSource/IDropTarget übergeben dasselbe IDataObject wie die Zwischenablage. RegisterDragDrop verlangt OleInitialize (STA).
- Ablegen auf eine erhöhte App blockiert UIPI. Move in DragDropEffects ist ein Vertrag, dass „das Original verschwindet“, und abgelegte Pfade werden vor der Aufnahme geprüft.
Für Benutzer sind Kopieren und Einfügen und D&D Funktionen so selbstverständlich wie Luft. Genau deshalb leidet die Erfahrung so stark, wenn „lässt sich nicht einfügen“, „fällt auseinander“ oder „ist verschwunden“ eintritt — und umgekehrt macht eine App, die mehrere Formate anbietet und Ablegen gründlich behandelt, den Alltag schon dadurch glatter. Ich hoffe, das dient als Grundlage, wenn Sie die Priorität von Überarbeitungen abwägen.
Verwandte Artikel
- Was sind COM / ActiveX / OCX? – Unterschiede und Zusammenhänge im Überblick
- Grundlagenwissen zu COM STA/MTA – Threadmodelle und wie man Hänger vermeidet
- Windows-Shell-Integration heute ── Kontextmenüs, Dateizuordnungen und was sich unter Windows 11 geändert hat
- Warum EXCEL.EXE-Prozesse nach C#-Excel-COM-Automatisierung bestehen bleiben — Muster zur Referenzfreigabe und die Ersatzentscheidung
- Windows-App-UX-Design - Prioritäten nach Nutzungsumgebung
- OneDrive „Dateien bei Bedarf“ und Business-Apps — welche Annahmen Platzhalter zerbrechen und wie man damit umgeht
Zugehörige Beratungsfelder
Die KomuraSoft LLC übernimmt Entwurf und Umsetzung der Unterstützung von Kopieren und Einfügen sowie Drag-and-Drop in Geschäftsanwendungen (Anbieten mehrerer Formate, Excel-Zusammenarbeit, Aufnahme abgelegter Dateien), Ursachenuntersuchung von Störungen wie „fällt beim Einfügen auseinander“ oder „die Kopie verschwindet“, Eingabeautomatisierung über Zwischenablageüberwachung und die Umsetzung von Schutz für vertrauliche Daten gegenüber Verlauf und Synchronisierung. Fälle, die die unteren Schichten von COM und OLE berühren, sind willkommen, auch wenn sie beim Eingrenzen des Symptoms beginnen.
- Windows-App-Entwicklung
- Entwicklung von COM-Komponenten
- Technische Beratung und Design-Review
- Kontakt
Quellen
-
Microsoft Learn, Clipboard Formats. Dazu, dass ein Fenster dieselbe Information in mehreren Zwischenablageformaten ablegen kann; zu registrierten Formaten über RegisterClipboardFormat (dieselbe Namensregistrierung liefert denselben Wert, Apps können ihn also teilen); zu synthetisierten Formaten; sowie zum Ausschluss von Inhalt aus Zwischenablageverlauf und Cloud-Synchronisierung mit ExcludeClipboardContentFromMonitorProcessing, CanIncludeInClipboardHistory und CanUploadToCloudClipboard. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Standard Clipboard Formats. Zu den Definitionen der Standardformate CF_TEXT (ANSI), CF_UNICODETEXT, CF_HDROP, CF_DIB und CF_LOCALE sowie dazu, dass das System zwischen CF_TEXT und CF_UNICODETEXT implizit mit der CF_LOCALE zugeordneten Codepage umwandelt. ↩ ↩2 ↩3
-
Microsoft Learn, Shell Clipboard Formats. Dazu, dass CF_HDROP aus einer DROPFILES-Struktur plus einem mit doppeltem NUL abgeschlossenen Array vollständiger Pfadzeichenfolgen besteht; zum Holen einzelner Pfade mit DragQueryFile; sowie dazu, dass die Shell-Formate CFSTR_ eine Registrierung über RegisterClipboardFormat verlangen. ↩ ↩2
-
Microsoft Learn, HTML Clipboard Format. Dazu, dass der registrierte Name „HTML Format“ ist; zur Headerstruktur mit Versätzen (in Bytes) wie Version, StartHTML, EndHTML, StartFragment und EndFragment; dazu, dass die Kodierung immer UTF-8 ist; sowie zur Kommentar-Konvention StartFragment/EndFragment. ↩ ↩2 ↩3
-
Microsoft Learn, OleGetClipboard function (ole2.h). Dazu, wie man ein IDataObject von der Zwischenablage erhält, und zur Warnung, dass Zwischenablagedaten nicht vertrauenswürdig sind und vor der Nutzung in der App sorgfältig geparst werden sollten. ↩ ↩2
-
Microsoft Learn, Clipboard Operations. Dazu, dass nur ein Fenster zur Zeit die Zwischenablage öffnen kann; zum Ablegen der Formate vom ausdrucksstärksten abwärts zur Kopierzeit; zur Formatwahl zur Einfügezeit mit EnumClipboardFormats / GetPriorityClipboardFormat; zum verzögerten Rendering durch Übergabe von NULL an SetClipboardData und den Pflichten WM_RENDERFORMAT / WM_RENDERALLFORMATS; sowie zu den Kompromissen des verzögerten Renderings. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Microsoft Learn, OleFlushClipboard function (ole2.h). Dazu, dass die Zwischenablage nach OleSetClipboard nur einen Zeiger auf das Datenobjekt hält; dazu, dass OleFlushClipboard die Daten auf der Zwischenablage materialisiert, sodass Einfügen nach dem Beenden der App weiter möglich ist; sowie zum Leeren der Zwischenablage mit OleSetClipboard(NULL), wenn die Daten beim Beenden nicht behalten werden müssen. ↩ ↩2
-
Microsoft Learn, Using the clipboard. Zum Vergleich der drei Arten, die Zwischenablage zu überwachen (Viewer-Fenster, Sequenznummern und Format-Listener); dazu, dass neue Programme einen Listener über AddClipboardFormatListener nutzen sollen; dazu, dass die Viewer-Kette anfällig für Lücken in der Kettenpflege ist; sowie dazu, dass Sequenznummern nichts sind, das man pollen sollte. ↩ ↩2
-
Microsoft Learn, Policy CSP - Experience. Zum Zulassen oder Sperren des Zwischenablageverlaufs mit der Richtlinie Experience/AllowClipboardHistory; zur Verfügbarkeit ab Windows 10 Version 1809; dazu, dass die Vorgabe zugelassen ist; sowie zur GPO-Zuordnung unter „System > Betriebssystemrichtlinien“ mit Änderungen, die sofort greifen. ↩ ↩2
-
Microsoft Learn, Policy CSP - Privacy. Zum Zulassen oder Sperren der geräteübergreifenden Zwischenablagesynchronisierung mit der Richtlinie Privacy/AllowCrossDeviceClipboard; dazu, dass die Synchronisierung zwischen Geräten geschieht, die mit demselben Microsoft-Konto oder Microsoft-Entra-Konto angemeldet sind; sowie dazu, dass die Vorgabe zugelassen ist. ↩ ↩2 ↩3
-
Microsoft Learn, Policy CSP - ADMX_TerminalServer. Dazu, dass TS_CLIENT_CLIPBOARD („Zwischenablageumleitung nicht zulassen“, Registrierungswert fDisableClip) das Teilen der Zwischenablage zwischen lokal und remote in einer Remotedesktopsitzung verbieten kann, und dazu, dass Umleitung standardmäßig zugelassen ist. ↩ ↩2
-
Microsoft Learn, RegisterDragDrop function (ole2.h). Zur Registrierung eines Ablegeziel-Fensters und seines IDropTarget; dazu, dass der Aufruf stets mit E_OUTOFMEMORY fehlschlägt, wenn COM mit CoInitialize/CoInitializeEx initialisiert wurde, sodass OleInitialize erforderlich ist; sowie dazu, dass die Ziehquellen-App hängt, wenn der aufrufende Thread keine Nachrichtenpumpe ausführt. ↩ ↩2 ↩3
-
Microsoft Learn, ChangeWindowMessageFilterEx function (winuser.h). Dazu, dass UIPI ein Sicherheitsmechanismus ist, der standardmäßig den Empfang von Nachrichten eines Senders niedrigerer Integrität blockiert, und zum Zulassen bestimmter Nachrichten (MSGFLT_ALLOW) mit einem Nachrichtenfilter pro Fenster. ↩ ↩2 ↩3
-
Microsoft Learn, How to add data to the Clipboard (Windows Forms). Zum gleichzeitigen Ablegen von Daten in mehreren Formaten mit DataObject und Clipboard.SetDataObject; zum Hinzufügen in mehreren Formaten, damit andere Apps sie erkennen; sowie dazu, dass die Clipboard-Klasse nur von einem STA-Thread nutzbar ist, sodass [STAThread] erforderlich ist. ↩ ↩2
-
Microsoft Learn, Drag and Drop (COM). Dazu, dass OLE-Drag-and-Drop über die drei Rollen IDropSource (Ziehquelle), IDropTarget (Ablegeziel) und DoDragDrop (die von OLE bereitgestellte Schleife) läuft; dazu, dieselbe Funktion wie Kopieren und Einfügen der Zwischenablage bereitzustellen, sodass eine App, die das bereits umsetzt, nur eine kleine Ergänzung braucht; sowie zu den Arten der Rückmeldung. ↩ ↩2
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Windows-App-Outsourcing und Auftragsentwicklung: Was Sie vor der Beauftragung klären sollten
Bevor Sie die Entwicklung einer Windows-App outsourcen oder in Auftrag geben, sollten Sie folgende Punkte klären: Überarbeitung bestehend...
Ende der Wartung von Windows-Druckertreibern — Wie Geschäftsanwendungen Bericht- und Etikettendruck vorbereiten
Microsoft stellt v3/v4-Druckertreiber schrittweise ein. Was Windows protected print mode entfernt und wie Geschäftsanwendungen Bericht- u...
Was ist ein OLE-Objekt? — Einbetten, Verknüpfen und die Fallstricke in Geschäftsdokumenten
Die Funktion, mit der sich eine Excel-Tabelle in Word einbetten lässt, ist in Wirklichkeit ein OLE-Objekt. Der Artikel erklärt praxisnah ...
Was „Keine Rückmeldung“ wirklich ist — Wie Windows entscheidet, dass eine App hängt, und Entwürfe, die nicht hängen
„Keine Rückmeldung“ unter Windows ist ein Mechanismus, bei dem das Betriebssystem urteilt, dass ein Fenster 5 Sekunden lang keine Nachric...
Dunkler Modus und Kontrastthemen in Windows-Apps — Dunkle DWM-Titelleisten, Systemthema-Nachführung in WinForms/WPF und Zeichnen unter hohem Kontrast
So lassen Sie WinForms/WPF-Apps dem dunklen Modus und den Kontrastthemen von Windows 11 folgen. Behandelt dunkle DWM-Titelleisten, SetCol...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
ActiveX-Migration
Entscheidungen zum Beibehalten, Kapseln oder Ersetzen von COM / ActiveX / OCX.
UI-Threading und Timer
WPF-/WinForms-UI-Thread, asynchrone Abläufe, Dispatcher und Timer-Entscheidungen.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
Nutzung und Migration bestehender Assets
Wiederverwendung und Migration von COM / ActiveX / OCX sowie 32-/64-Bit-Abhängigkeiten.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Warum fällt die Formatierung auseinander, wenn ich eine aus Excel kopierte Tabelle in meine App einfüge?
- Weil die Zwischenablage nicht „ein Datenstück“ hält: Derselbe Inhalt liegt gleichzeitig in mehreren Formaten (privates App-Format, HTML Format, CSV, Unicode-Text und so weiter), und die Ziel-App wählt das Format, das sie versteht, und holt genau das heraus. Fällt die Formatierung auseinander, liest das Ziel typischerweise nur einfachen Text (CF_UNICODETEXT). Soll auch die Tabellenstruktur ankommen, muss die Einfügeseite HTML Format oder CSV bevorzugen. Umgekehrt: Soll eine Kopie aus der eigenen App in anderen Apps korrekt landen, bietet die Kopierseite zur Kopierzeit ein reiches und ein einfaches Format gleichzeitig an.
- Warum kann ich nicht mehr einfügen, nachdem ich die App geschlossen habe, aus der ich kopiert habe?
- Weil die Quelle verzögertes Rendering (delayed rendering) nutzt. Apps, die große Daten behandeln, legen zur Kopierzeit nicht die Daten selbst ab, sondern nur das Versprechen, sie „auf Anfrage zu erzeugen“. Beendet sich die Quelle dann, ohne die Daten als Antwort auf WM_RENDERALLFORMATS beim Beenden zu materialisieren, gehen die noch nicht gerenderten Formate verloren. Eine App, die die OLE-Zwischenablage (IDataObject) nutzt, kann Einfügen nach dem Beenden ermöglichen, indem sie beim Beenden OleFlushClipboard aufruft und die Daten materialisiert.
- Wie kann meine eigene App Änderungen der Zwischenablage überwachen?
- Die derzeit empfohlene Methode ist, das eigene Fenster mit AddClipboardFormatListener als Listener zu registrieren und die Nachricht WM_CLIPBOARDUPDATE zu verarbeiten, die bei jeder Inhaltsänderung eintrifft. Periodisches Lesen per Timer (Polling) verschwendet Arbeit, und die alte Viewer-Kette über SetClipboardViewer bleibt nur aus Abwärtskompatibilität, weil ein Fehler in einer App der Kette die ganze Kette zerstört. OpenClipboard beim Lesen kann außerdem durch Konkurrenz mit einem anderen Prozess fehlschlagen; ein erneuter Versuch nach kurzem Warten macht das Lesen stabil.
- Gibt es einen Weg, Geheimnisse wie Kennwörter aus dem Zwischenablageverlauf (Win+V) herauszuhalten?
- Es gibt zwei Wege, einen auf der App-Seite und einen auf der Richtlinienseite. Auf der App-Seite legen Sie beim Kopieren zusätzlich das registrierte Format ExcludeClipboardContentFromMonitorProcessing ab; dann gehört der Inhalt weder zum Verlauf noch zur geräteübergreifenden Synchronisierung. Mit CanIncludeInClipboardHistory (nur Verlauf) und CanUploadToCloudClipboard (nur Synchronisierung) lässt sich jedes getrennt steuern. Das ist der Mechanismus, den Kennwortmanager nutzen. Soll die Organisation das insgesamt unterbinden, deaktivieren Sie Verlauf und Cloud-Synchronisierung selbst mit AllowClipboardHistory und AllowCrossDeviceClipboard über Gruppenrichtlinie oder Intune (Policy CSP).
- Warum kann ich eine Datei nicht auf eine App ziehen, die als Administrator läuft?
- Weil der Sicherheitsmechanismus UIPI (User Interface Privilege Isolation) das Senden von Nachrichten von einem Prozess niedrigerer Integrität an ein Fenster höherer Integrität blockiert. Der Datei-Explorer läuft mit gewöhnlichen Rechten (mittlere Integrität), daher erreichen Drag-and-Drop-Benachrichtigungen das Fenster einer erhöhten App nicht. Ein Workaround, der Nachrichten wie WM_DROPFILES einzeln mit ChangeWindowMessageFilterEx zulässt, ist bekannt, gilt aber nur für die ältere Ablegebenachrichtigung. Der eigentliche Weg ist, die App nicht dauerhaft erhöht laufen zu lassen und nur die Arbeit, die Erhöhung braucht, in einen eigenen Prozess zu legen.
Autorenprofil
Profilseite des Artikelautors.
Go Komura
Geschäftsführer von KomuraSoft LLC
Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.