WebView2 site not loading - c#

I have downloaded and attached the FixedVersionRuntime.88.0.705.81.x64 for WebView2 and attached it to my project.
Using the following it should load the necessary page but when loading the WebView is not crashing but no page is loaded:
public async Task InitializeAsync()
{
string installPath = #"C:\Program Files (x86)\WebView2Runtime\Microsoft.WebView2.FixedVersionRuntime.88.0.705.81.x64\";
var webView2Environment = await CoreWebView2Environment.CreateAsync(installPath);
await browserControl.EnsureCoreWebView2Async(webView2Environment);
}
I am then setting the source after this:
await InitializeAsync();
me.Source = new Uri(((MainViewModel)this.DataContext).Config.DefaultURL);
When using the evergreen installer it worked fine but when moving to the fixed version it seems to not load correctly when deployed.

I've tested the following, which seems to work:
Download WebView2 Fixed Version
Example
Given:
WebView2 Fixed Version: Microsoft.WebView2.FixedVersionRuntime.88.0.705.81.x86.cab
Project folder: C:\Projects\WpfTestFixedVersion
Output folder: C:\Projects\WpfTestFixedVersion\WpfTestFixedVersion\bin\Debug
Project compiled using:
Configuration: Debug
Platform: Any CPU (Prefer 32-bit)
Extract files from .cab
Open a cmd window
cmd window
C:\Users\Test\Downloads> expand Microsoft.WebView2.FixedVersionRuntime.88.0.705.81.x86.cab -F:* "C:\Projects\WpfTestFixedVersion\WpfTestFixedVersion\bin\Debug"
Note: When using expand in the above command, the destination folder must already exist and the name must not end with '\'.
C:\Projects\WpfTestFixedVersion\WpfTestFixedVersion\bin\Debug
C:\Projects\WpfTestFixedVersion\WpfTestFixedVersion\bin\Debug\Microsoft.WebView2.FixedVersionRuntime.88.0.705.81.x86
Option 1:
InitializeAsync
public async Task InitializeAsync()
{
string installPath = #".\Microsoft.WebView2.FixedVersionRuntime.88.0.705.81.x86";
var webView2Environment = await CoreWebView2Environment.CreateAsync(installPath);
await browserControl.EnsureCoreWebView2Async(webView2Environment);
}
Option 2:
Note: This option allows one to specify the userDataFolder. If it's not specified, it uses the user's temp folder as the location for the userDataFolder.
InitializeAsync
public async Task InitializeAsync(WebView2 wv, string webCacheDir = "")
{
CoreWebView2EnvironmentOptions options = null;
string tempWebCacheDir = string.Empty;
CoreWebView2Environment webView2Environment = null;
//set value
tempWebCacheDir = webCacheDir;
if (String.IsNullOrEmpty(tempWebCacheDir))
{
//get fully-qualified path to user's temp folder
tempWebCacheDir = System.IO.Path.GetTempPath();
tempWebCacheDir = System.IO.Path.Combine(tempWebCacheDir, System.Guid.NewGuid().ToString("N"));
}
//use with WebView2 FixedVersionRuntime
webView2Environment = await CoreWebView2Environment.CreateAsync(#".\Microsoft.WebView2.FixedVersionRuntime.88.0.705.81.x86", tempWebCacheDir, options);
//webView2Environment = await CoreWebView2Environment.CreateAsync(#"C:\Program Files (x86)\Microsoft\Edge Dev\Application\90.0.810.1", tempWebCacheDir, options);
//webView2Environment = await CoreWebView2Environment.CreateAsync(null, tempWebCacheDir, options);
//wait for CoreWebView2 initialization
await wv.EnsureCoreWebView2Async(webView2Environment);
}

The answer by #user9938 is comprehensive. But please also note that the version of "WebView2Loader.dll" which is in use is very crucial. I had almost the same problem with "Microsoft.WebView2.FixedVersionRuntime.101.0.1210.39.x64" when I tried to use the WebView2 component in the MMC Snap-Ins with types of "HTMLView" or "FormView".
I just copied the abovementioned dll file (version 1.0.1248.0, size=157640 bytes) in a proper path that was accessible for the project (you could just put it beside your project output files first to test it) and then WebView2 browser started to function as expected. Microsoft error messages sometimes (at least in my case) was a little bit misleading and did not convey enough and to the point information.
I received "BadImageFormatException" that normally occurs when you mix platform targets (for example using a dll file compiled in X64 in an application that targeted for x86 or vice versa) or mix native code and .NET but that was not my problem at all. I hope this help one who may stuck in.

Related

Read audio file duration in C# on Linux with .net 6

I have an asp.net core API that was recently updated from .net5 to .net6.
There is a piece of code that should read a duration of an audio file. The code that seems to have worked on previous versions was this:
try
{
//
// NAudio -- Windows only
//
using var fileReader = new AudioFileReader(filePath);
return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (DllNotFoundException)
{
try
{
//
// LibVLCSharp is crossplatform
//
using var libVLC = new LibVLC();
using var media = new Media(libVLC, filePath, FromType.FromPath);
MediaParsedStatus parsed = Task.Run(async () => await media.Parse(MediaParseOptions.ParseNetwork, timeout: 2000).ConfigureAwait(false)).Result;
if (parsed != MediaParsedStatus.Done) throw new ArgumentException("Could not read audio file");
if (!media.Tracks.Any(t => t.TrackType == TrackType.Audio) || (media.Duration <= 100)) throw new ArgumentException("Could not read audio from file");
return Convert.ToInt32(Math.Ceiling(TimeSpan.FromMilliseconds(media.Duration).TotalSeconds));
}
catch (Exception ex) when (ex is DllNotFoundException || ex is LibVLCSharp.Shared.VLCException)
{
try
{
using var fileReader = new Mp3FileReader(filePath);
return Convert.ToInt32(Math.Ceiling(fileReader.TotalTime.TotalSeconds));
}
catch (InvalidOperationException)
{
throw new ArgumentException("Could not read audio file");
}
}
}
The application was deployed on Linux and, I don't know which part of the code did the exact calculation (I am assuming the VLC part), but since the update to .NET6, all of these fail, and since the last fallback is NAudio, we get the following exception:
Unable to load shared library 'Msacm32.dll' or one of its dependencies.
I am using Windows, but I tried running the app with WSL, and I can't get the VLC part to run either - it always throws the following exception (even after installing vlc and vlc dev SDK):
LibVLC could not be created. Make sure that you have done the following:
Installed latest LibVLC from nuget for your target platform.
Unable to load shared library 'libX11' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibX11: cannot open shared object file: No such file or directory at LibVLCSharp.Shared.Core.Native.XInitThreads()
at LibVLCSharp.Shared.Core.InitializeDesktop(String libvlcDirectoryPath)
at LibVLCSharp.Shared.Helpers.MarshalUtils.CreateWithOptions(String[] options, Func`3 create)
Is there any clean way to read a duration of an audio file on all platforms?
Needless to say, NAudio works like a charm on Windows, and so does the VLC (with the proper nuget package).
If you install ffmpeg, you can do this quite easily. ffmpeg comes installed in most linux distros by default, but in case it isn't, you can install it with your favorite package manager.
sudo apt install ffmpeg
To install it in windows, you'll need to download the build files, extract it, and add it to the PATH.
Next, install Xabe.FFMpeg package in your project.
Finally, you can call the static method Xabe.FFMpeg.FFMpeg.GetMediaInfo() to get all information regarding your audio file. Here is a sample snippet that I tested on my linux machine.
using System;
using System.IO;
using Xabe.FFmpeg;
namespace Program;
public static class Program
{
public static void Main(string[] args)
{
string filename;
if (args.Length == 0)
{
Console.WriteLine("No arguments found! Provide the audio file path as argument!");
return;
}
else if (File.Exists(filename = args[0]) == false)
{
Console.WriteLine("Given file does not exist!");
return;
}
try
{
var info = FFmpeg.GetMediaInfo(filename).Result;
TimeSpan duration = info.Duration;
Console.WriteLine($"Audio file duration is {duration}");
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
The error you are seeing is because we were assuming that you would display a video on linux, using X11, so we are always initializing X11. See here.
We shouldn't do that for your use case(because you may not have a GUI available). Please report the issue here : https://code.videolan.org/videolan/LibVLCSharp/-/issues
or even better, submit a pull request on github or gitlab.
As for your question of why did it work on .net 5 and not anymore, I'm not sure we have enough info to tell why, because you didn't send us the error message from that machine.
I would encourage you to take a look at atldotnet. It is a small, well maintained completely managed code / cross platform library without any external dependencies and was accurate detecting audio file duration in all of my test cases (more accurate than ffmpeg). Most common audio formats are supported.
var t = new Track(audioFilePath);
// Works the same way on any supported format (MP3, FLAC, WMA, SPC...)
System.Console.WriteLine("Duration (ms) : " + t.DurationMs);

Winforms WebView2 with fixed runtime not working from shared folder

I'm using a fixed version of WebView2 runtime like described in WebView2 working without WebView2 Runtime.
When I save this fixed runtime folder on my local machine it works fine. But as soon as I try to access the exact same folder on a shared folder/server it does not work. Any ideas?
public Form1()
{
InitializeComponent();
this.InitWeb();
}
public async void InitWeb()
{
var webEnv = await CoreWebView2Environment.CreateAsync(#"\\SharedFolder\FixedVersionFolder", Path.GetTempPath());
//var webEnv = await CoreWebView2Environment.CreateAsync(#"C:\FixedVersionFolder", Path.GetTempPath());
await this.webView21.EnsureCoreWebView2Async(webEnv);
webView21.Source = new Uri("https://www.microsoft.com");
}
In this case the webview does not show but if I replace the webEnv init line with the commented one, which points to my local folder it works just fine. I have tried multiple shared folders including creating one on my computer and it does not work.
The solution that worked for me was setting the WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS to --no-sandbox before the initialization of webview. I'm aware that this can cause some security risk, so use at your own risk.
Environment.SetEnvironmentVariable("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--no-sandbox");

C# Selenium Webdriver

I started using selenium with CS and have one issue. When code is compiled, program cannot find webdriver path, because it's being moved into the .exe file. I fixed this problem, by copying driver into the bin folder, so program can access it again. However, I want it to be able to access that driver inside .exe file.
I was doing this in python using os path:
def resource_path(relative_path: str) -> str:
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.dirname(__file__)
return os.path.join(base_path, relative_path)
If anyone knows how to do this in cs, please let me know.
Code that I'm using in c#:
var browser = new EdgeDriver();
browser.Navigate().GoToUrl(link);
webdrivermanager should be more helpful here. you can add its Nuget and use to manage drivers for browsers without requiring the driver exe files.
I use something like this and call this method everytime I need a browser.
public static InternetExplorerDriver InitBrowser(string browserName)
{
switch (browserName)
{
case "IE":
{
var IE_DRIVER_PATH = #"C:\PathTo\IEDriverServer";
InternetExplorerDriver driver = new InternetExplorerDriver(IE_DRIVER_PATH);
return driver;
}
}
return null;
}
This allows you to define the path from which to grab the driver, and so you wont have to depend on it being in your BIN folder. There are other solutions but this is what I have that works really well for me. You are set up to use this method for other browsers by adding more switch cases, and also from here you can easily add your browser options. You can call the method in your tests using:
InternetExplorerDriver driver = InitBrowser(IE);
Here it is simplified without the switch case:
var IE_DRIVER_PATH = #"C:\PathTo\IEDriverServer";
InternetExplorerDriver driver = new InternetExplorerDriver(IE_DRIVER_PATH);

KnownFolders.GetFolderAsync never returns in .NET Core 5

I am using Uno Platform to make an app which access a specific folder inside the user's Documents library from a game (BeamNG.drive). I want the app to read all the mod files inside this folder to be able to edit and display them to users on startup. I installed the Nito.Mvvm.Async Package to help me bind everything to the UI.
Here's part of the method that loads the mod files from the Documents folder:
public static async Task<List<Mod>> GetModList()
{
StorageFolder documents = await KnownFolders.DocumentsLibrary.GetFolderAsync("BeamNG.drive");
IReadOnlyList<StorageFile> fileList = await documents.GetFilesAsync();
List<Mod> foundModsList = new();
foreach (StorageFile file in fileList)
{
//...
}
return foundModsList;
}
Here's the code on MainPage.xaml.cs inside the Shared project in my solution, based on code from this answer
public NotifyTask<ObservableCollection<Mod>> ModsData { get; }
public MainPage()
{
InitializeComponent();
ModsData = NotifyTask.Create(InitModData());
}
private static async Task<ObservableCollection<Mod>> InitModData()
{
return new(await ModManager.GetModList());
}
The GetModList() method is called, but the GetFolderAsync("BeamNG.drive") method never returns, and the app keeps running normally (not UI freezes or anything). If I add a breakpoint in that line, Visual Studio stops there normally. But if I press "Step Over", instead of continuing on that method, VS jumps to this line...
return new(await ModManager.GetModList());
...then this one:
ModsData = NotifyTask.Create(InitModData());
Using ConfigureAwait(false) in any of the calls using await doesn't help anything. I'm really not sure what is going on and I suspect that Nito.Mvvm.Async might have something to do with it (considering its last update was in 2017) but I'm really not sure.
From your question it seems this problem occurs under .NET 5 - meaning targeting WebAssembly or Skia targets of Uno Platform. Under Uno, the KnownFolders type is not yet supported, so accessing DocumentLibrary is not possible. If you want to have this supported, please file an issue on Uno Platform GitHub.
In case of UWP, to access the Documents library, you need to declare a special capability in app manifest (see Docs). However, it is a restricted capability and it is quite likely that if you utilize it, the app will not pass Microsoft Store certification. Instead, it is recommended to use FolderPicker instead and let the user decide on the location when files are stored, or to use ApplicationData.Current.LocalFolder to store the data for the app privately.

SSIS Script Task is not running code inside but not failing

I'm new in generating SSIS packages programmatically and I have an issue in one of the components that I'm generating.
I'm generating a Script Task programmatically with the code below:
private void EditScriptTask(ref ScriptTask pScriptTask, List<VariablesSsis> variablesSsis)
{
pScriptTask.ScriptProjectName = ScriptTaskProjectName;
// Set the script language - "CSharp"
pScriptTask.ScriptLanguage = VSTAScriptLanguages.GetDisplayName("CSharp");
// Set variables to be used in the script task code (read and write variables)
pScriptTask.ReadWriteVariables = ReadVariableScriptString(variablesSsis);
// Create a new project from the template located in the default path - script task associated project
pScriptTask.ScriptingEngine.VstaHelper.LoadNewProject(pScriptTask.ProjectTemplatePath, null, ScriptTaskProjectName);
//Initialize the designer project, add a new code file, and build
pScriptTask.ScriptingEngine.VstaHelper.Initalize("", true);
pScriptTask.ScriptingEngine.VstaHelper.AddFileToProject("ScriptMain.cs", "file contents");
pScriptTask.ScriptingEngine.VstaHelper.Build("");
// Persist the VSTA project + binary to the task
if (!pScriptTask.ScriptingEngine.SaveProjectToStorage())
{
throw new ArgumentNullException("Save failed");
}
// Replace ScriptMain contents
var contents = GetScriptMainContent();
pScriptTask.ScriptStorage.ScriptFiles["ScriptMain.cs"] = new VSTAScriptProjectStorage.VSTAScriptFile(VSTAScriptProjectStorage.Encoding.UTF8, contents);
// Reload the script project, build and save
pScriptTask.ScriptingEngine.LoadProjectFromStorage();
pScriptTask.ScriptingEngine.VstaHelper.Build("");
//Cleanup
pScriptTask.ScriptingEngine.DisposeVstaHelper();
}
private string GetScriptMainContent()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "Va.Api.MyServiceSSIS.Infrastructure.Scripts.ScriptMain.txt";
Stream stream = assembly.GetManifestResourceStream(resourceName);
StreamReader reader = new StreamReader(stream);
return reader.ReadToEnd();
}
The package and the Script Task in it are generated with no issues but when I try to run the package in Visual Studio that's when I get the issue:
for the Script Task it seems that it runs the code inside (giving execution finished with success) but actually it doesn't.
To solve this problem I have to open the script task editor, click on "Edit Script" that opens Visual Studio and the code to be run by the Script Task, then close VS and click OK in the Script Task editor.
If I do the above the Script Task runs the code correctly and I have no problems.
I'm using SQL Server 2014, VS 2013 (but when I open the script of the Script Task he opens the VS 2012)
Anyone had already a similar problem? Or can give me a tip?
I think it's maybe compilation problem, but theoretical in my code I'm already doing it by calling the Build method or not? (if I look at the xml code it seems like it has already hte binary code has already been built)
Thanks in advance.

Categories

Resources