C# WPF 控制台管理器调试断言崩溃
Posted
技术标签:
【中文标题】C# WPF 控制台管理器调试断言崩溃【英文标题】:C# WPF Console Manager Debug Assert Crash 【发布时间】:2021-10-05 11:00:24 【问题描述】:我目前正在 dotNet 中从事一个项目,我正处于一个有趣的困境中。目前,我的项目是一个 WPF 应用程序,它为控制台应用程序配置设置,然后启动应用程序的主要功能(一个无限循环的 API Hook,用于更新地图上的对象)。以前,我一直在使用在No output to console from a WPF application? 找到的解决方案,并且作为解决方案提供的 ConsoleManager 类运行良好。我最近遇到了解决方案停止工作的问题,在Debug.Assert(_out!=NULL)
的调试或发布版本中总是失败,向我吐出以下错误消息。
Process terminated. Assertion failed.
at CT_API_GUI.ConsoleManager.InvalidateOutAndError() in C:\Users\pixel\RiderProjects\AFMChronotrackAPI\ConsoleManager.cs:line 82
at CT_API_GUI.ConsoleManager.Show() in C:\Users\pixel\RiderProjects\AFMChronotrackAPI\ConsoleManager.cs:line 38
at CT_API_GUI.WinApi.Main() in C:\Users\pixel\RiderProjects\AFMChronotrackAPI\WinApi.cs:line 53
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
at CT_API_GUI.WinApi.Main()
at CT_API_GUI.MainWindow.Run_OnClick(Object sender, RoutedEventArgs e) in C:\Users\pixel\RiderProjects\AFMChronotrackAPI\MainWindow.xaml.cs:line 41
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.Controls.Primitives.ButtonBase.OnClick()
at System.Windows.Controls.Button.OnClick()
at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
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.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(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 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()
at CT_API_GUI.App.Main()
ConsoleManager 的第 82 行是Debug.Assert(_out != NULL)
当前从 JetBrains Rider IDE 2021.1.5 运行 dotNet 5.0.302。
我发现让 WPF 应用程序启动控制台有点少见,但为了正确配置设置,它使它最方便。
非常感谢任何帮助!
编辑:这是我用于 ConsoleManager 的具体代码
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace CT_API_GUI
public static class ConsoleManager
private const string Kernel32_DllName = "kernel32.dll";
[DllImport(Kernel32_DllName)]
private static extern bool AllocConsole();
[DllImport(Kernel32_DllName)]
private static extern bool FreeConsole();
[DllImport(Kernel32_DllName)]
private static extern IntPtr GetConsoleWindow();
[DllImport(Kernel32_DllName)]
private static extern int GetConsoleOutputCP();
public static bool HasConsole
get return GetConsoleWindow() != IntPtr.Zero;
/// <summary>
/// Creates a new console instance if the process is not attached to a console already.
/// </summary>
public static void Show()
//#if DEBUG
if (!HasConsole)
AllocConsole();
InvalidateOutAndError();
//#endif
/// <summary>
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
/// </summary>
public static void Hide()
//#if DEBUG
if (HasConsole)
SetOutAndErrorNull();
FreeConsole();
//#endif
public static void Toggle()
if (HasConsole)
Hide();
else
Show();
static void InvalidateOutAndError()
Type type = typeof(System.Console);
System.Reflection.FieldInfo _out = type.GetField("_out",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo _error = type.GetField("_error",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
Debug.Assert(_out != null);
Debug.Assert(_error != null);
Debug.Assert(_InitializeStdOutError != null);
_out.SetValue(null, null);
_error.SetValue(null, null);
_InitializeStdOutError.Invoke(null, new object[] true);
static void SetOutAndErrorNull()
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
【问题讨论】:
【参考方案1】:从 .NET Framework 4x 迁移到 .NET Core,System.Console
中包含对 StdOut 文本编写器的引用的字段名称已从 .NET Framework
中的 _out
更改为 .NET Core
中的 s_out
。
所以你需要调整你的反射代码...
#if NET_CORE
System.Reflection.FieldInfo _out = type.GetField("s_out", ...);
#else
System.Reflection.FieldInfo _out = type.GetField("_out", ...);
#endif
源码System.Console
.NET Core
https://source.dot.net/#System.Console/System/Console.cs,f907d79481da6ba4
源码System.Console
.NET Framework 4.6
https://github.com/microsoft/referencesource/blob/master/mscorlib/system/console.cs
【讨论】:
这正是我所需要的。像魅力一样工作。非常感谢!以上是关于C# WPF 控制台管理器调试断言崩溃的主要内容,如果未能解决你的问题,请参考以下文章
python.exe 崩溃(使用了所有系统允许的窗口管理器对象句柄)