我已引用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':'对垃圾进行了回调 收集的委托类型 'KeystrokeAPI!Keystroke.API.User32 + LowLevelHook :: Invoke'。这可能 导致应用程序崩溃,损坏和数据丢失。通过时 委托非托管代码,它们必须保持托管状态 应用程序,直到确保它们不会被调用为止。'
答案 0 :(得分:3)
我假设是您的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();
,它现在覆盖先前的初始化并重新开始。这意味着您的Window,Console和Delegate现在位于先前的,被覆盖的实例中,并已被GC破坏。因此,您已将KeystrokeAPI绑定到已被销毁的委托-(character) => { Console.Write(character); }
-。