public async Task ServerCanAwaitForClient() { var name = GetUniqueName(); OutboundChannel outboundChannel = null; InboundChannel inboundChannel = null; try { var outboundChannelResult = Channel.CreateOutboundLocal(name); outboundChannel = outboundChannelResult.Data; InconclusiveWhenNotCompleted(outboundChannelResult); var task = outboundChannel.WhenClientConnectedAsync(TimeSpan.FromSeconds(1)); var inboundChannelResult = Channel.OpenInboundLocalNoncontainerized(name); inboundChannel = inboundChannelResult.Data; InconclusiveWhenNotCompleted(inboundChannelResult); var status = await task; Assert.AreEqual(OperationStatus.Completed, status); } finally { inboundChannel?.Dispose(); outboundChannel?.Dispose(); } }
private async Task ListenAndSendFiles() { const long megabyte = 1024 * 1024; var cancellationToken = _cts.Token; OutboundChannel fileChannel = null; InboundChannel pathChannel = null; try { var acl = new[] { new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null), new SecurityIdentifier(AppContainerSid) }; var pathChannelOperationResult = Channel.CreateInboundGlobal("sample_path", megabyte, acl); var fileChannelOperationResult = Channel.CreateOutboundGlobal("sample_file", megabyte, acl); pathChannel = pathChannelOperationResult.Data; fileChannel = fileChannelOperationResult.Data; if (pathChannelOperationResult.Status == OperationStatus.ObjectAlreadyInUse || fileChannelOperationResult.Status == OperationStatus.ObjectAlreadyInUse) { _eventLog.WriteEntry("Channel wasn't disposed during previous run of the service."); return; } if (pathChannelOperationResult.Status == OperationStatus.ElevationRequired || fileChannelOperationResult.Status == OperationStatus.ElevationRequired) { _eventLog.WriteEntry("Process doesn't have permission to create global shared objects. See https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/create-global-objects for details."); return; } while (!cancellationToken.IsCancellationRequested) { var waitingForPathStatus = await pathChannel.WhenQueueHasMessagesAsync(cancellationToken, Timeout.InfiniteTimeSpan); if (waitingForPathStatus == OperationStatus.Cancelled) { return; } string path = null; var pathOperationResult = await pathChannel.ReadAsync(async (stream) => { using (var reader = new StreamReader(stream)) path = await reader.ReadLineAsync(); return(OperationStatus.Completed); }, cancellationToken, Timeout.InfiniteTimeSpan); if (pathOperationResult.Status == OperationStatus.Cancelled) { return; } // Actually app is already connected, line below is just example of waiting for connection var waitingForClientStatus = await fileChannel.WhenClientConnectedAsync(cancellationToken, Timeout.InfiniteTimeSpan); if (waitingForClientStatus == OperationStatus.Cancelled) { return; } FileStream fileStream = null; try { var fileOpened = false; try { fileStream = File.OpenRead(path); fileOpened = true; } catch (Exception e) { _eventLog.WriteEntry(e.ToString()); await TryWriteString(fileChannel, "Cannot open this file. Please check Event Log for details."); } if (fileOpened) { var writingOperationResult = await fileChannel.WriteAsync(async (targetStream, parameter, token) => { try { var sourceStream = (Stream)parameter; await sourceStream.CopyToAsync(targetStream, 4096, token); return(OperationStatus.Completed); } catch (Exception e) { if (!(e is OperationCanceledException)) { _eventLog.WriteEntry(e.ToString()); // WriteAsync does not throw, it returns OperationStatus.DelegateFailed } throw; } }, fileStream, fileStream.Length, cancellationToken, Timeout.InfiniteTimeSpan); if (writingOperationResult.Status == OperationStatus.Cancelled) { return; } if (writingOperationResult.Status == OperationStatus.DelegateFailed) { await TryWriteString(fileChannel, "Cannot send file. Please check Event Log for details."); } if (writingOperationResult.Status == OperationStatus.RequestedLengthIsGreaterThanLogicalAddressSpace || writingOperationResult.Status == OperationStatus.RequestedLengthIsGreaterThanVirtualAddressSpace || writingOperationResult.Status == OperationStatus.OutOfSpace) { await TryWriteString(fileChannel, "File is too large."); _eventLog.WriteEntry($"Failed to send file {path} because it is too large."); } } } finally { fileStream?.Close(); } } } catch (Exception e) { _eventLog.WriteEntry(e.ToString()); Stop(); } finally { pathChannel?.Dispose(); fileChannel?.Dispose(); } }