Как автоматизировать ответ на msgbox - PullRequest
1 голос
/ 17 апреля 2010

Я занимаюсь разработкой приложения на C # для автоматизации запуска устаревшего файла VBScript (vbs), который вызывает несколько файлов VB6 .exe. Файлы .exe имеют всплывающие окна с сообщениями, на которые мне нужно «ответить», чтобы позволить процессу VBScript запускаться без присмотра. Ответ должен быть ключом Enter. У меня нет источника для файлов .exe, и я не знаю точно, что они делают. Я был бы очень признателен за любую помощь с этим ...

Ответы [ 6 ]

2 голосов
/ 17 апреля 2010

Вы можете использовать функцию wsh SendKeys () . Однако, поскольку вам необходимо убедиться, что окно сообщения активировано, вам также необходимо вызвать AppActivate () непосредственно перед вызовом SendKeys.

Даже если это глючит, но я написал несколько скриптов, которые делают именно это, и если вы можете предсказать, когда появятся окна сообщений, вы можете отправить клавишу [Enter], чтобы ответить на нее.

2 голосов
/ 17 апреля 2010

Вы можете найти AutoIt полезным.

AutoIt v3 является бесплатной BASIC-подобной скриптовый язык предназначен для автоматизация графического интерфейса Windows и общего сценарии. Он использует комбинацию симулированные нажатия клавиш, движение мыши и окно / управление манипуляциями в Для того, чтобы автоматизировать задачи таким образом, не возможно или надежно с другими языки (например, VBScript и SendKeys).

Вы можете разрабатывать что-либо, используя только язык программирования AutoIt, или вы можете управлять им из своих собственных приложений. Моя команда использует это с большим успехом.

1 голос
/ 18 апреля 2010

Может потребоваться использовать SetWinEventHook PInvoke, чтобы определить, когда создаются диалоги. Вы можете указать хук как глобальный или для определенного процесса. Вы можете установить флаг WINEVENT_OUTOFCONTEXT, чтобы гарантировать, что ваш код на самом деле не работает в процессе, который вы подключаете. И событие, которое вы ищете, должно быть EVENT_SYSTEM_DIALOGSTART.

После того, как вы получили hwnd диалога (из ловушки событий), вы можете использовать SendMesssage с WM_COMMAND или WM_SYSCOMMAND, чтобы избавиться от него.

1 голос
/ 18 апреля 2010

Вы можете сделать это в C # без какой-либо внешней утилиты. Хитрость заключается в том, чтобы найти диалоговое окно сообщения и нажать кнопку «ОК». Чтобы сделать это более одного раза, требуется таймер, который продолжает поиск такого диалога и щелкает по нему. Добавьте новый класс в ваш проект и вставьте этот код:

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);
}

Пример использования:

private void button1_Click(object sender, EventArgs e) {
  using (new MessageBoxClicker()) {
    MessageBox.Show("gonzo");
  }
}
0 голосов
/ 28 апреля 2010

Используя метод sendkey, передайте значение клавиши клавиатуры и продолжите выполнение.

0 голосов
/ 18 апреля 2010

Потратив последние 2 дня, пытаясь заставить это работать, я наконец сдался и выбрал другой подход. Я запрашиваю данные, отправляемые внешнему процессу, и проверяю их на наличие условий, вызывающих всплывающие окна с сообщениями. Спасибо всем, кто ответил с ответами!

...