Reputation: 6878
I have referenced System.Windows.Forms.dll, and want to use Application.Run();
but my application won't open. I don't get any errors in the console, and the application is visible in Task Manager.
This is my code:
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();
}
}
}
Without Application.Run();
the application does run but crashes immediately after pressing any key. I get this message when it crashes:
CallbackOnCollectedDelegate' : 'A callback was made on a garbage collected delegate of type 'KeystrokeAPI!Keystroke.API.User32+LowLevelHook::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.'
I am using this API: https://github.com/fabriciorissetto/KeystrokeAPI
Upvotes: 0
Views: 738
Reputation: 321
A WPF application, which I assume is yours, will call Application.Run();
from the application's entry point. You should be able to set the hook in your application before you run it then set the Console output when your Window loads.
App.xaml
;
Remove the StartupUri tag and replace it with Startup, creating a new event callback in App.xaml.cs
.
App.xaml.cs
Inside the new startup event callback, you can set the hook.
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => { Console.Write(character); });
Application.Run();
}
MainWindow.cs
Then, once your window has loaded, you should be able to Console's output.
public void Init()
{
outputter = new TextBoxOutputter(TestBox);
Console.SetOut(outputter);
}
This means you do not call Application.Run();
twice whilst hook is still made.
Currently, I believe the problem is, you launch the app, which automatically initializes a new instance and runs it. You then, also call Application.Run();
which now overrides previous initialization and starts again. This means your Window, Console & Delegate are now in a previous, overridden instance, and destroyed by GC. Thus, you have bound the KeystrokeAPI to a delegate - (character) => { Console.Write(character); }
- which has been destroyed.
Upvotes: 3