Domanda

Perché il codice riportato di seguito, a volte, causa un'Eccezione con il contenuto "CLIPBRD_E_CANT_OPEN":

Clipboard.SetText(str);

Questo di solito si verifica la prima volta negli Appunti è utilizzata nell'applicazione e non dopo.

È stato utile?

Soluzione

In realtà, credo che questo è il colpa delle API Win32.

Per impostare i dati negli appunti, è necessario aprirlo per prima.Solo un processo può avere appunti aperte contemporaneamente.Così, quando si verifica, e se un altro processo ha appunti apri per qualsiasi motivo, il tentativo di aprire avrà esito negativo.

Così succede che di Servizi Terminal tiene traccia degli appunti e versioni di Windows precedenti (pre-Vista), è necessario aprire gli appunti per vedere cosa c'è dentro...che finisce il blocco.L'unica soluzione è aspettare di Servizi Terminal chiude appunti e provare di nuovo.

È importante rendersi conto che questo non è specifico per Servizi Terminal, anche se:può succedere qualsiasi cosa.Lavorare con gli appunti in Win32 è una gara di gigante condizione.Ma, dal momento che dal disegno si è solo dovuto muck intorno con gli appunti in risposta all'input dell'utente, questo di solito non è un problema.

Altri suggerimenti

Questo è causato da un bug/feature di Servizi Terminal appunti (ed eventuali altre cose) e l' .NET attuazione degli appunti.Un ritardo nell'apertura appunti causa l'errore, che di solito passa in pochi millisecondi.

La soluzione è di provare più volte all'interno di un ciclo di sonno e tra.

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

So che questa domanda è vecchia, ma il problema esiste ancora.Come accennato prima, questa eccezione si verifica quando la clipboard di sistema è bloccato da un altro processo.Purtroppo, molti di cattura, strumenti, programmi per le schermate di copia di file e di strumenti in grado di bloccare gli appunti di Windows.Così si otterrà l'eccezione ogni volta che si tenta di utilizzare Clipboard.SetText(str) quando un tale strumento viene installato sul vostro PC.

Soluzione:

non utilizzare mai

Clipboard.SetText(str);

utilizzare invece

Clipboard.SetDataObject(str);

In realtà ci potrebbe essere un altro problema a portata di mano.Il quadro di chiamata (sia WPF e winform sapori) a qualcosa di simile a questo (il codice è da riflettore):

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);
}

Nota che SetDataObject è sempre chiamato con il vero in questo caso.

Internamente, che genera due chiamate all'api win32, uno per impostare i dati ed uno per lavare dalla tua app è disponibile dopo l'applicazione si chiude.

Ho visto diverse applicazioni (alcuni chrome plugin, e un download manager) che ascoltare appunti evento.Non appena la prima di chiamare i colpi, l'app verrà aperta appunti di esaminare i dati, e la seconda chiamata a filo avrà esito negativo.

Non hai trovato una buona soluzione se non a scrivere la mia classe di appunti che usi diretti di win32 API o chiamare setDataObject direttamente con false per mantenere i dati dopo l'applicazione si chiude.

Ho risolto questo problema per mia app, utilizzando il nativo Win32 funzioni:OpenClipboard(), CloseClipboard() e SetClipboardData().

Di seguito la classe wrapper che ho fatto.Qualcuno potrebbe si prega di la revisione e dire se è giusto o meno.Soprattutto quando il codice gestito è in esecuzione come x64 app (io uso Qualsiasi CPU le opzioni di progetto). Cosa succede quando c'è il link per x86 librerie x64 app?

Grazie!

Ecco il codice:

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;
    }
}

Questo succede a me, nella mia applicazione WPF.Ho avuto Impossibile eseguire OpenClipboard (Eccezione da HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN)).

io uso

ApplicationCommands.Copy.Execute(null, myDataGrid);

la soluzione è quella di cancellare gli appunti prima

Clipboard.Clear();
ApplicationCommands.Copy.Execute(null, myDataGrid);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top