dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.08k stars 1.17k forks source link

Crash 'Unable to cast object of type 'System.__ComObject' to type 'ITfThreadMgr'.' #6463

Open jim-jiang-github opened 2 years ago

jim-jiang-github commented 2 years ago

image

It looks like the ‘threadManager’ value is of the wrong type?

image

Expected behavior:

Minimal repro:

lindexi commented 2 years ago

Could you add the demo ?

jim-jiang-github commented 2 years ago

Could you add the demo ?

This crash happened in our company's project, I can't disclose it, it's a once bug found by QA, we can't reproduce this problem at present

singhashish-wpf commented 2 years ago

A sample/minimal repro will be required to check this further.

miloush commented 2 years ago

The comment in the WPF code suggests this might be due to IME configuration issues which might be challenging to reproduce on other machines.

2.Is it possible that the problem is caused by the Chinese input ?

Yes, Cicero is a text services framework that deals with IMEs.

jim-jiang-github commented 2 years ago

The comment in the WPF code suggests this might be due to IME configuration issues which might be challenging to reproduce on other machines.

2.Is it possible that the problem is caused by the Chinese input ?

Yes, Cicero is a text services framework that deals with IMEs.

Is there any way we can catch this exception so far? Or is there any Workaround that can ignore this exception?

lindexi commented 2 years ago

Or is there any Workaround that can ignore this exception?

@jim-jiang-github You can disable it by Disable Thread Input Manager. But it is not the good ideas.

How to Disable Thread Input Manager? See https://social.msdn.microsoft.com/Forums/en-US/b464ecfa-1673-4f06-bba0-bf3eacaae9fc/how-do-you-turn-off-the-automation-features-of-windows-speech-recognition?forum=netfxbcl

HKEY_CURRENT_USER\Software\Microsoft\CTF "Disable Thread Input Manager"=dword:00000001

           string keyPath = @"Software\Microsoft\CTF";

            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true))
            {
                key.SetValue("Disable Thread Input Manager", 1);
            }

Why it is not the good ideas? Because the IME can not work or work well after disable Thread Input Manager.

jim-jiang-github commented 2 years ago

Or is there any Workaround that can ignore this exception?

@jim-jiang-github You can disable it by Disable Thread Input Manager. But it is not the good ideas.

How to Disable Thread Input Manager? See https://social.msdn.microsoft.com/Forums/en-US/b464ecfa-1673-4f06-bba0-bf3eacaae9fc/how-do-you-turn-off-the-automation-features-of-windows-speech-recognition?forum=netfxbcl

HKEY_CURRENT_USER\Software\Microsoft\CTF "Disable Thread Input Manager"=dword:00000001

           string keyPath = @"Software\Microsoft\CTF";

            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyPath, true))
            {
                key.SetValue("Disable Thread Input Manager", 1);
            }

Why it is not the good ideas? Because the IME can not work or work well after disable Thread Input Manager.

Thank you very much, I will try this solution. And another question is this a bug in WPF?

miloush commented 2 years ago

Can you tell us which input methods you enabled or installed? Which OS is this?

lindexi commented 2 years ago

And another question is this a bug in WPF?

I don't think so. IME has a hundred ways to crash applications.

miloush commented 2 years ago

@lindexi If the IME is valid but does not implement ITfThreadMgr then that is probably for WPF to deal with.

lindexi commented 2 years ago

@miloush Sorry, I means that we should not catch it. Because it can crash the application in any code which call the IME. Such as my call stack:

