1
- using Microsoft . Win32 . SafeHandles ;
2
- using System ;
1
+ using System ;
2
+ using System . Collections . Concurrent ;
3
3
using System . Collections . Generic ;
4
4
using System . Diagnostics ;
5
5
using System . Linq ;
6
6
using System . Text ;
7
+ using System . Threading . Tasks ;
8
+ using Microsoft . Win32 . SafeHandles ;
7
9
using Windows . Win32 ;
8
10
using Windows . Win32 . Foundation ;
9
11
using Windows . Win32 . System . Threading ;
@@ -72,8 +74,21 @@ public List<Process> GetMatchingProcesses()
72
74
/// </summary>
73
75
public static unsafe Dictionary < int , string > GetProcessesWithNonEmptyWindowTitle ( )
74
76
{
75
- var processDict = new Dictionary < int , string > ( ) ;
77
+ // Collect all window handles
78
+ var windowHandles = new List < HWND > ( ) ;
76
79
PInvoke . EnumWindows ( ( hWnd , _ ) =>
80
+ {
81
+ if ( PInvoke . IsWindowVisible ( hWnd ) )
82
+ {
83
+ windowHandles . Add ( hWnd ) ;
84
+ }
85
+ return true ;
86
+ } , IntPtr . Zero ) ;
87
+
88
+ // Concurrently process each window handle
89
+ var processDict = new ConcurrentDictionary < int , string > ( ) ;
90
+ var processedProcessIds = new ConcurrentDictionary < int , byte > ( ) ;
91
+ Parallel . ForEach ( windowHandles , hWnd =>
77
92
{
78
93
var windowTitle = GetWindowTitle ( hWnd ) ;
79
94
if ( ! string . IsNullOrWhiteSpace ( windowTitle ) && PInvoke . IsWindowVisible ( hWnd ) )
@@ -82,20 +97,26 @@ public static unsafe Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle
82
97
var result = PInvoke . GetWindowThreadProcessId ( hWnd , & processId ) ;
83
98
if ( result == 0u || processId == 0u )
84
99
{
85
- return false ;
100
+ return ;
86
101
}
87
102
88
- var process = Process . GetProcessById ( ( int ) processId ) ;
89
- if ( ! processDict . ContainsKey ( ( int ) processId ) )
103
+ // Ensure each process ID is processed only once
104
+ if ( processedProcessIds . TryAdd ( ( int ) processId , 0 ) )
90
105
{
91
- processDict . Add ( ( int ) processId , windowTitle ) ;
106
+ try
107
+ {
108
+ var process = Process . GetProcessById ( ( int ) processId ) ;
109
+ processDict . TryAdd ( ( int ) processId , windowTitle ) ;
110
+ }
111
+ catch
112
+ {
113
+ // Handle exceptions (e.g., process exited)
114
+ }
92
115
}
93
116
}
117
+ } ) ;
94
118
95
- return true ;
96
- } , IntPtr . Zero ) ;
97
-
98
- return processDict ;
119
+ return new Dictionary < int , string > ( processDict ) ;
99
120
}
100
121
101
122
private static unsafe string GetWindowTitle ( HWND hwnd )
0 commit comments