Uploading Files Not Working - Need Assistance

后端 未结 2 1002
旧巷少年郎
旧巷少年郎 2020-11-27 23:12

I am trying to upload a file (an image) using the WebBrowser control. Can\'t seem to do it and need some help.

Here is the Html:

2条回答
  •  生来不讨喜
    2020-11-27 23:40

    IMO, what you're trying to do is indeed a legit scenario for UI testing automation. IIRC, in early versions of IE it was possible to populate the field with a file name, without showing up the Choose File dialog. For security reason, this is no longer possible, so you have to send keys to the dialog.

    The problem here is that file.InvokeMember("Click") shows a modal dialog, and you want the keys to be sent to that dialog, but SendKeys.Send gets executed after the dialog has been closed (it's modal, after-all). You need to let the dialog open first, then send the keys and let it close.

    This problem can be solved using WinForms Timer, but I'd prefer using async/await and Task.Delay for this (working code):

    async Task PopulateInputFile(HtmlElement file)
    {
        file.Focus();
    
        // delay the execution of SendKey to let the Choose File dialog show up
        var sendKeyTask = Task.Delay(500).ContinueWith((_) =>
        {
            // this gets executed when the dialog is visible
            SendKeys.Send("C:\\Images\\CCPhotoID.jpg" + "{ENTER}");
        }, TaskScheduler.FromCurrentSynchronizationContext());
    
        file.InvokeMember("Click"); // this shows up the dialog
    
        await sendKeyTask;
    
        // delay continuation to let the Choose File dialog hide
        await Task.Delay(500); 
    }
    
    async Task Populate()
    {
        var elements = webBrowser.Document.GetElementsByTagName("input");
        foreach (HtmlElement file in elements)
        {
            if (file.GetAttribute("name") == "file")
            {
                file.Focus();
                await PopulateInputFile(file);
            }
        }
    }
    

    IMO, this approach is very convenient for UI automation scripts. You can call Populate like this, for example:

    void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        this.webBrowser.DocumentCompleted -= webBrowser_DocumentCompleted;
        Populate().ContinueWith((_) =>
        {
            MessageBox.Show("Form populated!");
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
    

提交回复
热议问题