Developing and testing features or extensions for Microsoft Edge
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Request to please suggest an approach where we can spawn C#,WebView2 application safely without any issue.
Thanks in advance.
Ajay Shinde
Developing and testing features or extensions for Microsoft Edge
Hey Ajay,
WebView2 usually breaks when launched from an elevated Winlogon shell.
Try starting the C# process with a lower integrity level from your C++ launcher, or move it to a logon scheduled task that runs in the interactive user context. Both approaches often fix it.
When you’re picking which one to test first, a quick ruleta aleatoria can help keep it simple.
Hello @Muhammad Mujahid Thank you for your response.
We have some additional runtime constraints as below,
Glad to share more details in case any are required.
Hello @ajay.shinde ,
Thank you for reaching out.
Per Develop secure WebView2 apps, WebView2 cannot be run as a system user, and that restriction specifically blocks system/session-level scenarios (the doc calls out Credential Provider as an example). Launching your app through the Winlogon/Shell registry value runs it in the system logon context rather than an interactive standard-user session, so the WebView2 Runtime has no valid user profile/user-data-folder environment to initialize, which produces the failure and white screen you're observing.
The same guidance also gives the supported direction: as a security best practice, the process hosting WebView2 should run at standard (non-elevated) user integrity, and any work requiring elevation should be isolated into a separate dedicated process while the WebView2 host stays de-elevated. In other words, the WebView2 UI needs to be created inside a logged-on standard-user session with an initialized user profile; running it under the system/Winlogon shell or elevated/admin context is not a supported configuration.
Given your constraints (no new standard user, no explorer.exe, and ShellLauncherV2 ruled out), there isn't a supported way to host WebView2 directly in the system-level startup context. The reliable path is to keep your C++ launcher as the startup trigger but have the WebView2 app started within a standard interactive user session that has a user profile available, rather than from the system logon shell.
If you can share whether the machine ever has an interactive standard-user session available at startup (for example an auto-logon standard user), I can help you map the launch flow to that supported model.
I hope this helps. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guidance or provide feedback.
Thank you.
Thank you for the response. Machine seems to have an interactive standard-user session available at startup. Since we are starting parent C++ application through 'Winlogon/Shell' value, immediately after user logs in to the system application is starting.
Please let me know if any more details are required.
Hello @ajay.shinde ,
Thanks for confirming that, knowing an interactive standard-user session is available right after logon is the important part, because that's the environment WebView2 needs, so this should be workable.
Now that the app runs inside a logged-on standard-user session, the white screen is most likely coming from the user data folder rather than the session itself. Because your C++ app replaces explorer.exe as the shell, the normal shell-initialized environment isn't fully set up, and by default WebView2 creates its user data folder next to your executable. As described in Manage user data folders, if that folder is in a protected/read-only location (for example under Program Files), WebView2 can't create or write the folder and startup fails, which matches the white screen you're seeing. The fix is to explicitly pass a custom user data folder in a per-user writable location such as %LocalAppData% when you create the WebView2 environment.
The second thing to verify is the integrity level of the spawned process. Per Develop secure WebView2 apps, the WebView2 host should run at standard (non-elevated) user integrity, so make sure the C# process isn't inheriting an elevated or system-level token from the C++ launcher; if any part of your flow needs elevation, keep that in a separate process and leave the WebView2 host de-elevated.
If the white screen persists after setting a writable custom user data folder at standard integrity, could you share any error text returned during WebView2 environment creation (for example an Access Denied / "Unable to create user data folder" message)? That will tell me exactly where initialization is stopping.
Thank you for your response.
We have used writable custom user data folder for WebView2 application. For standard integrity in place of launching application through parent C++ application we tried launching it through Task Scheduler.
WebView2 application launched with standard integrity, however white screen persists. As such no error is thrown by parent C++ app and WebView2 app.
Please let me know if any more details are required.
Hello @ajay.shinde ,
Thanks for the update, and for methodically ruling out the user-data-folder and integrity angles, a window that appears but stays white at standard integrity points to a rendering/initialization problem rather than a launch or permissions failure.
A white window with no error is most often a GPU/compositing issue in restricted or custom-shell environments. Since your C++ app replaces explorer.exe as the shell, the graphics and compositor state that the normal shell sets up isn't fully in place, and WebView2's GPU process can fail to produce a frame. The quickest way to confirm this is to disable GPU acceleration for the WebView2 process by passing Chromium switches through CoreWebView2EnvironmentOptions.AdditionalBrowserArguments when you create the environment, try --disable-gpu (and, if needed, add --disable-gpu-compositing). If the page renders after that, the root cause is GPU compositing in that session and you can keep the switch or configure software rendering.
Because no error is surfacing, I'd also suggest instrumenting where initialization actually stops: subscribe to CoreWebView2.ProcessFailed and to the NavigationCompleted event (check IsSuccess and WebErrorStatus). A white screen can mean the render process fell over, the navigation failed silently, or the initial content never loaded, and those handlers will tell you which one it is.
If the white screen remains after disabling GPU, could you let me know whether the exact same build renders correctly when you launch it manually by double-clicking from the interactive desktop, and share the WebErrorStatus from NavigationCompleted? That comparison isolates whether it's the startup/shell environment or the app itself.
Thankyou for your inputs. With manual execution by double-clicking from the interactive desktop, white screen issue does not appear. This issue is observed only when we execute WebView2 on Windows logon through C++ application.
For further testing our target system is available in the week of 3-Aug-2026, thus we shall be able to verify suggested changes in the week of 3-Aug-2026. Sorry for the inconvenience.
Meanwhile just wanted to understand if flags --disable-gpu and--disable-gpu-compositing would have any impact in runtime environment. Because GPU rendering is one of the core functionality WebView2 would require and we are disabling it.
Please let us know if any more details are required.
@Damien Pham (WICLOUD CORPORATION)
We were able to execute updated code with --disable-gpu and--disable-gpu-compositing since system got available before time. We observed with above changes also white screen is occurring.
CoreWebView2.ProcessFailed event did not execute and NavigationCompleted event returned IsSuccess.
When we checked WebView2 application in task manager, it was running in elevated mode.
One more point to inform is UAC is disabled on the device. We feel 'UAC disable' would also impact execution in elevated mode.
Please let us know if any more details are required. Thank you again for your support.
Hello @ajay.shinde ,
Thank you for testing so thoroughly and for the very useful details, they actually point away from rendering and toward the privilege context. Since --disable-gpu / --disable-gpu-compositing didn't help, ProcessFailed never fired, and NavigationCompleted returned IsSuccess, we can conclude the content loaded and the render process is healthy; this is not a GPU crash or a navigation failure. That leaves the fact you spotted in Task Manager: the WebView2 process is running elevated.
Your instinct about UAC is correct, and it ties the two observations together. WebView2 is designed to run at standard (non-elevated) user integrity, and running the host elevated is explicitly discouraged. On a normal device, when an administrator signs in, Windows creates a filtered standard-user token and runs the shell and its child processes at standard integrity, so a WebView2 app inherits that standard level. With UAC disabled (EnableLUA=0), that filtered token is not created, so every process an administrator starts, including your C++ launcher and the WebView2 app it spawns, runs at high (elevated) integrity. That's also why the Task Scheduler "run with lowest privileges" approach couldn't drop it to standard: while UAC is off, there is no medium-integrity token to fall back to, so the host stays pinned to the elevated configuration that WebView2 recommends against.
So the most reliable fix is to re-enable UAC on the device (set EnableLUA=1 and reboot) so a genuine standard, non-elevated session is available, and then let the WebView2 host run at that standard integrity rather than elevated. If enabling UAC broadly isn't possible in your environment, the goal is the same: ensure the WebView2-hosting process ends up at medium (standard) integrity rather than high.
When you're able to test, could you re-enable UAC, confirm in Task Manager that the WebView2 process now shows standard (non-elevated) integrity, and let me know whether the page renders? That will confirm whether the elevated context under disabled UAC is the root cause.
Hi @Damien Pham (WICLOUD CORPORATION)
As sugegsted we tested with 'UAC enable'(set EnableLUA=1 and reboot).
This time WebView2 process launched successfully with standard (non-elevated) integrity. However it still displayed white screen on start. Also 'msedgewebview2.exe' was not running in the background.
On the other hand when 'UAC disable'(set EnableLUA=0 and reboot).
This time WebView2 process launched with elevated integrity. Also 'msedgewebview2.exe' was running in the background. However white screen was displayed when we closed WebView2 application.
Please let us know if any more details are required. Thank you.
Hi @ajay.shinde ,
Thanks for running both configurations so cleanly, that side-by-side comparison is exactly what we needed, and it actually shows real progress. The key detail is msedgewebview2.exe: in the UAC-enabled (standard integrity) run it never appears in the background, whereas in the UAC-disabled (elevated) run it is present. msedgewebview2.exe is the WebView2 Runtime browser process, so its absence means the WebView2 environment isn't being created at all in the standard run, the window paints white simply because there is no runtime behind it to render. In the elevated run the runtime does start and the page renders; the white you see only when closing is just the control tearing down, which is harmless.
So, the standard-integrity result is the direction we want, because it matches WebView2's recommended non-elevated model, we just need to find why the runtime fails to launch there. The most reliable next step is to capture the HRESULT from the environment-creation callback (the completion handler of CreateCoreWebView2EnvironmentWithOptions, or the exception from EnsureCoreWebView2Async) in the standard run. That call returns a specific documented reason such as E_ACCESSDENIED (user data folder can't be created), ERROR_FILE_EXISTS (a folder with the same name already exists), E_FAIL (Edge runtime unable to start), or CO_E_NOTINITIALIZED / RPC_E_CHANGED_MODE (COM not initialized as a single-threaded apartment), these are listed under the error values for CreateCoreWebView2EnvironmentWithOptions.
Two things are worth doing before that test, because they line up with the most common causes. First, point the app at a fresh custom user data folder in a per-user writable path such as %LocalAppData%, and delete any user data folder that a previous elevated run created next to the executable, a folder created by an elevated (high integrity) process can block a later standard-integrity process with Access Denied or file-exists, which would explain why the runtime starts elevated but not standard; the docs cover specifying a writable custom UDF and the related error messages. Second, confirm the thread that creates the environment calls CoInitializeEx as a single-threaded apartment, since a logon/startup launch path can otherwise leave COM in a state that fails environment creation.
Could you share the exact HRESULT or error text from the environment-creation callback in the UAC-enabled run, and confirm whether a leftover .WebView2 folder from the elevated runs exists next to the exe? That will tell precisely why the runtime isn't launching at standard integrity.
If you found my response helpful or informative, I would greatly appreciate it if you could follow this guidance or provide feedback.
Thank you.
@Damien Pham (WICLOUD CORPORATION)
We executed WebView2 application in non elevated mode when UAC is disabled, with below conditions,
On execution, we received below exception from EnsureCoreWebView2Async(),
Exception: Exception occured while calling Login InitializeAsync()System.Runtime.InteropServices.COMException (0x80010108): The object invoked has disconnected from its clients. (Exception from HRESULT: 0x80010108 (RPC_E_DISCONNECTED))
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
at Microsoft.Web.WebView2.Core.CoreWebView2Environment.<CreateCoreWebView2ControllerAsync>d__37.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Web.WebView2.Wpf.WebView2.<>c__DisplayClass25_0.<<EnsureCoreWebView2Async>g__Init|0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at USAuthWebScreens.Views.LoginScreen.<InitializeAsync>d__3.MoveNext()
We have also checked for the existence of '.WebView2' folder at the location from where 'WebView2' application is executed. In both scenarios with UAC enabled and disabled, '.WebView2' folder was created after execution.
Your response is certainly helpful. I tried to follow <guidance> link in above comment to provide feedback, but URL seems broken. Please let me know where can I submit feedback.
Thank you.
Hello @ajay.shinde ,
Thanks for the detailed exception and for confirming the folder behavior, that gives us two concrete things to act on.
First, the .WebView2 folder still appearing next to the executable tells us the custom user data folder isn't actually being applied. For a .NET WPF app that folder (the executable path + .WebView2) is the default UDF location, so the control is still initializing with defaults instead of your %LocalAppData% path. In WPF the user data folder must be set before initialization begins, either by setting WebView2.CreationProperties.UserDataFolder before the first EnsureCoreWebView2Async call, or by creating the environment yourself with CoreWebView2Environment.CreateAsync(browserExecutableFolder, userDataFolder, options) and passing it into EnsureCoreWebView2Async(environment). As the CreationProperties documentation notes, "Setting this property will not work after initialization of the control's CoreWebView2 has started," so if it is applied too late it is silently ignored and you fall back to the default folder.
Second, the exception itself, RPC_E_DISCONNECTED (0x80010108), "The object invoked has disconnected from its clients", is a COM error, and here the most likely trigger is the manual CoInitializeEx() call you added. A WPF UI thread is already initialized as a single-threaded apartment with a running Dispatcher message loop, which is exactly the environment WebView2 needs; adding your own CoInitializeEx() (and any matching CoUninitialize) on that thread can change or tear down the apartment and disconnect the WebView2 COM objects mid-creation, which produces this exact error at CreateCoreWebView2ControllerAsync. I'd suggest removing the manual CoInitializeEx() and making sure EnsureCoreWebView2Async is called on the WPF UI/Dispatcher thread, letting WPF provide the STA and message pump.
Could you apply both changes together, wire the UDF through CreationProperties or CreateAsync before initialization, and drop the manual CoInitializeEx(), and let me know whether the .WebView2 folder stops being created next to the exe and whether the disconnect still occurs? That will confirm whether the manual COM initialization was the trigger.
Here is the alternative link for the broken link above https://learn.microsoft.com/en-us/answers/support/accept-answer.
Thank you.
We updated code as suggested by removing explicit call CoInitializeEx().
After executing 'WebView2Launcher' through 'winlogon/shell' registry value it started 'SampleWebView2' application in non elevated mode. UAC was disabled on the Win 11 Pro system.
We observed UDF created on the specified environment path and not at the path of 'SampleWebView2' exe. Same exception occurred and 'msedgewebview2.exe' was not running.
For your reference I have attached application code below,
After downloading change extension to zip. If we extract attachment on 'C:' for example "C:\POC_WebView" then on execution it generates log files as below,
"C:\POC_WebView\DebugLogs\DebugLogs.txt"
"C:\POC_WebView\WebViewLog\webview2.log"
I have also checked feedback link and went through details. As suggested once our solution works, I shall update the feedback. Please let me know if any more details are required. Thank you for your support.
Hello @ajay.shinde ,
Thanks for sharing your application code and the new results, this genuinely moves us forward. Removing the manual CoInitializeEx(), and your %LocalAppData%\WebView2 folder now being used instead of a folder next to the exe, confirm the environment is being created correctly, so those two earlier problems are resolved.
The remaining symptom is now well isolated. RPC_E_DISCONNECTED (0x80010108) at CreateCoreWebView2ControllerAsync, together with msedgewebview2.exe not running, means the WebView2 browser process never came up, so the COM object the controller was talking to "disconnected." As the WebView2 process model explains, the browser process is started when the first WebView2 instance is created and every other runtime process hangs off it; if that process fails to launch, controller creation fails in exactly this way.
Looking at your WebView2Launcher.cpp, the most likely cause is how the host is de-elevated. StartSampleWebView2NonElevated() builds a restricted token with CreateRestrictedToken (DISABLE_MAX_PRIVILEGE plus a disabled Administrators SID) and launches SampleWebView2.exe through CreateProcessAsUserW. WebView2 relies on the Chromium sandbox, which derives its own further-restricted tokens for the browser and renderer child processes from the host process token. When the host is already running under a hand-built, heavily restricted token, those child processes typically can't be created, which matches msedgewebview2.exe never starting and the disconnect you observe. It also lines up with your earlier finding that a normal double-click launch renders fine: the differentiator is the restricted token, not the app.
Given that, I'd move away from manufacturing a restricted token and instead launch the host with the interactive logged-on user's own token, which is the standard way to spawn a non-elevated process from a startup/shell component and keeps the WebView2 host at standard user integrity, the recommended privilege level for WebView2 hosts ("we recommend hosting WebView2 in a process that runs at standard (non-elevated) user integrity"). As a quick confirmation, launch the same exe once with a normal token (your StartSampleWebView2() path or a manual double-click) and check whether msedgewebview2.exe then appears; if it does, the restricted token is the cause.
Since --enable-logging is now producing webview2.log, could you share that file (and DebugLogs.txt) from a failing run? The Chromium browser-process/sandbox startup entry in webview2.log will show exactly why msedgewebview2.exe exits and confirm this.
Hi @Damien Pham (WICLOUD CORPORATION)
We have executed with a normal token (StartSampleWebView2() ) and observed msedgewebview2.exe started. SampleWebView2.exe started in elevated mode.
Please find attached logs as requested, please rename file extension to zip and extract. Logs.txt
It seems restricted token is a problem. Please let us know if any more details are required.
Thank you.
Hello @ajay.shinde ,
Thank you, the two log sets settle this conclusively, and your reading is correct: the restricted token is the problem.
In the failing run (the restricted-token launch), webview2.log shows the browser process starting normally and then failing to create its child process:
GPU process launch failed: error_code=49
The GPU process has crashed 6 time(s)
FATAL:...gpu_data_manager_impl_private.cc:426] GPU process isn't usable. Goodbye.
WebView2 runs on the Chromium multi-process model, where the browser process spawns child processes (GPU, renderer, utility) using tokens it derives from its own process token (see the WebView2 process model). Because your host was started under a hand-built restricted token (CreateRestrictedToken with DISABLE_MAX_PRIVILEGE and a disabled Administrators SID), it cannot create those child processes; Chromium treats an unusable GPU process as fatal, terminates the browser process, and the controller's COM object then disconnects, which is exactly the RPC_E_DISCONNECTED you see in DebugLogs.txt at CreateCoreWebView2ControllerAsync. Note this happens even with --disable-gpu, because a GPU process is still launched (in software) and still needs to be created. Your normal-token run confirms the contrast: webview2.log there shows the GPU and renderer child processes starting and index.html rendering.
So the fix is to stop manufacturing a restricted token. To launch the host non-elevated from your startup component, use the interactive logged-on user's own primary token rather than a derived, restricted one. The standard Windows pattern is WTSQueryUserToken for the active session followed by CreateProcessAsUser with that token passed through unmodified. That gives the WebView2 host a normal, unrestricted user token, so the sandbox can spawn its child processes as it did in your working run.
One caveat to set expectations: you observed that the normal-token launch runs elevated. That is because UAC is disabled on the device, so the interactive user's token is a full administrator (high-integrity) token and there is no linked filtered standard token to fall back to. To reach true standard (non-elevated) integrity, which is the recommended privilege level for WebView2 hosts ("we recommend hosting WebView2 in a process that runs at standard (non-elevated) user integrity"), UAC needs to be enabled so that filtered standard token exists. If your environment must keep UAC disabled, the working normal-token path is a functioning option, with the understanding that it runs elevated, which is the discouraged configuration in that guidance.
Hello @Damien Pham (WICLOUD CORPORATION)
Thank you for the detailed explanation.
We had tried WTSQueryUserToken as well, it failed somehow to get token. we are checking it further.
However with UAC disabled WTSQueryUserToken approach may not work, I feel. In this scenario I would request if you have any suggestion or other option that we can try out to solve this problem, kindly suggest.
Hi @ajay.shinde ,
Thanks for trying that and for the detail. Let me clear up one point first: disabling UAC does not block WTSQueryUserToken, that API returns the interactive user's token regardless of UAC state. The reason it fails to return a token is almost certainly a privilege issue. Per the WTSQueryUserToken documentation, "the calling application must be running within the context of the LocalSystem account and have the SE_TCB_NAME privilege." A launcher started from the Winlogon\Shell value runs inside the interactive user's own session (not as LocalSystem), so it lacks SE_TCB_NAME and the call fails, GetLastError in that case is typically ERROR_PRIVILEGE_NOT_HELD (1314). WTSQueryUserToken is really meant for a SYSTEM service in session 0 launching into a user session, which is not your topology.
The good news is that because your launcher already runs inside the logged-on user's session, you don't actually need WTSQueryUserToken at all. Launch the WebView2 host with a plain CreateProcess and no token manipulation, the child then inherits the launcher's own, unrestricted user token. That is exactly your working StartSampleWebView2() path where msedgewebview2.exe started and the page rendered, and it avoids the restricted-token problem entirely.
The only remaining trade-off is the one we discussed: with UAC disabled the interactive user's token is a full-admin (high-integrity) token, and there is no linked filtered standard token, so that plain-CreateProcess child runs elevated. To reach true standard (non-elevated) integrity, the recommended level for WebView2 hosts , UAC needs to be enabled so the filtered standard token exists. If the environment must keep UAC disabled, the plain CreateProcess path is a functioning option, with the understanding that it runs elevated, which is the discouraged configuration.
So my suggestion is to drop the token manipulation and start with the plain CreateProcess launch, since it is the simplest path that renders. If you specifically need non-elevated integrity without enabling UAC, tell me your exact constraints and I'll look at whether a lower-integrity (filtered-token) approach can fit, but I'd validate the plain launch first.
Hello @Damien Pham (WICLOUD CORPORATION)
Thank you for your support. Constraints are as below,
Please let me know in case any more details are required.
Hello @ajay.shinde ,
Thanks for listing the constraints, that makes it clear that enabling UAC or adding a standard user aren't options, so we need to de-elevate the app another way.
The restricted token you built earlier failed for a specific reason: DISABLE_MAX_PRIVILEGE and the disabled Administrators SID stripped the token's privileges and blocked its group SIDs. WebView2 (Chromium) needs to create its own child processes from your process token, and it can't do that once the token is stripped, that's the error_code=49 GPU failure and the white screen. The problem was the stripping, not a lower integrity level.
The simpler fix is to lower only the integrity level to medium and leave everything else on the token alone. In your launcher: call DuplicateTokenEx on your own token, then SetTokenInformation with TokenIntegrityLevel set to medium (SID S-1-16-8192), then start the app with CreateProcessAsUser. Because privileges and groups stay intact, WebView2 can still start msedgewebview2.exe and render, but the app now runs at medium (standard) integrity. Per the Mandatory Integrity Control docs, medium is the standard-user level, which is the level Microsoft recommends for a WebView2 host.
If you just want to confirm it renders first, your plain CreateProcess path already works, it simply runs elevated because UAC is off. The medium-integrity token is how you get it non-elevated.
Give it a try and let me know if the app renders. Happy to help if anything comes up.
Hi @Damien Pham (WICLOUD CORPORATION)
As suggested we tried calling DuplicateTokenEx on 'WebView2Launcher.exe' process token, then called SetTokenInformation with TokenIntegrityLevel set to medium (SID S-1-16-8192). Then started the 'SampleWebView2.exe' with CreateProcessAsUser.
However this approach started 'SampleWebView2.exe' as elevated process and white screen appeared again.
Request to suggest and please let us know if any more details are required. Thank you for your help.
Hello @ajay.shinde ,
Thanks for testing that so quickly. The white screen coming back does not necessarily mean the integrity change failed, because Task Manager's Elevated column does not show the integrity level. It only shows whether the token still carries administrator rights (TOKEN_ELEVATION), and lowering integrity intentionally leaves the Administrators group in place. With UAC disabled that column cannot change at all, so your process may already be running at Medium.
Could you check the integrity level directly instead? In Process Explorer, add the Integrity column and look at SampleWebView2.exe, or call GetTokenInformation with TokenIntegrityLevel from inside the app (example here).
Also worth confirming in the launcher: that SetTokenInformation returned non zero, that the token was duplicated with TOKEN_ADJUST_DEFAULT (required for this change, otherwise the call fails with ERROR_ACCESS_DENIED), and that you pass a TOKEN_MANDATORY_LABEL with the matching size, since a wrong length returns ERROR_BAD_LENGTH (24).
If it reads High, the token change did not apply and GetLastError will tell us why. If it reads Medium, the likely cause is the user data folder: it was created by your earlier high integrity runs, and a Medium process cannot write to it (details). Please delete that folder, plus any .WebView2 folder next to the exe, and let the Medium run recreate it (folder guidance).
From that run, two things would tell us almost everything: whether msedgewebview2.exe appears in Task Manager, and the exact HRESULT from the environment creation callback.
If anything is unclear, feel free to comment.
Hello @Damien Pham (WICLOUD CORPORATION)
.WebView2 folder present next to the 'SampleWebView2.exe' before execution.HRESULT from the environment creation callback.It seems WebView2 is failing for some other issues now. We have attached 'webview2.log' here, generated for above run. webview2.log
Please let us know if any more details are required. Thanking you.
Hi @ajay.shinde ,
Thank you for confirming the integrity level in Process Explorer and for clearing the user data folders before the run, and for attaching webview2.log, which is the most informative piece we have had so far.
The log shows three WebView2 processes coming up (15420 as the browser process, 19016 as the GPU process, and 16520 as a further child), the viz compositor initializing, and no FATAL entry. That differs from your earlier restricted-token run, which contained "GPU process launch failed: error_code=49" followed by "GPU process isn't usable. Goodbye." Per the WebView2 process model, a browser process with live child processes indicates the runtime itself started, so the medium-integrity token addressed the sandbox failure and the host is now at the recommended non-elevated integrity level.
On your point about the log not naming the failure: webview2.log is Chromium's internal diagnostic log at default verbosity, so it records subsystem messages rather than application-level errors. It will show a crash or a process that failed to launch, but it does not report a failed navigation or an unpainted page. A white window alongside a healthy process tree therefore places the remaining problem above the runtime, in navigation or in the window and visual layer. The two errors that stand out, the DPI awareness failures and "GetGpuDriverOverlayInfo: Failed to retrieve video device", are consistent with a session that has no interactive shell, and neither is fatal on its own.
Three things would help close this out, and none of them require repeating what you have already tested. First, could you confirm whether msedgewebview2.exe now appears in Task Manager for this run, and whether EnsureCoreWebView2Async completes or still returns RPC_E_DISCONNECTED. Second, please capture the application-level result rather than the Chromium log: subscribe to CoreWebView2InitializationCompleted and log IsSuccess and InitializationException, and log NavigationCompleted with its IsSuccess and WebErrorStatus values along with [com/en-us/dotnet/api/microsoft.web.webview2.core.corewebview2.processfailed). Those surface exactly what the Chromium log cannot. Third, you can raise the log verbosity by passing --enable-logging --v=1 through AdditionalBrowserArguments, which adds navigation and renderer detail.
One hypothesis worth checking in the same run, now that the runtime is starting, is the timing and size of the host window. At Winlogon-shell startup your window is created in a very different order than on a double-click, so it would help to log the WebView2 control's ActualWidth and ActualHeight and the window's visibility at the moment initialization runs, and to try deferring EnsureCoreWebView2Async until after the window is shown and sized, or calling Reload once it is visible.
If you can share DebugLogs.txt from the same run together with the verbose webview2.log, that should give enough to pinpoint it. Happy to walk through any of the above if something is unclear, just leave a comment.
Thank you.
Hello @Damien Pham (WICLOUD CORPORATION)
We executed application through 'Winlogon/shell' registry with UAC disabled on Win 11 Pro and verified requested points as below,
We observed minimal sample application worked well without white screen. However main application failed with same code changes.
We have attached execution logs from the main application. Please rename extension to zip and extract.
Please let us know in case any more details are required. Thank you for your support.
Hello @ajay.shinde ,
Thank you for the detailed run and logs. This is a meaningful change from the earlier failure: WebView2 is now starting successfully.
In DebugLogs.txt, the main app records WebView2 initialized, captures browser process IDs, completes NavigationCompleted with "Page loaded successfully", the window reaches 1920 x 1080, and WebMessageReceived fires; in some runs the app also logs "Authentication success." In webview2.log, I do not see the previous fatal GPU-process failure or RPC_E_DISCONNECTED. That matches the WebView2 process model: once the browser process and child processes are running and NavigationCompleted/messages are firing, the remaining white screen is less likely to be WebView2 runtime startup and more likely to be application code after navigation.
The actionable error in this log is in the main app: System.Threading.WaitHandleCannotBeOpenedException: No handle of the given name exists, thrown at System.Threading.EventWaitHandle.OpenExisting(...) from USAuthWebScreens.ViewModel.LoginScreenViewModel.webView2NavigationComplete(...).
EventWaitHandle.OpenExisting opens a named synchronization event only if it already exists; per the .NET API documentation, it throws WaitHandleCannotBeOpenedException when the named synchronization object cannot be opened because it does not exist, is a different object type, or the name/namespace is invalid. The same documentation calls out the Global\ and Local\ namespaces and that Local\ is session-scoped by default.
So I would keep the current launcher/token/UDF/WebView2 setup unchanged and focus the next check on the named event used by LoginScreenViewModel.webView2NavigationComplete: confirm the exact event name, whether it is Global\ or session-local Local\/default, which process creates it, and whether that creation definitely happens before NavigationCompleted runs in the Winlogon-shell path. If the creator is in a different session or creates the event later, OpenExisting will fail exactly this way even though WebView2 itself has initialized and navigated successfully.
If you can share the small code block that creates this EventWaitHandle and the line in webView2NavigationComplete that opens it, we can narrow whether this is a creation-order, namespace, or access-rights issue.
Hello @Damien Pham (WICLOUD CORPORATION)
Thank you for your prompt response.
We resolved the Event related exception and re-executed the application. We observed now event related exception is not present in logs. Please find attached log, DebugLogs.txt.
However white screen issue still occurred. It is observed while closing the WebView2 screen. Please let us know in case any more details are required.
Hello @ajay.shinde ,
Thank you for confirming. Since the EventWaitHandle exception is now gone, the page renders correctly, and the blank screen appears only for about a second while the WebView2 login screen is closing before the next UI appears, this no longer looks like the earlier WebView2 startup/rendering problem.
The latest DebugLogs.txt also supports that: WebView2 initializes, the browser process ID is captured, navigation completes with "Page loaded successfully", web messages are received, and authentication succeeds before Window_Closed starts the cleanup path. Based on that sequence, I would focus on the application transition/teardown order rather than the launcher/token/UDF setup.
WebView2 uses a browser process plus renderer/helper processes, and the WebView2 process model recommends using the WebView2 controller close/lifetime path for shutdown. In your close path, please check whether the login WebView is being cleared/disposed, the browser process is being cleaned up, or the user data folder is being deleted before the next UI is visible. A common way to avoid this kind of one-second white flash is to show or activate the next UI first, then hide/close the login WebView, and only after that dispose WebView2 / perform browser-process or UDF cleanup.
At this point I do not think more WebView2 startup details are required unless the blank screen remains visible, appears before the page finishes loading, or ProcessFailed/NavigationCompleted starts reporting an error again. For the current one-second close-time flash, the next useful check is the code order around Window_Closed, Dispose WebView, browser-process cleanup, UDF deletion, and showing the next UI.
Hi @Damien Pham (WICLOUD CORPORATION)
The current code order is as below,
First LoginWebViewWindow.Close(), then inside Window_Closed(), trigger next UI, the WebViewCleanup()(Dispose WebView, browser-process cleanup, UDF deletion)
First trigger next UI then LoginWebViewWindow.Close(), then inside Window_Closed(), the WebViewCleanup()(Dispose WebView, browser-process cleanup, UDF deletion)
First trigger next UI, then wait for 5 seconds, then call LoginWebViewWindow.Close(), then inside Window_Closed(), the WebViewCleanup()(Dispose WebView, browser-process cleanup, UDF deletion)
Thus it seems as mentioned in point 2 above, Webview2.exe is not closing immediately on dispose. And remains running with complete white screen.
Please let us know in case any more details are required. Thank you for your support.
Hello @ajay.shinde ,
Thank you for testing the different close orders. Based on those results, I would not treat this as WebView2 failing to initialize or render anymore. This now looks like the close/shutdown lifetime of the WebView2 Runtime process group.
WebView2 runs a browser process plus renderer/helper processes that are tied to the user data folder, as described in the WebView2 process model. Calling dispose on the WPF WebView2 control releases the WebView resources, but it should not be used as a guarantee that msedgewebview2.exe has already exited. The documented shutdown path is CoreWebView2Controller.Close, which closes the WebView and cleans up the underlying browser instance, and the browser instance shuts down when no other WebViews are using it: CoreWebView2Controller.Close. In WPF, WebView2.Dispose releases the underlying COM resources, including CoreWebView2: WebView2.Dispose.
If you need a definite signal that the WebView2 Runtime process collection has completed normal shutdown, use CoreWebView2Environment.BrowserProcessExited. That event is raised when the WebView2 Runtime processes for that environment terminate, for example after all associated WebViews are closed and resources including the user data folder are released: BrowserProcessExited.
So the practical recommendation is to separate the visual transition from Runtime cleanup: show/activate the next UI, hide or remove the login window from the taskbar/visible UI, then run the normal WebView close/dispose path. Please avoid direct browser-process cleanup or UDF deletion during that visible transition; if you need to delete the UDF, do it only after BrowserProcessExited or when the application is exiting and all WebViews using that UDF are closed.