/// <summary> /// Attach a DpiHandler to the specified window /// </summary> /// <param name="window">Windows</param> /// <param name="dpiHandler">DpiHandler</param> private static void AttachDpiHandler(Window window, DpiHandler dpiHandler) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Registering the UpdateLayoutTransform subscription for {0}", window.GetType()); } // Add the layout transform action var transformSubscription = dpiHandler.OnDpiChanged.Subscribe(dpiChangeInfo => window.UpdateLayoutTransform((double)dpiChangeInfo.NewDpi / DpiHandler.DefaultScreenDpi)); window.WinProcMessages().Subscribe(message => { dpiHandler.HandleWindowMessages(message); switch (message.Message) { case WindowsMessages.WM_NCCREATE: // Apply scaling 1x time window.UpdateLayoutTransform((double)NativeDpiMethods.GetDpi(message.Handle) / DpiHandler.DefaultScreenDpi); break; case WindowsMessages.WM_DESTROY: // Remove layout transform if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Removing the UpdateLayoutTransform subscription for {0}", window.GetType()); } transformSubscription.Dispose(); break; } }); }
private void RegistrationOnActivated(object sender, IActivatedEventArgs <object> e) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("{0}Activated {1}", GetPrefix(), e.Component.Activator.LimitType); } }
/// <summary> /// Helper to create the location of a file /// </summary> private void ScanFiles(LanguageConfig languageConfig) { var directories = new List <string>(); if (languageConfig.SpecifiedDirectories != null) { directories.AddRange(languageConfig.SpecifiedDirectories); } if (languageConfig.CheckStartupDirectory) { var startupDirectory = FileLocations.StartupDirectory; if (startupDirectory != null) { directories.Add(Path.Combine(startupDirectory, "languages")); } } if (languageConfig.CheckAppDataDirectory) { var appDataDirectory = FileLocations.RoamingAppDataDirectory(languageConfig.ApplicationName); if (appDataDirectory != null) { directories.Add(Path.Combine(appDataDirectory, "languages")); } } if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Scanning directories: {0}", string.Join(",", directories)); } Files = FileLocations.Scan(directories, _filePattern) .GroupBy(x => x.Item2.Groups["IETF"].Value) .ToDictionary(group => group.Key, group => group.Select(x => x.Item1) .ToList()); if (Log.IsDebugEnabled()) { Log.Debug().WriteLine("Detected language ietfs: {0}", string.Join(",", Files.Keys)); } var allCultures = CultureInfo.GetCultures(CultureTypes.AllCultures) .ToLookup(e => e.IetfLanguageTag, StringComparer.OrdinalIgnoreCase).ToDictionary(x => x.Key, x => x.First()); // TODO: Create custom culture for all not available, see: https://msdn.microsoft.com/en-us/library/ms172469(v=vs.90).aspx // TODO: Add Embedded resources, especially for the assemblies to which ILanguage interfaces belong AvailableLanguages = (from ietf in Files.Keys where allCultures.ContainsKey(ietf) select ietf).Distinct().ToDictionary(ietf => ietf, ietf => allCultures[ietf].NativeName); if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Languages found: {0}", string.Join(",", AvailableLanguages.Keys)); } }
/// <summary> /// Get the ManifestResourceNames for the specified assembly from cache or directly. /// </summary> /// <param name="possibleResourceAssembly">Assembly</param> /// <returns>string array with resources names</returns> public string[] GetCachedManifestResourceNames(Assembly possibleResourceAssembly) { var assemblyName = possibleResourceAssembly.GetName().Name; // Get the resources from the cache if (AssemblyResourceNames.TryGetValue(assemblyName, out var manifestResourceNames)) { return(manifestResourceNames); } // If there was no cache, create it by retrieving the ManifestResourceNames for non dynamic assemblies manifestResourceNames = possibleResourceAssembly.IsDynamic ? new string[] {}: possibleResourceAssembly.GetManifestResourceNames(); AssemblyResourceNames[assemblyName] = manifestResourceNames; if (Log.IsVerboseEnabled() && manifestResourceNames.Length > 0) { Log.Verbose().WriteLine("Assembly {0} contains the following resources: {1}", possibleResourceAssembly.FullName, string.Join(", ", manifestResourceNames)); } return(manifestResourceNames); }
/// <inheritdoc /> public async Task <object> ConvertFromHttpContentAsync(Type resultType, HttpContent httpContent, CancellationToken cancellationToken = default) { if (!CanConvertFromHttpContent(resultType, httpContent)) { throw new NotSupportedException("CanConvertFromHttpContent resulted in false, this is not supposed to be called."); } var jsonString = await httpContent.ReadAsStringAsync().ConfigureAwait(false); // Check if verbose is enabled, if so log but only up to a certain size if (Log.IsVerboseEnabled()) { var defaultJsonHttpContentConverterConfiguration = HttpBehaviour.Current.GetConfig <DefaultJsonHttpContentConverterConfiguration>(); var logThreshold = defaultJsonHttpContentConverterConfiguration.LogThreshold; if (logThreshold > 0) { Log.Verbose() .WriteLine("Read Json content: {0}{1}", jsonString.Substring(0, Math.Min(jsonString.Length, logThreshold)), jsonString.Length > logThreshold ? defaultJsonHttpContentConverterConfiguration.AppendedWhenCut : string.Empty); } else { Log.Verbose().WriteLine("Read Json content: {0}", jsonString); } } // Check if we can just pass it back, as the target is string if (resultType == typeof(string)) { return(jsonString); } // empty json should return the default of the resultType if (string.IsNullOrEmpty(jsonString)) { if (resultType.GetTypeInfo().IsValueType) { return(Activator.CreateInstance(resultType)); } return(null); } var httpBehaviour = HttpBehaviour.Current; try { return(httpBehaviour.JsonSerializer.Deserialize(resultType == typeof(object) ? null : resultType, jsonString)); } catch (SerializationException sEx) { // Make sure that the content which can't be deserialized is visible in the log. Log.Error().WriteLine(sEx, "Can't deserialize the JSON from the server."); Log.Error().WriteLine(jsonString); throw; } }
/// <summary> /// Method to set the ScrollbarInfo, if we can get it /// </summary> /// <param name="forceUpdate">set to true to force an update, default is false</param> /// <returns>ScrollBarInfo?</returns> public ScrollBarInfo?GetScrollbarInfo(bool forceUpdate = false) { // Prevent updates, if there is already a value if (ScrollBar.HasValue && !forceUpdate) { return(ScrollBar); } var objectId = ObjectIdentifiers.Client; switch (ScrollBarType) { case ScrollBarTypes.Control: objectId = ObjectIdentifiers.Client; break; case ScrollBarTypes.Vertical: objectId = ObjectIdentifiers.VerticalScrollbar; break; case ScrollBarTypes.Horizontal: objectId = ObjectIdentifiers.HorizontalScrollbar; break; } var scrollbarInfo = ScrollBarInfo.Create(); var hasScrollbarInfo = User32Api.GetScrollBarInfo(ScrollBarWindow.Handle, objectId, ref scrollbarInfo); if (!hasScrollbarInfo) { var error = Win32.GetLastErrorCode(); if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Error retrieving Scrollbar info : {0}", Win32.GetMessage(error)); } return(null); } ScrollBar = scrollbarInfo; return(scrollbarInfo); }
/// <summary> /// Configure the Bootstrapper /// </summary> public virtual ApplicationBootstrapper Configure() { // It's no problem when the builder is already created, skip recreating! if (_builder != null) { return(this); } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Configuring"); } _builder = new ContainerBuilder(); _builder.Properties[nameof(ApplicationName)] = ApplicationName; foreach (var propertiesKey in _applicationConfig.Properties.Keys) { _builder.Properties[propertiesKey] = _applicationConfig.Properties[propertiesKey]; } // Provide the IResourceProvider _builder.RegisterInstance(Resolver.Resources).As <IResourceProvider>().ExternallyOwned(); return(this); }
/// <summary> /// Retrieve position from the scrollInfo /// </summary> /// <param name="scrollInfo">ScrollInfo out</param> /// <returns>bool</returns> private bool TryRetrievePosition(out ScrollInfo scrollInfo) { var hasScrollInfo = GetPosition(out scrollInfo); if (Log.IsVerboseEnabled()) { if (hasScrollInfo) { Log.Verbose().WriteLine("Retrieved ScrollInfo: {0}", scrollInfo); } else { Log.Verbose().WriteLine("Couldn't get scrollinfo."); } } return(hasScrollInfo); }
/// <summary> /// Wait for a response /// </summary> /// <returns>MpdResponse</returns> private async Task <MpdResponse> ReadResponseAsync() { var result = new MpdResponse(); using (var reader = new StreamReader(_networkStream, Encoding.UTF8, true, 512, true)) { string line; do { line = await reader.ReadLineAsync().ConfigureAwait(false); } while (!result.AddLine(line)); if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Received answer: {0}", string.Join(Environment.NewLine, result.ResponseLines)); } } return(result); }
/// <summary> /// This is more for debugging, with retrieve the complete DirectoryEntry for the AdsPath /// </summary> /// <param name="adsPath"> /// string with the AdsPath, this can be retrieved by setting AdProperty(AdProperties.Id) on a string /// property for the type passed to Execute /// </param> /// <param name="username">Username for the connection, by default the current user is used</param> /// <param name="password">Password for the supplied user</param> /// <returns>DirectoryEntry</returns> public static DirectoryEntry GetByAdsPath(string adsPath, string username = null, string password = null) { var directoryEntry = new DirectoryEntry(adsPath, username, password); if (!Log.IsVerboseEnabled()) { return(directoryEntry); } Log.Verbose().WriteLine("List of all properties and their value:"); foreach (var propertyName in directoryEntry.Properties.PropertyNames.Cast <string>().OrderBy(x => x)) { Log.Verbose().WriteLine($"{propertyName} = {{0}}", directoryEntry.ConvertProperty(propertyName)); } directoryEntry.RefreshCache(new[] { AdProperties.AllowedAttributesEffective.EnumValueOf() }); Log.Verbose().WriteLine("List of all writable properties:"); foreach (var writableProperty in directoryEntry.Properties[AdProperties.AllowedAttributesEffective.EnumValueOf()].Cast <string>().OrderBy(x => x)) { Log.Verbose().WriteLine("Writable property: {0}", writableProperty); } return(directoryEntry); }
/// <summary> /// Message handler of the Per_Monitor_DPI_Aware window. /// The handles the WM_DPICHANGED message and adjusts window size, graphics and text based on the DPI of the monitor. /// The window message provides the new window size (lparam) and new DPI (wparam) /// See /// <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/dn312083(v=vs.85).aspx">WM_DPICHANGED message</a> /// </summary> /// <param name="windowMessageInfo">WindowMessageInfo</param> /// <returns>IntPtr</returns> internal bool HandleWindowMessages(WindowMessageInfo windowMessageInfo) { bool handled = false; var currentDpi = DefaultScreenDpi; bool isDpiMessage = false; switch (windowMessageInfo.Message) { // Handle the WM_NCCREATE for Forms / controls, for WPF this is done differently case WindowsMessages.WM_NCCREATE: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Processing {0} event, enabling DPI scaling for window {1}", windowMessageInfo.Message, windowMessageInfo.Handle); } TryEnableNonClientDpiScaling(windowMessageInfo.Handle); break; // Handle the WM_CREATE, this is where we can get the DPI via system calls case WindowsMessages.WM_CREATE: isDpiMessage = true; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Processing {0} event, retrieving DPI for window {1}", windowMessageInfo.Message, windowMessageInfo.Handle); } currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle); _scopedThreadDpiAwarenessContext.Dispose(); break; // Handle the DPI change message, this is where it's supplied case WindowsMessages.WM_DPICHANGED: isDpiMessage = true; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Processing {0} event, resizing / positioning window {1}", windowMessageInfo.Message, windowMessageInfo.Handle); } // Retrieve the adviced location var lprNewRect = (NativeRect)Marshal.PtrToStructure(windowMessageInfo.LongParam, typeof(NativeRect)); // Move the window to it's location, and resize User32Api.SetWindowPos(windowMessageInfo.Handle, IntPtr.Zero, lprNewRect.Left, lprNewRect.Top, lprNewRect.Width, lprNewRect.Height, WindowPos.SWP_NOZORDER | WindowPos.SWP_NOOWNERZORDER | WindowPos.SWP_NOACTIVATE); currentDpi = (uint)windowMessageInfo.WordParam & 0xFFFF; // specify that the message was handled handled = true; break; case WindowsMessages.WM_PAINT: // This is a workaround for non DPI aware applications, these don't seem to get a WM_CREATE if (Dpi == 0) { isDpiMessage = true; currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle); } break; case WindowsMessages.WM_SETICON: // This is a workaround for handling WinProc outside of the class if (_needsListenerWorkaround) { isDpiMessage = true; // disable workaround _needsListenerWorkaround = false; currentDpi = NativeDpiMethods.GetDpi(windowMessageInfo.Handle); } break; case WindowsMessages.WM_DPICHANGED_BEFOREPARENT: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Dpi changed on {0} before parent", windowMessageInfo.Handle); } break; case WindowsMessages.WM_DPICHANGED_AFTERPARENT: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Dpi changed on {0} after parent", windowMessageInfo.Handle); } break; case WindowsMessages.WM_DESTROY: if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Completing the observable for {0}", windowMessageInfo.Handle); } // If the window is destroyed, we complete the subject _onDpiChanged.OnCompleted(); // Dispose all resources Dispose(); break; } // Check if the DPI was changed, if so call the action (if any) if (!isDpiMessage) { return(false); } if (Dpi != currentDpi) { var beforeDpi = Dpi; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Changing DPI from {0} to {1}", beforeDpi, currentDpi); } Dpi = currentDpi; _onDpiChanged.OnNext(new DpiChangeInfo(beforeDpi, currentDpi)); } else if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("DPI was unchanged from {0}", Dpi); } return(handled); }
/// <summary> /// Extension method reading the HttpResponseMessage to a Type object /// Currently we support Json objects which are annotated with the DataContract/DataMember attributes /// We might support other object, e.g MemoryStream, Bitmap etc soon /// </summary> /// <typeparam name="TResponse">The Type to read into</typeparam> /// <param name="httpResponseMessage">HttpResponseMessage</param> /// <param name="cancellationToken">CancellationToken</param> /// <returns>the deserialized object of type T or default(T)</returns> public static async Task <TResponse> GetAsAsync <TResponse>(this HttpResponseMessage httpResponseMessage, CancellationToken cancellationToken = default) where TResponse : class { Log.Verbose().WriteLine("Response status code: {0}", httpResponseMessage.StatusCode); var resultType = typeof(TResponse); // Quick exit if the caller just wants the HttpResponseMessage if (resultType == typeof(HttpResponseMessage)) { return(httpResponseMessage as TResponse); } // See if we have a container if (resultType.GetTypeInfo().GetCustomAttribute <HttpResponseAttribute>() != null) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Filling type {0}", resultType.FriendlyName()); } // special type var instance = Activator.CreateInstance <TResponse>(); var properties = resultType.GetProperties().Where(x => x.GetCustomAttribute <HttpPartAttribute>() != null).ToList(); // Headers if (properties.TryFindTarget(HttpParts.ResponseHeaders, out PropertyInfo targetPropertyInfo)) { targetPropertyInfo.SetValue(instance, httpResponseMessage.Headers); } // StatusCode if (properties.TryFindTarget(HttpParts.ResponseStatuscode, out targetPropertyInfo)) { targetPropertyInfo.SetValue(instance, httpResponseMessage.StatusCode); } var responsePart = httpResponseMessage.IsSuccessStatusCode ? HttpParts.ResponseContent : HttpParts.ResponseErrorContent; var contentSet = false; // Try to find the target for the error response if (properties.TryFindTarget(responsePart, out targetPropertyInfo)) { contentSet = true; // get the response var httpContent = httpResponseMessage.Content; // Convert the HttpContent to the value type var convertedContent = await httpContent.GetAsAsync(targetPropertyInfo.PropertyType, httpResponseMessage.StatusCode, cancellationToken).ConfigureAwait(false); // If we get null, we throw an error if the if (convertedContent is null) { httpResponseMessage.EnsureSuccessStatusCode(); // If still here, we have a mapping issue var message = $"Unsupported result type {targetPropertyInfo.PropertyType.Name} & {httpContent.GetContentType()} combination."; Log.Error().WriteLine(message); throw new NotSupportedException(message); } if (targetPropertyInfo.PropertyType.IsInstanceOfType(convertedContent)) { // Now set the value targetPropertyInfo.SetValue(instance, convertedContent); } else { // Cleanup, but only if the value is not passed onto the container httpContent?.Dispose(); } } if (!contentSet && !httpResponseMessage.IsSuccessStatusCode) { await httpResponseMessage.HandleErrorAsync().ConfigureAwait(false); } return(instance); } if (httpResponseMessage.IsSuccessStatusCode) { var httpContent = httpResponseMessage.Content; var result = await httpContent.GetAsAsync <TResponse>(httpResponseMessage.StatusCode, cancellationToken).ConfigureAwait(false); // Make sure the httpContent is only disposed when it's not the return type if (!typeof(HttpContent).IsAssignableFrom(typeof(TResponse))) { httpContent?.Dispose(); } return(result); } await httpResponseMessage.HandleErrorAsync().ConfigureAwait(false); return(default);
/// <summary> /// Get a lock to the clipboard /// </summary> /// <param name="hWnd">IntPtr with a hWnd for the potential new owner</param> /// <param name="retries">int with number of retries, default is 5</param> /// <param name="retryInterval">TimeSpan for the time between retries</param> /// <param name="timeout">optional TimeSpan for the timeout, default is 400ms</param> /// <returns>IClipboardLock</returns> public IClipboardAccessToken Lock(IntPtr hWnd = default, int retries = 5, TimeSpan?retryInterval = null, TimeSpan?timeout = null) { // Set default retry interval retryInterval = retryInterval ?? DefaultRetryInterval; // Set default timeout interval timeout = timeout ?? DefaultTimeout; #if !NETSTANDARD2_0 if (hWnd == IntPtr.Zero) { // Take the default if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Taking windows handle {0} from the WinProcHandler", WinProcHandler.Instance.Handle); } hWnd = WinProcHandler.Instance.Handle; } #endif // If a timeout is passed, use this in the wait if (!_semaphoreSlim.Wait(timeout.Value)) { // Timeout return(new ClipboardAccessToken { CanAccess = false, IsLockTimeout = true }); } // Create the clipboard lock itself bool isOpened = false; do { if (OpenClipboard(hWnd)) { isOpened = true; break; } retries--; // No reason to sleep, if there are no more retries if (retries >= 0) { Thread.Sleep(retryInterval.Value); } } while (retries >= 0); if (!isOpened) { return(new ClipboardAccessToken { CanAccess = false, IsOpenTimeout = true }); } // Return a disposable which cleans up the current state. return(new ClipboardAccessToken(() => { CloseClipboard(); _semaphoreSlim.Release(); })); }
/// <summary> /// This will assert that the log levels work /// </summary> private static void AssertLogLevels(LogSource logSource, ILogger loggerUnderTest) { var initialLevel = loggerUnderTest.LogLevel; try { // Assert the log levels loggerUnderTest.LogLevel = LogLevels.None; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.False(logSource.IsWarnEnabled()); Assert.False(logSource.IsErrorEnabled()); Assert.False(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Verbose; Assert.True(logSource.IsVerboseEnabled()); Assert.True(logSource.IsDebugEnabled()); Assert.True(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Debug; Assert.False(logSource.IsVerboseEnabled()); Assert.True(logSource.IsDebugEnabled()); Assert.True(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Info; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.True(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Warn; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.True(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Error; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.False(logSource.IsWarnEnabled()); Assert.True(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); loggerUnderTest.LogLevel = LogLevels.Fatal; Assert.False(logSource.IsVerboseEnabled()); Assert.False(logSource.IsDebugEnabled()); Assert.False(logSource.IsInfoEnabled()); Assert.False(logSource.IsWarnEnabled()); Assert.False(logSource.IsErrorEnabled()); Assert.True(logSource.IsFatalEnabled()); } finally { loggerUnderTest.LogLevel = initialLevel; } }
/// <summary> /// Logic to load an embedded assembly /// </summary> /// <param name="assemblyLocationInformation"></param> /// <returns>Assembly</returns> private Assembly LoadEmbeddedAssembly(AssemblyLocationInformation assemblyLocationInformation) { if (!assemblyLocationInformation.IsEmbedded) { return(null); } // Check if we can work with temporary files if (_applicationConfig.CopyEmbeddedAssembliesToFileSystem) { var assembly = LoadEmbeddedAssemblyViaTmpFile(assemblyLocationInformation); if (assembly != null) { return(assembly); } } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Loading {0} internally, this COULD cause assembly load context issues...", assemblyLocationInformation.Name); } using (var stream = Resources.AbsoluteResourceAsStream(assemblyLocationInformation.ContainingAssembly, assemblyLocationInformation.Filename)) { return(Assembly.Load(stream.ToByteArray())); } }
/// <summary> /// This tries to get the Mutex, which takes care of having multiple instances running /// </summary> /// <returns>true if it worked, false if another instance is already running or something went wrong</returns> public bool Lock() { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("{0} is trying to get Mutex {1}", _resourceName, _mutexId); } IsLocked = true; // check whether there's an local instance running already, but use local so this works in a multi-user environment try { #if NET461 // Added Mutex Security, hopefully this prevents the UnauthorizedAccessException more gracefully var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null); var mutexsecurity = new MutexSecurity(); mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow)); mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.ChangePermissions, AccessControlType.Deny)); mutexsecurity.AddAccessRule(new MutexAccessRule(sid, MutexRights.Delete, AccessControlType.Deny)); // 1) Create Mutex _applicationMutex = new Mutex(true, _mutexId, out var createdNew, mutexsecurity); #else // 1) Create Mutex _applicationMutex = new Mutex(true, _mutexId, out var createdNew); #endif // 2) if the mutex wasn't created new get the right to it, this returns false if it's already locked if (!createdNew) { IsLocked = _applicationMutex.WaitOne(2000, false); if (!IsLocked) { Log.Warn().WriteLine("Mutex {0} is already in use and couldn't be locked for the caller {1}", _mutexId, _resourceName); // Clean up _applicationMutex.Dispose(); _applicationMutex = null; } else { Log.Info().WriteLine("{0} has claimed the mutex {1}", _resourceName, _mutexId); } } else { Log.Info().WriteLine("{0} has created & claimed the mutex {1}", _resourceName, _mutexId); } } catch (AbandonedMutexException e) { // Another instance didn't cleanup correctly! // we can ignore the exception, it happend on the "waitone" but still the mutex belongs to us Log.Warn().WriteLine(e, "{0} didn't cleanup correctly, but we got the mutex {1}.", _resourceName, _mutexId); } catch (UnauthorizedAccessException e) { Log.Error().WriteLine(e, "{0} is most likely already running for a different user in the same session, can't create/get mutex {1} due to error.", _resourceName, _mutexId); IsLocked = false; } catch (Exception ex) { Log.Error().WriteLine(ex, "Problem obtaining the Mutex {1} for {0}, assuming it was already taken!", _resourceName, _mutexId); IsLocked = false; } return(IsLocked); }