-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using WebView2 in a WPF Assembly #730
Comments
I think I'm also having the same problem. It is a class library that is an add-in for another app with a Windows Form user control that has Webview2 in it but it does the same thing "control comes up blank, and does not load the website hard coded in the SRC element." Pulling the form out into a standalone Windows Form App everything works. |
@AndrewMore1 @dwatkins-FNA, Thanks for reporting the issue. We'll try to repro the issue from our side and investigate. |
This may be affecting our WPF assembly as well. Using 1.0.721-prerelease, I see a grey screen load about 1 in 6 times. If I resize the parent window, the web page redraws correctly. |
|
Yeah, I believe I'm having the same issue trying to use this in a .Net Framework class library. It's a plugin for Autodesk software, built in .Net Framework 4.7, and I can get nothing but a blank grey screen when trying to launch the window contained in my dll. I can get it working if I build my own .Net Framework application, but since this is a plugin for third party software that is not an option for us unless we were to use IPC, at which point we may as well just use Electron. |
Hey all - it's a bit tough to parse this thread as there seem to be many examples of this, but it's unclear if they all stem from the same problem. I tried the following repro:
For everyone - is anyone getting a crash or stack during launch? Are you adding the WebView2 nuget package to the project that is also consuming the WPF/WebView2 control assembly? @AndrewMore1 - If the WebView2Loader.dll is not deployed with the app, WebView2 will not load properly. Typically, WebView2Loader.dll is deployed by building with the WebView2 nuget package .targets file, which specifies where it should be placed. How are you doing this in your scenario? If your control is being deployed as a nuget package, are you specifying WebView2 nuget as a dependency? Or are you just including references to the WebView2 assemblies (Microsoft.Web.WebView2.Core/WPF.dll)? @dwatkins-FNA - When you say "pull the form out in a standalone Windows Form App" are you saying take your WebView2 code and put it directly into the app instead of using a separate control assembly? @dmcgloin - This sounds like it may be a separate issue if it's transient and inconsistent. Can you try with the latest prerelease package to see if the issue persists, and open a new issue if it does? @ingemarson - Your example makes it sound like the core scenario is working (adding a WebView2 in a separate control assembly to an app), but it's not working only when included in a console application. Is that right? Does the console application work if you try to include the WebView2 control directly, rather than using a separate assembly? May be related to #970. @m-sterspace - If I understand correctly your scenario is also broken similar to @ingemarson's and #970, in that it works fine if you include your assembly in a normal .NET Framework app, but when trying to launch differently it fails. Can you share the code you are using to launch the WebView2 in your assembly that's failing? Thanks all! |
I've been able to repro using the following steps:
<wv2:WebView2 x:Name="webView2" Source="https://bing.com"/>
using System.Windows;
using WpfUserControl;
namespace ConsoleApp
{
class Program
{
[STAThread]
static void Main(string[] args)
{
Application app = new Application();
app.Run(new WV2Window());
}
}
} However, if I switch to using private async void Window_Loaded(object sender, RoutedEventArgs e)
{
var env = await CoreWebView2Environment.CreateAsync();
await webView2.EnsureCoreWebView2Async(env);
webView2.CoreWebView2.Navigate("https://bing.com");
} For those of you running into this issue, can you try that workaround? |
@champnic Yes, if I remove the WebView2 code from the class library and put it into a test Windows Form App it worked. When it is part of the class library it did not. I tried testing your workaround and at System.DllNotFoundException: Unable to load DLL 'WebView2Loader.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E) |
How are you including WebView2 in your app that's consuming the library? Are you including the WebView2 nuget package? |
Yes, NuGet Microsoft.Web.WebView2 1.0.774.44, it shows WebView2.Core, .WinForm & .Wpf in the referneces. |
Do you have a repro you would be able to share that I could debug? |
@champnic I have tried a couple of different things to distribute the WebView2 control. First I tried just the nuget package on the assembly that was using the WebView2 control. Then I added it to the application as well. This seemed to work for a period, and then stopped working for no apparent reason. I have also tried copying the WebView2.dll and the platform specific dlls into various directories manually, which also failed. I just tried your suggested work around, and I don't see any change. I'll see if I can simplify the code I'm using down far enough for a demo of the problem. |
@champnic my class library is used as an add-in for SolidWorks PDM. I don't think there is a way to run it without SolidWorks PDM. |
FWIW, mine is used as an add in to an Office Client VTSO plug-in. |
@champnic I've added a sample application which demonstrates the problem. Note I've changed the normal background of the control to Rose so that you can clearly see the control has loaded, but it has not started the WebView2 correctly. |
Hi folks, I've discovered a bug which is a probable culprit for at least some of the troubles that are being described on this thread. Let me start by describing how using WebView2 in a .NET library project should work. Say you've got two projects, MyLibrary and MyApp. MyLibrary uses WebView2, and MyApp uses MyLibrary. For our purposes here MyLibrary is always a .NET project, and MyApp is usually a .NET project but isn't necessarily required to be. Here's some ASCII art showing the general dependency relationships, where
The nature of each of those dependencies might vary. Let's talk about them one at a time, with the easy one first. The Now let's start to zero in on the case at hand. Here are the two exemplar scenarios: A) You're a developer responsible for creating/publishing both projects as part of a single system (e.g. you're developing an app but have factored the portion of it that uses WebView2 out into a library for whatever reason). This maps to the case where the B) You're a developer responsible for creating/publishing MyLibrary and expect your customers to use it with a MyApp that's created by someone else (e.g. you're developing an Office plugin). This maps to the case where the To setup scenario A, here's what we expect that you should need to do:
To setup scenario B, here's what we expect that you should need to do:
So, if you need to package WebView2's runtime dependencies with your .NET library, then what are those dependencies exactly? (Scenario A people, this will be relevant to you later as well, so keep reading.) At the moment, they are:
If you build a MyLibrary project which is configured to reference the WebView2 NuGet package then in general you should find those files automatically copied into the output folder of your library's build (e.g. its bin/Debug folder). However, unfortunately it's not entirely that simple, and here is where we finally start to uncover at least one bug. In particular, the bug I've uncovered which I believe is causing some trouble has to do with WebView2Loader.dll. WebView2Loader.dll is tricky for a .NET project to use because, unlike the others, it's a native DLL rather than a managed one. Native DLLs can't be built to target "Any CPU" the same way that managed DLLs like MyLibrary can (and do, by default). So, although a customer running an x86 process and a customer running an x64 process can both use the same MyLibrary.dll, they cannot both use the same WebView2Loader.dll. The customer running an x86 process needs a WebView2Loader.dll which was built for x86, and the customer running an x64 process needs a WebView2Loader.dll which was built for x64. This means that if we want to distribute a MyLibrary which is built for AnyCPU then we effectively need to include a WebView2Loader.dll for every possible architecture that MyLibrary will be used in. Now, in practice WebView2 only currently supports three architectures (x86, x64, and arm64), so we're basically talking about including three copies of WebView2Loader.dll when we distribute an AnyCPU MyLibrary. When MyApp is running on the customer's machine and loads MyLibrary.dll, it in turn loads one or more of the Microsoft.Web.WebView2.*.dll files, which then find and use the WebView2Loader.dll that matches the architecture of MyApp. So how do we keep track of the various separate copies of WebView2Loader.dll? If you build your MyLibrary you'll notice that your output folder doesn't actually directly contain WebView2Loader.dll, but it does contain a folder called "runtimes". If you dig into that folder you'll find various subfolders for various architectures (e.g. "win-x86" for x86). If you dig into the folder for a specific architecture then you should find a "native" folder which contains the WebView2Loader.dll for that architecture. Different architectures will be available in the "runtimes" folder depending on whether your build targeted AnyCPU or some specific architecture like x64 or x86. From the perspective of distributing MyLibrary.dll, basically you should just consider the whole "runtimes" folder to be a WebView2 dependency which needs to be included in your distribution in the same place as MyLibrary.dll and the other WebView2 DLLs listed above. It is additionally worth pointing out that the name of the "runtimes" folder as well as its internal structure is not designed by the WebView2 team; I believe that comes from the implementation of .NET Core, but I'm not completely certain. With all of that context, it's finally possible to understand the bug that I've uncovered and I believe is affecting at least some of you on this thread. When you build your .NET library to target AnyCPU, the WebView2 SDK is supposed to include all three versions of WebView2Loader.dll in the "runtimes" folder, but in certain cases (which I'll explain later) it is only including the x86 version. So, to determine if you're affected by this bug, look in your library's output folder for AnyCPU (by default that's the project's "bin/Debug" or "bin/Release" folder, but you may have configured it to be elsewhere), open the "runtimes" folder you find there, and examine the contents. If you only see a "win-x86" subfolder then you're affected; if you see three folders ("win-x86", "win-x64", and "win-arm64") then you're not affected. You may recall above where we considered two separate scenarios depending on whether MyApp has a build-time dependency or a runtime dependency on MyLibrary. This bug obviously affects the runtime scenario (B), but it also affects the build-time scenario (A). Even if one build system has all of the knowledge necessary to automatically copy all of the correct files all the way to MyApp's output folder, the bug in MyLibrary's build effectively propagates to MyApp. When you build MyApp, the build system automatically builds its dependency (MyLibrary) first and copies its output to MyApp's output. However, MyLibrary's output files are incorrect/bugged, so MyApp's build simply ends up copying the incorrect set of files to its own output, where they continue to be incorrect. Why does the missing runtime cause the symptoms described here where the WebView2 is simply blank? The code that attempts to find and load WebView2Loader.dll is executed when a Now, let's dive into why this bug happens and I'll show you a workaround that you can use until we're able to publish a fixed WebView2 SDK. Basically, the logic in the WebView2 SDK about which architectures to copy into the "runtimes" folder when the dependent project is built for AnyCPU is flawed. The specific case where it is flawed is when the project does not define A reasonable question to ask at this point is how this bug only affects libraries. Turns out that it doesn't only affect libraries, but there's a good reason that it's mostly popping up there. Many of the common types of .NET Framework projects created by Visual Studio explicitly define The workaround is hopefully relatively obvious: update your library's project to explicitly define You'll need to locate the
All you need to do is add
After you make this change and build your library again (maybe Rebuild for good measure) you should find that all three architectures exist in the output "runtimes" folder. If you have an application which references that library (i.e. scenario A above) and you build the application again then you should also see that all of those "runtimes" subfolders are copied to the application's output as well. Now that you have all of the architectures in the "runtimes" folder the app/library should be able to find and load the appropriate WebView2Loader.dll, resolving the problem. I hope that this helps you understand a current bug, diagnose whether it's affecting you, and if so work around it until we can publish a fixed version of the WebView2 SDK. If you believe you're affected but the workaround isn't resolving the issue then please reply back and provide any additional information you can discover. If you've been reporting a problem in this thread but turn out to not be affected by the exact bug I described, then I hope that this information is still helpful in investigating your problem (especially the part about how to find exceptions that occur during initialization). In that case, please report anything new that you discover about your issue and we'll try to help get that sorted out as well, though if it turns out that you have all of the expected WebView2 files in the expected locations in your project's output folder as described above -- i.e. your issue appears to be unrelated to missing WebView2 files in your project's output -- then please consider starting a new thread about it, perhaps referencing this one as appropriate. |
@AndyT-MS thanks for the explanation! I do only have the X86 in the runtimes folder as you said. I will try the workaround next week and report back. |
@AndyT-MS Thank you, that makes a lot of sense. It also explains why I was sometimes able to get a sample application to work correctly and then break, I more than likely changed the arch and didn't realize it. Your explanation of the directory structure also explains why my copying the DLLs into the runtime folder for my app wasn't sufficient either. Finally while I appreciate your explanation for why the exception was hidden, I'm curious why the solution doesn't involve making sure the exception is propagated further up the stack. The lack of ANY feedback as to what was failing is one of the most frustrating parts of dealing with this defect. I saw no logs, no error messages, no exceptions in the console, no messages anywhere. This seems like such a fundamental and fatal exception I would expect a much more visible display of the problem, even if it only occurs in the debugger. |
I made the change to the platform and it did make all of the runtimes and I did not get the missing dll error but I did get a new one.
|
@dwatkins-FNA Access denied errors are usually the result of the User Data Folder being in a location where the browser/runtime process(es) doesn't have the necessary permissions to create/access it (the User Data Folder is where the browser/runtime stores caches, history, cookies, etc). If you don't specify a location for the User Data Folder then one will automatically be created in the same folder as your EXE. In development environments that often works fine, but maybe not always. You can specify the location to use for the User Data Folder as one of the arguments to
@AndrewMore1 I'm really glad that my explanation was helpful. Absolutely fair criticism regarding the lack of notification about the failure. We'd definitely like to improve that, and knowing what sorts of things you looked for is helpful, thanks! Regarding why the exception doesn't propagate further up the stack into your code, the trouble is that initialization is a long and expensive operation so we don't want setting the |
@AndyT-MS I appreciate your explaination, and I think you've probably got a better handle on the ins and outs of C# than I do. I've worked with it off and on over the years, but I'm far from a subject matter expert and my primary focus in recent years has been javascript. So I believe you're probably correct for why the error doesn't move further up the stack. I also appreciate the suggestion of checking the CoreWebView2InitializationCompleted for more information, that's helpful. However, I must admit I don't understand why a debug message for the catastrophic failure cannot be output to the debugger Output window. |
@AndrewMore1 Writing to the debugger output window is definitely a possibility, and one that I'm certain we'll consider when we try to improve the reporting of initialization failures like these. |
There are a few other possibilities that might be contributing to problems loading
Full disclaimer this is a passing comment and I've done exactly no testing in the context of |
I believe this is a problem I am having as well, but it is only happening to some of the test users we're deploying to. Like @m-sterspace I'm building an add-in to an Autodesk app so I am unable to test it as a standalone application. I have attempted many of the suggestions here (resizing the window, using Navigate instead of setting the Source, and making sure all three platforms had the loader .dlls) but am still having no luck. I am also unable to isolate why it's only happening to some of my users. They're all using the evergreen bootstrapper, so that shouldn't be an issue. Are there other environment scenarios that could be throwing this off? |
@jdaless That sounds like it may be a separate issue from this one. Do you want to open a separate issue with more details so we can try to help? Off the top of my head I would check where your user data folder is getting created, and if that folder has write permissions: https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/userdatafolder |
@AndyT-MS I've done some more digging based on your detailed analysis above. I have implemented the changes suggested in the project file, and built another sample application to illustrate the problem. From what I can tell, your suggests does result in the runtime libraries being correctly placed into the working/build directory, but it does not resolve the issue of the control showing the correct information. I've attached a copy of the sample code showing this problem. In this case as a sanity test I've included two WebView2 controls side by side, one of which is directly created in the application, the second in a library. The library based version still fails to work, while the simpler example works correctly. |
@AndrewMore1 Thanks for the easy repro app, that helps a lot. Here's how I dug into it and what I found. At first, the app didn't work at all: neither WebView2 appeared, and the Output window showed exceptions loading the WebView2 DLLs as well as an error about an invalid binding. In MainWindow.xaml the library control is added to the page like this:
However, there's no element named "Holder" for that binding to bind to, so I just removed the After that, when I ran the app it was as you described: the WebView2 referenced directly from the app correctly showed Bing, but the WebView2 inside the library control didn't appear at all. Next thing I did was to set a breakpoint to go off when I resized the window so that I could easily examine the state of both WebView2 controls. Somewhat unexpectedly, even the WebView2 inside of the library control had a valid I figured that out by poking around in the live WPF visual tree. I noticed that the automatically calculated height of the
When I followed that advice and changed the I hope this resolves your problem and unblocks your work! |
For the record since I couldn't get WebView2 working, I switched to Electron and just bundled an Electron application and communicated back and forth with it using IPC. If you want to go down a similar path, let me know and I can share some code for it. |
@m-sterspace, sorry for not updating here, but @champnic was correct, the issue was with user data. Instead of keeping user data next to the executable, which is the default, we keep it with the plugin where we know the user has permission to write since they installed the plugin. |
@AndyT-MS Thank you again Andy. I made the changes you suggested and it worked correctly. I am puzzled that the sample app worked for me with the erroneous binding element, but it worked before I uploaded it. As you might guess this is my attempt to provide a simplified version of a much larger, more complex app, which was based on the original WebBrowser control which hosted IE11. The use of the element StackPanel works correctly with that control, in pretty much the same layout as the sample app, while it does not with the replacement control. I also don't claim to know what the correct setting should be for this panel, but I suspect you're going to get a lot of people doing something similar to what I've done, do a drop in replacement, and not understanding why it's not working. Also thanks for the recommendation of using the WPF Tree visualizer. As I said before, C# is something I haven't used much for about 10 years, getting pulled off into SWT/Jave and then Angularjs/Javascript, so it's nice to learn some of the tricks along the way. |
@AndrewMore1 I'm glad that my changes worked for you as well, and I'm happy that I could provide some tips along the way. Thanks for the extra context that this |
@AndyT-MS One other fact that might be helpful. The large sample app I've been trying to get working with WebView2 but haven't posted was working correctly with an earlier version of the WebView2 control. This was in the October/November time frame, so not only do I believe the StackPanel 0 height to be a bug, I believe it's also a regression from previous versions of the WebView2 control for WPF. |
That's exactly what helped to overcome the situation for me too. I can't thank you enough. |
@AndyT-MS Repro: WebView2LoaderRepro.zip
If App targets net472, I see different behavior depending on the PlatformTarget element in the App csproj.
If App targets netcoreapp3.1, then everything works, even if the app doesn't explicitly specify PlatformTarget. Runtime: 91.0.864.59 |
@AndyT-MS My App does not know about MyLibrary's existence. I get the following error: Following is the stack trace: I have tried the steps mentioned:
They do not work. Moreover, the user data folder is not being generated in the default location. Would be very grateful for any insight on the matter. Refer also: #1601 (comment) Thank you |
@pmaytak - sorry that it has taken a while to find the time to follow up. Thanks much for the easy repro! I was able to replicate your results, and after some additional investigation there seem to be two additional considerations happening which differentiate that case from my original work on this bug. First, as you point out your case is using the library as a NuGet package. The second extra consideration is that your app and library are targeting .NET Framework (e.g. net472) from a new SDK-style csproj. Until I investigated your repro I didn't think that either of those considerations should matter, but it turns out that they both have an effect on how WebView2 creates files in the app's build output. It also unfortunately turns out that my eventual fix from my original investigation (which should be in the next release) doesn't solve the problem with regard to either of these new considerations. I think that #1418 is another example of the bug caused by using WebView2 in an sdk-style csproj which targets .NET Framework. To make the tracking easier, I'm going to use that bug for comments and investigation regarding both of these new considerations. I've posted a comment there with some additional detail regarding my current findings. Thanks for your help in finding these problems. I'm sorry that I don't have an easy fix or workaround for them yet, but hopefully the additional information will still be helpful for you in the meantime. |
The main issues here are fixed in SDK package 1.0.1056-prerelease, and should be available in the upcoming release SDK. Thanks! |
I found out that when the program path contains non-English characters, you will get this error |
@champnic |
@gileli121 Could you please post that as a new issue? That will make it a lot easier for us to track since this one is closed and it sounds like your new one has a very different cause despite having similar symptoms. It would also be helpful if you could include more information about the error or incorrect behavior that you're seeing because this thread includes reports of several different errors so I'm not sure which one you're referring to. |
I got related problems:
Remaining question why did the await webView.EnsureCoreWebView2Async not work? |
@Avdam It might be easiest to open a new issue for this problem, including version info, repro steps, sample app, etc. |
Description
I'm having some issues with integrating the Webview2 WPF control into a larger control packaged as an assembly. That assembly is then integrated into other applications.
Ex:
Application - Exe
+- Control Assembly - .NET Dll
+- WebView2 control - Microsoft.Web.Webview2.Wpf
+- WebView2Loader.dll
While I can build and run the application successfully, the control containing the WPF WebView2 control comes up blank, and does not load the website hard coded in the SRC element. Looking into this further, I believe this is related to how the WebView2Loader is handled. I've seen other people reporting issues with this when the WebView2Loader dll is not correctly integrated.
I can get the sample applications, and stand alone apps to work correctly, this seems to be related to packaging this in an assembly DLL.
I'm guessing there's some place the application is expected to load this DLL from. I also know there are multiple versions, depending on architecture.
Version
SDK: .NET Framework 4.6.2. Webview2 ver 1.0.664.37
DLL Output: Class Library
Framework: WPF
OS: Windows 10
Other stuff: the application this control is currently being integrated into is an Office VSTO add-in. Therefore the target application for the .NET runtime is x86. We will potentially have other applications using the library in the future.
We set the compiler flag CPU=any such that our add-in can run in a 32-bit or 64-bit process. It's also possible that future users of the control assembly will be using x64.
AB#31148967
The text was updated successfully, but these errors were encountered: