Frage

Warum funktioniert der folgende Code manchmal eine Ausnahme mit dem Inhalt „CLIPBRD_E_CANT_OPEN“ bewirkt:

Clipboard.SetText(str);

Dies tritt in der Regel das erste Mal in der Zwischenablage in der Anwendung verwendet wird und danach nicht mehr.

War es hilfreich?

Lösung

Eigentlich denke ich, das ist die Fehler des Win32-API .

Um die Daten in der Zwischenablage zu setzen, müssen Sie öffnen zuerst. Es kann nur ein Prozess die Zwischenablage offen zu einer Zeit hat. Also, wenn Sie überprüfen, ob ein anderer Prozess die Zwischenablage hat offen aus irgendeinem Grunde , Ihr Versuch zu öffnen, wird es scheitern.

Es ist einfach so passiert, dass die Terminaldienste Übersicht über die Zwischenablage hält, und auf älteren Versionen von Windows (pre-Vista), müssen Sie die Zwischenablage öffnen, um zu sehen, was drin ist ..., die Sie blockieren endet. Die einzige Lösung ist, zu warten, bis die Terminaldienste über die Zwischenablage wird geschlossen, und versuchen Sie es erneut.

Es ist wichtig zu erkennen, dass dies zu Terminaldienste nicht spezifisch ist, aber: es mit etwas passieren kann. Arbeiten mit der Zwischenablage in Win32 ist eine Riesen-Race-Bedingung. Da aber nach Design sind Sie nur mit der Zwischenablage in Reaktion auf Benutzereingaben sollten vertrödeln, dies in der Regel stellt kein Problem dar.

Andere Tipps

Dies wird durch einen Bug / Feature in Terminal Services Zwischenablage (und möglichen anderen Dinge) und die .NET-Implementierung der Zwischenablage verursacht. Eine Verzögerung in die Zwischenablage Öffnen bewirkt, dass die Fehler, die in der Regel innerhalb von wenigen Millisekunden durchlaufen.

Die Lösung ist mehrfach in einer Schleife und schläft dazwischen.

, um zu versuchen
for (int i = 0; i < 10; i++)
{
    try
    {
        Clipboard.SetText(str);
        return;
    }
    catch { }
    System.Threading.Thread.Sleep(10);
} 

Ich weiß, diese Frage ist alt, aber das Problem weiterhin besteht. Wie bereits erwähnt, tritt diese Ausnahme, wenn die System-Zwischenablage von einem anderen Prozess gesperrt ist. Leider sind die vielen Snipping Tools, Programme für Screenshots und Dateikopiertools, die die Windows-Zwischenablage blockieren kann. So finden Sie die Ausnahme erhalten jedes Mal, wenn Sie versuchen, Clipboard.SetText(str) zu verwenden, wenn ein solches Werkzeug auf Ihrem PC installiert ist.

Lösung:

nie verwenden

Clipboard.SetText(str);

Verwendung anstelle

Clipboard.SetDataObject(str);

Eigentlich könnte es ein weiteres Problem bei der Hand sein. Der Framework Aufruf (sowohl die WPF und winform Aromen), um so etwas wie diese (Code ist aus Reflektor):

private static void SetDataInternal(string format, object data)
{
    bool flag;
    if (IsDataFormatAutoConvert(format))
    {
        flag = true;
    }
    else
    {
        flag = false;
    }
    IDataObject obj2 = new DataObject();
    obj2.SetData(format, data, flag);
    SetDataObject(obj2, true);
}

Beachten Sie, dass SetDataObject immer wahr in diesem Fall aufgerufen wird.

Intern, die zwei Anrufe an die win32 api löst, man die Daten setzen und man es von Ihrer Anwendung zu spülen, so dass es verfügbar ist, nachdem die App geschlossen wird.

Ich habe mehrere Anwendungen (einige Chrom-Plugin, und einen Download-Manager) zu sehen, die in die Zwischenablage Ereignis hören. Sobald der erste Anruf trifft, wird die App die Zwischenablage öffnen, um die Daten zu schauen, und der zweite Aufruf zu spülen wird fehlschlagen.

Haben Sie eine gute Lösung gefunden, außer meine eigene Zwischenablage Klasse zu schreiben, die direkt win32-API verwendet oder SetDataObject ruft direkt mit falschen Daten halten, nachdem die App geschlossen wird.

Ich löste dieses Problem für meine eigene App mit nativen Win32-Funktionen:. Open (), Closeclipboard () und SetClipboardData ()

Unter der Wrapper-Klasse I gemacht. Könnte jemand Sie es überprüfen und sagen, ob es richtig ist oder nicht . Vor allem, wenn der verwaltete Code wird als x64 App läuft (ich verwende Jede CPU in den Projektoptionen). Was passiert, wenn ich auf x86-Bibliotheken von x64-App-Link?

Danke!

Hier ist der Code:

public static class ClipboardNative
{
    [DllImport("user32.dll")]
    private static extern bool OpenClipboard(IntPtr hWndNewOwner);

    [DllImport("user32.dll")]
    private static extern bool CloseClipboard();

    [DllImport("user32.dll")]
    private static extern bool SetClipboardData(uint uFormat, IntPtr data);

    private const uint CF_UNICODETEXT = 13;

    public static bool CopyTextToClipboard(string text)
    {
        if (!OpenClipboard(IntPtr.Zero)){
            return false;
        }

        var global = Marshal.StringToHGlobalUni(text);

        SetClipboardData(CF_UNICODETEXT, global);
        CloseClipboard();

        //-------------------------------------------
        // Not sure, but it looks like we do not need 
        // to free HGLOBAL because Clipboard is now 
        // responsible for the copied data. (?)
        //
        // Otherwise the second call will crash
        // the app with a Win32 exception 
        // inside OpenClipboard() function
        //-------------------------------------------
        // Marshal.FreeHGlobal(global);

        return true;
    }
}

Das passiert mir in meinem WPF-Anwendung. Ich habe fehlgeschlagen Open (Ausnahme von HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN)).

ich verwende

ApplicationCommands.Copy.Execute(null, myDataGrid);

Lösung ist die Zwischenablage löschen ersten

Clipboard.Clear();
ApplicationCommands.Copy.Execute(null, myDataGrid);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top