Search code examples
c#seleniumhtml2canvas

Capturing full screen screenshot using C# Selenium WebDriver html2canvas returns null


I have problem getting output from html2canvas JS library within Chrome automated by selenium. Response is always null, but I can see in the Chrome console that code executed successfully and screenshot has been encoded

public byte[] TakeScreenshot(string fileName)
    {
        this.logger.Debug($"Taking screenshot");
        var seleniumDownloadPath = this.seleniumEngine.GetDownloadPath();
        IJavaScriptExecutor js = Driver as IJavaScriptExecutor;
        var html2canvasJs = System.IO.File.ReadAllText(Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), this.seleniumEngine.GetHtml2CanvasPath()));
        var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(60));
        var response = new object { };

        js.ExecuteScript(html2canvasJs);

        string generateScreenshotJS =
             var canvasImgContentDecoded;
             @"function genScreenshot () {
             html2canvas(document.body).then(function(canvas) {
             window.canvasImgContentDecoded = canvas.toDataURL(""image/png"");
             console.log(window.canvasImgContentDecoded);
             return window.canvasImgContentDecoded;
             });
             }
             genScreenshot();";

        response = js.ExecuteScript(generateScreenshotJS);
}

enter image description here

I also tried solution from this Here but the behavior was unstable (e.g. when running realtime i got error of nulls, but if running using breakpoints, I got result sometime)


Solution

  • Finally found the solution after finding out that execution of script takes more time and variable was null. So added wait function to retrieve once its filled - window.canvasImgContentDecoded

    public byte[] TakeScreenshot(string fileName)
        {
            this.logger.Debug($"Taking screenshot");
            var seleniumDownloadPath = this.seleniumEngine.GetDownloadPath();
            IJavaScriptExecutor js = Driver as IJavaScriptExecutor;
            var html2canvasJs = System.IO.File.ReadAllText(Path.Combine(Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath), this.seleniumEngine.GetHtml2CanvasPath()));
            var wait = new WebDriverWait(Driver, TimeSpan.FromSeconds(60));
            var response = new object { };
    
            js.ExecuteScript(html2canvasJs);
    
            string generateScreenshotJS =
                 @"
                 var canvasImgContentDecoded;
                 function genScreenshot () {
                 html2canvas(document.body).then(function(canvas) {
                 window.canvasImgContentDecoded = canvas.toDataURL(""image/png"");
                 console.log(window.canvasImgContentDecoded);
                 });
                 }
                 genScreenshot();";
    
            response = js.ExecuteScript(generateScreenshotJS);
    
            string getSCreenShot = "return window.canvasImgContentDecoded;";
    
            var encodedPngContent = new object { };
            
            /*ADDED WAIT FUNCTION*/
            wait.Until(
            wd =>
            {
                encodedPngContent = js.ExecuteScript(getSCreenShot);
                if (encodedPngContent != null)
                {
                    return true;
                }
                return false;
            });
    
            string pngContent = encodedPngContent.ToString();
            pngContent = pngContent.Replace("data:image/png;base64,", string.Empty);
            string fileSavePath = this.seleniumEngine.GetDownloadPath() + fileName;
            File.WriteAllBytes(fileSavePath, Convert.FromBase64String(pngContent));
            byte[] fileByte = System.IO.File.ReadAllBytes(fileSavePath);
            File.Delete(fileSavePath);
            return fileByte;
        }