CLIPBRD_E_CANT_OPEN errore durante l'impostazione di Appunti .NET
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.
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);