diff --git a/Desktop.Unix/App.xaml b/Desktop.Linux/App.xaml similarity index 93% rename from Desktop.Unix/App.xaml rename to Desktop.Linux/App.xaml index f3419d25..1bd7b475 100644 --- a/Desktop.Unix/App.xaml +++ b/Desktop.Linux/App.xaml @@ -1,7 +1,7 @@  + xmlns:local="clr-namespace:Remotely.Desktop.Linux;assembly=Remotely_Desktop" + x:Class="Remotely.Desktop.Linux.App"> diff --git a/Desktop.Linux/App.xaml.cs b/Desktop.Linux/App.xaml.cs new file mode 100644 index 00000000..294d699f --- /dev/null +++ b/Desktop.Linux/App.xaml.cs @@ -0,0 +1,29 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; +using Remotely.Desktop.Linux.ViewModels; +using Remotely.Desktop.Linux.Views; + +namespace Remotely.Desktop.Linux +{ + public class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(), + }; + } + + base.OnFrameworkInitializationCompleted(); + } + } +} diff --git a/Desktop.Unix/Assets/Gear.png b/Desktop.Linux/Assets/Gear.png similarity index 100% rename from Desktop.Unix/Assets/Gear.png rename to Desktop.Linux/Assets/Gear.png diff --git a/Desktop.Unix/Assets/avalonia-logo.ico b/Desktop.Linux/Assets/avalonia-logo.ico similarity index 100% rename from Desktop.Unix/Assets/avalonia-logo.ico rename to Desktop.Linux/Assets/avalonia-logo.ico diff --git a/Desktop.Unix/Assets/favicon.ico b/Desktop.Linux/Assets/favicon.ico similarity index 100% rename from Desktop.Unix/Assets/favicon.ico rename to Desktop.Linux/Assets/favicon.ico diff --git a/Desktop.Unix/Controls/HostNamePrompt.xaml b/Desktop.Linux/Controls/HostNamePrompt.xaml similarity index 86% rename from Desktop.Unix/Controls/HostNamePrompt.xaml rename to Desktop.Linux/Controls/HostNamePrompt.xaml index c022a3f2..588db61b 100644 --- a/Desktop.Unix/Controls/HostNamePrompt.xaml +++ b/Desktop.Linux/Controls/HostNamePrompt.xaml @@ -3,8 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Remotely.Desktop.Unix.Controls.HostNamePrompt" - xmlns:ViewModels="clr-namespace:Remotely.Desktop.Unix.ViewModels;assembly=Remotely_Desktop" + x:Class="Remotely.Desktop.Linux.Controls.HostNamePrompt" + xmlns:ViewModels="clr-namespace:Remotely.Desktop.Linux.ViewModels;assembly=Remotely_Desktop" Title="Remotely Host Name" Height="150" Width="350" WindowStartupLocation="CenterOwner"> diff --git a/Desktop.Unix/Controls/HostNamePrompt.xaml.cs b/Desktop.Linux/Controls/HostNamePrompt.xaml.cs similarity index 74% rename from Desktop.Unix/Controls/HostNamePrompt.xaml.cs rename to Desktop.Linux/Controls/HostNamePrompt.xaml.cs index 066768f6..89635b6c 100644 --- a/Desktop.Unix/Controls/HostNamePrompt.xaml.cs +++ b/Desktop.Linux/Controls/HostNamePrompt.xaml.cs @@ -1,8 +1,9 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Remotely.Desktop.Linux.Views; -namespace Remotely.Desktop.Unix.Controls +namespace Remotely.Desktop.Linux.Controls { public class HostNamePrompt : Window { @@ -17,7 +18,7 @@ namespace Remotely.Desktop.Unix.Controls private void InitializeComponent() { AvaloniaXamlLoader.Load(this); - this.Icon = App.Current?.MainWindow?.Icon; + this.Icon = MainWindow.Current?.Icon; } } } diff --git a/Desktop.Unix/Controls/MessageBox.xaml b/Desktop.Linux/Controls/MessageBox.xaml similarity index 92% rename from Desktop.Unix/Controls/MessageBox.xaml rename to Desktop.Linux/Controls/MessageBox.xaml index cc64f638..b460b6f0 100644 --- a/Desktop.Unix/Controls/MessageBox.xaml +++ b/Desktop.Linux/Controls/MessageBox.xaml @@ -3,8 +3,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - xmlns:vm="clr-namespace:Remotely.Desktop.Unix.ViewModels;assembly=Remotely_Desktop" - x:Class="Remotely.Desktop.Unix.Controls.MessageBox" + xmlns:vm="clr-namespace:Remotely.Desktop.Linux.ViewModels;assembly=Remotely_Desktop" + x:Class="Remotely.Desktop.Linux.Controls.MessageBox" Title="{Binding Caption}" SizeToContent="WidthAndHeight" MinWidth="200" MinHeight="100" WindowStartupLocation="CenterOwner"> diff --git a/Desktop.Unix/Controls/MessageBox.xaml.cs b/Desktop.Linux/Controls/MessageBox.xaml.cs similarity index 83% rename from Desktop.Unix/Controls/MessageBox.xaml.cs rename to Desktop.Linux/Controls/MessageBox.xaml.cs index 764e32ab..7b5ff8d6 100644 --- a/Desktop.Unix/Controls/MessageBox.xaml.cs +++ b/Desktop.Linux/Controls/MessageBox.xaml.cs @@ -1,10 +1,11 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; -using Remotely.Desktop.Unix.ViewModels; +using Remotely.Desktop.Linux.ViewModels; +using Remotely.Desktop.Linux.Views; using System.Threading.Tasks; -namespace Remotely.Desktop.Unix.Controls +namespace Remotely.Desktop.Linux.Controls { public class MessageBox : Window { @@ -29,11 +30,11 @@ namespace Remotely.Desktop.Unix.Controls messageBox.DataContext = viewModel; - await messageBox.ShowDialog(App.Current.MainWindow); + await messageBox.ShowDialog(MainWindow.Current); return viewModel.Result; } - private MessageBox() + public MessageBox() { this.InitializeComponent(); #if DEBUG @@ -46,7 +47,7 @@ namespace Remotely.Desktop.Unix.Controls private void InitializeComponent() { AvaloniaXamlLoader.Load(this); - this.Icon = App.Current?.MainWindow?.Icon; + this.Icon = MainWindow.Current?.Icon; } } diff --git a/Desktop.Unix/Desktop.Unix.csproj b/Desktop.Linux/Desktop.Linux.csproj similarity index 85% rename from Desktop.Unix/Desktop.Unix.csproj rename to Desktop.Linux/Desktop.Linux.csproj index 5138a3e9..53b5bee8 100644 --- a/Desktop.Unix/Desktop.Unix.csproj +++ b/Desktop.Linux/Desktop.Linux.csproj @@ -4,7 +4,7 @@ netcoreapp3.1 Assets\favicon.ico Remotely_Desktop - Remotely.Desktop.Unix + Remotely.Desktop.Linux AnyCPU;x64;x86 @@ -32,9 +32,9 @@ - - - + + + diff --git a/Desktop.Unix/Program.cs b/Desktop.Linux/Program.cs similarity index 52% rename from Desktop.Unix/Program.cs rename to Desktop.Linux/Program.cs index d4044221..d20dc7c6 100644 --- a/Desktop.Unix/Program.cs +++ b/Desktop.Linux/Program.cs @@ -1,35 +1,25 @@ using System; using Avalonia; using Avalonia.Logging.Serilog; -using Remotely.Desktop.Unix.ViewModels; -using Remotely.Desktop.Unix.Views; +using Avalonia.ReactiveUI; +using Remotely.Desktop.Linux.ViewModels; +using Remotely.Desktop.Linux.Views; -namespace Remotely.Desktop.Unix +namespace Remotely.Desktop.Linux { class Program { // Initialization code. Don't use any Avalonia, third-party APIs or any // SynchronizationContext-reliant code before AppMain is called: things aren't initialized // yet and stuff might break. - public static void Main(string[] args) => BuildAvaloniaApp().Start(AppMain, args); + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); // Avalonia configuration, don't remove; also used by visual designer. public static AppBuilder BuildAvaloniaApp() => AppBuilder.Configure() .UsePlatformDetect() - .LogToDebug(); - - // Your application's entry point. Here you can initialize your MVVM framework, DI - // container, etc. - private static void AppMain(Application app, string[] args) - { - var window = new MainWindow - { - DataContext = new MainWindowViewModel(), - }; - - app.Run(window); - - } + .LogToDebug() + .UseReactiveUI(); } } diff --git a/Desktop.Unix/Services/Config.cs b/Desktop.Linux/Services/Config.cs similarity index 95% rename from Desktop.Unix/Services/Config.cs rename to Desktop.Linux/Services/Config.cs index 7fe80083..dbb7dd7f 100644 --- a/Desktop.Unix/Services/Config.cs +++ b/Desktop.Linux/Services/Config.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; @@ -7,7 +7,7 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; -namespace Remotely.Desktop.Unix.Services +namespace Remotely.Desktop.Linux.Services { public class Config { diff --git a/Desktop.Unix/Services/Executor.cs b/Desktop.Linux/Services/Executor.cs similarity index 95% rename from Desktop.Unix/Services/Executor.cs rename to Desktop.Linux/Services/Executor.cs index 976cb7ed..758373de 100644 --- a/Desktop.Unix/Services/Executor.cs +++ b/Desktop.Linux/Services/Executor.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Input; -namespace Remotely.Desktop.Unix.Services +namespace Remotely.Desktop.Linux.Services { public class Executor : ICommand { diff --git a/Desktop.Unix/ViewLocator.cs b/Desktop.Linux/ViewLocator.cs similarity index 90% rename from Desktop.Unix/ViewLocator.cs rename to Desktop.Linux/ViewLocator.cs index f78a27c5..6a69ecb7 100644 --- a/Desktop.Unix/ViewLocator.cs +++ b/Desktop.Linux/ViewLocator.cs @@ -1,9 +1,9 @@ using System; using Avalonia.Controls; using Avalonia.Controls.Templates; -using Remotely.Desktop.Unix.ViewModels; +using Remotely.Desktop.Linux.ViewModels; -namespace Remotely.Desktop.Unix +namespace Remotely.Desktop.Linux { public class ViewLocator : IDataTemplate { diff --git a/Desktop.Unix/ViewModels/HostNamePromptViewModel.cs b/Desktop.Linux/ViewModels/HostNamePromptViewModel.cs similarity index 89% rename from Desktop.Unix/ViewModels/HostNamePromptViewModel.cs rename to Desktop.Linux/ViewModels/HostNamePromptViewModel.cs index df59cd9f..a7172898 100644 --- a/Desktop.Unix/ViewModels/HostNamePromptViewModel.cs +++ b/Desktop.Linux/ViewModels/HostNamePromptViewModel.cs @@ -7,9 +7,9 @@ using System.Threading.Tasks; using System.Windows.Input; using Avalonia.Controls; using ReactiveUI; -using Remotely.Desktop.Unix.Services; +using Remotely.Desktop.Linux.Services; -namespace Remotely.Desktop.Unix.ViewModels +namespace Remotely.Desktop.Linux.ViewModels { public class HostNamePromptViewModel : ViewModelBase { diff --git a/Desktop.Unix/ViewModels/MainWindowViewModel.cs b/Desktop.Linux/ViewModels/MainWindowViewModel.cs similarity index 96% rename from Desktop.Unix/ViewModels/MainWindowViewModel.cs rename to Desktop.Linux/ViewModels/MainWindowViewModel.cs index 49ea932f..1977900a 100644 --- a/Desktop.Unix/ViewModels/MainWindowViewModel.cs +++ b/Desktop.Linux/ViewModels/MainWindowViewModel.cs @@ -2,8 +2,9 @@ using Avalonia.Controls; using Avalonia.Threading; using ReactiveUI; -using Remotely.Desktop.Unix.Controls; -using Remotely.Desktop.Unix.Services; +using Remotely.Desktop.Linux.Controls; +using Remotely.Desktop.Linux.Services; +using Remotely.Desktop.Linux.Views; using Remotely.ScreenCast.Core; using Remotely.ScreenCast.Core.Capture; using Remotely.ScreenCast.Core.Interfaces; @@ -25,7 +26,7 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Input; -namespace Remotely.Desktop.Unix.ViewModels +namespace Remotely.Desktop.Linux.ViewModels { public class MainWindowViewModel : ReactiveObject { @@ -37,6 +38,10 @@ namespace Remotely.Desktop.Unix.ViewModels public MainWindowViewModel() { Current = this; + if (!OSUtils.IsLinux) + { + return; + } var screenCaster = new LinuxScreenCaster(); var casterSocket = new CasterSocket(new X11Input(), screenCaster, new LinuxAudioCapturer(), new LinuxClipboardService()); Conductor = new Conductor(casterSocket, screenCaster); @@ -140,11 +145,6 @@ namespace Remotely.Desktop.Unix.ViewModels return; } - if (OSUtils.IsWindows) - { - return; - } - await Conductor.CasterSocket.SendDeviceInfo(Conductor.ServiceID, Environment.MachineName, Conductor.DeviceID); await Conductor.CasterSocket.GetSessionID(); } @@ -156,8 +156,8 @@ namespace Remotely.Desktop.Unix.ViewModels { HostNamePromptViewModel.Current.Host = Host; } - prompt.Owner = App.Current?.MainWindow; - await prompt.ShowDialog(App.Current?.MainWindow); + prompt.Owner = MainWindow.Current; + await prompt.ShowDialog(MainWindow.Current); var result = HostNamePromptViewModel.Current.Host.TrimEnd("/".ToCharArray()); if (result != Host) { diff --git a/Desktop.Unix/ViewModels/MessageBoxViewModel.cs b/Desktop.Linux/ViewModels/MessageBoxViewModel.cs similarity index 88% rename from Desktop.Unix/ViewModels/MessageBoxViewModel.cs rename to Desktop.Linux/ViewModels/MessageBoxViewModel.cs index cd49e7cd..39dd4ada 100644 --- a/Desktop.Unix/ViewModels/MessageBoxViewModel.cs +++ b/Desktop.Linux/ViewModels/MessageBoxViewModel.cs @@ -1,12 +1,12 @@ using Avalonia.Controls; -using Remotely.Desktop.Unix.Controls; -using Remotely.Desktop.Unix.Services; +using Remotely.Desktop.Linux.Controls; +using Remotely.Desktop.Linux.Services; using System; using System.Collections.Generic; using System.Text; using System.Windows.Input; -namespace Remotely.Desktop.Unix.ViewModels +namespace Remotely.Desktop.Linux.ViewModels { public class MessageBoxViewModel : ViewModelBase { diff --git a/Desktop.Unix/ViewModels/ViewModelBase.cs b/Desktop.Linux/ViewModels/ViewModelBase.cs similarity index 77% rename from Desktop.Unix/ViewModels/ViewModelBase.cs rename to Desktop.Linux/ViewModels/ViewModelBase.cs index 42499eb4..6527fe14 100644 --- a/Desktop.Unix/ViewModels/ViewModelBase.cs +++ b/Desktop.Linux/ViewModels/ViewModelBase.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; using ReactiveUI; -namespace Remotely.Desktop.Unix.ViewModels +namespace Remotely.Desktop.Linux.ViewModels { public class ViewModelBase : ReactiveObject { diff --git a/Desktop.Unix/Views/MainWindow.xaml b/Desktop.Linux/Views/MainWindow.xaml similarity index 96% rename from Desktop.Unix/Views/MainWindow.xaml rename to Desktop.Linux/Views/MainWindow.xaml index 88de3021..e1a89e64 100644 --- a/Desktop.Unix/Views/MainWindow.xaml +++ b/Desktop.Linux/Views/MainWindow.xaml @@ -1,14 +1,14 @@  - + diff --git a/Desktop.Unix/Views/MainWindow.xaml.cs b/Desktop.Linux/Views/MainWindow.xaml.cs similarity index 58% rename from Desktop.Unix/Views/MainWindow.xaml.cs rename to Desktop.Linux/Views/MainWindow.xaml.cs index 3df5ade3..d0cbd653 100644 --- a/Desktop.Unix/Views/MainWindow.xaml.cs +++ b/Desktop.Linux/Views/MainWindow.xaml.cs @@ -1,15 +1,18 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; -using Remotely.Desktop.Unix.ViewModels; +using Remotely.Desktop.Linux.ViewModels; using System.Threading.Tasks; -namespace Remotely.Desktop.Unix.Views +namespace Remotely.Desktop.Linux.Views { public class MainWindow : Window { + public static MainWindow Current { get; set; } public MainWindow() { + Current = this; + InitializeComponent(); #if DEBUG this.AttachDevTools(); @@ -18,23 +21,19 @@ namespace Remotely.Desktop.Unix.Views private void TitleBanner_PointerPressed(object sender, Avalonia.Input.PointerPressedEventArgs e) { - if (e.MouseButton == Avalonia.Input.MouseButton.Left) + if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == Avalonia.Input.PointerUpdateKind.LeftButtonPressed) { - this.BeginMoveDrag(); + this.BeginMoveDrag(e); } } - private async void InitializeComponent() + private void InitializeComponent() { AvaloniaXamlLoader.Load(this); this.FindControl("TitleBanner").PointerPressed += TitleBanner_PointerPressed; - while (App.Current.MainWindow == null) - { - await Task.Delay(1); - } - await MainWindowViewModel.Current.Init(); + _ = (this.DataContext as MainWindowViewModel).Init(); } } } diff --git a/Desktop.Unix/nuget.config b/Desktop.Linux/nuget.config similarity index 100% rename from Desktop.Unix/nuget.config rename to Desktop.Linux/nuget.config diff --git a/Desktop.Unix/App.xaml.cs b/Desktop.Unix/App.xaml.cs deleted file mode 100644 index b8d4ee0b..00000000 --- a/Desktop.Unix/App.xaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia; -using Avalonia.Markup.Xaml; - -namespace Remotely.Desktop.Unix -{ - public class App : Application - { - public override void Initialize() - { - AvaloniaXamlLoader.Load(this); - } - } -} diff --git a/Remotely.sln b/Remotely.sln index f88f9094..6315469b 100644 --- a/Remotely.sln +++ b/Remotely.sln @@ -39,7 +39,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScreenCast.Core", "ScreenCa EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{3B1B36AE-7A60-4974-A868-1E24894D4149}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Desktop.Unix", "Desktop.Unix\Desktop.Unix.csproj", "{FF7FD66A-B3E2-4D39-A457-A00C94EDE9E6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Desktop.Linux", "Desktop.Linux\Desktop.Linux.csproj", "{FF7FD66A-B3E2-4D39-A457-A00C94EDE9E6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Server/Pages/Agents.cshtml b/Server/Pages/Agents.cshtml index d98d5087..187d36e3 100644 --- a/Server/Pages/Agents.cshtml +++ b/Server/Pages/Agents.cshtml @@ -30,7 +30,7 @@

