WebView2 headless doesn't work in non-interactive login
What happened?
As noted by @Screaminlean in issue 202 it seems that calling CreateCoreWebView2ControllerAsync with HWND_MESSAGE works fine in an interactive login, but if you run it from a non-interactive login (such as a service or scheduled task) it does not work.
In my use case, the goal is to have an unattended service render a page that users would typically see interactively in WebView2, export that page view to a PNG, and provide it as part of an automated export to the customer.
In the sample code from issue 202 this manifests as a hang, but really a COMException is being thrown from CreateCoreWebView2ControllerAsync after the internal WebView2 code encounters an error. I also tried creating a dummy Form object inside the UI thread and passing that form's handle to CreateCoreWebView2ControllerAsync, but it fails with the same error.
Errors reported in the debugger output in the failing scenario:
WebView2_SetWindowPos failed: Invalid window handle.
SetWindowPos failed before parenting browser window with error: Invalid window handle.
WebView2_SetParent failed: Invalid window handle.
SetParent failed while parenting browser window with error: Invalid window handle.
I'm not sure if this scenario is supported but I really hope it's possible!
Importance
Important. My app's user experience is significantly compromised.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
120.0.2210.77
SDK Version
1.0.2210.55
Framework
Other
Operating System
Windows 10, Windows Server
OS Version
Windows 10: 19045.3693; Server 2022: 20348.2159
Repro steps
- Create a console app using the code below.
- Build the app and create a scheduled task to run it. Task should be configured to "Run whether the use is logged on or not".
- I gather from some other reported issues that elevation may cause sandboxing issues with WebView2 so I did not set the scheduled task to run elevated.
- Run the scheduled task and note that it hangs at CreateCoreWebView2ControllerAsync.
- If you add a try/catch around this line you'll see a COMException.
- If you attach a debugger, you'll see the trace messages noted above, regarding invalid window handles.
static readonly IntPtr HWND_MESSAGE = new IntPtr( -3 );
static void Main( string[] args )
{
// Optional: wait for debugger
//while( !Debugger.IsAttached )
// Thread.Sleep( 1000 );
var uiThread = new Thread( () =>
{
Dispatcher.CurrentDispatcher.Invoke( async () =>
{
var environment = await CoreWebView2Environment.CreateAsync( null, null, null );
// Program hangs here, due to COMException being thrown
var controller = await environment.CreateCoreWebView2ControllerAsync( HWND_MESSAGE );
controller.CoreWebView2.Navigate( "https://microsoft.com" );
} );
Dispatcher.Run();
} );
uiThread.SetApartmentState( ApartmentState.STA );
uiThread.Start();
uiThread.Join();
}
Repros in Edge Browser
Not Applicable
Regression
No, this never worked
Last working version (if regression)
No response
I don't believe this is intended to be supported previously. @champnic or @bradp0721 should know better.
I believe this is currently By Design and has to do with trying to run as a non-logged-in user, rather than an issue with being headless or the HWND. Please see https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/security: "WebView2 cannot be run as a system user. This restriction blocks scenarios such as building a Credential Provider."
@cnevill-ge in your example does it end up trying to run the app as SYSTEM user?
We weren't trying to run it as SYSTEM, but it was running as an elevated user in a non-interactive window station. From the debugger view in Visual Studio it sure looked like an async task was stuck waiting to run and never getting scheduled, but I'm not very strong on debugging that stuff.
I Have Exactly Same Problem Any Solution ?
For now we "solved" it by switching to CefSharp. :/ Not the solution we hoped for, but we couldn't find any other workaround.
I got this to work at some point with:
private IntPtr HWND_MESSAGE = new IntPtr(-3);
protected async void InitializeAsync()
{
StringUtils.LogString("About to create WebView Controller " + HtmlToPdfHost.WebViewEnvironmentPath);
// must create a data folder if running out of a secured folder that can't write like Program Files
var environment = await CoreWebView2Environment.CreateAsync(userDataFolder: HtmlToPdfHost.WebViewEnvironmentPath);
// Worked a few releases back - now it's hanging here and never gets past this in unattended context
var controller = await environment.CreateCoreWebView2ControllerAsync(HWND_MESSAGE);
controller.DefaultBackgroundColor = ColorTranslator.FromHtml(HtmlToPdfHost.BackgroundHtmlColor ?? "white");
}
Just to show that this was working with SYSTEM and ApplicationPoolIdentity in IIS a few months back.
But... it looks like this behavior has a regression to no longer working in more recent builds and it now once again hangs on CreateCoreWebView2ControllerAsync() - but only in non-Interactive (ie. non-desktop) situations. It works fine unattended as long as there's a logged on user.
Point of this is that this was possible to do but something that's changed in the WebView code recently has broken to make this no longer work.
FWIW, my use case is running this from IIS in an ASP.NET Core application. In that scenario it hangs now - again.
I've tried using different user accounts SYSTEM, NETWORK Service, separate ADMIN user accounts (that do have a profile and profile enabled), but it always hangs.
As said it was working at some point as shown in the screen cap - so what changed? Unfortunately I don't know what version of the SDK worked at the time - I've rolled back a through versions and I can't find any SDK version that works, but it could also be the Runtime that has the change?
If anybody wants to mess around with this the above code comes from my Westwind.WebView repo, which includes HtmlToPdf functionality. It works fine interactively but problems non-interactive even though the code aims at the non-interactive environment.
Relevant code here:
https://github.com/RickStrahl/Westwind.WebView/blob/7f189719c42acf716294e8dc741234145ea3dc49/Westwind.WebView/HtmlToPdf/CoreWebViewHeadlessHost.cs#L72
@RickStrahl do you have a reference for the NuGet package version that used to work? And did you by chance try again with newer versions since last November?