Add check for ensuring there's only single instance to avoid endless (feeling) locked screensaver.

This commit is contained in:
DannyAAM 2022-08-29 11:18:17 +08:00
parent 62927d0d3f
commit f96f2daf69
No known key found for this signature in database
GPG key ID: 60E63253B07605B6

View file

@ -23,6 +23,8 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using System.Security.AccessControl;
using System.Security.Principal;
namespace Screensavers
{
@ -291,7 +293,7 @@ namespace Screensavers
switch (screensaverMode)
{
case ScreensaverMode.Windowed:
RunWindowed();
RunWithSingleInstanceMutex(screensaverMode);
break;
case ScreensaverMode.Settings:
ShowSettingsDialog();
@ -304,7 +306,7 @@ namespace Screensavers
if (!closeOnKeyboardInputOverride)
closeOnKeyboardInput = true;
RunNormal();
RunWithSingleInstanceMutex(screensaverMode);
break;
case ScreensaverMode.Preview:
RunPreview();
@ -504,6 +506,81 @@ namespace Screensavers
set { windowTitle = value; }
}
private void RunWithSingleInstanceMutex(ScreensaverMode screensaverMode)
{
// From: https://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567
// get application GUID as defined in AssemblyInfo.cs
string appGuid =
((GuidAttribute)System.Reflection.Assembly.GetExecutingAssembly().
GetCustomAttributes(typeof(GuidAttribute), false).
GetValue(0)).Value.ToString();
// unique id for global mutex - Global prefix means it is global to the machine
string mutexId = string.Format("Global\\{{{0}}}", appGuid);
// Need a place to store a return value in Mutex() constructor call
bool createdNew;
// edited by Jeremy Wiebe to add example of setting up security for multi-user usage
// edited by 'Marc' to work also on localized systems (don't use just "Everyone")
var allowEveryoneRule =
new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid
, null)
, MutexRights.FullControl
, AccessControlType.Allow
);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
// edited by MasonGZhwiti to prevent race condition on security settings via VanNguyen
using (var mutex = new Mutex(false, mutexId, out createdNew, securitySettings))
{
// edited by acidzombie24
var hasHandle = false;
try
{
try
{
// note, you may want to time out here instead of waiting forever
// edited by acidzombie24
// mutex.WaitOne(Timeout.Infinite, false);
hasHandle = mutex.WaitOne(5000, false);
if (hasHandle == false)
throw new TimeoutException("Timeout waiting for exclusive access");
}
catch (AbandonedMutexException)
{
// Log the fact that the mutex was abandoned in another process,
// it will still get acquired
hasHandle = true;
}
// Actuall Run.
switch (screensaverMode)
{
case ScreensaverMode.Windowed:
RunWindowed();
break;
case ScreensaverMode.Settings:
ShowSettingsDialog();
break;
case ScreensaverMode.Normal:
RunNormal();
break;
case ScreensaverMode.Preview:
RunPreview();
break;
}
}
finally
{
// edited by acidzombie24, added if statement
if (hasHandle)
mutex.ReleaseMutex();
}
}
}
private void RunNormal()
{
Cursor.Hide();