Search code examples
vb.netwinformsasync-awaitwebview2

How do I save an image from CapturePreviewAsync stream?


I don't understand much about Async, but I get no errors when running this, and still I don't get an image in C:\temp\test.jpg - what am I doing wrong?

Private Sub WebView22_Click(sender As Object, e As EventArgs) Handles WebView22.Click
    grabpic()
End Sub

Public Async Function grabpic() As Threading.Tasks.Task
    Dim ms As System.IO.Stream
    Await (WebView22.CoreWebView2.CapturePreviewAsync(CoreWebView2CapturePreviewImageFormat.Jpeg, ms))
    Dim file As New System.IO.FileStream("C:\temp\test.jpg", IO.FileMode.Create)
    ms.CopyTo(file)
    ms.Close()
End Function

Solution

  • There are a few problems with your code:

    1. You're not awaiting the graphics() function, and therefore exceptions are being silently swallowed. Also, I'm not exactly sure what triggers the Click event of a WebView2 control (assuming it can actually be triggered). So, instead, you probably should test using a button click, for example.

    2. You're not initializing ms at all, which will cause a NullReferenceException. You probably wanted to create an instance of MemoryStream.

    3. You're calling ms.CopyTo after writing to the stream. At that point, the current position will be at the end of the stream and nothing will be written to file. You either need to set the position at the beginning (i.e., ms.Seek(0, SeekOrigin.Begin) or use ms.WriteTo() instead.

    With that, the graphics() method would look something like this:

    Public Async Function grabpic() As Task
        Using ms As New IO.MemoryStream()
            Await WebView22.CoreWebView2.CapturePreviewAsync(
                CoreWebView2CapturePreviewImageFormat.Jpeg, ms)
            Using file As New IO.FileStream("C:\temp\test.jpg", IO.FileMode.Create)
                ms.Seek(0, IO.SeekOrigin.Begin)
                ms.CopyTo(file)
            End Using
        End Using
    End Function
    

    However, you don't really need a MemoryStream in this case. You could just write directly to the FileStream. Here's what the final code should look like:

    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Await grabpic()
    End Sub
    
    Public Async Function grabpic() As Task
        Using file As New IO.FileStream("C:\temp\test.jpg", IO.FileMode.Create)
            Await WebView22.CoreWebView2.CapturePreviewAsync(
                CoreWebView2CapturePreviewImageFormat.Jpeg, file)
        End Using
    End Function