You can inject JavaScript to return file to your C# code from WebBrowser control and save it wherever you want without popping up the save as dialog box. Injecting JavaScript is really helpful if a website being automated requires login and implements sessions or request verifications etc.
The logic is to inject JavaScript that downloads file as bytes (in the WebBrowser control) and then convert bytes to base64 string and return base64 string to C#. Then C# code will convert base64 string to bytes and will save bytes as file on disk. It can be any file e.g. Excel or PDF etc.
Because WebBrowser control is based on Internet Explorer, so it does not support fetch API, so you have to use XMLHttpRequest. When the page in WebBrowser control has download link ready, then inject following script into the document in WebBrowser control:
string strScript = "var fileInBase64; " +
"var oReq = new XMLHttpRequest();" +
" oReq.onload = function(e) {" +
" var buffer = oReq.response;" +
" //Convert response to base64 string" +
" var reader = new FileReader();" +
" reader.readAsDataURL(buffer);" +
" reader.onloadend = function() {" +
" fileInBase64 = reader.result;//Buffer value in fileInBase64" +
" }" +
" };" +
" oReq.open('GET', 'downloadLink');" +
" oReq.responseType = 'blob';" +
" oReq.send(); ";
HtmlElement head = wb.Document.GetElementsByTagName("head")[0];
HtmlElement script = wb.Document.CreateElement("script");
script.SetAttribute("text", strScript);
head.AppendChild(script);
Because result from XMLHttpRequest may not be ready immediately, so to retrieve value of fileInBase64 variable inject other script after a wait of 1 or 2 seconds or add another condition (or logic) to wait until file in fileInBase64 variable is not ready.
string strScript = "function getBase64(){return fileInBase64;}";
HtmlElement head = wb.Document.GetElementsByTagName("head")[0];
HtmlElement script = wb.Document.CreateElement("script");
script.SetAttribute("text", strScript);
head.AppendChild(script);
object o = wb.Document.InvokeScript("getBase64");
Now object o has the file as base64 string and is ready to be saved wherever you want. Use following code to save it on disk:
o = o.ToString().Replace("data:application/excel;base64,", ""); //replace to make a valid base64 string.
System.IO.File.WriteAllBytes("D:/file.xls", Convert.FromBase64String(o.ToString()));
For me this was the best solution to bypass save dialog box when file is downloaded from WebBrowser control. I hope this will help others also.