2016-02-27 334 views
1

我在大量的Excel工作簿上運行C#腳本,這涉及到在每個工作簿中調用宏;由於錯誤處理程序,宏有時會生成一個MsgBox,並暫停該腳本的執行,直到在MsgBox中單擊「確定」。如何獲得VBA MsgBox的窗口句柄?

MsgBox的標題文本是「processSub中的錯誤」,主文本是「錯誤(類型不匹配)」。

我想也許我可以有一個併發線程來查找所有當前打開的窗口,如果它發現MsgBox,單擊「確定」。我試圖找到這樣的窗口使用這樣的事情:

using System.Diagnostics; 
public Process getErrorWindow() 
    { 
     Process[] processList = Process.GetProcesses(); 
     foreach (Process process in processList) 
     { 

      if (process.MainWindowTitle=="Error in processSub") 
      { 
       return process; 
      } 
     } 

    } 

但是,這沒有找到任何東西。當我查看processList[]時,它似乎只能找到主Excel窗口,而不是其VBA代碼生成的任何子窗口。有沒有辦法找到MsgBox並點擊OK按鈕?

回答

2

您可以使用winapi函數FindWindow通過標題和類檢索窗口的句柄。下面的代碼添加到您的程序:

[DllImport("user32.dll", SetLastError = true)] 
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool SetForegroundWindow(IntPtr hWnd); 

public static IntPtr FindExcelErrorPopup() 
{ 
    return FindWindow(null, "Error in processSub"); 
} 

單擊按鈕:

IntPtr hwnd = FindExcelErrorPopup(); 
if (hwnd != IntPtr.Zero) 
{ 
    SetForegroundWindow(hwnd); // activates the window 
    SendKeys.SendWait("{ENTER}"); // send ENTER key 
} 

如果默認的按鈕是不是「OK」,發送一些TAB招ENTER之前選擇它。 不要忘記把using System.Runtime.InteropServices;換成DllImport

編輯: 對於遠程桌面試試這個本地方法:

[DllImport("user32.dll")] 
private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); 

private const uint KEYEVENTF_EXTENDEDKEY = 0x0001; 
private const uint KEYEVENTF_KEYUP = 0x0002; 
const uint KEYEVENTF_EXTENDEDKEY = 0x0001; 
const uint KEYEVENTF_KEYUP = 0x0002; 

,提高這樣的鍵:

keybd_event(Keys.Enter, 0x45, KEYEVENTF_EXTENDEDKEY, UIntPtr.Zero); // key down 
keybd_event(Keys.Enter, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, UIntPtr.Zero); // key up 
+0

這個成功的作品,但是當我遠程桌面,'的SendKeys上運行.SendInput()'拋出'System.ComponentModel.Win32Exception:訪問被拒絕。有關如何解決此問題的任何想法,因爲我將在遠程桌面上運行該腳本,以便即使關閉筆記本電腦,該過程也可以繼續進行。 – sigil

+0

難道你不能添加一個try/catch來捕獲該錯誤並且在沒有窗口彈出任何消息框的情況下處理它嗎? – user3598756

+0

如果您正在執行整個FindWindow舞蹈,只需找到默認按鈕並按下即可。避免注入鍵盤事件的困難。 (如果你堅持這樣做,你應該完全使用SendInput,而不是keybd_event。) –