Webview2 - URL to Image - vb.net

Background
I am relatively new to using the Webview2 control instead of the built in Webbrowser one. I have successfully made some javascripts that help me log in and authenticate myself to a particular website. Within a table from this website, there are a bunch of images.
My end goal is to have a datatable on my application that has all of these images displayed. So far I have all of the source URLs for each image but just need to convert them to the actual images themselves.
How I used to be able to do it using built in Webbrowser Control
Private Async Function GetBitmapFromLink(ByVal ImagePath As String) As Task(Of Image)
Dim request As System.Net.WebRequest = System.Net.WebRequest.Create(ImagePath)
Dim response As System.Net.WebResponse = Await request.GetResponseAsync()
Dim responseStream As System.IO.Stream = response.GetResponseStream()
Dim Img As New Bitmap(responseStream)
Return Img
End Function
Goal
I would like to be able to do a similar function using the Webview2 control instead but am having a hard time finding similar functions. For example, there is no Webview2.WebRequest. I am guessing that similar functions exist in Webview2 but I am just not able to find them.
My question is: How do I make a similar image download function like the one I have shown for the old built in Webbrowser control?

WebView2 does not have a mechanism to start a web request. However, it does have CoreWebView2.WebResourceResponseReceived which you can use to monitor the responses to web requests made from within the WebView2.
You may be able to CoreWebView2.ExecuteScriptAsync to inject script to start background web requests via fetch() or new Request() and then watch for the result of those with CoreWebView2.WebResourceResponseReceived. In the CoreWebView2WebResourceResponseReceivedEventArgs there is a Response property that has a GetContentAsync() async method that gives you the response stream.

Related

How to read an arbitrary folder in a Universal app?

I'm trying to learn to write Universal apps, and I'm starting out by trying to recreate another project I wrote in WinForms. I need to be able to read from log files in an arbitrary folder, and as I understand it I need to get the users permissions to access the folder. I should then store an access token so I can re-read that folder in future. By reading around I've managed to cobble together the following code:
Friend Async Function GetLogFolder() As Task(Of StorageFolder)
Dim myLogFolder As StorageFolder
If ApplicationData.Current.LocalSettings.Values.ContainsKey("LogFolder") Then
Dim sToken As String = ApplicationData.Current.LocalSettings.Values("LogFolder")
myLogFolder = StorageApplicationPermissions.FutureAccessList.GetFileAsync(sToken)
Else
Dim myFolderPicker As FolderPicker = New FolderPicker
myFolderPicker.FileTypeFilter.Add("*")
myLogFolder = Await myFolderPicker.PickSingleFolderAsync
Dim sToken As String = StorageApplicationPermissions.FutureAccessList.Add(myLogFolder)
ApplicationData.Current.LocalSettings.Values.Add("LogFolder", sToken)
End If
Return myLogFolder
End Function
But it doesn't seem to work. At this stage I have a form containing just a TextBlock and Button. Clicking the Button calls a method that will parse all the *.log files in a given folder. The first thing it does is:
Dim myFolder As StorageFolder = GetLogFolder.Result
When the code runs, and I click the button, I get a folder browser dialog shown, but then everything freezes and I have to switch to Visual Studio and hit stop. I've probably made some silly error, but I can't figure out what it is.
Any help would be much appreciated.
The problem is very likely not caused by the file access code itself, but by the way you use the asynchronous API.
Because the GetLogFolder method returns a Task of StorageFolder, you will need to await the result instead of getting it using the Result property. The reason is that the async/await pattern allows you to do I/O work on a separate thread but return control back to the UI thread when finished. What you are doing here is to call the GetLogFolder method, in which you let the user choose a folder using FolderPicker. Here is the problem - the user is presented with a folder picker while the control returns to your code and you query the Result property of the Task returned by the GetLogFolder method. Querying the Result property causes the UI thread to stop and wait until the Task is finished to get the result. Unfortunately, when the user picks the folder, the control wants to return to the UI thread to continue executing the rest of the GetLogFolder method and we have a deadlock. Result property stopped the UI thread to wait for the Task result and the Task waits for the UI thread to become available. Neither can continue so the app completely freezes.
The solution is quite simple - using the async / await keywords. You can read up more about them in VB.NET here with a clear example.
In your case the first step would be to make the button's Click handler method async and then replace the code inside by the following:
Dim myFolder As StorageFolder = Await GetLogFolder

VB.NET Background Worker check propriety of the form TargetInvocationException

I'm working on a program that should find some image's urls from a website and should download them, i already wrote the parsing code and the downloading code, and it work, but since i noticed it's really slow i thought that it would be better if i make it work async from the form, so i created 2 background worker:
1) The parser
2) The downloader
When the parser starts the downloader starts too, the parser should add urls to a listbox, and the downloader should download them and delete from the list, i don't think it will be a problem to manage that, my real problem is... that i never used background worker...
The parser should load the page in a Webbrowser, than parse the images, but when i call the function navigate on the webbrowser... it stop giving me a TargetInvocationException.
I searched online, and from what i have seen it seems that backgrond workers cannot directly access to proprieties and methods of the GUI controls, from what i've understand it shold use Invoke, so i created a function that do all the work, and it check if the browser is in another thread or is in this thread by doing this:
Sub parse(ByVal url As String)
If wb.InvokeRequired Then 'wb is the Webbrowser
wb.Invoke(New Action(AddressOf prova))
Return
End If
'Navigate to the url, wait for browser to complete loading then do the parsing
End Sub
Now my problems are two:
1)The invokerequired propriety value is false even if i call the method from the worker, so the invoke is not called and it still give me the same exception
2)If i call invoke i should force the method to run in the GUI thread, right?
If so... shouldn't it slow my program as before?
I did it alone, the problem was that i created the components in runtime, so I should have created the handles for the components, it was enough to do something like this after creating the components:
If Not wb.IsHandleCreated Then
Dim handle As IntPtr = wb.Handle
End If
The variable handle is useless, but calling the handle propriety of the component it force the component to create the handle, that's why I made that assignment.

