2010-06-08 8 views
5

Sto lavorando sull'automazione di internet explorer e parte di esso comporta il download di file da un sito che è ospitato su asp 2.0 e utilizza l'autenticazione basata su moduli, in modo da creare fine per finire l'automazione ho usato l'automazione del browser.Premere il pulsante Salva di "Finestra di download del file" di internet explorer via C#

Sono stato in grado di raggiungere il punto in cui posso arrivare a fare clic su un URL che porta la finestra di dialogo "Download del file" del browser, quindi stavo cercando di utilizzare SendKeys per fare clic sul pulsante Salva ma per inutilmente non funzionava.

Ecco il codice in cui utilizzo il metodo FindWindow per ottenere il puntatore hWnd della finestra di dialogo Download del file, quindi utilizzando setActiveWindow, lo rendono la finestra attiva in modo che i comandi SendKeys funzionino su di esso e quindi utilizzando SendKeys che ho provato inviare Alt + S ma non ha funzionato. Ho osservato che, Tab, Escape e Invio funzionano, ma il pulsante Invio su Salva non funziona.

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

Utilizzando lo stesso codice sono stato in grado di accedere notepad modificando il valore in FindWindow a "Senza titolo - Blocco note".

Devo fare qualcosa di diverso in quanto è una finestra di dialogo e ora una finestra? Sto usando IE8.

Questo è il codice alternativo che ho provato dopo la risposta.

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

Per chiarezza, aggiungo lo schermo della finestra di dialogo.

alt text http://www.freeimagehosting.net/uploads/4f23586401.png

+0

Hai scritto la tua applicazione di automazione o stai usando qualcosa come il selenio? –

+0

ho scritto la mia automazione, che è piuttosto banale. Prende essenzialmente l'oggetto IE Application, naviga in un URL. Accede tramite DOM e quindi fa clic su un URL che porta la finestra di download. –

risposta

1

bene, devi trovare la finestra con il titolo della finestra di dialogo download. e poi devi trovare finestra con titolo di pulsante per il download/e quindi inviare a quel messaggio finestra, fare clic

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

ed è possibile utilizzare winspector (analogico di Spy ++). è un'utilità molto utile. È possibile scoperta molte cose su finestre;)

+0

vedi la domanda aggiornata, res sta restituendo 0. e in spy ++ però posso vedere che il messaggio di click è stato registrato ma non sta forando la finestra per caricare la finestra di dialogo di salvataggio del file. –

+0

quindi, puoi provare a mandare il mouse su e giù per gli eventi – smash

1

provare la seguente, che sembrava funzionare per 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"); 

vorrei suggerire di verificare i rendimenti da ogni funzione però.

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

Questo in realtà era un falso positivo se non sbaglio; il comportamento predefinito apparentemente come un errore sembra essere quello di chiudere la finestra di dialogo. Piuttosto, è stato positivo che il pulsante Annulla possa essere cliccato, ma tentare di fare clic su Apri o Salva genererà lo stesso ancora in quel contesto risposta indesiderata ...

Sembra che questa sia una finestra di dialogo siamo solo intenzione di avere a che fare a meno che qualcun altro possa confermare con gratitudine altrimenti?

1

Ho trovato un modo per farlo con Internet Explorer 6 in Windows XP.

(Siamo spiacenti, codice 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 

prega, dire se funziona per voi.

2

questo funziona in C++ Nota che il pulsante 'Salva' si chiama '& Salva' non 'Salva'

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

}

1

ho trovato la maggior parte di questo su StackOverflow: How to handle Message Boxes while using webbrowser in C#? e l'ho modificato per me

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

troppo codice e meno descrizione non è il benvenuto. Si prega di spiegare la soluzione. Grazie – Nabin

0

Nessuno del codice suggerito ha funzionato, fine per utilizzare una finestra di dialogo Stampa automatica, il codice segue:

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