WebView2Feedback icon indicating copy to clipboard operation
WebView2Feedback copied to clipboard

WebView2 headless doesn't work in non-interactive login

Open cnevill-ge opened this issue 2 years ago • 8 comments

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

  1. Create a console app using the code below.
  2. 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.
  3. 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

cnevill-ge avatar Dec 22 '23 15:12 cnevill-ge

I don't believe this is intended to be supported previously. @champnic or @bradp0721 should know better.

david-risney avatar Jan 10 '24 22:01 david-risney

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?

champnic avatar Jan 11 '24 20:01 champnic

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.

cnevill-ge avatar Feb 01 '24 21:02 cnevill-ge

I Have Exactly Same Problem Any Solution ?

lucaswhob avatar Apr 16 '24 11:04 lucaswhob

For now we "solved" it by switching to CefSharp. :/ Not the solution we hoped for, but we couldn't find any other workaround.

cnevill-ge avatar Apr 16 '24 12:04 cnevill-ge

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.

image

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?

RickStrahl avatar Nov 24 '24 01:11 RickStrahl

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 avatar Nov 24 '24 01:11 RickStrahl

@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?

CocoDico78 avatar Apr 09 '25 14:04 CocoDico78