Search code examples
c#file-uploadaddeventlistenergeckogeckofx

How to choose and upload a local file to a website using Geckofx in C#?


I'm using Geckofx in my winform application to fill a form on a website. One of the controls is a button "Choose Files" which lets you select and upload a local file. I want to automate this process by doing this fully via code.

I managed to click this button via code:

Gecko.DOM.GeckoButtonElement button = new Gecko.DOM.GeckoButtonElement(doc.GetElementsByClassName("choose_files_btn").First().DomObject);
button.Click();

As a result a file dialog is opened automatically but I want to automate the file choosing part and clicking 'OK' as well. I tried inspecting the webpage to find whether I could assign the path of my local file to some Gecko element but couldn't find anything of this sort.

I also thought about handling the event of opening the file dialog but couldn't find any event handler in Gecko. I found Gecko.LauncherDialog.Download event handler which is used for handling downloading a file using Geckofx browser. But there's no such event handler for uploading files using Geckofx browser, if there is and I missed it, do tell.

Maybe I can use an event handler not from Gecko but from System, if I write an event handler which will catch every open file dialog event but I don't know whether that's even possible.


Solution

  • Here is a solution, to upload without showing the file upload dialog:

    GeckoHtmlElement el = webbrowser.DomDocument.GetElementsByTagName("input").FirstOrDefault(elz => elz.GetAttribute("type") == "file"); //inpout type file element
    var fileNames = new IntPtr[1];
    fileNames[0] = new Gecko.CustomMarshalers.WStringMarshaler().MarshalManagedToNative(file); //file = path to file you want to upload
    
    
    var domInput = Xpcom.QueryInterface<nsIDOMHTMLInputElement>(el.DOMHtmlElement);
    domInput.MozSetFileNameArray(fileNames, (uint)fileNames.Length);
    
    Marshal.ReleaseComObject(domInput);
    
    DomEventArgs ev = webbrowser.Document.CreateEvent("HTMLEvents");
    var webEvent = new Event(webbrowser.Window.DomWindow, ev.DomEvent as nsISupports);
    webEvent.InitEvent("change", true, true);
    el.GetEventTarget().DispatchEvent(ev);
    
    new Gecko.CustomMarshalers.WStringMarshaler().CleanUpNativeData(fileNames[0]); //delete everything