Skip to content

Commit cdaf832

Browse files
Merge pull request #5401 from MicrosoftEdge/api-get-processid
API Review: ProcessId for ProcessFailedEventArgs
2 parents 94ede54 + 61ba25b commit cdaf832

File tree

1 file changed

+212
-0
lines changed

1 file changed

+212
-0
lines changed

specs/api-get_ProcessId.md

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
ProcessId for ProcessFailedEventArgs
2+
===
3+
4+
# Background
5+
6+
WebView2 provides applications with the
7+
[ProcessFailed](https://learn.microsoft.com/microsoft-edge/webview2/reference/win32/icorewebview2?view=webview2-1.0.705.50#add_processfailed)
8+
event so they can react accordingly when a process failure occurs. However,
9+
this event does not currently provide the process ID of the failed process.
10+
This is particularly problematic when running multiple renderers. It becomes
11+
difficult for the application to determine which process to address.
12+
13+
In this document we describe an extended version of the
14+
[ProcessFailedEventArgs](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2processfailedeventargs?view=webview2-1.0.2151.40),
15+
which provides access to an `ICoreWebView2ProcessInfo` object for the failed process. This object includes the process ID, process kind, and other relevant information. This enables the host application to collect
16+
additional information about the process failure, whether it is a renderer, GPU, or
17+
even the browser process.
18+
19+
The updated API is detailed below. We'd appreciate your feedback.
20+
21+
# Description
22+
23+
The `ICoreWebView2ProcessFailedEventArgs4` interface extends the existing
24+
`ProcessFailedEventArgs` to include, when available, the `ICoreWebView2ProcessInfo` of the failed process. Note that `ProcessInfo` may be null or unavailable in certain scenarios. This
25+
enables applications to:
26+
- Correlate process failures with running process data from the ProcessInfo API
27+
- Collect process-specific diagnostic information for logging and telemetry
28+
- Analyze crash dumps for specific processes
29+
- Better track and respond to failures in multi-renderer scenarios
30+
31+
# Examples
32+
33+
The following code snippets demonstrate how the updated
34+
`ProcessFailedEventArgs` can be used by the host application:
35+
36+
## Win32 C++
37+
38+
```cpp
39+
//! [ProcessFailed]
40+
// Register a handler for the ProcessFailed event.
41+
// This handler collects extended diagnostics so the host can:
42+
// * Inspect the failure kind together with reason, description, and exit code.
43+
// * Retrieve the CoreWebView2ProcessInfo for the failed process (ID and kind).
44+
// * Log the gathered information for telemetry or later correlation and decide
45+
// how to react (reload/recreate) based on app policy outside of this sample.
46+
CHECK_FAILURE(m_webView->add_ProcessFailed(
47+
Callback<ICoreWebView2ProcessFailedEventHandler>(
48+
[this](ICoreWebView2* sender,
49+
ICoreWebView2ProcessFailedEventArgs* argsRaw)
50+
-> HRESULT {
51+
wil::com_ptr<ICoreWebView2ProcessFailedEventArgs> args = argsRaw;
52+
COREWEBVIEW2_PROCESS_FAILED_KIND kind;
53+
CHECK_FAILURE(args->get_ProcessFailedKind(&kind));
54+
55+
// Try to get the newer interface with additional failure details
56+
auto args2 =
57+
args.try_query<ICoreWebView2ProcessFailedEventArgs2>();
58+
if (args2)
59+
{
60+
COREWEBVIEW2_PROCESS_FAILED_REASON reason;
61+
wil::unique_cotaskmem_string processDescription;
62+
INT32 exitCode;
63+
CHECK_FAILURE(args2->get_Reason(&reason));
64+
CHECK_FAILURE(
65+
args2->get_ProcessDescription(&processDescription));
66+
CHECK_FAILURE(args2->get_ExitCode(&exitCode));
67+
68+
// Get the process ID of the failed process
69+
wil::com_ptr<ICoreWebView2ProcessInfo> processInfo;
70+
auto argProcessInfo = args.try_query<ICoreWebView2ProcessFailedEventArgs4>();
71+
if (argProcessInfo)
72+
{
73+
CHECK_FAILURE(argProcessInfo->get_ProcessInfo(&processInfo));
74+
}
75+
INT32 processId = 0;
76+
COREWEBVIEW2_PROCESS_KIND processKind = COREWEBVIEW2_PROCESS_KIND_UNKNOWN;
77+
if (processInfo)
78+
{
79+
CHECK_FAILURE(processInfo->get_ProcessId(&processId));
80+
CHECK_FAILURE(processInfo->get_Kind(&processKind));
81+
}
82+
83+
// Log the failure details including the process ID
84+
std::wstringstream message;
85+
message << L"Kind: " << ProcessFailedKindToString(kind)
86+
<< L"\n"
87+
<< L"Reason: " << ProcessFailedReasonToString(reason)
88+
<< L"\n"
89+
<< L"Exit code: " << exitCode << L"\n"
90+
<< L"Process ID: " << processId << L"\n"
91+
<< L"Process Kind: " << ProcessKindToString(processKind) << L"\n"
92+
<< L"Process description: "
93+
<< processDescription.get();
94+
95+
OutputDebugString(message.str().c_str());
96+
// Collect the process ID for telemetry or further
97+
// analysis
98+
}
99+
return S_OK;
100+
})
101+
.Get(),
102+
&m_processFailedToken));
103+
//! [ProcessFailed]
104+
```
105+
106+
## .NET C#
107+
108+
```c#
109+
void WebView_CoreWebView2InitializationCompleted(object sender,
110+
CoreWebView2InitializationCompletedEventArgs e)
111+
{
112+
if (e.IsSuccess)
113+
{
114+
webView.CoreWebView2.ProcessFailed += WebView_ProcessFailed;
115+
}
116+
}
117+
118+
void WebView_ProcessFailed(object sender,
119+
CoreWebView2ProcessFailedEventArgs e)
120+
{
121+
// Collect failure details including the process ID
122+
StringBuilder messageBuilder = new StringBuilder();
123+
messageBuilder.AppendLine($"Process kind: {e.ProcessFailedKind}");
124+
messageBuilder.AppendLine($"Reason: {e.Reason}");
125+
messageBuilder.AppendLine($"Exit code: {e.ExitCode}");
126+
messageBuilder.AppendLine(
127+
$"Process description: {e.ProcessDescription}");
128+
129+
// Get the process ID of the failed process
130+
if (e.ProcessInfo != null)
131+
{
132+
messageBuilder.AppendLine($"Process ID: {e.ProcessInfo.ProcessId}");
133+
messageBuilder.AppendLine($"Process Kind: {e.ProcessInfo.Kind}");
134+
}
135+
else
136+
{
137+
messageBuilder.AppendLine("Process Info: unavailable (process may have been terminated externally, e.g., via Task Manager)");
138+
}
139+
140+
// Log the failure or send to telemetry
141+
System.Diagnostics.Debug.WriteLine(messageBuilder.ToString());
142+
143+
// You can also correlate with process info collected earlier
144+
var failedProcessInfo = _processInfoList.FirstOrDefault(
145+
p => p.ProcessId == e.ProcessInfo.ProcessId);
146+
if (failedProcessInfo != null)
147+
{
148+
System.Diagnostics.Debug.WriteLine(
149+
$"Failed process was of kind: {failedProcessInfo.Kind}");
150+
}
151+
}
152+
```
153+
154+
# Remarks
155+
156+
The `ProcessInfo` property returns an `ICoreWebView2ProcessInfo` object that contains the process ID of the failed process
157+
and the process kind (GPU, Renderer, Browser, Utility, etc.). When the failing
158+
process starts successfully (for example, GPU process hangs, browser process
159+
exits, utility process exits, renderer process hangs), the process ID is
160+
available so apps can correlate diagnostics. If the process never starts or if
161+
the main frame renderer process is terminated externally (for example, by Task
162+
Manager or taskkill) the associated process information is unavailable and the
163+
reported process ID is 0.
164+
165+
# API Details
166+
167+
## COM
168+
169+
```cpp
170+
171+
/// A continuation of the ICoreWebView2ProcessFailedEventArgs3 interface
172+
/// for getting the process ID of the failed process.
173+
///
174+
[uuid(f71c6e90-b2dc-4f81-bb56-bb3ef56dd8c7), object,
175+
pointer_default(unique)]
176+
interface ICoreWebView2ProcessFailedEventArgs4 :
177+
ICoreWebView2ProcessFailedEventArgs3 {
178+
/// The process info of the failed process, which can be used to
179+
/// correlate the failing process with the running process data or to
180+
/// analyze crash dumps for that process. The process ID is available when the
181+
/// process starts successfully (GPU process hangs, browser process exits,
182+
/// utility process exits, renderer process hangs). If the process never
183+
/// started or when the main frame renderer process is terminated externally
184+
/// (for example by Task Manager or taskkill), the process ID will be set to 0.
185+
// MSOWNERS: core ([email protected])
186+
[propget] HRESULT ProcessInfo([out, retval] ICoreWebView2ProcessInfo** value);
187+
}
188+
189+
```
190+
191+
## .NET / WinRT
192+
193+
```c#
194+
namespace Microsoft.Web.WebView2.Core
195+
{
196+
runtimeclass CoreWebView2ProcessFailedEventArgs
197+
{
198+
/// The process info of the failed process, which can be used to
199+
/// correlate the failing process with the running process data or to
200+
/// analyze crash dumps for that process.
201+
///
202+
/// This property may be <c>null</c> if the process never started or when the main frame renderer process
203+
/// is terminated externally (for example, by Task Manager or taskkill). In these cases, process information
204+
/// is not available. When available, the process ID is set to 0 if the process could not be identified.
205+
206+
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2ProcessFailedEventArgs4")]
207+
{
208+
CoreWebView2ProcessInfo ProcessInfo { get; };
209+
}
210+
}
211+
}
212+
```

0 commit comments

Comments
 (0)