WebView2Loader.dll not found is Outlook VSTO addin - outlook

I read allot about the WebView2Loader.dll - file not found issue, but couldn't solve the problem in my case:
A simple Outlook VSTO add-in with FormRegion,
Inside the FormRegion I placed the WebView2 control, and initialized it:
private async void FormRegionWebView2_FormRegionShowing(object sender, System.EventArgs e)
{
await InitializeCoreWebView2Async(webView2Ctrl, #"C:\temp");
webView2Ctrl.Source = new Uri("http://www.bing.com");
}
public async Task InitializeCoreWebView2Async(WebView2 wv, string webCacheDir)
{
CoreWebView2EnvironmentOptions options = null;
CoreWebView2Environment webView2Environment = null;
webView2Environment = await CoreWebView2Environment.CreateAsync(null, webCacheDir, options);
await wv.EnsureCoreWebView2Async(webView2Environment);
}
The native dlls are in the bin\Debug\runtimes folders,
But I still get 'WebView2Loader.dll': The specified module could not be found' in InitializeCoreWebView2Async()
Here is the code:
https://github.com/MicrosoftEdge/WebView2Feedback/files/8117191/OutlookAddInWithWebView.zip
Any help would be very appreciated.

First of all, make sure the WebView2 Runtime is installed on the system. You can read more about that in the WebView2 Runtime installation section in MSDN.
WebView2Loader.dll is a native and architecture-specific binary, so you need to include all flavors of this binary that you expect your app to run in. For example:
For x86, you would include the x86 version of WebView2Loader.dll.
For a managed app using AnyCPU, you would include the x86, x64, and arm64 versions of WebView2Loader.dll. The correct version of WebView2Loader.dll is loaded from the appropriate architecture-specific folder.
Make sure that you included all the required platform-specific assemblies. Read more about that in the Files to ship with the app article.
BTW I have found a similar issue - Unable to load DLL 'WebView2Loader.dll': The specified module could not be found.. It is very close to what you are describing.

It turns out that Outlook is not able to get the WebView2Loader.dll from inside the runtimes folders,
it has to be in the output directory itself.
Specifying the Platform target (to x86) was not enough, the dll was still in runtimes only.
(target framework is: .NET framework 4.7.2)
Only migrating from nuget packages.config to PackageReference (as described here: https://learn.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference)
and specifying the platform target
caused the dll to be copied to the output dir (bin\Debug).
We will have to prepare two separate ClickOnce installers, one for x86 and one for x64,
but now the dll is found by Outlook and WebView2 displays web pages inside FormRegion.
Update: Actually that wasn't enough for adding the WebView2Loader.dll to ClickOnce application_files too.
For that I had to define the dll as content in the csproj file:
In Visual Studio (2022) "Unload Project", then "Edit Project File" to get the .csproj of the add-in as xml, and adding the following:
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)bin\$(Configuration)\runtimes\win-$(EffectivePlatform)\native\WebView2Loader.dll">
<Link>%(Filename)%(Extension)</Link>
<PublishState>Included</PublishState>
<Visible>False</Visible>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Pack>false</Pack>
</Content>
</ItemGroup>
After reloading and publishing the Loader dll was in the ClickOnce installer application files and the add-in could be distributed.

Related

How to add native DLLs to ClickOnce deployment of .NET app

I've been trying for days to figure out how to get my native C++ DLL dependencies included in my ClickOnce deployment of a C# WinForms app built with VS2019. The native DLLs do not appear under Publish -> Application Files on the Properties page of the main .NET app (though the .NET DLLs do).
I've read this a hundred times:
Set the Build Action for the native DLLs to 'Content'.
... and I think I'm interpreting/doing that wrong.
Output from the native C++ projects is naturally not 'included' in any projects, (an apparent prerequisite for exposing the Build Action property,) and thus does not appear in Solution Explorer to allow me to set it to 'Content'. So I
[Solution Explorer] -> Project -> Add -> Existing Item -> [select native C++ DLL]
to add the native C++ DLLs to the Project to enable the Build Action property, which I then set to 'Content'. {Important Note: It has to be 'included' in a Project, rather than just the Solution to get a Build Action property.}
So I do that and it works, but of course I had to select a specific platform and configuration (e.g., x64 & release) of the native DLL, and this selection is fixed (not controlled by the selections in the VS2019 GUI when I build), and worse -- not even labeled as to which platform & configuration is 'included' in the project. {Side note: How did I not have to select which version (x86 vs x64) of the .NET DLLs to use under Publish -> Application Files ? It just automatically picks the right ones? How do I set up an x86 version and a x64 version that I can switch back & forth between & build each?} I cannot imagine this is the way it is supposed to be done. It is fragile and opaque. Surely there is a better way. I think I'm missing something that everyone else finds 'obvious'. Any other developer who tries to use or maintain this configuration will curse my name, and be right for doing so.
What is the 'right way' of making the ClickOnce deployment (via the VS2019 GUI) include my native DLLs (the projects for which are included in the same solution) in the ClickOnce deployment package?
Note, I found one promising setting in the Properties Page for the native C++ projects: Custom Build Setup -> General -> Treat Output as Content. But it does not seem to have any effect.
I'd be eternally grateful for any pointers.
After refining this for another day or so, I've found that the VS2019 GUI just comes up short for this purpose. The better answer is to just manually edit your .csproj file for the .NET project to Include the native DLLs as Content. Find the other elements in that project file and add the native DLLs like this:
<ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<Content Include="..\bin\MyApp\x64\Release\native1.dll">
</Content>
<Content Include="..\bin\MyApp\x64\Release\native2.dll">
</Content>
</ItemGroup>
<ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<Content Include="..\bin\MyApp\x86\Release\native1.dll">
</Content>
<Content Include="..\bin\MyApp\x86\Release\native2.dll">
</Content>
</ItemGroup>
(where *..\bin\MyApp{x86|x64}{Debug|Release}* is your output folder where your native DLLs, native1.dll and native2.dll have been copied, post-compile, to be used by your .NET app, MyApp.exe). Of course the x86 folder contains the 32-bit native DLLs, the x64 folder contains the 64-bit native DLLs, etc. - you know the drill.
No confusing extra links and whatnot to clutter up the solution/project, and the .dll files appear where they are supposed to, rather than in separate child sub-directories.
Of course you could add additional elements for the remaining conditions -- namely the debug builds, but who wants ClickOnce deployments for debug versions? You're probably running those directly from Visual Studio, right?
Adapted from here :
Compile your solution.
Right click on the managed project and select "Add/Existing Item". Do not use "Add Reference".
Navigate to your compiled native DLL and select it (adjust file types as needed to expose it).
Click on the down arrow in the "Add" split button and select "Add As Link" (this allows us to not keep multiple copies of the DLLs floating around).
Right click on that freshly added file and select "Properties".
Make sure "Build Action" is "Content" and "Copy To Output Directory" is set to "Do not copy" (since you already automated that task elsewhere, long before getting to the deployment stage of development).
Note that you'll get a 'File Not Found' error upon initial build after a proper cleaning of all output folders, but the native DLL will be created anyway, preempting that error on the next full build.
On the Properties page for the .NET app, do Publish -> Application Files -> Reset All to populate the native DLLs into the list. Adjust 'Publish Status' et. al. as needed.
Publish.
I found that I can maintain a 'virtual' folder structure in the project to store the links to the various versions (e.g., x86 vs. x64 and debug vs. release) of the native DLLs without cluttering up the file system, (and to ensure the DLLs aren't stale): Add the folder structure (e.g., ".\NativeDLLs\x64\Release", etc.) via the Solution Explorer, and add Links only (no real files) to the folders. Then delete the folders from the file system using Windows Explorer or shell commands. They will remain in Solution Explorer after deletion from the file system because they still contain the links.
The hierarchy of those virtual folders now exists only in the project file ([appname.csproj]) as Content elements (containing the Links) within Item Group elements (which seems to be the key to getting them to appear in the ClickOnce deployment world).
One pointer (for myself) that would have helped: Don't be afraid to hit the Reset All button on the Publish -> Application Files dialog.

Windows service build includes DLL's not referenced

Using Visual Studio 2017 I have created a Windows service using VB.net. I have the root service class and a project installer class. The Service builds, installs, and runs as expected. With the following exception - the output to the BIN folder is enormous.
The references listed are as follows:
System
System.Configuration
System.Configuration.Install
System.Deployment
System.Net.Http
System.Runtime.CompilerServices.Unsafe
System.ServiceProcess
System.Threading.Tasks.Extensions
TSLogger (internall DLL that logs to Event log)
When I build the service the output to the bin folder includes over 100 .NET DLLs. At different points during development, using NuGet package manager, I have installed and uninstalled CsvHelper and Newtonsoft.Json.
Any idea what would set the compiler to include all these DLLs as part of the output? Or how I can control it?
I have attached a screenshot of the bin folder.
Bin folder screenshot:
So it turns out it was CsvHelper v15.0.0. I created a new solution, didn't add any code but just added references and as soon as I added CsvHelper with NuGet Package manager, the bin folder would fill up with all these framework DLLs.
UPDATE
I have confirmed I get the same result from CsvHelper version 14.0.0; versions 13.0.0 and 12.3.2 do not produce these results. I didn't test any other versions. The only difference I can see is that the latest 2 versions include a reference to System.Runtime.CompilerServices.Unsafe - could this be what brings in so much of the .NET Framework libraries??

Xamarin Archive error when generating apk

When I set Linking to None it works but when I set linking to Sdk and User Assemblies following error occurs
Microsoft.Build.Tasks.v4.0 is a desktop .NET assembly so it breaks your Xamarin.Android build. The same goes with System.Security.Cryptography.Xml.SignedXml which doesn't belong to the Xamarin.Android profile of Mono (as seen here)
As explained by Brendan Zagaeski from Xamarin, you'll need to find out how Microsoft.Build.Tasks.v4.0 is getting pulled in:
Are you explicitly referencing any .dll files from C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework that are outside of the MonoAndroid\ subfolder?
Are you explicitly including any 3rd-party libraries that might have been compiled against the desktop .NET profile?
You could post a screenshot of your References for the project, that could help narrow down the possibilities.

How to include MFC and Visual Studio CRT libraries into MSI installer?

I'm trying to learn how to write MSI installer. I'm using WiX, and I'm curious. My application comes with the dependencies to the followign MFC and CRT libraries:
mfc90u.dll
msvcr90.dll
How do you install those?
There are some choices listed here. I recommend using the appropriate redistributables instead of installing individual DLLs.
With WiX 3.6 and later, you can create a chainer that runs multiple installers. You can create a VS project for that with a WiX Bootstrapper template.
Distibuting the vcredist dlls as private DLLs creates security risks for the user, and is discouraged, however if you distribute the version mentioned it must live in a subfolder of the app folder with a name specified in msdn docs. It is far better to use the vcredist exe (even if your app does not need all of the vc redist files),or the related msm. The location of the msm or private dlls is part of your VS installation and detailed in the VS redistribution license. The vcredist exe is available from microsoft's site. There are many different versions of the vs 2008 redist. Open your binary in a text editor and search for manifest to read the embedded manifest which details which version of the vcredist you need to deploy. Never take anything from the SXS folder. Regarding wix you can add the msm to your msi but there are issues with doing that. The prefered method is create a Wix bundle using the vcredist exe.

How to reference assembly from GAC?

I have installed the strong named assembly TestReflection into the GAC (I am using .NET 4.0 and VS 2010).
Different versions of the TestReflection DLL are in GAC of .NET 4.0 (C:\WINDOWS\Microsoft.NET\assembly\GAC_32\TestReflection\), however, the assembly does not appear in the "Project" -> "Add reference" box of VS 2010.
How can I refer to my assembly deployed in GAC at design time from another project?
This page says that:
You cannot add references from the Global Assembly Cache (GAC), as it is strictly part of the run-time environment.
Referring to this statement, I would like to know how to make your project's DLL shared assembly for other consumers if it's the requirement?
The dll's shown in the .Net tab of the "Add references" dialog are not actually the ones registered in the GAC. They are found by searching a few paths on your filesystem.
The paths being searched are located by Visual Studio by looking up the following registry entries:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NetFramework\{Version}\AssemblyFoldersEx\
There should be some keys added there already, so if you want your own dll to show up on the .Net tab, you can add it to one of the folders defined there. You could also add a new registry key pointing to a custom folder, which would only contain your own dll's.
The GAC is only meant for loading assemblies at runtime after your application has been deployed, so I don't think you should use it while developing. When you deploy your app, make sure to set "Copy local" to false on your reference so the dll won't be copied to the bin folder, and then install it into the GAC and it will be loaded from there instead.
Another simple option would be to manually edit the project file as XML in visual studio (You will have to unload the project first), and simply add node <Reference Include="<name of dll>" /> in MSBuild project file. After reloading the project, VS will pick up the reference without problem.
If you want to add Global Assembly Cache references to your VS2010 project, there is an extension you can use: Muse.VSExtensions.
It has some quirks but does a decent job. Check it out...
The answer is the Reference Paths in the property windows, you have to set it with the GAC path
Please see my post here:

Resources