public override void ProcessCommand(byte[] parameter, IConnectionInfo connectionInfo) { Program.WriteLine("Remote Desktop command received: " + (RemoteDesktopCommunication)parameter[0]); switch ((RemoteDesktopCommunication)parameter[0]) { case RemoteDesktopCommunication.GetInfo: var remoteDesktopInformation = new RemoteDesktopInformation { Screens = new List <ScreenInfo>() }; var screens = Screen.AllScreens; var allNames = ScreenExtensions.GetAllMonitorsFriendlyNames().ToArray(); for (int i = 0; i < screens.Length; i++) { remoteDesktopInformation.Screens.Add(new ScreenInfo { Number = i, Width = screens[i].Bounds.Width, Height = screens[i].Bounds.Height, Name = allNames.Length >= i && !string.IsNullOrEmpty(allNames[i]) ? allNames[i] : screens[i].DeviceName }); } foreach (var screenCaptureService in _screenCaptureServices) { if (screenCaptureService.Value().IsSupported) { remoteDesktopInformation.AvailableCaptureTypes |= screenCaptureService.Key; } } ResponseBytes((byte)RemoteDesktopCommunication.ResponseInfo, new Serializer(typeof(RemoteDesktopInformation)).Serialize(remoteDesktopInformation), connectionInfo); break; case RemoteDesktopCommunication.InitializeConnection: var connectionGuid = new Guid(parameter.Skip(1).Take(16).ToArray()); _connection?.Dispose(); _connection = connectionInfo.ConnectionInitializer.TakeConnection(connectionGuid); break; case RemoteDesktopCommunication.InitializeDirectConnection: _connection = new ServerConnection(connectionInfo, this, (byte)RemoteDesktopCommunication.ResponseFrame); break; case RemoteDesktopCommunication.Initialize: var captureType = (CaptureType)parameter[1]; var monitor = (int)parameter[2]; var quality = (int)parameter[3]; var drawCursor = parameter[4] == 1; var compression = (ImageCompressionType)parameter[5]; Program.WriteLine("Lock _streamComponents, InitializeStreamingComponents"); lock (_streamComponentsLock) InitializeStreamingComponents(captureType, monitor, quality, connectionInfo, drawCursor, compression); break; case RemoteDesktopCommunication.ChangeQuality: var newQuality = (int)parameter[1]; lock (_streamComponentsLock) { if (_unsafeCodec.ImageQuality != newQuality) { _unsafeCodec.ImageQuality = newQuality; } } break; case RemoteDesktopCommunication.Start: if (_isStreaming) { return; } Program.WriteLine("Start streaming; _isStreaming = true"); _connectionInfo = connectionInfo; _isStreaming = true; new Thread(Streaming) { IsBackground = true }.Start(); break; case RemoteDesktopCommunication.Stop: Program.WriteLine("Stop streaming...; _isStreaming = false; Lock _streamComponentsLock"); _isStreaming = false; //important, it locks this command until the stuff is stopped lock (_streamComponentsLock) { } Program.WriteLine("Stopped streaming"); break; case RemoteDesktopCommunication.ChangeMonitor: monitor = parameter[1]; lock (_streamComponentsLock) { _screenCaptureService.ChangeMonitor(monitor); _unsafeCodec?.Dispose(); _unsafeCodec = new UnsafeStreamCodec(GetImageCompression(_compressionType), UnsafeStreamCodecParameters.UpdateImageEveryTwoSeconds | UnsafeStreamCodecParameters.DontDisposeImageCompressor); _currentMonitor = monitor; } break; case RemoteDesktopCommunication.DesktopAction: DoDesktopAction((RemoteDesktopAction)parameter[1], parameter, 2); break; case RemoteDesktopCommunication.ChangeDrawCursor: lock (_streamComponentsLock) { if (parameter[1] == 1) { _drawCursor = true; _cursorStreamCodec = new CursorStreamCodec(); } else { _cursorStreamCodec?.Dispose(); _drawCursor = false; } } break; } }