通过c#按下Internet Explorer的“文件下载对话框”的保存按钮

我正在研究Internet Explorer自动化,其中一部分涉及从asp 2.0上托管的站点下载文件并使用基于表单的身份validation,因此为了创建端到端自动化,我使用了浏览器自动化。

我能够到达我可以点击一个带有浏览器“文件下载”对话框的URL的步骤,然后我试图利用SendKeys点击保存按钮,但无济于事不工作

下面是我使用FindWindow方法获取文件下载对话框的hWnd指针的代码,然后使用setActiveWindow使其成为活动窗口,以便SendKeys命令对其起作用,然后使用SendKeys我尝试发送Alt +但它没有用。 我观察到,Tab,Escape和Enter工作正常,但是Enter on Save按钮不起作用。

[DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr SetActiveWindow(IntPtr hWnd); private void Form1_Load(object sender, EventArgs e) { IntPtr hwnd = FindWindow(null, "File Download"); IntPtr nullptr = (IntPtr)0; if (hwnd != nullptr) { SetActiveWindow(hwnd); SendKeys.SendWait("%S"); } } 

使用相同的代码,我可以通过将FindWindow中的值更改为“Untitled – Notepad”来访问记事本。

我是否需要做一些不同的事情,因为它是一个对话框,现在是一个窗口? 我正在使用IE8。

这是我在答案后尝试的备用代码。

 IntPtr hwnd = FindWindow(null, "File Download"); IntPtr hokBtn = IntPtr.Zero; hokBtn = FindWindowEx(hwnd, hokBtn, "Button", IntPtr.Zero); hokBtn = FindWindowEx(hwnd, hokBtn, "Button", IntPtr.Zero); uint id = GetDlgCtrlID(hokBtn); SetActiveWindow(hwnd); IntPtr res = SendMessage(hokBtn, (int)0x00F5, 0, IntPtr.Zero); if (res.ToInt32() == 1) MessageBox.Show("success"); 

为清楚起见,我添加了对话框的屏幕。

alt text http://sofzh.miximages.com/c%23/www.freeimagehosting.net

这适用于C ++请注意,“保存”按钮名为“&Save”而非“保存”

 CString Title; Title=_T("File Download"); HWND FEX = ::FindWindowEx( NULL,NULL,NULL,Title); if (FEX != NULL) { //press the Save button on the dialog. HWND hokBtn = ::FindWindowEx(FEX, NULL, L"Button", L"&Save"); if (hokBtn != NULL) { UINT id = ::GetDlgCtrlID(hokBtn); ::SetActiveWindow(hokBtn); ::PostMessage(hokBtn, WM_KEYDOWN, 0x20, 0); ::PostMessage(hokBtn, WM_KEYUP, 0x20, 0); } 

}

好吧,你必须找到下载对话框标题的窗口。 而且你必须找到带有下载按钮标题的窗口/然后发送到该窗口点击消息

  BM_CLICK = 0x00F5 [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr next, string sClassName, IntPtr sWindowTitle); [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] public static extern uint GetDlgCtrlID(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam); //hDialog - handle of dialog window. idBtn - Id of button public static bool ClickButtonOnDialog(IntPtr hDialog, UInt32 idBtn) { IntPtr res = IntPtr.Zero; uint id; IntPtr hOkBtn = IntPtr.Zero; int attempt = 0; do { Thread.Sleep(300); //searching for button hOkBtn = User32.FindWindowEx(hDialog, hOkBtn, "Button", IntPtr.Zero); id = User32.GetDlgCtrlID(hOkBtn); attempt++; } while (id != idBtn && attempt < 20); if (!hOkBtn.Equals(IntPtr.Zero)) { //click the button res = User32.SendMessage(hOkBtn, (int)WindowsMessages.BM_CLICK, 1, IntPtr.Zero); } if (res.ToInt32() == 1) return true; return false; } 

你可以使用winspector(类似spy ++)。 这是非常有用的实用程序。 你可以发现很多关于windows的东西;)

