WPF应用程序无法使用Application.Run()打开。

时间:2018-08-09 23:50:39

标签: c# wpf

我已引用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'。这可能   导致应用程序崩溃,损坏和数据丢失。通过时   委托非托管代码,它们必须保持托管状态   应用程序,直到确保它们不会被调用为止。'

我正在使用以下API:https://github.com/fabriciorissetto/KeystrokeAPI

1 个答案:

答案 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); }-。