L'OpenClipboard a échoué lorsqu'on a copié les données de collage à partir de la base de données WPF.
j'ai une application WPF utilisant datagrid. L'application a bien fonctionné jusqu'à ce que J'installe Visual Studio 2012 et Blend+SketchFlow preview. Maintenant, quand j'essaie de copier les données de la grille dans le bloc-notes avec Ctrl + C (dans n'importe quelle application), j'obtiens l'exception suivante:
System.Runtime.InteropServices.COMException (0x800401D0): OpenClipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
at System.Windows.Clipboard.Flush()
at System.Windows.Clipboard.CriticalSetDataObject(Object data, Boolean copy)
at System.Windows.Controls.DataGrid.OnExecutedCopy(ExecutedRoutedEventArgs args)
at System.Windows.Controls.DataGrid.OnExecutedCopy(Object target, ExecutedRoutedEventArgs args)
at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
at System.Windows.Input.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e)
at System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
at System.Windows.Input.RoutedCommand.ExecuteCore(Object parameter, IInputElement target, Boolean userInitiated)
at System.Windows.Input.CommandManager.TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
at System.Windows.UIElement.OnKeyDownThunk(Object sender, KeyEventArgs e)
at System.Windows.Input.KeyEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndKeyboardInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawKeyboardActions actions, Int32 scanCode, Boolean isExtendedKey, Boolean isSystemKey, Int32 virtualKey)
at System.Windows.Interop.HwndKeyboardInputProvider.ProcessKeyAction(MSG& msg, Boolean& handled)
at System.Windows.Interop.HwndSource.CriticalTranslateAccelerator(MSG& msg, ModifierKeys modifiers)
at System.Windows.Interop.HwndSource.OnPreprocessMessage(Object param)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
at System.Windows.Interop.HwndSource.OnPreprocessMessageThunk(MSG& msg, Boolean& handled)
at System.Windows.Interop.HwndSource.WeakEventPreprocessMessage.OnPreprocessMessage(MSG& msg, Boolean& handled)
at System.Windows.Interop.ComponentDispatcherThread.RaiseThreadMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
C'est vraiment ennuyeux.
j'ai vu quelques références à ce problème ici et à divers endroits sur le web, sans véritable solution.
je peux vérifier que le presse-papiers est verrouillé lorsque cette exception est soulevée dans Visual Studio, car je ne pouvais pas copier coller le message (a dû l'écrire dans un fichier). De plus, le presse-papiers n'était pas verrouillé avant le début du processus de copie.
Comment résoudre ce problème?
9 réponses
nous utilisons .NET 4.0. Nous avions le même problème, mais après avoir déconnecté le système, le code fonctionnait bien pendant un certain temps.
finalement nous avons trouvé l'alternative.
si vous voulez copier une chaîne de caractères dans le presse-papiers,
string data = "Copy This"
Jusqu'à présent j'utilisais la méthode suivante
Clipboard.SetText(data);
il a échoué encore et encore. Puis j'ai regardé d'autres méthodes pour mettre du texte dans le presse-papiers dans Classe Clipboard et j'ai essayé le suivant:
Clipboard.SetDataObject(data);
Et ça a marché :). Je n'ai jamais eu de nouveau le problème.
C'est un bug dans le Gestionnaire de presse-papiers WPF. Vous devez gérer l'exception sans entrave dans la demande.DispatcherUnhandledException event.
ajouter cet attribut à l'élément Application
de votre application.xaml
DispatcherUnhandledException="Application_DispatcherUnhandledException"
ajoutez ce code à votre application.XAML.fichier cs
void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
var comException = e.Exception as System.Runtime.InteropServices.COMException;
if (comException != null && comException.ErrorCode == -2147221040)
e.Handled = true;
}
moi aussi, j'ai eu un problème dans une application où je copie des informations dans le presse-papiers que les utilisateurs parcourent une boîte de liste. L'information qui est copiée est liée à l'article sélectionné, et il leur permet de la coller (dit info) dans d'autres applications pour la commodité. De temps en temps je reçois le CLIPBRD_E_CANT_OPEN sur les systèmes de certains utilisateurs, mais pas sur d'autres.
alors que je n'ai pas encore été en mesure de fixer l'argument, j'ai été en mesure de créez du code pour trouver l'application à l'origine de la contestation. J'aimerais au moins partager ce code en espérant que cela aide quelqu'un. Je vais ajouter le en utilisant déclaration, attributs, et la méthode que j'ai créé pour trouver le processus objet du coupable. À partir de l'item Process , vous pouvez obtenir le nom du processus, le PID, le titre de la fenêtre principale (s'il y en a un) et d'autres données potentiellement utiles. Voici les lignes de code que j'ai ajouté sans la code qui l'appelle. ( NOTE: ci-dessous l'extrait de code j'ai encore une info à partager):
using System.Diagnostics; // For Process class
using System.Runtime.InteropServices; // For DllImport's
...
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetOpenClipboardWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
...
///-----------------------------------------------------------------------------
/// <summary>
/// Gets the Process that's holding the clipboard
/// </summary>
/// <returns>A Process object holding the clipboard, or null</returns>
///-----------------------------------------------------------------------------
public Process ProcessHoldingClipboard()
{
Process theProc = null;
IntPtr hwnd = GetOpenClipboardWindow();
if (hwnd != IntPtr.Zero)
{
uint processId;
uint threadId = GetWindowThreadProcessId(hwnd, out processId);
Process[] procs = Process.GetProcesses();
foreach (Process proc in procs)
{
IntPtr handle = proc.MainWindowHandle;
if (handle == hwnd)
{
theProc = proc;
}
else if (processId == proc.Id)
{
theProc = proc;
}
}
}
return theProc;
}
autre NOTE: une autre chose que j'ai changée qui a simplifié mon code un peu était de passer de l'utilisation du système .Windows.Presse-papiers à système.Windows.Forme.Bloc-notes (voir Système.Windows.Forme.Classe de bloc-notes ) parce que cette dernière a un 4-paramètre SetDataObject () méthode qui comprend un nombre de réessais et un délai de réessais en millisecondes. Cela a au moins enlevé une partie de la reprise noise de mon code.
Votre kilométrage peut varier...de plus, il peut y avoir des effets secondaires dans ce que je n'ai pas encore trébuché sur, Donc si quelqu'un les connaît s'il vous plaît commenter. En tout cas, j'espère que cela s'avère utile à la quelqu'un.
j'ai également eu ce problème dans WPF 4.0 et 4.5 depuis que j'ai installé TeraCopy (Windows 7, 64-bit). Tous Les Presse-Papiers.SetText () a échoué avec un système.Runtime.InteropServices.COMException.
ma première solution a été de désinstaller TeraCopy - cela a fonctionné, mais j'adore cette application, donc j'ai dû chercher une autre solution pour résoudre ce problème. La solution était de remplacer
Clipboard.SetText("my string");
avec
Clipboard.SetDataObject("my string");
J'ai eu le même problème avec RichTextBox. Le code suivant s'est écrasé au hasard:
TextRange tr = new TextRange(rich.Document.ContentStart, rich.Document.ContentEnd);
System.Windows.Clipboard.SetDataObject(tr.Text);
il semble préférable d'utiliser le système .Windows.Contrôle.RichTextBox.Copie
j'ai eu un problème pour récupérer des données XAML depuis le presse-papiers avec .NET 4.6.1.
message d'erreur:
Openclipboard Failed (Exception from HRESULT: 0x800401D0 (CLIPBRD_E_CANT_OPEN))
je l'ai résolu comme suit:
int counter = 0;
object xamlClipData = null;
while (xamlClipData == null)
{
try
{
if (counter > 10)
{
System.Windows.MessageBox.Show("No access to clipboard xaml data.");
break;
}
counter++;
if (System.Windows.Clipboard.GetDataObject().GetDataPresent(DataFormats.Xaml))
{
xamlClipData = System.Windows.Clipboard.GetData(DataFormats.Xaml);
}
}
catch { }
}
j'ai eu le même problème en copiant des cellules Excel au presse-papiers et en obtenant des données du presse-papiers comme une chaîne HTML.
Vous pouvez utiliser (tout-try-catch) comme dans le code ci-dessous.
Excel.Application exap = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbook wb = exap.Workbooks.Open(
sourceFileNameTextBox.Text,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
Excel.Sheets sh = wb.Worksheets;
bool clip = false;
// Copy Excel cells to clipboard
while (!clip)
{
try
{
ws.Cells.get_Range(cells[0], cells[1]).Copy(Type.Missing);
clip = true;
}
catch
{
clip = false;
}
}
string b = "";
// Get Excel cells data from the clipboard as HTML
clip = false;
while(!clip)
{
try
{
b = Clipboard.GetData(DataFormats.Html) as string;
clip = true;
}
catch
{
clip = false;
}
}
aussi, vous pouvez avoir un compteur dans le while
si la boucle est plus de 10 fois ou plus, exception se produisent. Je teste son compteur maximum est un et en boucle de temps de travail de bloc-notes.
il y a une signature d'événement/méthode de DataGrid pour ce but précis Copieringrowclipboardcontent(object sender, DataGridRowClipboardEventArgs e) et est plus fiable que le presse-papier.SetDataObject (données) ou Presse-papiers.SetText (data).
Voici comment l'utiliser.
mettre "FullRow" dans le mode SelectionUnit pour dataGrid appelé myDataGrid
<DataGrid x:Name="myDataGrid" SelectionUnit="FullRow"></DataGrid>
nous avons une méthode, myDataGrid_CopyingRowClipboardContent, qui obtient appelé pour chaque ligne dans le dataGrid pour copier son contenu dans le bloc-notes. Par exemple, pour un datagrid avec sept lignes, il est appelé sept fois.
public int clipboardcalledcnt { get; set; } // CopyingRowClipboardContent invoked count
private void myDataGrid_CopyingRowClipboardContent(object sender, DataGridRowClipboardEventArgs e)
{
PathInfo cellpath = new PathInfo(); // A custom class to hold path information
string path = string.Empty;
DataGrid dgdataPaths = (DataGrid)sender;
int rowcnt = dgdataPaths.SelectedItems.Count;
cellpath = (PathInfo)e.Item;
path = "Row #" + clipboardcalledcnt + " Len=" + cellpath.Length.ToString() + ", path=" + cellpath.Path;
e.ClipboardRowContent.Clear();
if (clipboardcalledcnt == 0) // Add header to clipboard paste
e.ClipboardRowContent.Add(new DataGridClipboardCellContent("", null, "--- Clipboard Paste ---\t\t\n")); // \t cell divider, repeat (number of cells - 1)
clipboardcalledcnt++;
e.ClipboardRowContent.Add(new DataGridClipboardCellContent(path, null, path));
if (clipboardcalledcnt == rowcnt)
clipboardcalledcnt = 0;
}
ajouter ma réponse à la question so mentionnée à titre de référence -
trouvé par Andrew Smith à http://blogs.infragistics.com/forums/t/35379.aspx -
techniquement, un seul procédé peut ouvrir le presse-papiers donc si un autre le processus a ouvert la les demandes suivantes échouer jusqu'à ce que le les premières versions du presse-papiers. Cela a été en quelque sorte manipulé dans les WinForms Classe de bloc-notes où il serait de nouveau l'ensemble avec un temps de retard entre chaque essai mais la classe de bloc-notes WPF ne fait pas cela ainsi si elle échoue sur la première montre l'exception se produit. Même alors, nous devrions probablement attraper l'exception et augmenter l'erreur d'opération de bloc-notes si elle ne fonctionne toujours pas.
la même chose est expliquée et certains moyens de la corriger sont mentionnés sur ce blog italien -
WPF DataGrid Clipboard BUG (?) Et du travail (mise en Cache de traduction) ( Orignal Lien )
suite au forum MSDN suggère qu'il pourrait s'agir d'un problème propre à la machine -
CLIPBRD_E_CANT_OPEN exception lors de la copie au bloc-notes à partir d'un DataGrid