为什么 PasswordBox 控件会导致我的 WPF 应用程序崩溃?

4
我花了一整天的时间试图找出为什么PasswordBox会给我带来这么多问题。
我的应用程序在我测试过的每台机器上都能正常工作。现在它已经被安装到其他机器上,每当我点击PasswordBox时,它就会崩溃。
我甚至制作了一个只有TextBoxPasswordBox控件的测试应用程序,看看是否是由于我的应用程序中的任何底层代码导致崩溃,但事实并非如此。我点击TextBox,它可以正常工作。允许我在其中输入文本。但是一旦我点击PasswordBox,应用程序就会崩溃。

我设置了以下事件以捕获任何未处理的异常:

  • Application.Current.DispatcherUnhandledException
  • AppDomain.CurrentDomain.UnhandledException
  • AppDomain.CurrentDomain.FirstChanceException

现在这应该会在发生任何错误时显示一个MessageBox。最糟糕的是,没有任何错误被抛到这些事件中。

我在我的应用程序中设置了一些日志记录,并得到了如下异常:

  • 对象引用未设置为对象的实例。
  • 尝试读取或写入受保护的内存。这通常是其他内存已损坏的迹象。

我为PasswordBox设置了一个事件,测试它是否在崩溃之前获得焦点,它确实获得了焦点,因此我不认为对象引用异常是指PasswordBox控件。
我一直在到处搜索,看看是否有其他人也遇到了这些问题,但只看到与TextBox控件及其焦点问题有关的问题,这些问题应该在.NET 4.0中得到解决。

哦!那提醒我了。我正在使用WPF .NET 4.0。

非常感谢您的帮助。

测试代码如下:

private void Application_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
    Application.Current.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler((x, y) => { ShowError(x, y); });  

    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler((x, y) => { ShowError(x, y); });
    AppDomain.CurrentDomain.FirstChanceException += new EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>((x, y) => { ShowError(x, y); });
}

private void ShowError(object sender, object o)
{
    Exception ex = null;
    if (o.GetType() == typeof(FirstChanceExceptionEventArgs))
    {
        ex = ((FirstChanceExceptionEventArgs)o).Exception;
    }
    else if (o.GetType() == typeof(DispatcherUnhandledExceptionEventArgs))
    {
        ex = ((DispatcherUnhandledExceptionEventArgs)o).Exception;
    }
    else if (o.GetType() == typeof(UnhandledExceptionEventArgs))
    {
        ex = (Exception)((UnhandledExceptionEventArgs)o).ExceptionObject;
    }
    MessageBox.Show(ex.Message + "\n\r" + ex.StackTrace, "Error at: " + ex.Source, MessageBoxButton.OK, MessageBoxImage.Error);
}

关于Xaml:

<Window x:Class="WPF_Control_Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="200" Width="300">
    <Grid>
        <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
            <StackPanel Orientation="Horizontal" Width="260">
                <TextBlock Text="TextBox: " TextAlignment="Right" Width="80" Height="Auto" VerticalAlignment="Center" />
                <TextBox Name="textBox" Width="120" VerticalAlignment="Center" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Width="260">
                <TextBlock Text="PasswordBox: " TextAlignment="Right" Width="80" Height="Auto" VerticalAlignment="Center" />
                <PasswordBox Name="passwordBoxTest" Width="120" VerticalAlignment="Center" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

事件查看器

这里是机器上的事件查看器中的异常信息:

