0

I have a CEF WinForm Application which loads a webpage for creating helpdesk tickets. I want the user to be able to click a SCREENSHOT button and have it save the file to the desktop and then automatically attach it to the webform inside the CHROMIUM Browser control.

enter image description here

I can easily save the file to the desktop, that is easy and not a problem. I have also tried

browser.DialogHandler = new TempFileDialogHandler(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\Capture.jpg");

This will take the file (CAPTURE.JPG) and attach it to the browser control, but not to the actual web page.

Can I use the javascript (script) option and somehow programmatically put this file into the FileUpload control in the page (see below)

enter image description here

I know I can have the user just click the button and manually add the file themselves, but I want to automate this process. Any help or direction would be greatly appreciated.

**** Edited Jan 7, 2021.

I tried to use the following code to use the DOM objects.

using (CefSharp.DevTools.DevToolsClient client = browser.GetDevToolsClient())
            {
                Task<GetDocumentResponse> dom = client.DOM.GetDocumentAsync();
                QuerySelectorResponse querySelectorResponse = await client.DOM.QuerySelectorAsync(dom.Result.Root.NodeId, "fileupload");
                _ = client.DOM.SetFileInputFilesAsync(new string[] { @"c:\temp\scr.png" }, querySelectorResponse.NodeId);
            }

I am using CefSharp WinForms v83. When I run the code, it hangs on the

await client.DOM.QuerySelectorAsync(dom.Result.Root.NodeId, "fileupload");

Do I need event handlers?

Edit Jan 7 2021 #2 The Following changes to the code made it work once.

await Task.Run(async () =>
                 {
                     using (CefSharp.DevTools.DevToolsClient client = browser.GetDevToolsClient())
                     {
                         var dom = client.DOM.GetDocumentAsync();
                         var querySelectorResponse = await client.DOM.QuerySelectorAsync(dom.Result.Root.NodeId, "#fileupload");
                         _ = client.DOM.SetFileInputFilesAsync(new string[] { @"C:\Users\Chris\Desktop\capture.jpg" }, querySelectorResponse.NodeId);
                         _ = client.DOM.SetFileInputFilesAsync(new string[] { @"C:\Users\Chris\Desktop\capture1.jpg" }, querySelectorResponse.NodeId);
                     }
                 });

When I try to do it again, I get the follow error: Generated MessageId 100005 doesn't match returned Message Id 100001

** Edit Jan 7 2021 #3 - I think this works.

 if (client == null)
                {
                    client = browser.GetDevToolsClient();
                    dom = client.DOM.GetDocumentAsync();
                }
                
                await Task.Run(async () =>
                 {                                              
                         var querySelectorResponse = await client.DOM.QuerySelectorAsync(dom.Result.Root.NodeId, "#fileupload");
                         _ = client.DOM.SetFileInputFilesAsync(new string[] { filename }, querySelectorResponse.NodeId);                                             
                 });
Chris Dunlop
  • 135
  • 1
  • 13
  • Likely the easiest option is to use the DevTools protocol https://chromedevtools.github.io/devtools-protocol/tot/DOM/#method-setFileInputFiles CEF supports sending DevTools commands directly to the browser. Please add the tag for the CEF wrapper you are using. – amaitland Jan 05 '21 at 04:44
  • Thank you for your comment on the DevTools. I am unable to find a suitable example. Are you aware of any? – Chris Dunlop Jan 05 '21 at 21:27
  • Are you using CefSharp? If yes please add the tag. The answer differs if you are using say CefGlue. – amaitland Jan 05 '21 at 21:42
  • Yes. CefSharp WinForm – Chris Dunlop Jan 05 '21 at 22:30
  • I think it should roughly look like https://gist.github.com/amaitland/0b05701710064203171bfd05f5002514#file-setfileinputfilesasync-cs nothing that I wrote that in notepad, so there are probably mistakes. The API doc is at http://cefsharp.github.io/api/86.0.x/html/R_Project_Documentation.htm, refer back to the DevTools API also. – amaitland Jan 07 '21 at 03:32
  • Thank you for your comments. I have looked the code and added an edit above. – Chris Dunlop Jan 07 '21 at 19:37
  • You'd have to upgrade to version 86. – amaitland Jan 07 '21 at 20:02
  • There is another option of using a DialogHandler and programatically triggering the file dialog. – amaitland Jan 07 '21 at 20:09
  • What is new in v86 that would make this work? – Chris Dunlop Jan 07 '21 at 20:14
  • See https://github.com/cefsharp/CefSharp/issues/3165 (technically it might work on version 85, though the DevTools protocol is version specific, so those methods may or may not exist in older versions). – amaitland Jan 07 '21 at 20:49
  • I upgraded to v86. I still get it hanging (just taking forever). When I try to debug, the DOM.GetDocumentAsync() keeps saying NOT YET COMPUTED and the client.DOM.QuerySelectorAsync() just runs forever. – Chris Dunlop Jan 07 '21 at 22:17
  • The GetDocumentAsync call should be awaited, my mistake. Calling Task.Result is a blocking operating and if called on the incorrect thread will cause a deadlock, await/ContinueWith should always be used. If you need to specify multiple files then add them to the string[]. As for the Generated MessageId exception can you provide a clearer description of how to reproduce the problem. – amaitland Jan 08 '21 at 00:27

1 Answers1

0

Thank you to amaitland for all the help I received on this one. Here is the code I used to make it all happen.

if (client == null)
   {
      client = browser.GetDevToolsClient();
      dom = client.DOM.GetDocumentAsync();
   }
                
await Task.Run(async () =>
   {                                              
      var querySelectorResponse = await 
           client.DOM.QuerySelectorAsync(dom.Result.Root.NodeId, "#fileupload");
      _ = client.DOM.SetFileInputFilesAsync(new string[] { filename }, 
           querySelectorResponse.NodeId);                                             
    });

I was receiving the error message:

Generated MessageId 100005 doesn't match returned Message Id 100001

until I moved the

  client = browser.GetDevToolsClient();
  dom = client.DOM.GetDocumentAsync();

out of the task.run... I am not sure why this works but it does. So... code above is what I used after the user clicked the SCREEN CAPTURE button on the windows form to capture the screen shot. I saved the file to disk (jpg) and then used this code to attach the newly created jpg file to the web page.

Chris Dunlop
  • 135
  • 1
  • 13