Exception: System.AccessViolationException
   in Lindexi.TextEditor.Editing.ImeNative+ITfThreadMgr.SetFocus(IntPtr)
   in Lindexi.TextEditor.Editing.ImeSupport.CreateContext()
   in Lindexi.TextEditor.Editing.ImeSupport.<.ctor>b__7_0(System.Object, System.Windows.Input.KeyboardFocusChangedEventArgs)
   in System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(System.Delegate, System.Object)
   in System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
   in System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
   in System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
   in System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)
   in System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs)
   in System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs, Boolean)
   in System.Windows.Input.InputManager.ProcessStagingArea()
   in System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
   in System.Windows.Input.KeyboardDevice.ChangeFocus(System.Windows.DependencyObject, Int32)
   in System.Windows.Input.KeyboardDevice.TryChangeFocus(System.Windows.DependencyObject, System.Windows.Input.IKeyboardInputProvider, Boolean, Boolean, Boolean)
   in System.Windows.Input.KeyboardDevice.Focus(System.Windows.DependencyObject, Boolean, Boolean, Boolean)
   in System.Windows.Input.KeyboardDevice.Focus(System.Windows.IInputElement)
   in System.Windows.UIElement.Focus()
   in Lindexi.TextEditor.TextEditor.EnterEdit()
   in Lindexi.TextEditor.TextEditor.ChangeIsEditableInner(Boolean)
   in Lindexi.TextEditor.TextEditor.OnIsEditableChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
   in System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
   in System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
   in Lindexi.TextEditor.TextEditor.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
   in System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
   in System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
   in System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, System.Object, System.Windows.PropertyMetadata, Boolean, Boolean, System.Windows.OperationType, Boolean)
   in Lindexi.Doubi.Extensions.NodeContainer.EditText()
   in Lindexi.Doubi.Extensions.SubjectNode.EditText()
   in Lindexi.Doubi.Extensions.DoubiDevice.NodeClick(System.Windows.Input.InputEventArgs, System.Windows.Point)
   in Lindexi.Doubi.Extensions.DoubiDevice.HandleDown(System.Windows.Input.InputEventArgs, System.Windows.Point)
   in Lindexi.Doubi.Extensions.DoubiDevice.Node_OnMouseDown(System.Object, System.Windows.Input.MouseButtonEventArgs)
   in System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate, System.Object)
   in System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
   in System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
   in System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
   in System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject, System.Windows.RoutedEventArgs, System.Windows.RoutedEvent)
   in System.Windows.UIElement.OnMouseDownThunk(System.Object, System.Windows.Input.MouseButtonEventArgs)
   in System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate, System.Object)
   in System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
   in System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
   in System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
   in System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)
   in System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs)
   in System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs, Boolean)
   in System.Windows.Input.InputManager.ProcessStagingArea()
   in System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
   in System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport)
   in System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr, System.Windows.Input.InputMode, Int32, System.Windows.Input.RawMouseActions, Int32, Int32, Int32)
   in System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr, MS.Internal.Interop.WindowMessage, IntPtr, IntPtr, Boolean ByRef)
   in System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   in MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
   in MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
   in System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
   in System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
   in System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
   in MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
   in MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
   in System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
   in System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
   in System.Windows.Application.RunDispatcher(System.Object)
   in System.Windows.Application.RunInternal(System.Windows.Window)
   in System.Windows.Application.Run(System.Windows.Window)
   in Lindexi.Doubi.Shell.Program.Main(System.String[])
   in Lindexi.Doubi.Program.Main(System.String[])

See my Chinese blog: https://blog.lindexi.com/post/WPF-%E8%A2%AB%E8%BE%93%E5%85%A5%E6%B3%95%E5%B8%A6%E5%B4%A9%E8%BF%9B%E7%A8%8B.html

jim-jiang-github commented 2 years ago

Can you tell us which input methods you enabled or installed? Which OS is this?

We installed Microsoft Chinese input, but we are not sure whether the Chinese input method was enabled when crash happened.

miloush commented 2 years ago

@lindexi so do you have a repro? I tried to type into a TextBox using Microsoft Pinyin and nothing happened.

lindexi commented 2 years ago

@miloush It's hard to give you a repro... Unless I find a user's computer for you remotely

miloush commented 2 years ago

@lindexi which input method at least?

lindexi commented 2 years ago

@miloush As my blog says, the Sogou input (搜狗输入法) may crash the application.

kant2002 commented 2 years ago

@lindexi I have only one idea, how can ITfThreadMgr maybe not implemented, and at the same time everything working for the user. Maybe Sogou input implement only ITfThreadMgr2 ? If you can try call TF_CreateThreadMgr and try to convert _ComObject to ITfThreadMgr2 ?

miloush commented 2 years ago

@kant2002 Doesn't ITfThreadMgr2 implement ITfThreadMgr?

kant2002 commented 2 years ago

If you implement properly, you usually implement 2 interfaces (IID), one for ITfThreadMgr and one for ITfThreadMgr2, but that not required strictly speaking. And if MS implement text services to query ITfThreadMgr2 first and fallback to old compatibility mode if it's missing, maybe that's make sense. That's pretty wild guess on my side, but we have pretty strange issue.

ThomasGoulet73 commented 2 years ago

According to the Windows SDK, ITfThreadMgr2 does not implement ITfThreadMgr (They do not share the same vtbl). It seems that even though ITfThreadMgr2 does not implement ITfThreadMgr, you can call QueryInterface with ITfThreadMgr2 on a ITfThreadMgr pointer. So if the pointer returned by TF_CreateThreadMgr is ITfThreadMgr2 it could cause this type of exception. I don't know if this is the case here because it would be very weird since TF_CreateThreadMgr returns ITfThreadMgr according to the SDK. I'm not setup to try it since it looks like it requires specific input but if anyone can try to cast everything to ITfThreadMgr2 before using the instance of the COM object it would be great.

lindexi commented 2 years ago

I find the other call stack break the application

   at System.Environment.FailFast(System.String)
   at MS.Internal.Invariant.FailFast(System.String, System.String)
   at System.Windows.Documents.TextStore.OnUpdateComposition(ITfCompositionView, ITfRange)
   at MS.Win32.UnsafeNativeMethods+ITextStoreACPSink.OnLockGranted(LockFlags)
   at System.Windows.Documents.TextStore.GrantLock()
   at System.Windows.Documents.TextStore.GrantLockWorker(LockFlags)
   at System.Windows.Documents.TextStore.RequestLock(LockFlags, Int32 ByRef)
   at MS.Win32.UnsafeNativeMethods+ITfKeystrokeMgr.TestKeyDown(Int32, Int32, Boolean ByRef)
   at System.Windows.Input.TextServicesContext.Keystroke(Int32, Int32, KeyOp)
   at System.Windows.Input.TextServicesManager.TextServicesKeystroke(System.Windows.Input.TextServicesContext, System.Windows.Input.KeyEventArgs, Boolean)
   at System.Windows.Input.TextServicesManager.PreProcessInput(System.Object, System.Windows.Input.PreProcessInputEventArgs)
   at System.Windows.Input.InputManager.ProcessStagingArea()
   at System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
