代码之家  ›  专栏  ›  技术社区  ›  Anirudh Goel

通过c语言按internet explorer“文件下载对话框”的保存按钮#

  •  5
  • Anirudh Goel  · 技术社区  · 16 年前

    我正在研究internet explorer自动化,其中一部分涉及从一个网站下载文件,该网站基于asp 2.0,并使用基于表单的身份验证,因此要创建端到端自动化,我使用浏览器自动化。

    我能够到达的步骤,我可以点击一个网址,带来“文件下载”对话框的浏览器,然后我试图利用SendKeys点击保存按钮,但没有结果,它没有工作。

    下面是我使用FindWindow方法获取文件下载对话框的hWnd指针的代码,然后使用setActiveWindow使其成为活动窗口,以便SendKeys命令在其上工作,然后使用SendKeys我尝试发送Alt+S,但没有工作。我注意到,Tab、Escape和Enter都可以工作,但Enter的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://www.freeimagehosting.net/uploads/4f23586401.png

    7 回复  |  直到 13 年前
        1
  •  2
  •   Jon Cage    16 年前

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

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

    我建议你检查每个函数的返回值。

        2
  •  2
  •   John TallSmith    13 年前

    这在C++中是有效的 请注意,“保存”按钮的名称为“&“保存”而不是“保存”

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

    }

        3
  •  1
  •   smash    16 年前

    嗯,你必须找到一个标题为下载对话框的窗口。然后你必须找到标题为下载按钮/的窗口,然后发送到该窗口单击消息

      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的东西;)

        4
  •  1
  •   ELF    15 年前

    我找到了一种在WindowsXP中使用InternetExplorer6的方法。

    '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
    

    拜托,告诉我这对你有用吗。

        5
  •  1
  •   Community Mohan Dere    9 年前

    我在StackOverflow上找到了大部分: How to handle Message Boxes while using webbrowser in C#?

    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);
    }
    }
    
        6
  •  0
  •   Nev    16 年前
    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");

    如果我没有错的话,那实际上是个假阳性;默认的故障保护行为似乎是关闭对话框。相反,这是一个积极的,取消按钮可以点击,但试图点击打开或保存将产生相同的,但在该上下文中不想要的响应。。。

        7
  •  0
  •   Miro Krsjak    10 年前

    建议的代码都不起作用,我最终使用AutoIt脚本关闭了一个打印对话框,代码如下:

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