views:

820

answers:

3

I am working on internet explorer automation and part of it involves downloading files from a site whcih is hosted on asp 2.0 and uses forms based authentication, so to create end to end automation i used browser automation.

I was able to reach to the step where i can get to click on a URL which brings the "File Download" dialog of the browser, then i was trying to make use of SendKeys to click on the save button but to no avail it was not working.

Here is the code where i make use of FindWindow method to get the hWnd pointer of the File Download Dialog, and then using setActiveWindow i make it the active window so that the SendKeys commands works on it and then using SendKeys i tried to send Alt + S but it didnt' work. I observed that, Tab, Escape and Enter works, but then Enter on Save button doesn't work.

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

using the same code i was able to access notepad by changing the value in FindWindow to "Untitled - Notepad".

Do i need to do something different as it is a dialog and now a window? I am using IE8.

Thanks

This is the alternate code i tried after the answer.

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

For clarity i am adding the screen of the dialog alt text

+1  A: 

well, you have to find window with title of downloading dialog. and than you have to find window with title of download button/ and then send to that window click message

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

and you can use winspector (analog of spy++). it's very useful utility. You can discovery many things about windows;)

smash
see the updated question, res is returning 0. and in spy++ though i can see click message is being registered but it is not foring the window to load the file save dialog.
Anirudh Goel
so, you can try send mouse down and up events
smash
+1  A: 

Try the following which seemed to work for me:

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

I would suggest you check the returns from each function though.

Jon Cage
A: 
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");

That was actually a false positive if I'm not wrong; the default behaviour seemingly as a failsafe appears to be to close the dialog box. Rather, it was a positive that the cancel button can be clicked, but attempting to click Open or Save will generate the same yet in that context unwanted response...

It seems that this is a dialog box we're just going to have to deal with unless someone else could gratefully confirm otherwise?

Nev