/// <summary> /// Opens channel for writing. Channel must be created by process running without app container and it must be visible from all user sessions. /// </summary> /// <param name="name">Channel name.</param> /// <returns> /// OperationResult with OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer), /// OperationStatus.ObjectDoesNotExist or OperationStatus.AccessDenied /// </returns> public static OperationResult <OutboundChannel> OpenOutboundGlobalNoncontainerized(string name) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to find shared memory channel"); } return(OutboundChannel.Open(LifecycleHelper.GlobalVisibilityPrefix + "\\" + name, name)); }
/// <summary> /// Creates or reopens channel for writing. Channel will be visible from processes in all user sessions. /// </summary> /// <param name="name">Channel name.</param> /// <param name="capacity">Capacity of the cannel's queue in bytes.</param> /// <param name="acl"> /// The list of security indentifiers for entities allowed to access this channel. /// Use new System.Security.Principal.SecurityIdentifier(yourUwpAppContainerSidString) to grant access to UWP app. /// Empty list is equivalent of WellKnownSidType.AuthenticatedUserSid. /// </param> /// <returns> /// OperationResult with OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer), /// OperationStatus.ElevationRequired (when current process does not have "Create global objects" permission), or OperationStatus.CapacityIsGreaterThanLogicalAddressSpace /// </returns> public static OperationResult <OutboundChannel> CreateOutboundGlobal(string name, long capacity, IEnumerable <IdentityReference> acl) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to create shared memory channel"); } if (capacity < Header.Size) { throw new ArgumentException($"Channel capacity must be at least {Header.Size} bytes"); } return(OutboundChannel.Create(LifecycleHelper.GlobalVisibilityPrefix + "\\" + name, name, capacity, WhenEmptyUse(acl, WellKnownSidType.AuthenticatedUserSid))); }
/// <summary> /// Creates or reopens channel for writing. Channel will be visible from processes in the local user session. /// </summary> /// <param name="name">Channel name.</param> /// <param name="capacity">Capacity of the cannel's queue in bytes.</param> /// <returns> /// OperationResult with OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer) /// or OperationStatus.CapacityIsGreaterThanLogicalAddressSpace /// </returns> public static OperationResult <OutboundChannel> CreateOutboundLocal(string name, long capacity) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to create shared memory channel"); } if (capacity < Header.Size) { throw new ArgumentException($"Channel capacity must be at least {Header.Size} bytes"); } return(OutboundChannel.Create(LifecycleHelper.LocalVisibilityPrefix + "\\" + name, name, capacity, null)); }
/// <summary> /// Opens channel for writing. Channel must be created by process running in app container and it must be visible only from current user session. /// </summary> /// <param name="name">Channel name.</param> /// <param name="sid">SID of the app container of the process that created this channel.</param> /// <returns> /// OperationResult with OutboundChannel and OperationStatus.Completed, OperationStatus.ObjectAlreadyInUse (when channel is already in use by another writer), /// OperationStatus.ObjectDoesNotExist or OperationStatus.AccessDenied /// </returns> public static OperationResult <OutboundChannel> OpenOutboundLocalContainerized(string name, string sid) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (name.Length == 0) { throw new ArgumentException("Channel name required to find shared memory channel"); } if (sid == null) { throw new ArgumentNullException(nameof(sid)); } if (sid.Length == 0) { throw new ArgumentException("Container's security identifier cannot be empty string"); } return(OutboundChannel.Open($"{LifecycleHelper.LocalVisibilityPrefix}\\AppContainerNamedObjects\\{sid}\\{name}", name)); }
internal static OperationResult <OutboundChannel> Create(string fullName, string name, long capacity, Acl acl) { Semaphore writerSemaphore = null; MemoryMappedFile file = null; Semaphore exclusiveAccessSemaphore = null; EventWaitHandle hasMessagesEvent = null; EventWaitHandle noMessagesEvent = null; EventWaitHandle clientConnectedEvent = null; Semaphore readerSemaphore = null; try { var writerSemaphoreOperationResult = LifecycleHelper.CreateAndSetWriterSemaphore(fullName, acl); if (writerSemaphoreOperationResult.Status != OperationStatus.Completed) { return(new OperationResult <OutboundChannel>(writerSemaphoreOperationResult.Status, null)); } writerSemaphore = writerSemaphoreOperationResult.Data; var fileOperationResult = LifecycleHelper.CreateMemoryMappedFile(fullName, capacity, acl); if (fileOperationResult.Status != OperationStatus.Completed && fileOperationResult.Status != OperationStatus.ObjectAlreadyInUse) { try { writerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(writerSemaphore); return(new OperationResult <OutboundChannel>(fileOperationResult.Status, null)); } file = fileOperationResult.Data; exclusiveAccessSemaphore = LifecycleHelper.CreateExclusiveAccessSemaphore(fullName, acl); hasMessagesEvent = LifecycleHelper.CreateHasMessagesEvent(fullName, acl); noMessagesEvent = LifecycleHelper.CreateNoMessagesEvent(fullName, acl); clientConnectedEvent = LifecycleHelper.CreateClientConnectedEvent(fullName, acl); readerSemaphore = LifecycleHelper.CreateReaderSemaphore(fullName, acl); OutboundChannel result; if (fileOperationResult.Status == OperationStatus.ObjectAlreadyInUse) { result = new OutboundChannel(name, writerSemaphore, file, exclusiveAccessSemaphore, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, readerSemaphore); } else { result = new OutboundChannel(name, writerSemaphore, file, capacity, exclusiveAccessSemaphore, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, readerSemaphore); } return(new OperationResult <OutboundChannel>(OperationStatus.Completed, result)); } catch { if (writerSemaphore != null) { try { writerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(writerSemaphore); } file?.Dispose(); LifecycleHelper.PlatformSpecificDispose(exclusiveAccessSemaphore); LifecycleHelper.PlatformSpecificDispose(hasMessagesEvent); LifecycleHelper.PlatformSpecificDispose(noMessagesEvent); LifecycleHelper.PlatformSpecificDispose(clientConnectedEvent); LifecycleHelper.PlatformSpecificDispose(readerSemaphore); throw; } }
internal static OperationResult <OutboundChannel> Open(string fullName, string name) { Semaphore writerSemaphore = null; MemoryMappedFile file = null; Semaphore exclusiveAccessSemaphore = null; EventWaitHandle hasMessagesEvent = null; EventWaitHandle noMessagesEvent = null; EventWaitHandle clientConnectedEvent = null; try { var writerSemaphoreOperationResult = LifecycleHelper.OpenAndSetWriterSemaphore(fullName); if (writerSemaphoreOperationResult.Status != OperationStatus.Completed) { return(new OperationResult <OutboundChannel>(writerSemaphoreOperationResult.Status, null)); } writerSemaphore = writerSemaphoreOperationResult.Data; var openCommonSharedObjectsStatus = LifecycleHelper.OpenCommonSharedObjects(fullName, out file, out exclusiveAccessSemaphore, out hasMessagesEvent, out noMessagesEvent, out clientConnectedEvent); if (openCommonSharedObjectsStatus != OperationStatus.Completed) { try { writerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(writerSemaphore); return(new OperationResult <OutboundChannel>(openCommonSharedObjectsStatus, null)); } var result = new OutboundChannel(name, writerSemaphore, file, exclusiveAccessSemaphore, hasMessagesEvent, noMessagesEvent, clientConnectedEvent, null); return(new OperationResult <OutboundChannel>(OperationStatus.Completed, result)); } catch { if (writerSemaphore != null) { try { writerSemaphore.Release(); } catch { } LifecycleHelper.PlatformSpecificDispose(writerSemaphore); } file?.Dispose(); LifecycleHelper.PlatformSpecificDispose(exclusiveAccessSemaphore); LifecycleHelper.PlatformSpecificDispose(hasMessagesEvent); LifecycleHelper.PlatformSpecificDispose(noMessagesEvent); LifecycleHelper.PlatformSpecificDispose(clientConnectedEvent); throw; } }
/// <summary> /// Disposes shared objects associated with this channel. /// Most of the resources associated with the channel and messages in the queue will stay alive until both client and server /// will be disposed. It's ok to reconnect or recreate channel with the same parameters. /// </summary> public void Dispose() { _internal?.Dispose(); _internal = null; }
internal OutboundChannel(Internal.OutboundChannel @internal) { _internal = @internal; }