应用程序: WPF Control Test.exe
框架版本: v4.0.30319
描述: 该应用程序通过System.Environment.FailFast(string message)请求终止进程。
消息: 不可恢复的系统错误。
堆栈:
at System.Environment.FailFast(System.String)
at MS.Internal.Invariant.FailFast(System.String, System.String)
at System.Windows.Media.FontFamily.get_FirstFontFamily()
at System.Windows.Documents.TextSelection.CalculateCaretRectangle(System.Windows.Documents.ITextSelection, System.Windows.Documents.ITextPointer)
at System.Windows.Documents.TextSelection.UpdateCaretStateWorker(System.Object)
at System.Windows.Documents.TextSelection.UpdateCaretState(System.Windows.Documents.CaretScrollMethod)
at System.Windows.Documents.TextSelection.EnsureCaret(Boolean, System.Windows.Documents.CaretScrollMethod)
at System.Windows.Documents.TextSelection.System.Windows.Documents.ITextSelection.UpdateCaretAndHighlight()
at System.Windows.Documents.TextEditor.OnGotKeyboardFocus(System.Object, System.Windows.Input.KeyboardFocusChangedEventArgs)
at System.Windows.Controls.PasswordBox.OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs)
at System.Windows.UIElement.OnGotKeyboardFocusThunk(System.Object, System.Windows.Input.KeyboardFocusChangedEventArgs)
at System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(System.Delegate, System.Object)
at System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
at System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)
at System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs)
at System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs, Boolean)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
at System.Windows.Input.KeyboardDevice.ChangeFocus(System.Windows.DependencyObject, Int32)
at System.Windows.Input.KeyboardDevice.TryChangeFocus(System.Windows.DependencyObject, System.Windows.Input.IKeyboardInputProvider, Boolean, Boolean, Boolean)
at System.Windows.Input.KeyboardDevice.Focus(System.Windows.DependencyObject, Boolean, Boolean, Boolean)
at System.Windows.Input.KeyboardDevice.Focus(System.Windows.IInputElement)
at System.Windows.UIElement.Focus()
at System.Windows.Documents.TextEditorMouse.MoveFocusToUiScope(System.Windows.Documents.TextEditor)
at System.Windows.Documents.TextEditorMouse.OnMouseDown(System.Object, System.Windows.Input.MouseButtonEventArgs)
at System.Windows.Controls.PasswordBox.OnMouseDown(System.Windows.Input.MouseButtonEventArgs)
at System.Windows.UIElement.OnMouseDownThunk(System.Object, System.Windows.Input.MouseButtonEventArgs)
at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate, System.Object)
at System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
at System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)
at System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs)
at System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs, Boolean)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
at System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr, System.Windows.Input.InputMode, Int32, System.Windows.Input.RawMouseActions, Int32, Int32, Int32)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr, MS.Internal.Interop.WindowMessage, IntPtr, IntPtr, Boolean ByRef)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)

1
我们需要看到你的代码。 - user7116
你需要查看错误的原因。既然你说已经安装了应用程序,我猜测你不会得到异常堆栈跟踪。因此,你应该查看Windows事件查看器(在运行对话框中键入“eventvwr”,然后选择“自定义视图”>“管理事件”)。这样可以让你看到通常在异常对象内找到的堆栈跟踪。 - Samuel Slade
1
这是与该xaml相关的唯一一个c#代码后台文件。对象引用错误不会发生在上面的代码中,只会发生在我的其他应用程序中。对我来说,似乎最引人注目的是那行代码,它说**System.Windows.Media.FontFamily.get_FirstFontFamily()**。也许在尝试获取字体时出现了问题?在PC上,许多字体已被删除。我不知道这是否会导致任何问题,但如果TextBox控件正常工作,这就没有太多意义了。 - mrstebo
1
相关的http://social.msdn.microsoft.com/Forums/ar/wpf/thread/fc2c9a54-8f66-4f1a-82be-cb40ada5fba5 - user7116
我会使用来自Sysinternals的procMonitor工具 http://technet.microsoft.com/en-us/sysinternals/bb896645 将过滤器设置为“processName is YourApplication”,“Result is not SUCCESS”,并查看在启动应用程序时是否出现打开字体文件或类似错误。如果需要,我可以详细说明作为答案... - SvenG
显示剩余4条评论
2个回答

3

看起来 .Net Framework 无法找到适合的默认字体。我不知道为什么会发生这种情况,但下面是 FontFamily内部 代码行,包括抛出异常的那一行:

fontFamily = this.FindFirstFontFamilyAndFace(
    ref normal, ref normal2, ref normal3);
if (fontFamily == null)
{
    // NullFontFamilyCanonicalName
    //  = CanonicalFontFamilyReference.Create(null, "#ARIAL");
    fontFamily = FontFamily.LookupFontFamily(
        FontFamily.NullFontFamilyCanonicalName);
    Invariant.Assert(fontFamily != null); // <- Your exception
}

显然,如果您没有指定字体,它将寻找一种基于Arial的字体,在该计算机上找不到,因此会出现异常。


我无法访问该机器,但我会更改我的代码以指定要使用的FontFamily。尝试后我会更新。谢谢您的解释@sixlettervariables :) - mrstebo
我今天早上刚测试了一下,现在一切都正常工作。只是有点奇怪的是 TextBoxPasswordBox 没有找到相同的默认字体! - mrstebo

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接