I am developing a C# application to automate the running of a legacy VBScript(vbs) file which calls several VB6 .exe files. The .exe files have message box pop-ups that I need to 'respond' to in order to allow the VBScript process to run unattended. The response would need to be the Enter key. I do not have the source for the .exe files and I do not know exactly what they do. I would greatly appreciate any help with this...
You might find AutoIt helpful.
AutoIt v3 is a freeware BASIC-like scripting language designed for automating the Windows GUI and general scripting. It uses a combination of simulated keystrokes, mouse movement and window/control manipulation in order to automate tasks in a way not possible or reliable with other languages (e.g. VBScript and SendKeys).
You can develop something using only the AutoIt programming language, or you can drive it from your own applications. My team's using this, with good success.
You can use the wsh SendKeys() function. However, because you need to ensure the message box is activated, you'll also need to call AppActivate() immediately before the SendKeys call.
Even this is buggy, but I've written several scripts that do just this, and as long as you can predict when the message boxes will come up, you can send the [Enter] key to respond to it.
You can do this in C# without needing some external utility. The trick is to search for the message box dialog and click its OK button. Doing it more than once requires a Timer that keeps searching for such a dialog and clicking it away. Add a new class to your project and paste this code:
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class MessageBoxClicker : IDisposable {
private Timer mTimer;
public MessageBoxClicker() {
mTimer = new Timer();
mTimer.Interval = 50;
mTimer.Enabled = true;
mTimer.Tick += new EventHandler(findDialog);
}
private void findDialog(object sender, EventArgs e) {
// Enumerate windows to find the message box
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
GC.KeepAlive(callback);
}
private bool checkWindow(IntPtr hWnd, IntPtr lp) {
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
// Got it, send the BN_CLICKED message for the OK button
SendMessage(hWnd, WM_COMMAND, (IntPtr)IDC_OK, IntPtr.Zero);
// Done
return false;
}
public void Dispose() {
mTimer.Enabled = false;
}
// P/Invoke declarations
private const int WM_COMMAND = 0x111;
private const int IDC_OK = 2;
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern IntPtr GetDlgItem(IntPtr hWnd, int item);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
Sample usage:
private void button1_Click(object sender, EventArgs e) {
using (new MessageBoxClicker()) {
MessageBox.Show("gonzo");
}
}
Might want to look at using SetWinEventHook PInvoke to detect when dialogs are being created. You can specify the hook to be global or for a specific process. You can set the WINEVENT_OUTOFCONTEXT flag to ensure that your code isn't actually running in the process you're hooking. And the event you're looking for should be EVENT_SYSTEM_DIALOGSTART.
Once you've got the hwnd of the dialog (from the event hook), you can use SendMesssage with WM_COMMAND or WM_SYSCOMMAND to get rid of it.
After spending the last 2 days trying to get this working, I finally gave up and decided on another approach. I am interrogating the data that is being sent to the external process and screening it for the conditions that are causing the message box pop-ups. Thanks to everyone who replied with answers!
Using sendkey method, Pass keyboard key value and continue execution.