public static Semaphore GetNamedSemaphore(string name, int maximumCount = 10, int initialCount = -1) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException("name", "Argument cannot be empty, null or white space."); Semaphore namedSemaphore = null; bool doesNotExist = false; bool unauthorized = false; if (initialCount < 0) initialCount = maximumCount; // Create a semaphore name that is specific to an object (e.g., a path and file name). string semaphoreName = Cipher.GetPasswordHash(name.ToLower(), SemaphoreHash).Replace('\\', '-'); // Attempt to open the named semaphore try { namedSemaphore = Semaphore.OpenExisting(semaphoreName); } catch (WaitHandleCannotBeOpenedException) { doesNotExist = true; } catch (UnauthorizedAccessException) { unauthorized = true; } // Mono Semaphore implementations do not include ability to change access rules #if MONO // If semaphore does not exist we create it if (doesNotExist || unauthorized) { try { bool semaphoreWasCreated; namedSemaphore = new Semaphore(initialCount, maximumCount, semaphoreName, out semaphoreWasCreated); if (!semaphoreWasCreated) throw new InvalidOperationException("Failed to create semaphore."); } catch (UnauthorizedAccessException ex) { throw new InvalidOperationException("Failed to create semaphore: " + ex.Message); } } #else // If semaphore does not exist we create it if (doesNotExist) { try { SemaphoreSecurity security = new SemaphoreSecurity(); bool semaphoreWasCreated; security.AddAccessRule(new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.FullControl, AccessControlType.Allow)); namedSemaphore = new Semaphore(initialCount, maximumCount, semaphoreName, out semaphoreWasCreated, security); if (!semaphoreWasCreated) throw new InvalidOperationException("Failed to create semaphore."); } catch (UnauthorizedAccessException) { SemaphoreSecurity security = new SemaphoreSecurity(); bool semaphoreWasCreated; security.AddAccessRule(new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow)); namedSemaphore = new Semaphore(initialCount, maximumCount, semaphoreName, out semaphoreWasCreated, security); if (!semaphoreWasCreated) throw new InvalidOperationException("Failed to create semaphore."); } } else if (unauthorized) { namedSemaphore = Semaphore.OpenExisting(semaphoreName, SemaphoreRights.ReadPermissions | SemaphoreRights.ChangePermissions); // Get the current ACL. This requires MutexRights.ReadPermission SemaphoreSecurity security = new SemaphoreSecurity(); SemaphoreAccessRule rule = new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.FullControl, AccessControlType.Allow); security.RemoveAccessRule(rule); // Now grant specific user rights for less than full access rule = new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow); security.AddAccessRule(rule); // Update the ACL. This requires MutexRighs.ChangePermission. namedSemaphore.SetAccessControl(security); namedSemaphore = Semaphore.OpenExisting(semaphoreName); } #endif return namedSemaphore; }