我已经引用了System.Windows.Forms.dll,并且想使用Application.Run();
但我的应用程序无法打开。我在控制台中没有收到任何错误,并且该应用程序在任务管理器中可见。
这是我的代码:
public partial class MainWindow : Window
{
TextBoxOutputter outputter;
public MainWindow()
{
InitializeComponent();
Init();
}
public void Init()
{
outputter = new TextBoxOutputter(TestBox);
Console.SetOut(outputter);
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => { Console.Write(character); });
Application.Run();
}
}
}
如果没有Application.Run();
应用程序会运行,但在按下任何键后立即崩溃。当它崩溃时,我收到此消息:
CallbackOnCollectedDelegate' : '对垃圾进行了回调 收集的委托类型 '击键!Keystroke.API.User32+LowLevelHook::Invoke'.这可能会 导致应用程序崩溃、损坏和数据丢失。通过时 委托给非托管代码,它们必须由托管代码保持活动状态 申请,直到保证他们永远不会被召唤。
我正在使用这个 API:https://github.com/fabriciorissetto/KeystrokeAPI
WPF 应用程序(我假设是您的(将从应用程序的入口点调用Application.Run();
。您应该能够在运行应用程序之前在应用程序中设置挂钩,然后在加载 Window 时设置控制台输出。
App.xaml
; 删除 StartupUri 标记并将其替换为 Startup,从而在App.xaml.cs
中创建新的事件回调。
App.xaml.cs
在新的启动事件回调中,您可以设置钩子。
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => { Console.Write(character); });
Application.Run();
}
MainWindow.cs
然后,一旦窗口加载完毕,您应该能够控制台的输出。
public void Init()
{
outputter = new TextBoxOutputter(TestBox);
Console.SetOut(outputter);
}
这意味着您不会在钩子仍然制作时调用Application.Run();
两次。
目前,我认为问题是,您启动应用程序,该应用程序会自动初始化新实例并运行它。然后,您还调用Application.Run();
它现在覆盖以前的初始化并重新开始。这意味着您的窗口、控制台和委托现在位于以前的被覆盖的实例中,并被 GC 销毁。因此,您已将击键 API 绑定到已销毁的委托 -(character) => { Console.Write(character); }
。