diff --git a/Agent.Installer.Win/Services/InstallerService.cs b/Agent.Installer.Win/Services/InstallerService.cs index 39f3ef56b..b14d60c35 100644 --- a/Agent.Installer.Win/Services/InstallerService.cs +++ b/Agent.Installer.Win/Services/InstallerService.cs @@ -80,24 +80,6 @@ public async Task Install(string serverUrl, } - private void CreateSupportShortcut(string serverUrl, string deviceUuid, bool createSupportShortcut) - { - var shell = new WshShell(); - var shortcutLocation = Path.Combine(InstallPath, "Get Support.lnk"); - var shortcut = (IWshShortcut)shell.CreateShortcut(shortcutLocation); - shortcut.Description = "Get IT support"; - shortcut.IconLocation = Path.Combine(InstallPath, "Remotely_Agent.exe"); - shortcut.TargetPath = serverUrl.TrimEnd('/') + $"/GetSupport?deviceID={deviceUuid}"; - shortcut.Save(); - - if (createSupportShortcut) - { - var systemRoot = Path.GetPathRoot(Environment.SystemDirectory); - var publicDesktop = Path.Combine(systemRoot, "Users", "Public", "Desktop", "Get Support.lnk"); - FileIO.Copy(shortcutLocation, publicDesktop, true); - } - } - public async Task Uninstall() { try @@ -117,7 +99,7 @@ public async Task Uninstall() ClearInstallDirectory(); ProcessEx.StartHidden("cmd.exe", $"/c timeout 5 & rd /s /q \"{InstallPath}\""); - ProcessEx.StartHidden("netsh", "advfirewall firewall delete rule name=\"Remotely Desktop\"").WaitForExit(); + ProcessEx.StartHidden("netsh", "advfirewall firewall delete rule name=\"Remotely Desktop Unattended\"").WaitForExit(); GetRegistryBaseKey().DeleteSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Remotely", false); @@ -132,9 +114,9 @@ public async Task Uninstall() private void AddFirewallRule() { - var screenCastPath = Path.Combine(InstallPath, "Desktop", "Remotely_Desktop.exe"); - ProcessEx.StartHidden("netsh", "advfirewall firewall delete rule name=\"Remotely Desktop\"").WaitForExit(); - ProcessEx.StartHidden("netsh", $"advfirewall firewall add rule name=\"Remotely Desktop\" program=\"{screenCastPath}\" protocol=any dir=in enable=yes action=allow profile=Private,Domain description=\"The agent that allows screen sharing and remote control for Remotely.\"").WaitForExit(); + var desktopExePath = Path.Combine(InstallPath, "Desktop", "Remotely_Desktop.exe"); + ProcessEx.StartHidden("netsh", "advfirewall firewall delete rule name=\"Remotely Desktop Unattended\"").WaitForExit(); + ProcessEx.StartHidden("netsh", $"advfirewall firewall add rule name=\"Remotely Desktop Unattended\" program=\"{desktopExePath}\" protocol=any dir=in enable=yes action=allow description=\"The agent that allows screen sharing and remote control for Remotely.\"").WaitForExit(); } private void BackupDirectory() @@ -204,6 +186,23 @@ private void CreateDeviceSetupOptions(string deviceGroup, string deviceAlias) } } + private void CreateSupportShortcut(string serverUrl, string deviceUuid, bool createSupportShortcut) + { + var shell = new WshShell(); + var shortcutLocation = Path.Combine(InstallPath, "Get Support.lnk"); + var shortcut = (IWshShortcut)shell.CreateShortcut(shortcutLocation); + shortcut.Description = "Get IT support"; + shortcut.IconLocation = Path.Combine(InstallPath, "Remotely_Agent.exe"); + shortcut.TargetPath = serverUrl.TrimEnd('/') + $"/GetSupport?deviceID={deviceUuid}"; + shortcut.Save(); + + if (createSupportShortcut) + { + var systemRoot = Path.GetPathRoot(Environment.SystemDirectory); + var publicDesktop = Path.Combine(systemRoot, "Users", "Public", "Desktop", "Get Support.lnk"); + FileIO.Copy(shortcutLocation, publicDesktop, true); + } + } private void CreateUninstallKey() { var version = FileVersionInfo.GetVersionInfo(Path.Combine(InstallPath, "Remotely_Agent.exe")); @@ -350,7 +349,7 @@ private void InstallService() Logger.Write("Service installed."); serv = ServiceController.GetServices().FirstOrDefault(ser => ser.ServiceName == "Remotely_Service"); - ProcessEx.StartHidden("cmd.exe", "/c sc.exe failure \"Remotely_Service\" reset=5 actions=restart/5000"); + ProcessEx.StartHidden("cmd.exe", "/c sc.exe failure \"Remotely_Service\" reset= 5 actions= restart/5000"); } if (serv.Status != ServiceControllerStatus.Running) { diff --git a/Desktop.Core/Models/Viewer.cs b/Desktop.Core/Models/Viewer.cs index c101e0dee..f28b98a27 100644 --- a/Desktop.Core/Models/Viewer.cs +++ b/Desktop.Core/Models/Viewer.cs @@ -174,7 +174,7 @@ await SendToViewer(() => RtcSession.SendWindowsSessions(Win32Interop.GetActiveSe } } - public async Task ThrottleIfNeeded() + public void ThrottleIfNeeded() { if (AutoAdjustQuality && DateTimeOffset.Now - lastQualityAdjustment > TimeSpan.FromSeconds(2)) { @@ -189,8 +189,8 @@ public async Task ThrottleIfNeeded() ImageQuality = defaultImageQuality; } } - - await TaskHelper.DelayUntil(() => PendingSentFrames.Count < 5 && + + TaskHelper.DelayUntil(() => PendingSentFrames.Count < 5 && ( !PendingSentFrames.TryPeek(out var result) || DateTimeOffset.Now - result < TimeSpan.FromSeconds(1) ), diff --git a/Desktop.Core/Services/ScreenCaster.cs b/Desktop.Core/Services/ScreenCaster.cs index 8ad0e587e..15a800edc 100644 --- a/Desktop.Core/Services/ScreenCaster.cs +++ b/Desktop.Core/Services/ScreenCaster.cs @@ -103,7 +103,7 @@ await viewer.SendScreenCapture( Debug.WriteLine($"Capture FPS: {fpsQueue.Count}"); } - await viewer.ThrottleIfNeeded(); + viewer.ThrottleIfNeeded(); viewer.Capturer.GetNextFrame(); diff --git a/Desktop.Win.Wrapper/MainWindow.xaml.cs b/Desktop.Win.Wrapper/MainWindow.xaml.cs index 3f325e4f4..a5bc02662 100644 --- a/Desktop.Win.Wrapper/MainWindow.xaml.cs +++ b/Desktop.Win.Wrapper/MainWindow.xaml.cs @@ -146,7 +146,7 @@ private void AddFirewallRule() Process.Start(psi).WaitForExit(); - psi.Arguments = $"advfirewall firewall add rule name=\"Remotely Desktop\" program=\"{Path.Combine(currentVersionDir, remotelyDesktopFilename)}\" protocol=any dir=in enable=yes action=allow profile=Private,Domain description=\"The agent that allows screen sharing and remote control for Remotely.\""; + psi.Arguments = $"advfirewall firewall add rule name=\"Remotely Desktop\" program=\"{Path.Combine(currentVersionDir, remotelyDesktopFilename)}\" protocol=any dir=in enable=yes action=allow description=\"The agent that allows screen sharing and remote control for Remotely.\""; Process.Start(psi).WaitForExit(); } diff --git a/Desktop.Win/Services/ScreenCapturerWin.cs b/Desktop.Win/Services/ScreenCapturerWin.cs index 6a25fd648..d9d483e6f 100644 --- a/Desktop.Win/Services/ScreenCapturerWin.cs +++ b/Desktop.Win/Services/ScreenCapturerWin.cs @@ -90,14 +90,16 @@ public void GetNextFrame() PreviousFrame?.Dispose(); PreviousFrame = (Bitmap)CurrentFrame.Clone(); - if (directxScreens.ContainsKey(SelectedScreen)) - { - GetDirectXFrame(); - } - else + // Sometimes DX will result in a timeout, even when there are changes + // on the screen. I've observed this when a laptop lid is closed, or + // on some machines that aren't connected to a monitor. This will + // have it fall back to BitBlt in those cases. + if (!directxScreens.ContainsKey(SelectedScreen) || + GetDirectXFrame() == GetDirectXFrameResult.Timeout) { GetBitBltFrame(); } + } catch (Exception e) { @@ -172,7 +174,14 @@ private void GetBitBltFrame() } } - private void GetDirectXFrame() + private enum GetDirectXFrameResult + { + Success, + Failure, + Timeout, + } + + private GetDirectXFrameResult GetDirectXFrame() { try { @@ -189,13 +198,13 @@ private void GetDirectXFrame() { if (result.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Code) { - return; + return GetDirectXFrameResult.Timeout; } else { Logger.Write($"TryAcquireFrame error. Code: {result.Code}"); NeedsInit = true; - return; + return GetDirectXFrameResult.Failure; } } @@ -206,7 +215,7 @@ private void GetDirectXFrame() duplicatedOutput.ReleaseFrame(); } catch { } - return; + return GetDirectXFrameResult.Failure; } // Copy resource into memory that can be accessed by the CPU @@ -240,6 +249,8 @@ private void GetDirectXFrame() screenResource.Dispose(); duplicatedOutput.ReleaseFrame(); + + return GetDirectXFrameResult.Success; } catch (SharpDXException e) { @@ -247,7 +258,9 @@ private void GetDirectXFrame() { Logger.Write(e); NeedsInit = true; + return GetDirectXFrameResult.Failure; } + return GetDirectXFrameResult.Timeout; } } diff --git a/Desktop.Win/ViewModels/MainWindowViewModel.cs b/Desktop.Win/ViewModels/MainWindowViewModel.cs index e61ee0ecb..314a12156 100644 --- a/Desktop.Win/ViewModels/MainWindowViewModel.cs +++ b/Desktop.Win/ViewModels/MainWindowViewModel.cs @@ -31,6 +31,18 @@ public class MainWindowViewModel : ViewModelBase public MainWindowViewModel() { Current = this; + + Application.Current.Exit += Application_Exit; + + CursorIconWatcher = Services?.GetRequiredService(); + CursorIconWatcher.OnChange += CursorIconWatcher_OnChange; + Services?.GetRequiredService().BeginWatching(); + Conductor = Services?.GetRequiredService(); + CasterSocket = Services?.GetRequiredService(); + Conductor.SessionIDChanged += SessionIDChanged; + Conductor.ViewerRemoved += ViewerRemoved; + Conductor.ViewerAdded += ViewerAdded; + Conductor.ScreenCastRequested += ScreenCastRequested; } public static IServiceProvider Services => ServiceContainer.Instance; @@ -175,18 +187,7 @@ public async Task GetSessionID() public async Task Init() { - Application.Current.Exit += Application_Exit; - - CursorIconWatcher = Services?.GetRequiredService(); - CursorIconWatcher.OnChange += CursorIconWatcher_OnChange; - Services?.GetRequiredService().BeginWatching(); - Conductor = Services?.GetRequiredService(); - CasterSocket = Services?.GetRequiredService(); - Conductor.SessionIDChanged += SessionIDChanged; - Conductor.ViewerRemoved += ViewerRemoved; - Conductor.ViewerAdded += ViewerAdded; - Conductor.ScreenCastRequested += ScreenCastRequested; - + SessionID = "Retrieving..."; Host = Config.GetConfig().Host; diff --git a/Server/API/RemoteControlController.cs b/Server/API/RemoteControlController.cs index 086467b0b..1209468ab 100644 --- a/Server/API/RemoteControlController.cs +++ b/Server/API/RemoteControlController.cs @@ -110,7 +110,7 @@ bool remoteControlStarted() .All(x => existingSessions.Contains(x.CasterSocketID)); }; - if (!await TaskHelper.DelayUntil(remoteControlStarted, TimeSpan.FromSeconds(30))) + if (!await TaskHelper.DelayUntilAsync(remoteControlStarted, TimeSpan.FromSeconds(30))) { return StatusCode(408, "The remote control process failed to start in time on the remote device."); } diff --git a/Server/API/ScriptingController.cs b/Server/API/ScriptingController.cs index bda5bf178..506419d7e 100644 --- a/Server/API/ScriptingController.cs +++ b/Server/API/ScriptingController.cs @@ -77,7 +77,7 @@ public async Task> ExecuteCommand(string mode, strin DataService.AddOrUpdateCommandResult(commandResult); var requestID = Guid.NewGuid().ToString(); await AgentHubContext.Clients.Client(connection.Key).SendAsync("ExecuteCommandFromApi", mode, requestID, command, commandResult.ID, Guid.NewGuid().ToString()); - var success = await TaskHelper.DelayUntil(() => AgentHub.ApiScriptResults.TryGetValue(requestID, out _), TimeSpan.FromSeconds(30)); + var success = await TaskHelper.DelayUntilAsync(() => AgentHub.ApiScriptResults.TryGetValue(requestID, out _), TimeSpan.FromSeconds(30)); if (!success) { return commandResult; diff --git a/Shared/Helpers/TaskHelper.cs b/Shared/Helpers/TaskHelper.cs index 552a4c10d..a242fa400 100644 --- a/Shared/Helpers/TaskHelper.cs +++ b/Shared/Helpers/TaskHelper.cs @@ -1,12 +1,23 @@ using System; using System.Diagnostics; +using System.Threading; using System.Threading.Tasks; namespace Remotely.Shared.Helpers { public static class TaskHelper { - public static async Task DelayUntil(Func condition, TimeSpan timeout, int pollingMs = 10) + public static bool DelayUntil(Func condition, TimeSpan timeout, int pollingMs = 10) + { + var sw = Stopwatch.StartNew(); + while (!condition() && sw.Elapsed < timeout) + { + Thread.Sleep(pollingMs); + } + return condition(); + } + + public static async Task DelayUntilAsync(Func condition, TimeSpan timeout, int pollingMs = 10) { var sw = Stopwatch.StartNew(); while (!condition() && sw.Elapsed < timeout) diff --git a/Utilities/Publish.ps1 b/Utilities/Publish.ps1 index 195d4c84b..9eebe0491 100644 --- a/Utilities/Publish.ps1 +++ b/Utilities/Publish.ps1 @@ -17,24 +17,37 @@ param ( [string]$RID = "", [string]$Hostname = "", [string]$CertificatePath = "", - [string]$CertificatePassword = "" + [string]$CertificatePassword = "", + [string]$CurrentVersion = "" ) $ErrorActionPreference = "Stop" -$Year = ([DateTime]::UtcNow).Year.ToString() -$Month = ([DateTime]::UtcNow).Month.ToString().PadLeft(2, "0") -$Day = ([DateTime]::UtcNow).Day.ToString().PadLeft(2, "0") -$Hour = ([DateTime]::UtcNow).Hour.ToString().PadLeft(2, "0") -$Minute = ([DateTime]::UtcNow).Minute.ToString().PadLeft(2, "0") -$CurrentVersion = "$Year.$Month.$Day.$Hour$Minute" $MSBuildPath = (Get-ChildItem -Path "${env:ProgramFiles(x86)}\Microsoft Visual Studio\" -Recurse -Filter "MSBuild.exe" -File | ForEach-Object { [System.Diagnostics.FileVersionInfo]::GetVersionInfo($_.FullName) } | Sort-Object -Property FileVersion -Descending | Select-Object -First 1).FileName $Root = (Get-Item -Path $PSScriptRoot).Parent.FullName $SignAssemblies = $false +if (!$CurrentVersion) { + $Year = ([DateTime]::UtcNow).Year.ToString() + $Month = ([DateTime]::UtcNow).Month.ToString().PadLeft(2, "0") + $Day = ([DateTime]::UtcNow).Day.ToString().PadLeft(2, "0") + $Hour = ([DateTime]::UtcNow).Hour.ToString().PadLeft(2, "0") + $Minute = ([DateTime]::UtcNow).Minute.ToString().PadLeft(2, "0") + $CurrentVersion = "$Year.$Month.$Day.$Hour$Minute" +} + +if ($CertificatePath.Length -gt 0 -and + (Test-Path -Path $CertificatePath) -eq $true -and + $CertificatePassword.Length -gt 0) +{ + $SignAssemblies = $true +} + + + Set-Location -Path $Root #region Functions @@ -65,14 +78,6 @@ if ([string]::IsNullOrWhiteSpace($MSBuildPath) -or !(Test-Path -Path $MSBuildPat return } -if ($CertificatePath.Length -gt 0 -and - (Test-Path -Path $CertificatePath) -eq $true -and - $CertificatePassword.Length -gt 0) -{ - $SignAssemblies = $true -} - - # Add Current Version file to root content folder for client update checks. # TODO: Remove after a few releases. Set-Content -Path "$Root\Server\CurrentVersion.txt" -Value $CurrentVersion.Trim() -Encoding UTF8 -Force diff --git a/Utilities/Remotely_CentOS_Install.sh b/Utilities/Remotely_CentOS_Install.sh index 2d8b06f27..e4d7ef440 100644 --- a/Utilities/Remotely_CentOS_Install.sh +++ b/Utilities/Remotely_CentOS_Install.sh @@ -134,6 +134,6 @@ firewall-cmd --permanent --zone=public --add-service=https firewall-cmd --reload # Install Certbot and get SSL cert. -yum -y install certbot python2-certbot-nginx +yum -y install certbot python3-certbot-nginx certbot --nginx \ No newline at end of file diff --git a/Utilities/Remotely_Server_Install.sh b/Utilities/Remotely_Server_Install.sh index 1e13d9c47..90c712ee8 100644 --- a/Utilities/Remotely_Server_Install.sh +++ b/Utilities/Remotely_Server_Install.sh @@ -138,6 +138,6 @@ systemctl restart remotely.service # Install Certbot and get SSL cert. -apt-get -y install certbot python-certbot-nginx +apt-get -y install certbot python3-certbot-nginx certbot --nginx \ No newline at end of file