尝试以下似乎对我有用的:

 IntPtr hwnd = FindWindow(null, "File Download"); IntPtr hokBtn = FindWindowEx(hwnd, null, "Button", "Cancel"); uint id = GetDlgCtrlID(hokBtn); SetActiveWindow(hwnd); IntPtr res = SendMessage(hokBtn, (int)0x00F5, 0, IntPtr.Zero); if (res.ToInt32() == 1) MessageBox.Show("success"); 

我建议你检查每个function的回报。

我在Windows XP中找到了使用Internet Explorer 6执行此操作的方法。

(对不起,VBA代码)

 'ButtonHwnd is the pointer to the Save button Private Declare Function SetCursorPos Lib "user32" (ByVal X As Integer, ByVal Y As Integer) As Long Private Declare Sub mouse_event Lib "user32.dll" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) Private Const MOUSEEVENTF_LEFTDOWN As Long = &H2 Private Const MOUSEEVENTF_LEFTUP As Long = &H4 Dim pos As RECT ' We get the button position GetWindowRect ButtonHwnd, pos ' We simulate an entering of the cursor in the button. IE think this is a human :-). ' We need three steps: out, entering and in. ' Out SetCursorPos (pos.Left - 10), (pos.Top - 10) Sleep 100 ' Entering SetCursorPos pos.Left, pos.Top Sleep 100 ' In SetCursorPos (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2 ' We do clic with the left button. You can use SendInput instead ' With 400 miliseconds it works. mouse_event MOUSEEVENTF_LEFTDOWN, (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2, 0, 0 Sleep 400 mouse_event MOUSEEVENTF_LEFTUP, (pos.Left + pos.Right) / 2, (pos.Top + pos.Bottom) / 2, 0, 0 

请告诉它是否适合你。

我在StackOverflow上找到了大部分内容: 如何在C#中使用webbrowser时处理消息框? 我为我修改了它

 using System.Runtime.InteropServices; //for the dll import (to press a key) [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); private async void downloadstuff() { await Task.Delay(40000); //i need this delay, but you might not :) { IntPtr hwnd = FindWindow("#32770", "File Download"); //this is the window it finds hwnd = FindWindowEx(hwnd, IntPtr.Zero, "Button", "&Save"); //this is the button to pres uint message = 0xf5; SendMessage(hwnd, message, IntPtr.Zero, IntPtr.Zero); } await Task.Delay(1000); { IntPtr hwnd2 = FindWindow("#32770", "Save As"); hwnd2 = FindWindowEx(hwnd2, IntPtr.Zero, "Button", "&Save"); uint message2 = 0xf5; SendMessage(hwnd2, message2, IntPtr.Zero, IntPtr.Zero); } await Task.Delay(1000); //i press it anyway, just in case :) { //this is the download complete box (if its checked it doesn't show up) IntPtr hwnd3 = FindWindow("#32770", "Download complete"); hwnd3 = FindWindowEx(hwnd3, IntPtr.Zero, "Button", "Close"); uint message3 = 0xf5; SendMessage(hwnd3, message3, IntPtr.Zero, IntPtr.Zero); } } 
  IntPtr hwnd = FindWindow(null,“File Download”);
 IntPtr hokBtn = FindWindowEx(hwnd,null,“Button”,“Cancel”);
 uint id = GetDlgCtrlID(hokBtn);
 SetActiveWindow(HWND);
 IntPtr res = SendMessage(hokBtn,(int)0x00F5,0,IntPtr.Zero);
 if(res.ToInt32()== 1)
    的MessageBox.show( “成功”); 

如果我没有错,那实际上是误报; 看似故障安全的默认行为似乎是关闭对话框。 相反,可以单击取消按钮是积极的,但是尝试单击打开或保存将在该上下文中生成相同的不需要的响应…

看来这是一个我们只需要处理的对话框,除非别人可以感激地另外确认一下?

没有任何代码建议工作,我最终使用AutoIt脚本关闭打印对话框,代码如下:

 Local $hWnd = WinWait("[CLASS:#32770]", "Print", 20) WinActivate($hWnd) WinWaitActive("[CLASS:#32770]", "Print", 10) Sleep(100) Send("{ENTER}")