@@ -175,12 +175,29 @@ public StateActions SuspendProcesses()
175175 {
176176 foreach ( var gameProcess in GameProcesses )
177177 {
178- if ( gameProcess is null || gameProcess . Process . Handle == null || gameProcess . Process . Handle == IntPtr . Zero )
178+ if ( gameProcess ? . Process is null )
179179 {
180180 continue ;
181181 }
182182
183- Ntdll . NtSuspendProcess ( gameProcess . Process . Handle ) ;
183+ try
184+ {
185+ if ( ! gameProcess . Process . HasExited )
186+ {
187+ var handle = gameProcess . Process . Handle ;
188+ Ntdll . NtSuspendProcess ( handle ) ;
189+ }
190+ }
191+ catch ( InvalidOperationException ex )
192+ {
193+ _logger . Error ( ex , "Error on process suspend" ) ;
194+ continue ;
195+ }
196+ catch ( Exception ex )
197+ {
198+ _logger . Error ( ex , "Error on process suspend" ) ;
199+ continue ;
200+ }
184201 }
185202
186203 IsSuspended = true ;
@@ -192,12 +209,29 @@ public StateActions ResumeProcesses()
192209 {
193210 foreach ( var gameProcess in GameProcesses )
194211 {
195- if ( gameProcess is null || gameProcess . Process . Handle == null || gameProcess . Process . Handle == IntPtr . Zero )
212+ if ( gameProcess ? . Process is null )
196213 {
197214 continue ;
198215 }
199216
200- Ntdll . NtResumeProcess ( gameProcess . Process . Handle ) ;
217+ try
218+ {
219+ if ( ! gameProcess . Process . HasExited )
220+ {
221+ var handle = gameProcess . Process . Handle ;
222+ Ntdll . NtResumeProcess ( handle ) ;
223+ }
224+ }
225+ catch ( InvalidOperationException ex )
226+ {
227+ _logger . Error ( ex , "Error on process resume" ) ;
228+ continue ;
229+ }
230+ catch ( Exception ex )
231+ {
232+ _logger . Error ( ex , "Error on process resume" ) ;
233+ continue ;
234+ }
201235 }
202236
203237 IsSuspended = false ;
@@ -235,36 +269,90 @@ public ProcessItem GetProcessByWindowHandle(IntPtr handle)
235269 return null ;
236270 }
237271
238- var process = GameProcesses . FirstOrDefault ( x => x . Process ? . MainWindowHandle == handle ) ;
239- return process ;
272+ foreach ( var processItem in GameProcesses )
273+ {
274+ if ( processItem ? . Process is null )
275+ {
276+ continue ;
277+ }
278+
279+ try
280+ {
281+ if ( ! processItem . Process . HasExited &&
282+ processItem . Process . MainWindowHandle == handle )
283+ {
284+ return processItem ;
285+ }
286+ }
287+ catch ( InvalidOperationException ex )
288+ {
289+ _logger . Warn ( ex , $ "GetProcessByWindowHandle: Failed to access process { processItem . Process ? . Id } .") ;
290+ continue ;
291+ }
292+ }
293+
294+ return null ;
240295 }
241296
242297 public void BringToForeground ( )
243298 {
244- if ( ! GameProcesses . HasItems ( ) || IsSuspended )
299+ if ( ! GameProcesses . HasItems ( ) )
245300 {
301+ _logger . Debug ( "BringToForeground: No game processes." ) ;
302+ return ;
303+ }
304+
305+ if ( IsSuspended )
306+ {
307+ _logger . Debug ( "BringToForeground: Skipped because game is suspended." ) ;
246308 return ;
247309 }
248310
249311 if ( IsWindowInForeground ( ) )
250312 {
313+ _logger . Debug ( "BringToForeground: Already in foreground." ) ;
251314 return ;
252315 }
253316
254- var processItem = GameProcesses ? . FirstOrDefault ( x => x . Process . MainWindowHandle != null && x . Process . MainWindowHandle != IntPtr . Zero ) ;
255- if ( processItem is null )
317+ IntPtr ? windowHandle = null ;
318+ foreach ( var processItem in GameProcesses )
319+ {
320+ if ( processItem ? . Process is null )
321+ {
322+ continue ;
323+ }
324+
325+ try
326+ {
327+ if ( ! processItem . Process . HasExited )
328+ {
329+ var handle = processItem . Process . MainWindowHandle ;
330+ if ( handle != IntPtr . Zero )
331+ {
332+ windowHandle = handle ;
333+ break ;
334+ }
335+ }
336+ }
337+ catch ( InvalidOperationException ex )
338+ {
339+ _logger . Warn ( ex , $ "BringToForeground: Process { processItem . Process ? . Id } may have exited.") ;
340+ }
341+ }
342+
343+ if ( windowHandle == null )
256344 {
345+ _logger . Warn ( $ "BringToForeground: No valid window handle found for game { Game . Name } .") ;
257346 return ;
258347 }
259348
260- var windowHandle = processItem . Process . MainWindowHandle ;
261349 try
262350 {
263- WindowsHelper . RestoreAndFocusWindow ( windowHandle ) ;
351+ WindowsHelper . RestoreAndFocusWindow ( windowHandle . Value ) ;
264352 }
265353 catch ( Exception e )
266354 {
267- _logger . Error ( e , $ "Error while restoring game window of game { Game . Name } , { windowHandle } ") ;
355+ _logger . Error ( e , $ "BringToForeground: Error while restoring game window { windowHandle } for game { Game . Name } . ") ;
268356 }
269357 }
270358
@@ -300,9 +388,29 @@ public bool IsWindowInForeground()
300388 }
301389
302390 var foregroundWindowHandle = WindowsHelper . GetForegroundWindowHandle ( ) ;
303- var isInForeground = GameProcesses ?
304- . Any ( x => x . Process . MainWindowHandle == foregroundWindowHandle ) == true ;
305- return isInForeground ;
391+ foreach ( var processItem in GameProcesses )
392+ {
393+ if ( processItem ? . Process is null )
394+ {
395+ continue ;
396+ }
397+
398+ try
399+ {
400+ if ( ! processItem . Process . HasExited &&
401+ processItem . Process . MainWindowHandle == foregroundWindowHandle )
402+ {
403+ return true ;
404+ }
405+ }
406+ catch ( InvalidOperationException ex )
407+ {
408+ _logger . Error ( ex , "IsWindowInForeground: Failed to check process. It may have exited." ) ;
409+ continue ;
410+ }
411+ }
412+
413+ return false ;
306414 }
307415
308416 public bool IsWindowMinimized ( )
@@ -317,14 +425,23 @@ private List<IntPtr> GetWindowHandles()
317425 var windowHandles = new List < IntPtr > ( ) ;
318426 foreach ( var gameProcess in GameProcesses )
319427 {
320- if ( gameProcess is null || gameProcess . Process . Handle == null || gameProcess . Process . Handle == IntPtr . Zero )
428+ if ( gameProcess ? . Process is null )
321429 {
322430 continue ;
323431 }
324432
325- if ( gameProcess . Process . MainWindowHandle != IntPtr . Zero )
433+ try
326434 {
327- windowHandles . AddMissing ( gameProcess . Process . MainWindowHandle ) ;
435+ if ( ! gameProcess . Process . HasExited && gameProcess . Process . MainWindowHandle != IntPtr . Zero )
436+ {
437+ windowHandles . AddMissing ( gameProcess . Process . MainWindowHandle ) ;
438+ }
439+ }
440+ catch ( InvalidOperationException e )
441+ {
442+ // Process has likely exited between checks
443+ _logger . Error ( e , $ "Error during while obtaining Handles of { nameof ( GameProcesses ) } ") ;
444+ continue ;
328445 }
329446 }
330447
0 commit comments