jim-jiang-github commented 2 years ago

I found another crash error info here.

image

And stack: at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease) at MS.Win32.UnsafeNativeMethods.ITextStoreACPSink.OnLayoutChange(TsLayoutCode lcode, Int32 viewCookie) at System.Windows.Documents.TextStore.OnLayoutUpdated() at System.Windows.Documents.TextEditor.OnTextViewUpdatedWorker(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) --- End of stack trace from previous location --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam) at MS.Win32.UnsafeNativeMethods.DispatchMessage(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()

Norc89 commented 1 year ago

Hi, Is here any improvement i start getting similar crashes after we make redesign of our app.

CurrentDomainOnUnhandledException The application is terminating.:Exception message:Unable to cast object of type 'System.__ComObject' to type 'ITfThreadMgr'. Exception stackTrace: at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease) at MS.Win32.UnsafeNativeMethods.ITfThreadMgr.Deactivate() at System.Windows.Input.TextServicesContext.Uninitialize(Boolean appDomainShutdown) at System.Windows.Input.TextServicesContext.TextServicesContextShutDownListener.OnShutDown(Object target, Object sender, EventArgs e) at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e) at System.EventHandler.Invoke(Object sender, EventArgs e) at System.Windows.Threading.Dispatcher.ShutdownImplInSecurityContext(Object state) at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state) at System.Windows.Threading.Dispatcher.ShutdownImpl() at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame) at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Application.RunDispatcher(Object ignore) at System.Windows.Application.RunInternal(Window window) at System.Windows.Application.Run(Window window) at MsaBrowserWPF.App.Main()

And

   CurrentOnDispatcherUnhandledException :Exception message:Error HRESULT E_FAIL has been returned from a call to a COM component.
Exception stackTrace:   at MS.Win32.UnsafeNativeMethods.ITfDocumentMgr.Pop(PopFlags flags)
   at System.Windows.Documents.TextServicesHost.OnUnregisterTextStore(Object arg)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)

According to previuse version off application i have made update of WPF Material Design.

lindexi commented 1 year ago

@Norc89 What is your IME ?

Norc89 commented 1 year ago

We are using TabTipAutomation to connect Virtual keyboard with our system.

TabTipAutomation.IgnoreHardwareKeyboard = HardwareKeyboardIgnoreOptions.IgnoreAll; TabTipAutomation.BindTo<TextBox>(); TabTipAutomation.BindTo<RichTextBox>(); TabTipAutomation.ExceptionCatched += TabTipAutomation_ExceptionCatched; TabTip.Closed += TabTip_Closed; TabTip.Opened += WpfTabTipTouch_Opened;

And check if virtualApp is running. public static bool StartKeyboardApp(bool force) { try { var runningProcessByName = Process.GetProcessesByName("TabTip"); _logger.Error("TabTip instances count:" + runningProcessByName.Length + " Force:" + force.ToString()); if (runningProcessByName.Length == 0 || force) { _logger.Error("TabTip started try to start"); var result = Process.Start(@"C:\Program Files\Common Files\microsoft shared\ink\TabTip.exe"); _logger.Error("TabTip started"); return true; } else _logger.Error("TabTip is already running:"); } catch (Exception exc) { _logger.Error("TabTip exception on start" + exc.ToString()); } return false; }

lindexi commented 1 year ago

@Norc89 This is an interesting way, because I never thought about Virtual keyboard.

Norc89 commented 1 year ago

@Norc89 This is an interesting way, because I never thought about Virtual keyboard.

Yes we have touch application, this is the reason why we user virtual keyboard.

lindexi commented 1 year ago

@Norc89 Sorry, I can not reproduce it by virtual keyboard. I think I need to try more devices and systems.

Norc89 commented 1 year ago

y, I means that we should not catch it. Because it can crash the application in any code which call the IME. Such as my call stack:

Does you have in mind any work around for this ? Because error happen on production machines after some time of use. It's not possible to reproduce it in office.

lindexi commented 1 year ago

@Norc89 Sorry I don't know how to fix this isseus except to change the IME

jim-jiang-github commented 1 year ago

@lindexi The root cause of the problem we ultimately discovered was that we used 'CoInitialize' and 'UnCoInitialize' in C++ and called them through C++/CLI, but they did not appear in pairs, which ultimately led to this crash.

lindexi commented 1 year ago

@jim-jiang-github Do you mean call the CoInitialize twice without call the UnCoInitialize?

jim-jiang-github commented 1 year ago

@jim-jiang-github Do you mean call the CoInitialize twice without call the UnCoInitialize?

Yes. Alternatively, you can reproduce this issue by making multiple calls to CoInitialize in the code.