2

I have a cmd line exe provided for me which I cannot change at and I need to write a script around, but it has a Pause in built to it and I cannot see any way to skip this pause so the rest of my script can continue.

I have tried all sorts of things, including

Appreciate any advice

Community
  • 1
  • 1
Arvin
  • 1,391
  • 4
  • 19
  • 33
  • I should note, a similar question was asked [here](http://stackoverflow.com/questions/27088802/batch-file-calling-an-exe-that-has-pause-in-it-how-to-skip) (and linked above) but was not properly answered – Arvin Jun 30 '15 at 13:45
  • Thank you! For Ada code calling a batch script, the answer was in your question, and you can use: `if GNAT.OS_Lib.Spawn (Program_Name => "program_with_pause.bat", Args => (1 => new String'("<"), 2 => new String'("nul"))) /= 0 then`. – TamaMcGlinn Jul 13 '20 at 12:33

1 Answers1

1

You can send data to a process using interop. It's called hooking the process, and there are a few resources on it. I like this answer.

This is a little code that allows you to send message to a backgrounded application. To send the "A" char for example, simply call sendKeystroke(Keys.A), and don't forget to use namespace System.windows.forms to be able to use the Keys object.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace keybound
{
class WindowHook
{
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll")]
    public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    public static void sendKeystroke(ushort k)
    {
        const uint WM_KEYDOWN = 0x100;
        const uint WM_SYSCOMMAND = 0x018;
        const uint SC_CLOSE = 0x053;

        IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");

        IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, ((IntPtr)k), (IntPtr)0);
        //IntPtr result3 = SendMessage(WindowToFind, WM_KEYUP, ((IntPtr)c), (IntPtr)0);
    }
}
}

You'll probably have an easier time than they did getting the application instead of searching for the process because you can start it from your application:

Process proc = new Process();
proc.StartInfo.FileName = executablePath;
proc.Start();
proc.WaitForInputIdle();

Then proc.Id will be the PID.

As an alternative, I just ran into a VB type of example that seems even simpler using the Shell function, but I haven't used it before. You'll need to add a pause in your application to wait for the prompt, but this seems cleaner to read than Interop:

Dim ProcID As Integer 
' Start the Calculator application, and store the process id.
ProcID = Shell("CALC.EXE", AppWinStyle.NormalFocus)
' Activate the Calculator application.
AppActivate(ProcID)
' Send the keystrokes to the Calculator application.
My.Computer.Keyboard.SendKeys("22", True)
My.Computer.Keyboard.SendKeys("*", True)
My.Computer.Keyboard.SendKeys("44", True)
My.Computer.Keyboard.SendKeys("=", True)
' The result is 22 * 44 = 968.

If you wind up with a System.ArgumentException, it's probably because the Shell function didn't get a process ID. This is because it needs full trust. The application would work if run as administrator. I don't think you'd find an easy way around this if you can't do that since it's a security issue to have applications run each other, but I could be wrong.

Community
  • 1
  • 1
Palu Macil
  • 1,708
  • 1
  • 24
  • 34
  • Ok so I'm trying the second method you said, and when I try it in Visual Studio 2015/2013 I get an ArgumentException was unhandled An unhandled exception of type 'System.ArgumentException' occurred in Microsoft.VisualBasic.dll Additional information: Process '{0}' was not found. Though if I hit Continue, it still works and I get 968 Seems the first time the code tries to read ProcID it's still 0, but when I hit continue and it tries again then it gets the real ProcID value. Any idea? – Arvin Jun 30 '15 at 14:27
  • I explained the exception. It means the Shell command was run in a partial trust situation. See my last paragraph. – Palu Macil Jun 30 '15 at 14:33
  • Hmm when I run the program as administrator I just get 'program has stopped working' with the option to Debug or Close program – Arvin Jun 30 '15 at 14:45
  • Figured out another way which works by using Dim process As New Process process.StartInfo.FileName = "calc.exe" process.Start() procID = process.Id – Arvin Jun 30 '15 at 14:55