I am attempting to simulate keyboard input to programmatically play a game in VisualBoy Advance. There is no response from VisualBoy Advance when SendKeys.SendWait() is used.
private const string VBA_PROCESS_NAME = "VBA-rr-svn480";
public void Up()
{
PressButton("{UP}");
}
public void Down()
{
PressButton("{DOWN}");
}
public void Left()
{
PressButton("{LEFT}");
}
public void Right()
{
PressButton("{RIGHT}");
}
public void A()
{
PressButton("z");
}
public void B()
{
PressButton("x");
}
public void LShoulder()
{
PressButton("a");
}
public void RShoulder()
{
PressButton("s");
}
public void Start()
{
PressButton("~");
}
public void Select()
{
PressButton("+");
}
private void PressButton(string Button)
{
var VBAProcess = GetVBAProcess();
// Verify that VBA is a running process.
if (VBAProcess == null)
throw new Exception("Visual Boy Advance could not be found.");
IntPtr VBAHandle = VBAProcess.MainWindowHandle;
// Make sure that VBA is running and that we have a valid handle.
if (VBAHandle == IntPtr.Zero)
throw new Exception("Visual Boy Advance is not running.");
// Make VBA the foreground application and send it the button press.
SetForegroundWindow(VBAHandle);
SendKeys.SendWait(Button);
}
// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private Process GetVBAProcess()
{
return Process.GetProcessesByName(VBA_PROCESS_NAME).FirstOrDefault();
}
If I swap out the process name for a different process (such as notepad++) the key presses work perfectly. This leads me to believe that I must have the wrong process or window for VisualBoy Advance, but I haven't found one that looks correct when I grab all processes and look through them.
Related
I tried to make kind of an API that would ease the creation of new behaviours, inspired on Unity's one.
I'm new to C# and don't why it doesn't work. The test class I made is supposed to write infinitely until program's end what you specified in the ctor, but it doesn't write anything in the console.
Here is what I made :
1 - Program.cs
using System.IO;
namespace Program {
public abstract class Script {
public abstract void Start();
public abstract void Update();
}
class Program {
static bool IsKeyDown(ConsoleKey key) {
if (Console.ReadKey(true).Key == key) return true;
else return false;
}
public static void Main(string[] args) {
Script[] scriptList = {
new Write("Hello World"),
};
foreach (Script s in scriptList) {
s.Start();
}
while (!IsKeyDown(ConsoleKey.Escape)) {
foreach (Script s in scriptList) {
s.Update();
}
}
}
}
}
2 - Write.cs
using System;
namespace Program {
public class Write : Script {
string str;
public Write(string _str) {
str = _str;
}
public override void Start(){}
public override void Update(){
Console.WriteLine(str);
}
}
}
Sorry for bad english I'm french :)
Your code blocks on the Console.ReadKey. If there are no keys available in the input buffer then ReadKey stops and waits for the user to press a key.
You can read this info in the docs where they say
One of the most common uses of the ReadKey() method is to halt program
execution until the user presses a key and the app either terminates
or displays an additional window of information.
You just need to add
static bool IsKeyDown(ConsoleKey key)
{
if (!Console.KeyAvailable) return false;
if (Console.ReadKey(true).Key == key) return true;
else return false;
}
I have found this solution for checking if a window is open:
How do I know if a WPF window is opened
It's throwing an error back at me since my wpf window is on another thread. Is there a way to still use it?
Solution:
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return string.IsNullOrEmpty(name)
? Application.Current.Windows.OfType<T>().Any()
: Application.Current.Windows.OfType<T>().Any(w => w.Name.Equals(name));
}
if (Helpers.IsWindowOpen<Window>("MyWindowName"))
{
// MyWindowName is open
}
if (Helpers.IsWindowOpen<MyCustomWindowType>())
{
// There is a MyCustomWindowType window open
}
if (Helpers.IsWindowOpen<MyCustomWindowType>("CustomWindowName"))
{
// There is a MyCustomWindowType window named CustomWindowName open
}
I have created a sample application solving your problem after spending entire day.
Solution can be downloaded here
What it does :
Click button to create window on new thread. A new window is created for you on new thread. The moment this new window is created, this button in your mainwindow is disabled. When you close your new window, creation button in your mainwindow is enabled again.
If it doesn't fit your needs, tell your requirements, I will improve it. Same can be done using pure Win32 functions too without using our event bridge class. I am working on it. And I will post win32 version soon.
I am creating NewWindow on a separate thread. If you close MainWindow, NewWindow still runs as it is on new thread.
I am keeping it completely separate as no instance is used in MainWindow to point to NewWindow. To solve this issue I am using a Win32 handle.
For NewWindow to send notifications to MainWindow, I am using a static class WindowNotifier with static events. This class acts as the bridge between the two. In NewWindow Closing/Closed/Loaded events are used to fire events.
MainWindow handle various events of this static class to remain updated about NewWindow.
Win32 functions used :
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
ThreadCreator.cs
public static class ThreadCreator
{
private static NewWindow W;
public static void CreateWindow()
{
Thread t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private static void ThreadProc(object obj)
{
W = new NewWindow();
W.ShowDialog();
}
}
WindowNotifier.cs
public static class WindowNotifier
{
public static event CreatedDelegateCallback IamCreatedEvent;
public delegate void CreatedDelegateCallback(IntPtr handle);
public static event ClosingDelegateCallback IamClosingEvent;
public delegate void ClosingDelegateCallback (IntPtr handle);
public static event ClosedDelegateCallback IamClosedEvent;
public delegate void ClosedDelegateCallback(IntPtr handle);
public static void OnIamCreated(IntPtr handle)
{
if (IamCreatedEvent != null)
IamCreatedEvent(handle);
}
public static void OnIamClosing(IntPtr handle)
{
if (IamClosingEvent != null)
IamClosingEvent(handle);
}
public static void OnIamClosed(IntPtr handle)
{
if (IamClosedEvent != null)
IamClosedEvent(handle);
}
}
MainWindow.xaml.cs
...
void WindowNotifier_IamCreatedEvent(IntPtr handle)
{
HandleOfWindowOnNewThread = handle;
Debug.WriteLine(string.Format("I am created : {0}", handle));
btnCreateNewWindow.Dispatcher.Invoke(() => btnCreateNewWindow.IsEnabled = false);
}
void WindowNotifier_IamClosedEvent(IntPtr handle)
{
if (HandleOfWindowOnNewThread == handle)
HandleOfWindowOnNewThread = IntPtr.Zero;
Debug.WriteLine(string.Format("I am closed : {0}", handle));
btnCreateNewWindow.Dispatcher.Invoke(() => btnCreateNewWindow.IsEnabled = true);
}
...
NewWindow.xaml.cs
...
private void Window_Closed(object sender, EventArgs e)
{
WindowNotifier.OnIamClosed(Handle);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
WindowNotifier.OnIamClosing(Handle);
}
// To get correct handle we need to ensure Window is fully created and active
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_handle = GetForegroundWindow();
WindowNotifier.OnIamCreated(Handle);
}
...
Dispatcher does not help here because when window is created on a different thread, it's not contained in the Application.Windows collection, but in a collection which for some reason is not exposed (called NonAppWindowsInternal). Shortly, there is no official way to do that. Of course you can use reflection on your own risk.
But if your window is on UI thread and you just want to call the function from another thread, then you can use something like this
Application.Current.Dispatcher.Invoke(() => IsWindowOpen<...>(...))
or better change the helper method to be
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return Application.Current.Dispatcher.Invoke(() => string.IsNullOrEmpty(name)
? Application.Current.Windows.OfType<T>().Any()
: Application.Current.Windows.OfType<T>().Any(w => w.Name.Equals(name)));
}
EDIT Here is something that works currently, but may change in the future, so as mentioned above, use it on your own risk
public static class WindowUtils
{
public static bool IsWindowOpen<T>(string name = "") where T : Window
{
return FindWindow<T>(name) != null;
}
public static T FindWindow<T>(string name = "") where T : Window
{
return FindWindow<T>(WindowsInternal, name) ?? FindWindow<T>(NonAppWindowsInternal, name);
}
private static T FindWindow<T>(Func<Application, WindowCollection> windowListAccessor, string name = "") where T : Window
{
bool matchName = !string.IsNullOrEmpty(name);
var windowList = windowListAccessor(Application.Current);
for (int i = windowList.Count - 1; i >= 0; i--)
{
var window = windowList[i] as T;
if (window != null && (!matchName || window.Name == name)) return window;
}
return null;
}
private static readonly Func<Application, WindowCollection> WindowsInternal = GetWindowCollectionAccessor("WindowsInternal");
private static readonly Func<Application, WindowCollection> NonAppWindowsInternal = GetWindowCollectionAccessor("NonAppWindowsInternal");
private static Func<Application, WindowCollection> GetWindowCollectionAccessor(string propertyName)
{
var property = typeof(Application).GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
return (Func<Application, WindowCollection>)Delegate.CreateDelegate(
typeof(Func<Application, WindowCollection>), property.GetMethod);
}
}
If you return the window from your IsWindowOpen method. U can use the Invoke or BeginInvoke on the window, to dispatch the work on the thread where the window was created on.
I´m uses a thread to show wait screen. User click on button process, system create a thread to show the wait screen and the process continue and i need to show the methods that the process has invoked.
public partial class Frm_Muestra_Consulta : Form
{
private void Btn_Procesa_Click(object sender, EventArgs e)
{
Cls_Generales.Iniciar_Proceso(this);//calls the warning screen processing
Cls_Consultas.Consultando(); //running process
Cls_Generales.Terminar_Proceso(this); //Close the warning screen processing
}
}
public class Cls_Generales
{
public static void Inicia_Proceso(Form _Form)
{
Pantalla_Proceso = new Thread(new
ThreadStart(Invoca_Pantalla_Proceso));
Pantalla_Proceso.Start();
_Form.Enabled = false;
}
public static void Invoca_Pantalla_Proceso()
{ Application.Run(new Frm_Procesando()); }
public static void Termina_Proceso(Form _Form)
{ Pantalla_Proceso.Abort(); }
}
public class Cls_Consultas
{
public static DataTable Consultando()
{
//Methos to exemple
//What I want is to tell the user when the system enters and
//leaves this method
Limpiar_Tabla();
Calcular_Espacio(); //and next
return Realizar_Consulta(); //and next
}
}
How do I make the yarn see or read these methods?
this is basically a follow up to a previous question (Triggering an event in c# from c++ and declaring LPCWSTR). I've revised my code based on the answers and comments I have received and I solved the initial issue, which was passing the event to the GpioSetupInterruptPin from a gpio api. I don't have a lot of documentation on the api but what i'm trying to achieve is: have a form with a white label; after pressing a switch, the label turns yellow.
The problem i'm having now is the event seems to trigger as soon as it's created (the "execute" message is passed to the debug dialog and the label turns yellow) but it doesn't do anything when i toggle the switch. I was told in the last question to use WaitForSingleObject but i'm not really sure where to call it and this article only added to my confusion.
public partial class Form1 : Form
{
// P/Invoke CreateEvent and WaitForSingleObject
private void GPIO_Open() //get handle for gpio
private void GPIO_Output() //output pin declaration
private void button1_Click(object sender, EventArgs e)
{
Interrupt_Setup();
}
private void Interrupt_Setup()
{
hGPIO = GPIOapi.GpioOpenHandle(); //returns a handle to the gpio
GIPO_ON = true;
Debug.WriteLine("Driver open \n" + hGPIO);
GPIO_Output(); //set output pins
GPIO_Interrupt(Trigger); //configure interrupt
}
private void GPIO_Interrupt(string trigger)
{
bool ok;
_Main();
//INTERRUPT DECALRATION
ok = GPIOapi.GpioSetupInterruptPin(hGPIO, port6, 4, GPIOapi.INT_TRIGGER_MODE.TRIGGER_MODE_EDGE,
GPIOapi.INT_TRIGGER_POLARITY.TRIGGER_POL_HIGH_RISING, trigger, true);
Thread waitThread=new Thread(WaitForTrigger);
waitThread.Start();
if (!ok)
Debug.WriteLine("NO interrupt");
else
Debug.WriteLine("Interrupt set for:" + port6 + "04" + " at " + hGPIO);
}
public static string Trigger = "InputProcessUpdateHandler";
public static IntPtr handle = CreateEvent(IntPtr.Zero, false, false, Trigger); //used P/Invoke
private static InputProcessor inputProcessor = null;
public Color[] color =
{
Color.Orchid, Color.DarkOrchid, Color.GreenYellow, Color.CornflowerBlue, Color.SteelBlue,Color.Crimson
};
public int i = 0;
public void WaitForTrigger()
{
while(true)
{try
{
if (WaitForSingleObject(handle, 0xFFFFFFFF) == false)
{
BeginInvoke(((System.Action)(() =>label2.BackColor = color[i])));
i++;
if (i > 4)
i = 0;
}
Thread.Sleep(300);
}
catch (Exception e)
{ Debug.WriteLine("exception: " + e); }}
}
}
private void _Main()
{
inputProcessor = new InputProcessor();
ShowToggle showToggle = new ShowToggle(inputProcessor);
inputProcessor.Process(label1);
}
public class ShowToggle
{
private InputProcessor _inputProcessor = null;
public ShowToggle(InputProcessor inputProcessor)
{
_inputProcessor = inputProcessor;
_inputProcessor.updateHandledBy += InputProcessUpdateHandler;
}
private void InputProcessUpdateHandler(Label label)
{
label.BackColor = Color.Yellow;
Debug.Write("execute");
}
}
public class InputProcessor
{
public delegate void InputProcessUpdateHandler(Label label);
public event InputProcessUpdateHandler updateHandledBy = null;
public void Process(Label label)
{
if (updateHandledBy != null)
updateHandledBy(label);
}
}
If anyone could help me with this, I would be very grateful.
*** I got it working but it looks a right mess. Could anyone help me straighten it out?
You code is really confusing to me. I think what you want is something like this. Bear in mind I'm typing this into the SO text editor, so don't expect it to compile and just work - it's a guide. Consider it a step above pseudocode.
public class DeviceInterrupt
{
IntPtr m_gpio;
string m_eventName;
public event EventHandler OnInterrupt;
public DeviceInterrupt(int port)
{
// get a driver handle
m_gpio = GPIO_Open();
// generate some unique event name
m_eventName = "GPIO_evt_" + port;
// wire up the interrupt
GpioSetupInterruptPin(m_gpio, port, m_eventName, ...);
// start a listener
new Thread(EventListenerProc)
{
IsBackground = true,
Name = "gpio listener"
}
.Start();
}
public void Dispose()
{
// TODO: release the handle
}
private void EventListenerProc()
{
// create the event with the name we sent to the driver
var wh = new WaitHandle(false, m_eventName);
while (true)
{
// wait for it to get set by the driver
if (wh.WaitOne(1000))
{
// we have an interrupt
OnInterrupt.Fire(this, EventArgs.Empty);
}
}
}
}
Usage would then be something like this:
var intr = new DeviceInterrupt(4);
intr.OnInterrupt += MyHandler;
....
void MyHandler(object sender, EventArgs a)
{
Debug.WriteLine("Interrupt occurred!");
}
Note
The Compact Framework doesn't support actual named system events, so the named WaitHandle I use in my code above is not a CF-supplied WaitHandle. Instead I'm using the one from the Smart Device Framework. You could also P/Invoke to CreateEvent and WaitForSingleObject yourself.
I have a main thread of a Console Application that runs few external processes this way
private static MyExternalProcess p1;
private static MyExternalProcess p2;
private static MyExternalProcess p3;
public void Main() {
p1 = new MyExternalProcess();
p2 = new MyExternalProcess();
p3 = new MyExternalProcess();
p1.startProcess();
p2.startProcess();
p3.startProcess();
}
public static void killEveryoneOnExit() {
p1.kill();
p2.kill();
p3.kill();
}
class MyExternalProcess {
private Process p;
...
public void startProces() {
// do some stuff
PlayerProcess = new Process();
....
PlayerProcess.Start();
// do some stuff
}
public void kill() {
// do some stuff
p.Kill();
}
}
What I need to do is: when the Main thread is interrupted (exit button or ctrl+c), the other processes should be killed.
How do I trigger my method killEveryoneOnExit on CTRL+C or Exit (X) button?
Based on your question there are two events you need to catch.
First there is the console close event which is explained here: "On Exit" for a Console Application
Second you want to catch control c which is explained here: How do I trap ctrl-c in a C# console app
If you put these two together with your example you get something like this:
static ConsoleEventDelegate handler;
private delegate bool ConsoleEventDelegate(int eventType);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);
private static MyExternalProcess p1;
public static void Main()
{
Console.CancelKeyPress += delegate
{
killEveryoneOnExit();
};
handler = new ConsoleEventDelegate(ConsoleEventCallback);
SetConsoleCtrlHandler(handler, true);
p1 = new MyExternalProcess();
p1.startProcess();
}
public static void killEveryoneOnExit()
{
p1.kill();
}
static bool ConsoleEventCallback(int eventType)
{
if (eventType == 2)
{
killEveryoneOnExit();
}
return false;
}
For a working ctrl c (fun intended) paste example: http://pastebin.com/6VV4JKPY