3

I want to send a single keyboard command (down arrow) to DOSBOX, followed by executing some processing code in C#, then looping. My aim is to automate the running of a DOS program.

The code I have works successfully on Notepad and Windows Explorer however will not work on DOSBOX.

This is my (simplified) code:

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

static void Main(string[] args)
{
    Console.ReadKey();
    System.Threading.Thread.Sleep(2000); //to give me time to set focus to the other window
    SendMessage(new IntPtr(0x001301CE), 0x0100, new IntPtr(0x28), new IntPtr(0));
}

I obtained the handle for the window using WinSpy++, DOSBOX only has one window and no child windows and this process works fine for notepad and explorer. The other perameters I'm sending to the SendMessage method are the code for the keyboard notification keydown and the code for the down arrow key.

So my question is, how can I modify my code to send keypresses to DOSBOX, or is there a different way that I can achieve this?

Adam
  • 524
  • 8
  • 10

2 Answers2

3

So I managed to get it working myself, here's what I found.

DOSBOX is an SDL application and so runs in OpenGL. Sending messages to OpenGL applications has been discussed before and is done using the SendInput() method. This is apparantly what SendKeys calls under the hood so I'm not sure why that wasn't working for me but it looks like I'm not the only one.

This unmaintained library seems to work fine, or a custom implementation can be done like this.

The other option as discussed in the stack overflow link above is to write a C or C++ library and call it through the C# application. This is what I ended up doing, here's the code.

Down.h

extern "C" __declspec(dllexport) void PressDownKey();

Down.cpp

#include <Windows.h>
#include "Down.h"
extern "C" __declspec(dllexport) void PressDownKey()
{
    KEYBDINPUT KeybdInput;
    ZeroMemory(&KeybdInput, sizeof(KeybdInput));
    KeybdInput.wVk = VK_DOWN;
    KeybdInput.dwExtraInfo = GetMessageExtraInfo();
    INPUT InputStruct;
    ZeroMemory(&InputStruct, sizeof(InputStruct));
    InputStruct.ki = KeybdInput;
    InputStruct.type = 1;
    int A = SendInput(1,&InputStruct,sizeof(INPUT));
    Sleep(10);
    ZeroMemory(&KeybdInput, sizeof(KeybdInput));
    KeybdInput.wVk = VK_DOWN;
    KeybdInput.dwFlags = KEYEVENTF_KEYUP;
    KeybdInput.dwExtraInfo = GetMessageExtraInfo();
    ZeroMemory(&InputStruct, sizeof(InputStruct));
    InputStruct.ki = KeybdInput;
    InputStruct.type = 1;
    A = SendInput(1,&InputStruct,sizeof(INPUT));
}
Community
  • 1
  • 1
Adam
  • 524
  • 8
  • 10
2

Microsoft has an article on this very topic from way back, along with a full implementation.

EDIT: per conversation in the comments - here is the code.

Console app:

class Program
{
    static void Main(string[] args)
    {

        ConsoleKeyInfo ki = Console.ReadKey();
        while (ki.KeyChar != 'Z')
        {
            Console.WriteLine(ki.KeyChar);
            ki = Console.ReadKey();
        }
    }
}

Winforms App:

SendKeys.SendWait("A");
Thread.Sleep(2000);
SendKeys.SendWait("Z");

You can see the output on the console app - which means it is receiving commands.

AngryHacker
  • 59,598
  • 102
  • 325
  • 594
  • This looks more to do with receiving messages in a console application, all I wish to do is to send a message to an application which I can't modify. – Adam Feb 07 '13 at 18:31
  • @Adam Oh, I see. I didn't realize you have no control over the console app? So all you want is to send keystrokes from your c# windows app to a console app? Why not just usee `System.Windows.Forms.SendKeys.SendWait()`? – AngryHacker Feb 07 '13 at 18:33
  • That was what I first tried, that doesn't work either. From my research that looked to be for sending messages to other windows forms applications. I took most of the code from [here](http://stackoverflow.com/questions/5083954/send-message-in-c-sharp) – Adam Feb 07 '13 at 18:37
  • I just tried that with notepad and it works fine, but does not work with DOSBOX. Did you try it with DOSBOX? – Adam Feb 07 '13 at 18:52
  • Tried your code, it does indeed work with a console window but not with DOSBOX, I assume because DOSBOX is an SDL application. – Adam Feb 07 '13 at 19:59
  • @Adam I just downloaded DOSBox 0.74 and my code still works. I hope we are talking about the [same DOSBox](http://imgur.com/ntuer70). – AngryHacker Feb 07 '13 at 20:07
  • @Adam I am not sure. I just downloaded, installed, double-clicked on it. It came to a DOS prompt and then I let my winforms app run. The only other thing I can think of is that you should make your DOSBox be the active app. – AngryHacker Feb 07 '13 at 21:28
  • @Adam From your screenshot, it looks like DOSBox is not the active app. – AngryHacker Feb 07 '13 at 21:33