Search code examples
c#processdesktop-applicationrpg

How to run interactive RPG Application from C#?


I'm trying to run interactive RPG/MAPICS programs from C#. To do this, I'm trying to launch a .ws file via PCSWS.EXE and write input to it from C#.

The emulator launches just fine, but I can't seem to be able to send input to it, either by Standard Input or by SendMessage (I tried both via SETTEXT and KEYDOWN).

What am I doing wrong, here? How should I approach launching an interactive RPG program from C#?

public void LaunchRPGApp(Application program)
{
    var processInfo = new ProcessStartInfo("pcsws.exe")
    {
        WindowStyle = ProcessWindowStyle.Normal,
        Arguments = "\"C:\\Program Files (x86)\\IBM\\Client Access\\Emulator\\Private\\veflast1.ws\"",
        RedirectStandardInput = true,
        UseShellExecute = false,
    };
    var process = Process.Start(processInfo);

    SendTextToProcess(process, "f");//Try via SendMessage

    using (var sr = process.StandardInput)//Try via StdIn
    {
        sr.Write("f");//does nothing
        sr.Close();
    }
}

[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
private void SendTextToProcess(Process p, string text)
{
    const int WM_SETTEXT = 0x000C;
    const int WM_KEYDOWN = 0x0100;
    const int F_KEY = 0x46;
    Thread.Sleep(500);
    var child = FindWindowEx(p.MainWindowHandle, new IntPtr(0), "Edit", null);
    SendMessage(child, WM_KEYDOWN, F_KEY, null);//does nothing
    SendMessage(child, WM_SETTEXT, 0, text);//does nothing
}

Solution

  • Found the solution - a VBScript macro may be run on starting the PCSWS.EXE by appending "/M={macroName}" to the arguments. Note that the macro must exist in a specific folder. The macro then sends keystrokes using autECLSession.autECLPS.SendKeys.

    Like so:

    public void LaunchRPGApp(Application program)
    {
        MakeMacro(program);
    
        const string wsPathAndFilename =
            "C:\\Program Files (x86)\\IBM\\Client Access\\Emulator\\Private\\flast1.ws";
        var processInfo = new ProcessStartInfo("pcsws.exe")
        {
            Arguments = "{wsPathandFilename} /M=name.mac"
        };
        Process.Start(processInfo);
    }
    
    private void MakeMacro(Application program)
    {
        var macroText = GetMacroText(program);//Method to get the content of the macro
    
        var fileName =
            $"C:\\Users\\{Environment.UserName}\\AppData\\Roaming\\IBM\\Client Access\\Emulator\\private\\name.mac";
    
        using (var writer = new StreamWriter(fileName))
        {
            writer.Write(macroText);
        }
    }