Skipping 'press any key to continue' on external exe program

时间:2015-06-30 13:44:30

标签: windows batch-file cmd exe

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

1 个答案:

答案 0 :(得分: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.