Download:
- Linux Zipped + Linux Zipped

diff --git a/Utilities/Publish.ps1 b/Utilities/Publish.ps1 index 21e72242..34261685 100644 --- a/Utilities/Publish.ps1 +++ b/Utilities/Publish.ps1 @@ -80,7 +80,7 @@ if ($Hostname.Length -gt 0) { Replace-LineInFile -FilePath "$Root\Desktop.Win\Desktop.Win.csproj" -MatchPattern "" -ReplaceLineWith "$($Hostname)/Downloads/WinDesktop/" -MaxCount 1 Replace-LineInFile -FilePath "$Root\Desktop.Win\Desktop.Win.csproj" -MatchPattern "" -ReplaceLineWith "$($Hostname)/Downloads/WinDesktop/" -MaxCount 1 Replace-LineInFile -FilePath "$Root\Desktop.Win\Services\Config.cs" -MatchPattern "public string Host " -ReplaceLineWith "public string Host { get; set; } = `"$($Hostname)`";" -MaxCount 1 - Replace-LineInFile -FilePath "$Root\Desktop.Unix\Services\Config.cs" -MatchPattern "public string Host " -ReplaceLineWith "public string Host { get; set; } = `"$($Hostname)`";" -MaxCount 1 + Replace-LineInFile -FilePath "$Root\Desktop.Linux\Services\Config.cs" -MatchPattern "public string Host " -ReplaceLineWith "public string Host { get; set; } = `"$($Hostname)`";" -MaxCount 1 } else { Write-Host "`nERROR: No hostname parameter was specified. Application auto-updates will default to the public test server. Please supply your server's hostname.`n" -ForegroundColor Red @@ -115,14 +115,14 @@ New-Item -Path "$Root\Agent\bin\Release\netcoreapp3.1\linux-x64\publish\ScreenCa dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-x64 --configuration Release --output "$Root\Agent\bin\Release\netcoreapp3.1\linux-x64\publish\ScreenCast\" "$Root\ScreenCast.Linux\" # Publish Linux GUI App -$PublishDir = "$Root\Desktop.Unix\bin\Release\netcoreapp3.1\linux-x64\publish\" -dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-x64 --configuration Release --output "$PublishDir" "$Root\Desktop.Unix\" +$PublishDir = "$Root\Desktop.Linux\bin\Release\netcoreapp3.1\linux-x64\publish\" +dotnet publish /p:Version=$CurrentVersion /p:FileVersion=$CurrentVersion --runtime linux-x64 --configuration Release --output "$PublishDir" "$Root\Desktop.Linux\" # Compress Linux GUI App -Compress-Archive -Path "$PublishDir\*" -DestinationPath "$PublishDir\Remotely_Desktop.Unix.zip" -CompressionLevel Optimal -Force -while ((Test-Path -Path "$PublishDir\Remotely_Desktop.Unix.zip") -eq $false){ +Compress-Archive -Path "$PublishDir\*" -DestinationPath "$PublishDir\Remotely_Desktop.Linux.zip" -CompressionLevel Optimal -Force +while ((Test-Path -Path "$PublishDir\Remotely_Desktop.Linux.zip") -eq $false){ Start-Sleep -Seconds 1 } -Move-Item -Path "$PublishDir\Remotely_Desktop.Unix.zip" -Destination "$Root\Server\wwwroot\Downloads\Remotely_Desktop.Unix.zip" -Force +Move-Item -Path "$PublishDir\Remotely_Desktop.Linux.zip" -Destination "$Root\Server\wwwroot\Downloads\Remotely_Desktop.Linux.zip" -Force # Build .NET Framework ScreenCaster (32-bit)