Saving an image via web service

Alright, long story short. I'm developing software similar to the devices UPS delivery divers use. We have to ways to get a proof of delivery(POD). The first is a signature and the second is a picture taken by the camera.
Now the device that is capturing these images sends them to a web service we have which then goes and saves them on the server. The device saves these two as different file types, png for the signature and jpg for the picture, but the web service saves them as jpg files. Currently the signatures are working but the pictures keep throwing an exception "generic exception occurred gdi+".
I don't understand why one will save just fine but the other keeps throwing the error message. Especially since they both use the same code when they are on the server side.
I've gone searched throw the stack overflow and haven't found anything that solves my issue and I've googled to no avail. Anyone have any suggestions on what to do to get the pictures to save?
Device logic to turn the image into a string so it can be sent to the web service.
**Picture from camera logic**
Using MS As New System.IO.MemoryStream(), BM As New Bitmap(ImagePath)
BM.Save(MS, System.Drawing.Imaging.ImageFormat.Jpeg)
ImageString = Convert.ToBase64String(MS.ToArray())
End Using
**Signature logic**
Using MS As New System.IO.MemoryStream(), BM As New Bitmap(ImagePath)
BM.Save(MS, System.Drawing.Imaging.ImageFormat.png)
ImageString = Convert.ToBase64String(MS.ToArray())
End Using
Web Service logic to turn image back into string, then save it as jpeg.
Dim Image As Drawing.Bitmap = Nothing
Dim ByteImage As Byte()
If ImageString.IsNullOrEmpty = False Then
ByteImage = Convert.FromBase64String(ImageString)
Using stream As New MemoryStream(ByteImage, 0, ByteImage.Length)
stream.Write(ByteImage, 0, ByteImage.Length)
Image = CType(Drawing.Bitmap.FromStream(stream, True), Drawing.Bitmap)
End Using
Image.Save(FileLocation,Drawing.Imaging.ImageFormat.Jpeg)
End If
That Image.Save is what is throwing the exception.
It appears that you save the image to some media on the phone, then you read it again and send it. Don't do that. Just save it, base 64 encode the whole file, send that base 64 encoded string.

How can I embed a swf object in a vb.net winform?

I have a swf object that I would like to embed using the COM Shockwave Flash Object control. I've searched around, but I've only found answers that involve using file or internet URLs. As I am using the One-Click publishing method, I would like to have a way to embed my flash object as a resource file into my application.
Thanks,
Matt
I've done something similar in the past but loading from a DB table rather than a resource
Swf is a AxShockwaveFlash Object on the Form to display the flash item.
If you add your resource as a .swf and set the FileType to binary it should return it as a byte array which you can then use in the memorystream constructor
Using ms As New IO.MemoryStream(my.resources.TheFlashFile), fs As New IO.MemoryStream()
Using bwriter As New IO.BinaryWriter(fs)
' Write length of stream for flash AxHost.State
bwriter.Write(8 + ms.ToArray.Length)
bwriter.Write(&H55665566)
' Length of flash movie file
bwriter.Write(ms.ToArray.Length)
bwriter.Write(ms.ToArray)
fs.Seek(0, IO.SeekOrigin.Begin)
swf.OcxState = New AxHost.State(fs, 1, False, Nothing)
End Using
End Using

vb.net - WebBrowser1.Navigate tries to download JSON file

I am trying to navigate to a website with json data using the webbrowser controls but it keeps prompting me to download the file instead of properly navigating to the page as firefox would.
I have tried doing a regular navigate:
frmBrowser.WebBrowser1.Navigate("http://us.wowarmory.com/auctionhouse/money.json")
As well as editing the header content type with many different types:
frmBrowser.WebBrowser1.Navigate("http://us.wowarmory.com/auctionhouse/money.json", "", Nothing, "Content-Type: text/plain" & vbCrLf)
But cant seem to get it working.. Keep in mind I need to use the webbrowser to navigate as you have to be logged in to access this file.
Edit: Also, manually editing my computers registry won't work as I need to distribute this program.
Edit2: Just wanted to add that this code would work if it were the same session, but since it webclient creates a new session it doesn't work
Dim oWeb As New System.Net.WebClient()
oWeb.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
Dim bytArguments As Byte() = System.Text.Encoding.ASCII.GetBytes(params)
Dim bytRetData As Byte() = oWeb.UploadData(url, "POST", bytArguments)
Return System.Text.Encoding.ASCII.GetString(bytRetData)
If your application will allow it, just rename it to money.json.html or something similar. Will download without a problem.