From 652cf9ee0117f23be2b6634dac72959aec1409dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rodrigo=20Qui=C3=B1ones=20Pinilla?= Date: Sun, 3 Sep 2023 19:12:49 +0200 Subject: [PATCH 01/37] Fix run with warnings (no errors), fix launch url without proxy, fix install dependencies --- .../Commands/DebugStartCommand.cs | 12 +- RaspberryDebugger/Commands/ProxyWebServer.cs | 28 +- RaspberryDebugger/Connection/Connection.cs | 391 ++++++++++-------- RaspberryDebugger/Connection/Status.cs | 10 +- RaspberryDebugger/DebugHelper.cs | 51 ++- RaspberryDebugger/Properties/AssemblyInfo.cs | 4 +- RaspberryDebugger/RaspberryDebugger.csproj | 16 +- .../source.extension.vsixmanifest | 3 + 8 files changed, 310 insertions(+), 205 deletions(-) diff --git a/RaspberryDebugger/Commands/DebugStartCommand.cs b/RaspberryDebugger/Commands/DebugStartCommand.cs index 476c388..ae71e63 100644 --- a/RaspberryDebugger/Commands/DebugStartCommand.cs +++ b/RaspberryDebugger/Commands/DebugStartCommand.cs @@ -205,7 +205,8 @@ await NeonHelper.WaitForAsync(async () => if (!launchReady) return; - OpenWebBrowser(projectProperties, foundWebServer, connection); + await Task.Delay(3000); + OpenWebBrowser(projectProperties, projectSettings, foundWebServer, connection); } } @@ -213,16 +214,17 @@ await NeonHelper.WaitForAsync(async () => /// Open web browser for debugging /// /// Related project properties + /// /// Active WebServer: Kestrel or Other (NGiNX, Apache, etc.) /// LinuxSshProxy connection - private static void OpenWebBrowser( - ProjectProperties projectProperties, - WebServer foundWebServer, + private static void OpenWebBrowser(ProjectProperties projectProperties, + ProjectSettings projectSettings, + WebServer foundWebServer, LinuxSshProxy connection) { // only '/' present or full relative uri const int fullRelativeUri = 2; - var baseUri = $"http://{connection.Name}.local"; + var baseUri = projectSettings.UseWebServerProxy ? $"http://{connection.Name}.local" : $"http://{connection.Name}"; var relativeBrowserUri = projectProperties.AspRelativeBrowserUri.FirstOrDefault() == '/' ? projectProperties.AspRelativeBrowserUri diff --git a/RaspberryDebugger/Commands/ProxyWebServer.cs b/RaspberryDebugger/Commands/ProxyWebServer.cs index 155c032..23c81ee 100644 --- a/RaspberryDebugger/Commands/ProxyWebServer.cs +++ b/RaspberryDebugger/Commands/ProxyWebServer.cs @@ -37,13 +37,13 @@ private static (bool, WebServer) SearchKrestel(int aspPort, LinuxSshProxy connec { // search for dotnet kestrel web server var appKestrelListeningScript = - $@" - if lsof -i -P -n | grep --quiet 'dotnet\|TCP\|:{aspPort}' ; then - exit 0 - else - exit 1 - fi - "; + $""" + if lsof -i -P -n | grep --quiet 'dotnet\|TCP\|:{aspPort}' ; then + exit 0 + else + exit 1 + fi + """; var response = ExecSudoCmd(appKestrelListeningScript, connection); @@ -62,13 +62,13 @@ private static (bool, WebServer) SearchReverseProxy(int aspPort, LinuxSshProxy c { // search for web server running as reverse proxy var appWebServerListeningScript = - $@" - if lsof -i -P -n | grep --quiet 'TCP 127.0.0.1:{aspPort}' ; then - exit 0 - else - exit 1 - fi - "; + $""" + if lsof -i -P -n | grep --quiet 'TCP 127.0.0.1:{aspPort}' ; then + exit 0 + else + exit 1 + fi + """; var response = ExecSudoCmd(appWebServerListeningScript, connection); diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index aef2060..92fe8f6 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -135,17 +135,17 @@ public static async Task ConnectAsync(ConnectionInfo connectionInfo, var homeFolder = LinuxPath.Combine("/", "home", connectionInfo.User); var publicKey = File.ReadAllText(connectionInfo.PublicKeyPath).Trim(); var keyScript = - $@" - mkdir -p {homeFolder}/.ssh - touch {homeFolder}/.ssh/authorized_keys - - if ! grep --quiet '{publicKey}' {homeFolder}/.ssh/authorized_keys ; then - echo '{publicKey}' >> {homeFolder}/.ssh/authorized_keys - exit $? - fi - - exit 0 - "; + $""" + mkdir -p {homeFolder}/.ssh + touch {homeFolder}/.ssh/authorized_keys + + if ! grep --quiet '{publicKey}' {homeFolder}/.ssh/authorized_keys ; then + echo '{publicKey}' >> {homeFolder}/.ssh/authorized_keys + exit $? + fi + + exit 0 + """; connection.ThrowOnError(connection.RunCommand(CommandBundle.FromScript(keyScript))); return connection; @@ -162,7 +162,7 @@ exit 0 RaspberryDebugger.Log.Exception(e, $"[{connectionInfo?.Host}]"); Log($"[{connectionInfo?.Host}]: Cannot reach device."); - return null; + throw; } } @@ -310,83 +310,91 @@ await PackageHelper.ExecuteWithProgressAsync( Log($"[{Name}]: Retrieving status"); var statusScript = - $@" - # This script will return the status information via STDOUT line-by-line - # in this order: - # - # Chip Architecture - # PATH environment variable - # Unzip Installed (""unzip"" or ""unzip-missing"") - # Debugger Installed (""debugger-installed"" or ""debugger-missing"") - # List of installed SDKs names (e.g. 3.1.108) separated by commas - # Raspberry Model like: Raspberry Pi 4 Model B Rev 1.2 - # Raspberry Revision like: c03112 - # - # This script also ensures that the [/lib/dotnet] directory exists, that - # it has reasonable permissions, and that the folder exists on the system - # PATH and that DOTNET_ROOT points to the folder. - - # Set the SDK and debugger installation paths. - - DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} - DEBUGFOLDER={PackageHelper.RemoteDebuggerFolder} - - # Get the chip architecture - uname -m - - # Get the current PATH - echo $PATH - - # Detect whether [unzip] is installed. - if which unzip &> /dev/nul ; then - echo 'unzip' - else - echo 'unzip-missing' - fi - - # Detect whether the [vsdbg] debugger is installed. - if [ -d $DEBUGFOLDER ] ; then - echo 'debugger-installed' - else - echo 'debugger-missing' - fi - - # List the SDK folders. These folder names are the same as the - # corresponding SDK name. We'll list the files on one line - # with the SDK names separated by commas. We'll return a blank - # line if the SDK directory doesn't exist. - if [ -d $DOTNET_ROOT/sdk ] ; then - ls -m $DOTNET_ROOT/sdk - else - echo '' - fi - - # Output the Raspberry board model. - cat /proc/cpuinfo | grep '^Model\s' | grep -o 'Raspberry.*$' - - # Output the Raspberry board revision. - cat /proc/cpuinfo | grep 'Revision\s' | grep -o '[0-9a-fA-F]*$' - - # Ensure that the [/lib/dotnet] folder exists, that it's on the - # PATH and that DOTNET_ROOT are defined. - mkdir -p /lib/dotnet - chown root:root /lib/dotnet - chmod 755 /lib/dotnet - - # Set these for the current session: - export DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} - export PATH=$PATH:$DOTNET_ROOT - - # and for future sessions too: - if ! grep --quiet DOTNET_ROOT /etc/profile ; then - echo """" >> /etc/profile - echo ""#------------------------------"" >> /etc/profile - echo ""# Raspberry Debugger:"" >> /etc/profile - echo ""export DOTNET_ROOT=$DOTNET_ROOT"" >> /etc/profile - echo ""export PATH=$PATH"" >> /etc/profile - echo ""#------------------------------"" >> /etc/profile - fi - "; + $""" + # This script will return the status information via STDOUT line-by-line + # in this order: + # + # Chip Architecture + # PATH environment variable + # Unzip Installed ("unzip" or "unzip-missing") + # Lsof Installed ("lsof" or "lsof-missing") + # Debugger Installed ("debugger-installed" or "debugger-missing") + # List of installed SDKs names (e.g. 3.1.108) separated by commas + # Raspberry Model like: Raspberry Pi 4 Model B Rev 1.2 + # Raspberry Revision like: c03112 + # + # This script also ensures that the [/lib/dotnet] directory exists, that + # it has reasonable permissions, and that the folder exists on the system + # PATH and that DOTNET_ROOT points to the folder. + + # Set the SDK and debugger installation paths. + + DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} + DEBUGFOLDER={PackageHelper.RemoteDebuggerFolder} + + # Get the chip architecture + uname -m + + # Get the current PATH + echo $PATH + + # Detect whether [unzip] is installed. + if which unzip &> /dev/null ; then + echo 'unzip' + else + echo 'unzip-missing' + fi + + # Detect whether [lsof] is installed. + if which lsof &> /dev/null ; then + echo 'lsof' + else + echo 'lsof-missing' + fi + + # Detect whether the [vsdbg] debugger is installed. + if [ -d $DEBUGFOLDER ] ; then + echo 'debugger-installed' + else + echo 'debugger-missing' + fi + + # List the SDK folders. These folder names are the same as the + # corresponding SDK name. We'll list the files on one line + # with the SDK names separated by commas. We'll return a blank + # line if the SDK directory doesn't exist. + if [ -d $DOTNET_ROOT/sdk ] ; then + ls -m $DOTNET_ROOT/sdk + else + echo '' + fi + + # Output the Raspberry board model. + cat /proc/cpuinfo | grep '^Model\s' | grep -o 'Raspberry.*$' + + # Output the Raspberry board revision. + cat /proc/cpuinfo | grep 'Revision\s' | grep -o '[0-9a-fA-F]*$' + + # Ensure that the [/lib/dotnet] folder exists, that it's on the + # PATH and that DOTNET_ROOT are defined. + mkdir -p /lib/dotnet + chown root:root /lib/dotnet + chmod 755 /lib/dotnet + + # Set these for the current session: + export DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} + export PATH=$PATH:$DOTNET_ROOT + + # and for future sessions too: + if ! grep --quiet DOTNET_ROOT /etc/profile ; then + echo "" >> /etc/profile + echo "#------------------------------" >> /etc/profile + echo "# Raspberry Debugger:" >> /etc/profile + echo "export DOTNET_ROOT=$DOTNET_ROOT" >> /etc/profile + echo "export PATH=$PATH" >> /etc/profile + echo "#------------------------------" >> /etc/profile + fi + """; Log($"[{Name}]: Fetching status"); @@ -398,6 +406,7 @@ chmod 755 /lib/dotnet var processor = await reader.ReadLineAsync(); var path = await reader.ReadLineAsync(); var hasUnzip = await reader.ReadLineAsync() == "unzip"; + var hasLsof = await reader.ReadLineAsync() == "lsof"; var hasDebugger = await reader.ReadLineAsync() == "debugger-installed"; var sdkLine = await reader.ReadLineAsync(); var model = await reader.ReadLineAsync(); @@ -408,6 +417,7 @@ chmod 755 /lib/dotnet Log($"[{Name}]: processor: {processor}"); Log($"[{Name}]: path: {path}"); Log($"[{Name}]: unzip: {hasUnzip}"); + Log($"[{Name}]: lsof: {hasLsof}"); Log($"[{Name}]: debugger: {hasDebugger}"); Log($"[{Name}]: sdks: {sdkLine}"); Log($"[{Name}]: model: {model}"); @@ -449,6 +459,7 @@ chmod 755 /lib/dotnet processor: processor, path: path, hasUnzip: hasUnzip, + hasLsof: hasLsof, hasDebugger: hasDebugger, installedSdks: sdks, model: model, @@ -480,19 +491,19 @@ await PackageHelper.ExecuteWithProgressAsync("Creating SSH keys...", try { var createKeyScript = - $@" - # Create the key pair - if ! ssh-keygen -t rsa -b 2048 -P '' -C '{workstationUser}@{workstationName}' -f {tempPrivateKeyPath} -m pem ; then - exit 1 - fi - - # Append the public key to the user's [authorized_keys] file to enable it. - mkdir -p {homeFolder}/.ssh - touch {homeFolder}/.ssh/authorized_keys - cat {tempPublicKeyPath} >> {homeFolder}/.ssh/authorized_keys - - exit 0 - "; + $""" + # Create the key pair + if ! ssh-keygen -t rsa -b 2048 -P '' -C '{workstationUser}@{workstationName}' -f {tempPrivateKeyPath} -m pem ; then + exit 1 + fi + + # Append the public key to the user's [authorized_keys] file to enable it. + mkdir -p {homeFolder}/.ssh + touch {homeFolder}/.ssh/authorized_keys + cat {tempPublicKeyPath} >> {homeFolder}/.ssh/authorized_keys + + exit 0 + """; ThrowOnError(RunCommand(CommandBundle.FromScript(createKeyScript))); @@ -521,10 +532,10 @@ exit 0 { // Delete the temporary key files on the Raspberry. var removeKeyScript = - $@" - rm -f {tempPrivateKeyPath} - rm -f {tempPublicKeyPath} - "; + $""" + rm -f {tempPrivateKeyPath} + rm -f {tempPublicKeyPath} + """; ThrowOnError(SudoCommand(CommandBundle.FromScript(removeKeyScript))); } @@ -579,30 +590,30 @@ private async Task DownloadSdkAsync(SdkCatalogItem targetSdk) async () => { var downloadScript = - $@" - # Ensure that the packages required by .NET Core are installed: - # https://docs.microsoft.com/en-us/dotnet/core/install/linux-debian#dependencies - if ! apt-get update ; then - exit 1 - fi - - if ! apt-get install -yq libc6 libgcc1 libgssapi-krb5-2 libicu-dev libssl1.1 libstdc++6 zlib1g libgdiplus ; then - exit 1 - fi - - # Remove any existing SDK download. This might be - # present if a previous installation attempt failed. - if ! rm -f /tmp/dotnet-sdk.tar.gz ; then - exit 1 - fi - - # Download the SDK installation file to a temporary file. - if ! wget --quiet -O /tmp/dotnet-sdk.tar.gz {targetSdk.Link} ; then - exit 1 - fi - - exit 0 - "; + $""" + # Ensure that the packages required by .NET Core are installed: + # https://docs.microsoft.com/en-us/dotnet/core/install/linux-debian#dependencies + if ! apt-get update ; then + exit 1 + fi + + if ! apt-get install -yq libc6 libgcc1 libgssapi-krb5-2 libicu-dev libssl1.1 libstdc++6 zlib1g libgdiplus ; then + exit 1 + fi + + # Remove any existing SDK download. This might be + # present if a previous installation attempt failed. + if ! rm -f /tmp/dotnet-sdk.tar.gz ; then + exit 1 + fi + + # Download the SDK installation file to a temporary file. + if ! wget --quiet -O /tmp/dotnet-sdk.tar.gz {targetSdk.Link} ; then + exit 1 + fi + + exit 0 + """; try { @@ -644,37 +655,37 @@ private async Task InstallSdkAsync(SdkCatalogItem targetSdk) async () => { var installScript = - $@" - export DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} - - # Verify the SHA512. - orgDir=$cwd - cd /tmp - - if ! echo '{targetSdk.Sha512} dotnet-sdk.tar.gz' | sha512sum --check - ; then - cd $orgDir - exit 1 - fi - - cd $orgDir - - # Make sure the installation directory exists. - if ! mkdir -p $DOTNET_ROOT ; then - exit 1 - fi - - # Unpack the SDK to the installation directory. - if ! tar -zxf /tmp/dotnet-sdk.tar.gz -C $DOTNET_ROOT --no-same-owner ; then - exit 1 - fi - - # Remove the temporary installation file. - if ! rm /tmp/dotnet-sdk.tar.gz ; then - exit 1 - fi - - exit 0 - "; + $""" + export DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} + + # Verify the SHA512. + orgDir=$cwd + cd /tmp + + if ! echo '{targetSdk.Sha512} dotnet-sdk.tar.gz' | sha512sum --check - ; then + cd $orgDir + exit 1 + fi + + cd $orgDir + + # Make sure the installation directory exists. + if ! mkdir -p $DOTNET_ROOT ; then + exit 1 + fi + + # Unpack the SDK to the installation directory. + if ! tar -zxf /tmp/dotnet-sdk.tar.gz -C $DOTNET_ROOT --no-same-owner ; then + exit 1 + fi + + # Remove the temporary installation file. + if ! rm /tmp/dotnet-sdk.tar.gz ; then + exit 1 + fi + + exit 0 + """; try { @@ -750,13 +761,13 @@ public async Task SetupDebuggerAsync() async () => { var installScript = - $@" - if ! curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l {PackageHelper.RemoteDebuggerFolder} ; then - exit 1 - fi + $""" + if ! curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l {PackageHelper.RemoteDebuggerFolder} ; then + exit 1 + fi - exit 0 - "; + exit 0 + """; try { @@ -783,6 +794,52 @@ exit 0 }); } + /// + /// Installs the Linux dependencies on the Raspberry if it's not already installed. + /// + /// true on success. + public async Task SetupLinuxDependenciesAsync() + { + if (PiStatus.HasUnzip && PiStatus.HasLsof) + { + return await Task.FromResult(true); + } + + LogInfo("Installing Linux dependencies"); + + return await PackageHelper.ExecuteWithProgressAsync("Installing Linux dependencies...", + async () => + { + var installScript = + $""" + if ! apt-get install -yq {(PiStatus.HasLsof ? null : "lsof")} {(PiStatus.HasUnzip ? null : "unzip")} ; then + exit 1 + fi + + exit 0 + """; + + try + { + var response = SudoCommand(CommandBundle.FromScript(installScript)); + + if (response.ExitCode == 0) + { + PiStatus.HasUnzip = true; + PiStatus.HasLsof = true; + return await Task.FromResult(true); + } + LogError(response.AllText); + return await Task.FromResult(false); + } + catch (Exception e) + { + LogException(e); + return await Task.FromResult(false); + } + }); + } + /// /// Uploads the files for the program being debugged to the Raspberry, replacing /// any existing files. diff --git a/RaspberryDebugger/Connection/Status.cs b/RaspberryDebugger/Connection/Status.cs index 4e8e834..4e35a4f 100644 --- a/RaspberryDebugger/Connection/Status.cs +++ b/RaspberryDebugger/Connection/Status.cs @@ -33,6 +33,7 @@ internal class Status /// /// The chip architecture. /// Indicates whether unzip is installed. + /// Indicates whether lsof is installed. /// Indicates whether the debugger is installed. /// The installed .NET Core SDKs. /// The current value of the PATH environment variable. @@ -43,6 +44,7 @@ public Status( string processor, string path, bool hasUnzip, + bool hasLsof, bool hasDebugger, IEnumerable installedSdks, string model, @@ -56,6 +58,7 @@ public Status( this.Processor = processor; this.Path = path; this.HasUnzip = hasUnzip; + this.HasLsof = hasLsof; this.HasDebugger = hasDebugger; this.InstalledSdks = installedSdks?.ToList(); this.RaspberryModel = model; @@ -77,7 +80,12 @@ public Status( /// Returns true if unzip is installed on the Raspberry Pi. /// This is required and will be installed automatically. /// - private bool HasUnzip { get; set; } + public bool HasUnzip { get; set; } + /// + /// Returns true if lsof is installed on the Raspberry Pi. + /// This is required and will be installed automatically. + /// + public bool HasLsof { get; set; } /// /// Indicates whether the vsdbg debugger is installed. diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index c46cb3d..5f385fd 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -283,20 +283,40 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, var errorList = dte?.ToolWindows.ErrorList.ErrorItems; + var warnings = 0; + var messages = 0; if (errorList?.Count > 0) { + var errors = 0; for (var i = 1; i <= errorList.Count; i++) { var error = errorList.Item(i); - Log.Error($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); + switch (error.ErrorLevel) + { + case vsBuildErrorLevel.vsBuildErrorLevelHigh: + Log.Error($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); + errors++; + break; + case vsBuildErrorLevel.vsBuildErrorLevelMedium: + Log.Warning($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); + warnings++; + break; + default: + Log.Info($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); + messages++; + break; + } } - Log.Error($"Build failed: [{errorList.Count}] errors"); - Log.Error("See the Build/Output panel for more information"); - return false; + if (errors > 0) + { + Log.Error($"Build failed: [{errors}] errors"); + Log.Error("See the Build/Output panel for more information"); + return false; + } } - Log.Info("Build succeeded"); + Log.Info($"Build succeeded{(warnings > 0 ? $", with {warnings} warnigns" : null)}{(messages > 0 ? $", with {messages} messages" : null)}"); // Publish the project so all required binaries and assets end up // in the output folder. @@ -312,7 +332,7 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, await Task.Yield(); const string allowedVariableNames = - @" + """ ALLUSERSPROFILE APPDATA architecture @@ -351,7 +371,7 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, USERNAME USERPROFILE windir - "; + """; var allowedVariables = new HashSet(StringComparer.InvariantCultureIgnoreCase); var environmentVariables = new Dictionary(); @@ -570,6 +590,22 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro return null; } + // Ensure that linux libraries are installed. + if (!await connection.SetupLinuxDependenciesAsync()) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + + MessageBoxEx.Show( + "Cannot install the Linux dependencies on the Raspberry.\r\n\r\nCheck the Debug Output for more details.", + "Linux Dependencies Installation Failed", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + + connection.Dispose(); + + return null; + } + // Upload the program binaries. if (await connection.UploadProgramAsync( projectProperties?.Name, @@ -592,4 +628,3 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro } } } - diff --git a/RaspberryDebugger/Properties/AssemblyInfo.cs b/RaspberryDebugger/Properties/AssemblyInfo.cs index 22bdae8..83fc188 100644 --- a/RaspberryDebugger/Properties/AssemblyInfo.cs +++ b/RaspberryDebugger/Properties/AssemblyInfo.cs @@ -45,5 +45,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.2.0.0")] -[assembly: AssemblyFileVersion("3.2.0.0")] +[assembly: AssemblyVersion("3.3.0.0")] +[assembly: AssemblyFileVersion("3.3.0.0")] diff --git a/RaspberryDebugger/RaspberryDebugger.csproj b/RaspberryDebugger/RaspberryDebugger.csproj index 7350d32..e037e24 100644 --- a/RaspberryDebugger/RaspberryDebugger.csproj +++ b/RaspberryDebugger/RaspberryDebugger.csproj @@ -153,21 +153,21 @@ 15.0.6142705 - 17.2.32505.113 + 17.5.33428.366 15.8.243 - + compile; build; native; contentfiles; analyzers; buildtransitive - 17.2.32505.113 + 17.7.37355 - 16.3.36 + 16.3.42 - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -181,16 +181,16 @@ 2.18.2 - 13.0.1 + 13.0.3 2.9.1 - 7.2.3 + 7.2.4 - 2.11.35 + 2.16.36 diff --git a/RaspberryDebugger/source.extension.vsixmanifest b/RaspberryDebugger/source.extension.vsixmanifest index 1763b08..e5c754e 100644 --- a/RaspberryDebugger/source.extension.vsixmanifest +++ b/RaspberryDebugger/source.extension.vsixmanifest @@ -20,6 +20,9 @@ Raspberry Debugger forked from nforgeio/RaspberryDebugger amd64 + + amd64 + From 515b3e8759ca6675a291c205a33bd7b8fdf8e4a2 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Thu, 14 Sep 2023 13:29:53 -0400 Subject: [PATCH 02/37] Allow AttachToProcess debugging. Unclear why this should be disabled. It works as any other situation might. --- RaspberryDebugger/RaspberryDebuggerPackage.cs | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/RaspberryDebugger/RaspberryDebuggerPackage.cs b/RaspberryDebugger/RaspberryDebuggerPackage.cs index 3692565..d136ae5 100644 --- a/RaspberryDebugger/RaspberryDebuggerPackage.cs +++ b/RaspberryDebugger/RaspberryDebuggerPackage.cs @@ -129,7 +129,6 @@ public static void Log(string text) private DTE2 dte; private CommandEvents debugStartCommandEvent; private CommandEvents debugStartWithoutDebuggingCommandEvent; - private CommandEvents debugAttachToProcessCommandEvent; private CommandEvents debugRestartCommandEvent; #pragma warning disable IDE0051 // Remove unused private members private readonly bool debugMode = false; @@ -174,19 +173,16 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke // debugging. debugStartCommandEvent = dte.Events.CommandEvents["{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 0x0127]; debugStartWithoutDebuggingCommandEvent = dte.Events.CommandEvents["{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 0x0170]; - debugAttachToProcessCommandEvent = dte.Events.CommandEvents["{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 0x00d5]; debugRestartCommandEvent = dte.Events.CommandEvents["{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 0x0128]; debugStartCommandEvent.BeforeExecute += DebugStartCommandEvent_BeforeExecute; debugStartWithoutDebuggingCommandEvent.BeforeExecute += DebugStartWithoutDebuggingCommandEvent_BeforeExecute; - debugAttachToProcessCommandEvent.BeforeExecute += AttachToProcessCommandEvent_BeforeExecute; debugRestartCommandEvent.BeforeExecute += DebugRestartCommandEvent_BeforeExecute; // Initialize the new commands. await SettingsCommand.InitializeAsync(this); await DebugStartCommand.InitializeAsync(this); await DebugStartWithoutDebuggingCommand.InitializeAsync(this); - await DebugAttachToProcessCommand.InitializeAsync(this); } /// @@ -304,24 +300,6 @@ private void DebugStartWithoutDebuggingCommandEvent_BeforeExecute(string guid, i ExecuteCommand(DebugStartWithoutDebuggingCommand.CommandSet, DebugStartWithoutDebuggingCommand.CommandId); } - /// - /// Debug.AttachToProcess - /// - private void AttachToProcessCommandEvent_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault) - { - ThreadHelper.ThrowIfNotOnUIThread(); - - var connectionName = GetConnectionName(); - - if (connectionName == null) - { - return; - } - - cancelDefault = true; - ExecuteCommand(DebugAttachToProcessCommand.CommandSet, DebugAttachToProcessCommand.CommandId); - } - /// /// Debug.Restart /// From 31a9aba6254445235b99414bd06dee6a28ab8755 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Thu, 14 Sep 2023 13:33:53 -0400 Subject: [PATCH 03/37] Fix: Searching SolutionItems results in ArgumentNullException Non project file solution items (.props/.json/etc files) will not have a subproject. --- RaspberryDebugger/PackageHelper.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RaspberryDebugger/PackageHelper.cs b/RaspberryDebugger/PackageHelper.cs index 3f5bb72..a21c89d 100644 --- a/RaspberryDebugger/PackageHelper.cs +++ b/RaspberryDebugger/PackageHelper.cs @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // FILE: PackageHelper.cs // CONTRIBUTOR: Jeff Lill // COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. @@ -439,6 +439,8 @@ private static void GetSolutionProjects(List solutionProjects, Solution { foreach (ProjectItem projectItem in project.ProjectItems) { + if ( projectItem.SubProject == null) continue; + GetSolutionProjects(solutionProjects, solution, projectItem.SubProject); } } From 0c5b3d68eb9c972d2ca840eef24eb38992c83f62 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Thu, 14 Sep 2023 15:59:54 -0400 Subject: [PATCH 04/37] Don't use Error List to test for build errors. The Error List has 2 problems. 1) It will contain errors for projects that are not in the dependency chain of the Raspberry Project. (so the launch would fail even though the target project built successfully) 2) It is slow to be updated which can result in reporting an error that's no longer valid after the build completes. Instead, Look at LastBuildInfo to determine if any project failed to build, and if so, redirect to the Error List window (give it focus) and notify. --- RaspberryDebugger/DebugHelper.cs | 48 +++++++++----------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index 5f385fd..d368f10 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // FILE: DebugHelper.cs // CONTRIBUTOR: Jeff Lill // COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. @@ -46,6 +46,7 @@ namespace RaspberryDebugger internal static class DebugHelper { private const string SupportedVersions = ".NET Core 3.1 or .NET 5 + 6"; + /// /// Ensures that the native Windows OpenSSH client is installed, prompting /// the user to install it if necessary. @@ -276,47 +277,24 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, } // Build the project to ensure that there are no compile-time errors. - Log.Info($"Building: {projectProperties?.FullPath}"); - + solution?.SolutionBuild.BuildProject(solution.SolutionBuild.ActiveConfiguration.Name, project?.UniqueName, WaitForBuildToFinish: true); - var errorList = dte?.ToolWindows.ErrorList.ErrorItems; - - var warnings = 0; - var messages = 0; - if (errorList?.Count > 0) + // if any projects failed to build notify and exit + if ( solution.SolutionBuild.LastBuildInfo != 0 ) { - var errors = 0; - for (var i = 1; i <= errorList.Count; i++) - { - var error = errorList.Item(i); - switch (error.ErrorLevel) - { - case vsBuildErrorLevel.vsBuildErrorLevelHigh: - Log.Error($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); - errors++; - break; - case vsBuildErrorLevel.vsBuildErrorLevelMedium: - Log.Warning($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); - warnings++; - break; - default: - Log.Info($"{error.FileName}({error.Line},{error.Column}: {error.Description})"); - messages++; - break; - } - } + // bring ErrorList window to the top of the z order. + dte.Application.ExecuteCommand( "View.ErrorList", " " ); + + Log.Error($"Build failed: See the Build/Output panel for more information"); - if (errors > 0) - { - Log.Error($"Build failed: [{errors}] errors"); - Log.Error("See the Build/Output panel for more information"); - return false; - } + await Task.Yield(); + + return false; } - Log.Info($"Build succeeded{(warnings > 0 ? $", with {warnings} warnigns" : null)}{(messages > 0 ? $", with {messages} messages" : null)}"); + Log.Info($"Build succeeded"); // Publish the project so all required binaries and assets end up // in the output folder. From b07d8e2b01ea77143d56759d2be95b1120458502 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Thu, 14 Sep 2023 16:04:52 -0400 Subject: [PATCH 05/37] Bring the Output Window into focus for Publish errors. Since we add publish errors to the Output Window. Adding to Error List is much more complicated. See: https://github.com/microsoft/VSSDK-Extensibility-Samples/blob/master/ErrorList/Readme.md --- RaspberryDebugger/DebugHelper.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index d368f10..8149385 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -419,6 +419,11 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, return true; } + // bring ErrorList window to the top of the z order. + dte.Application.ExecuteCommand("View.Output", " "); + + await Task.Yield(); + Log.Error($"Publish failed: ExitCode={response.ExitCode}"); Log.WriteLine(response.AllText); From 0fde6bc04749b85cd8f910b34947381517b110d9 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Thu, 14 Sep 2023 16:38:27 -0400 Subject: [PATCH 06/37] Split Build and Publish into different methods. Allows different behavior when errors occur. --- RaspberryDebugger/DebugHelper.cs | 101 +++++++++++++++++++------------ 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index 8149385..c28aa40 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -225,21 +225,47 @@ public static async Task PublishProjectWithUiAsync(DTE2 dte, Solution solu await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (!await BuildProjectAsync(dte, solution, project, projectProperties)) + { + // bring ErrorList window to the top of the z order. + dte.Application.ExecuteCommand("View.ErrorList", " "); + + await Task.Yield(); + + MessageBox.Show( + """ + There were one or more errors building the project. + Please review the Error List. + """, + @"Build Failed", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + + return false; + } + + await Task.Yield(); + if (!await PublishProjectAsync(dte, solution, project, projectProperties)) { + // bring Output window to the top of the z order. + dte.Application.ExecuteCommand("View.Output", " "); + + await Task.Yield(); + MessageBox.Show( - @"[dotnet publish] failed for the project. - Look at the Output/Debug panel for more details.", + """ + There were one or more errors Publishing the project. + Please review the Output Window for more details. + """, @"Publish Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } - else - { - return true; - } + + return true; } /// @@ -251,13 +277,9 @@ public static async Task PublishProjectWithUiAsync(DTE2 dte, Solution solu /// The project. /// The project properties. /// true on success. - private static async Task PublishProjectAsync(DTE2 dte, Solution solution, Project project, ProjectProperties projectProperties) + private static async Task BuildProjectAsync(DTE2 dte, Solution solution, Project project, + ProjectProperties projectProperties) { - Covenant.Requires(dte != null, nameof(dte)); - Covenant.Requires(solution != null, nameof(solution)); - Covenant.Requires(project != null, nameof(project)); - Covenant.Requires(projectProperties != null, nameof(projectProperties)); - // Build the project within the context of VS to ensure that all changed // files are saved and all dependencies are built first. Then we'll // verify that there were no errors before proceeding. @@ -268,7 +290,8 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, // random crashes when building or publishing projects when VS is still loading // projects. - var solutionService4 = (IVsSolution4)await RaspberryDebuggerPackage.Instance.GetServiceAsync(typeof(SVsSolution)); + var solutionService4 = + (IVsSolution4)await RaspberryDebuggerPackage.Instance.GetServiceAsync(typeof(SVsSolution)); if (solutionService4 == null) { @@ -278,24 +301,32 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, // Build the project to ensure that there are no compile-time errors. Log.Info($"Building: {projectProperties?.FullPath}"); - - solution?.SolutionBuild.BuildProject(solution.SolutionBuild.ActiveConfiguration.Name, project?.UniqueName, WaitForBuildToFinish: true); - // if any projects failed to build notify and exit - if ( solution.SolutionBuild.LastBuildInfo != 0 ) - { - // bring ErrorList window to the top of the z order. - dte.Application.ExecuteCommand( "View.ErrorList", " " ); - - Log.Error($"Build failed: See the Build/Output panel for more information"); - - await Task.Yield(); + solution?.SolutionBuild.BuildProject( + solution.SolutionBuild.ActiveConfiguration.Name, project?.UniqueName, WaitForBuildToFinish: true); + // if any projects failed to build + if (solution.SolutionBuild.LastBuildInfo != 0) + { return false; } Log.Info($"Build succeeded"); + return true; + } + + /// + /// Builds and publishes a project locally to prepare it for being uploaded to the Raspberry. This method + /// does not display error message box to the user on failures + /// + /// The DTE. + /// The solution. + /// The project. + /// The project properties. + /// true on success. + private static async Task PublishProjectAsync(DTE2 dte, Solution solution, Project project, ProjectProperties projectProperties) + { // Publish the project so all required binaries and assets end up // in the output folder. // @@ -307,9 +338,7 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, Log.Info($"Publishing: {projectProperties?.FullPath}"); - await Task.Yield(); - - const string allowedVariableNames = + const string allowedVariableNames = """ ALLUSERSPROFILE APPDATA @@ -351,7 +380,7 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, windir """; - var allowedVariables = new HashSet(StringComparer.InvariantCultureIgnoreCase); + var allowedVariables = new HashSet(StringComparer.InvariantCultureIgnoreCase); var environmentVariables = new Dictionary(); using (var reader = new StringReader(allowedVariableNames)) @@ -375,10 +404,10 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, } } + ExecuteResponse response; + try { - ExecuteResponse response; - if (!string.IsNullOrEmpty(projectProperties?.Framework)) { response = await NeonHelper.ExecuteCaptureAsync( @@ -419,22 +448,16 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, return true; } - // bring ErrorList window to the top of the z order. - dte.Application.ExecuteCommand("View.Output", " "); - - await Task.Yield(); - Log.Error($"Publish failed: ExitCode={response.ExitCode}"); Log.WriteLine(response.AllText); - - return false; } catch (Exception e) { + Log.Error($"Publish failed:"); Log.Error(NeonHelper.ExceptionError(e)); - - return false; } + + return false; } /// From 2a96b5e12dcdbcadaa92241f13c60e37da9b93f1 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Fri, 15 Sep 2023 07:11:03 -0400 Subject: [PATCH 07/37] Fix: Processor will choose the wrong OS Bitness If you dig into the VS bug report you'll see that the OS bit size can't be determined by the processor only. Whether that's a bug in Raspian or not is not for me to argue. --- RaspberryDebugger/Connection/Connection.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index 92fe8f6..5ebc996 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // FILE: Connection.cs // CONTRIBUTOR: Jeff Lill // COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. @@ -334,7 +334,10 @@ await PackageHelper.ExecuteWithProgressAsync( # Get the chip architecture uname -m - + + # Get the kernel bit size + getconf LONG_BIT + # Get the current PATH echo $PATH @@ -404,6 +407,7 @@ chmod 755 /lib/dotnet using (var reader = new StringReader(response.OutputText)) { var processor = await reader.ReadLineAsync(); + var kernelBit = await reader.ReadLineAsync(); var path = await reader.ReadLineAsync(); var hasUnzip = await reader.ReadLineAsync() == "unzip"; var hasLsof = await reader.ReadLineAsync() == "lsof"; @@ -415,6 +419,7 @@ chmod 755 /lib/dotnet revision = revision.Trim(); // Remove any whitespace at the end. Log($"[{Name}]: processor: {processor}"); + Log($"[{Name}]: kernelBit: {kernelBit}"); Log($"[{Name}]: path: {path}"); Log($"[{Name}]: unzip: {hasUnzip}"); Log($"[{Name}]: lsof: {hasLsof}"); @@ -432,7 +437,9 @@ chmod 755 /lib/dotnet if (OperatingSystem.Bitness64.Any(bitness => processor.Contains(bitness))) { - osBitness = SdkArchitecture.Arm64; + // A 64bit arm arch running a 32 bit OS. + // https://developercommunity.visualstudio.com/t/VS2022-remote-debugging-over-SSH-does-no/10394545 + osBitness = kernelBit == "32" ? SdkArchitecture.Arm32 : SdkArchitecture.Arm64; } // Convert the comma separated SDK names into a [PiSdk] list. From c2c3ef33d69f6dd47a748e4bb2d6c6bb882c2de3 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Fri, 15 Sep 2023 07:19:51 -0400 Subject: [PATCH 08/37] Extract the project property and use with publish. For the time being assume the default is "linux-arm64". This could be inferred from the the Pi Status.Architecture property but some program flow will need adjustments. Could also put it in the ProjectSettings. --- .../Models/VisualStudio/ProjectProperties.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs index 13a3149..5cf734e 100644 --- a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs +++ b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs @@ -71,6 +71,7 @@ public static ProjectProperties CopyFrom(Solution solution, EnvDTE.Project proje OutputFolder = null, OutputFileName = null, IsExecutable = false, + Runtime = string.Empty, AssemblyName = null, DebugEnabled = false, DebugConnectionName = null, @@ -278,6 +279,13 @@ string SetLaunchUrl(JObject profileObject) outputType == 1 && // 1=EXE isSupportedSdkVersion; + var platformTarget = (string)project.ConfigurationManager.ActiveConfiguration.Properties + .Item( "PlatformTarget" ).Value; + + // For the time being make linux-arm64 the default. + //var runtime = string.IsNullOrEmpty( platformTarget ) ? platformTarget : $"linux-{platformTarget}"; + var runtime = string.IsNullOrEmpty(platformTarget) ? "linux-arm64" : $"linux-{platformTarget}"; + // We need to jump through some hoops to obtain the project GUID. var solutionService = RaspberryDebuggerPackage.Instance.SolutionService; @@ -296,6 +304,7 @@ string SetLaunchUrl(JObject profileObject) OutputFolder = Path.Combine(projectFolder, project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString()), OutputFileName = (string)project.Properties.Item("OutputFileName").Value, IsExecutable = outputType == 1, // 1=EXE + Runtime = runtime, AssemblyName = project.Properties.Item("AssemblyName").Value.ToString(), DebugEnabled = debugEnabled, DebugConnectionName = debugConnectionName, @@ -484,7 +493,7 @@ private static List ParseArgs(string commandLine) /// /// Returns the publish runtime. /// - public string Runtime => "linux-arm"; + public string Runtime { get; set; } /// /// Returns the framework version. From 996a6397f3d6edd6da604d5b805e5b370c2e7c09 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Fri, 15 Sep 2023 11:27:35 -0400 Subject: [PATCH 09/37] Use VS paradigm for placing the debugger in the users home dir. VS's Attach to Process command installs and uses the debugger in the user's context. Mimic that here. But it's never updated (Future?). --- RaspberryDebugger/Connection/Connection.cs | 32 +++++++++++-------- RaspberryDebugger/DebugHelper.cs | 3 ++ RaspberryDebugger/PackageHelper.cs | 5 ++- RaspberryDebugger/RaspberryDebuggerPackage.cs | 10 ++++++ 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index 5ebc996..927e116 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -309,6 +309,10 @@ await PackageHelper.ExecuteWithProgressAsync( // We're going to execute a script the gathers everything in a single operation for speed. Log($"[{Name}]: Retrieving status"); + // VS tries to update/install the debugger on every Attach to Process command. + // This conversion to user path would go away if the extension always tried the install. + var userDebugFolder = PackageHelper.RemoteDebuggerFolder.Replace( "~", LinuxPath.Combine("/", "home", Username) ); + var statusScript = $""" # This script will return the status information via STDOUT line-by-line @@ -329,8 +333,8 @@ await PackageHelper.ExecuteWithProgressAsync( # Set the SDK and debugger installation paths. - DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} - DEBUGFOLDER={PackageHelper.RemoteDebuggerFolder} + DOTNET_ROOT="{PackageHelper.RemoteDotnetFolder}" + DEBUGFOLDER="{userDebugFolder}" # Get the chip architecture uname -m @@ -356,7 +360,7 @@ getconf LONG_BIT fi # Detect whether the [vsdbg] debugger is installed. - if [ -d $DEBUGFOLDER ] ; then + if [ -d "$DEBUGFOLDER" ] ; then echo 'debugger-installed' else echo 'debugger-missing' @@ -366,8 +370,8 @@ getconf LONG_BIT # corresponding SDK name. We'll list the files on one line # with the SDK names separated by commas. We'll return a blank # line if the SDK directory doesn't exist. - if [ -d $DOTNET_ROOT/sdk ] ; then - ls -m $DOTNET_ROOT/sdk + if [ -d "$DOTNET_ROOT"/sdk ] ; then + ls -m "$DOTNET_ROOT"/sdk else echo '' fi @@ -767,18 +771,18 @@ public async Task SetupDebuggerAsync() return await PackageHelper.ExecuteWithProgressAsync("Installing [vsdbg] debugger...", async () => { - var installScript = - $""" - if ! curl -sSL https://aka.ms/getvsdbgsh | /bin/sh /dev/stdin -v latest -l {PackageHelper.RemoteDebuggerFolder} ; then - exit 1 - fi - - exit 0 - """; + // Use VS paradigm for placing the debugger in the users home dir. + // see: https://developercommunity.visualstudio.com/t/VS2022-remote-debugging-over-SSH-does-no/10394545#T-N10410651 + // This structure is used when Debug->Attach to Process is used. Unfortunately it's tied to + // the VS version. + // Currently the VSIX is only targeted to VS2022 so keep the version selector fixed. + // TODO: Use RaspberryDebuggerPackage.VisualStudioVersion for DIR. + var installCommand = + $"""curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v vs2022 -l {PackageHelper.RemoteDebuggerFolder}"""; try { - var response = SudoCommand(CommandBundle.FromScript(installScript)); + var response = SudoCommandAsUser(Username, installCommand); if (response.ExitCode == 0) { diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index c28aa40..809520d 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -581,6 +581,9 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro } // Ensure that the debugger is installed. + // TODO: Visual Studio tries to update/install the package each time it attaches. + // Maybe only try the update/install once per session/device? Lots of permutations to track tho. + // Would need to quietly fail if no internet connection. if (!await connection.SetupDebuggerAsync()) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); diff --git a/RaspberryDebugger/PackageHelper.cs b/RaspberryDebugger/PackageHelper.cs index a21c89d..9b85983 100644 --- a/RaspberryDebugger/PackageHelper.cs +++ b/RaspberryDebugger/PackageHelper.cs @@ -81,8 +81,10 @@ internal static class PackageHelper /// /// Directory on the Raspberry Pi where the vsdbg remote debugger will be installed. + /// Currently the VSIX is only targeted to VS2022 so keep the version selector fixed. + /// TODO: Use RaspberryDebuggerPackage.VisualStudioVersion for DIR.. /// - public const string RemoteDebuggerFolder = RemoteDotnetFolder + "/vsdbg"; + public const string RemoteDebuggerFolder = "~/.vs-debugger/vs2022"; /// /// Path to the vsdbg program on the remote machine. @@ -409,6 +411,7 @@ private static Project FindInSubProjects(Project parentProject, string projectNa foreach (ProjectItem projectItem in parentProject.ProjectItems) { if (projectItem.SubProject == null) continue; + project = FindInSubProjects(projectItem.SubProject, projectName); if (project != null) diff --git a/RaspberryDebugger/RaspberryDebuggerPackage.cs b/RaspberryDebugger/RaspberryDebuggerPackage.cs index d136ae5..f362e4d 100644 --- a/RaspberryDebugger/RaspberryDebuggerPackage.cs +++ b/RaspberryDebugger/RaspberryDebuggerPackage.cs @@ -16,6 +16,7 @@ // limitations under the License. using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; using System.Threading; @@ -74,6 +75,11 @@ internal sealed class RaspberryDebuggerPackage : AsyncPackage /// public static RaspberryDebuggerPackage Instance { get; private set; } + /// + /// Current VS version. + /// + public static Version VisualStudioVersion { get; private set; } + /// /// Logs text to the Visual Studio Debug output panel. /// @@ -167,6 +173,10 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke debugWindow?.GetPane(ref generalPaneGuid, out _debugPane); + // VS version + var devenvInfo = FileVersionInfo.GetVersionInfo(dte.FullName); + VisualStudioVersion = new Version(devenvInfo.ProductVersion); + // Intercept the debugger commands and quickly decide whether the startup project is enabled // for Raspberry remote debugging so we can invoke our custom commands instead. We'll just // let the default command implementations do their thing when we're not doing Raspberry From 03a9dcbc0d96d94b3339d0a7241816593087c7de Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Fri, 15 Sep 2023 15:02:18 -0400 Subject: [PATCH 10/37] Don't download the program unless the project dll has changed. Building will not change the project output unless required by edit or dependency change. Record the previously uploaded file info and use that to trigger another upload if needed. --- RaspberryDebugger/Connection/Connection.cs | 71 ++++++++++--------- RaspberryDebugger/DebugHelper.cs | 36 ++++++++-- .../Models/VisualStudio/ProjectProperties.cs | 2 +- 3 files changed, 69 insertions(+), 40 deletions(-) diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index 927e116..0a7c4fe 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -870,24 +870,27 @@ public async Task UploadProgramAsync(string programName, string assemblyNa // We're going to ZIP the program files locally and then transfer the zipped // files to the Raspberry to be expanded there. + return await PackageHelper.ExecuteWithProgressAsync( + $"Uploading program {programName}...", + async () => + { + var debugFolder = LinuxPath.Combine(PackageHelper.RemoteDebugBinaryRoot(Username), programName); + var groupScript = string.Empty; - var debugFolder = LinuxPath.Combine(PackageHelper.RemoteDebugBinaryRoot(Username), programName); - var groupScript = string.Empty; - - if (!string.IsNullOrEmpty(projectSettings.TargetGroup)) - { - groupScript = - $@" + if (!string.IsNullOrEmpty(projectSettings.TargetGroup)) + { + groupScript = + $@" # Add the program assembly to the user specified target group (if any). # This defaults to [gpio] so users will be able to access the GPIO pins. if ! chgrp {projectSettings.TargetGroup} {debugFolder}/{assemblyName} ; then exit 1 fi "; - } + } - var uploadScript = - $@" + var uploadScript = + $@" # Ensure that the debug folder exists. if ! mkdir -p {debugFolder} ; then exit 1 @@ -911,33 +914,35 @@ exit 1 exit 0 "; - // I'm not going to do a progress dialog because this should be fast. - try - { - LogInfo($"Uploading program to: [{debugFolder}]"); + // I'm not going to do a progress dialog because this should be fast. + try + { + LogInfo($"Uploading program to: [{debugFolder}]"); - var bundle = new CommandBundle(uploadScript); + var bundle = new CommandBundle(uploadScript); - bundle.AddZip("program.zip", publishedBinaryFolder); + bundle.AddZip("program.zip", publishedBinaryFolder); - var response = RunCommand(bundle); + var response = RunCommand(bundle); - if (response.ExitCode == 0) - { - LogInfo("Program uploaded"); - return await Task.FromResult(true); - } - else - { - LogError(response.AllText); - return await Task.FromResult(false); - } - } - catch (Exception e) - { - LogException(e); - return await Task.FromResult(false); - } + if (response.ExitCode == 0) + { + LogInfo("Program uploaded"); + return await Task.FromResult(true); + } + else + { + LogError(response.AllText); + return await Task.FromResult(false); + } + } + catch (Exception e) + { + LogException(e); + return await Task.FromResult(false); + } + + }); } } } diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index 809520d..e819f18 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -30,7 +30,6 @@ using Neon.Common; using Neon.Windows; -using RaspberryDebugger.Connection; using RaspberryDebugger.Dialogs; using RaspberryDebugger.Models.Connection; using RaspberryDebugger.Models.Project; @@ -47,6 +46,11 @@ internal static class DebugHelper { private const string SupportedVersions = ".NET Core 3.1 or .NET 5 + 6"; + /// + /// Track the last output file that was uploaded. + /// + private static FileInfo LastUploadedFileInfo { get; set; } + /// /// Ensures that the native Windows OpenSSH client is installed, prompting /// the user to install it if necessary. @@ -300,7 +304,7 @@ private static async Task BuildProjectAsync(DTE2 dte, Solution solution, P } // Build the project to ensure that there are no compile-time errors. - Log.Info($"Building: {projectProperties?.FullPath}"); + Log.Info($"Build Started: {projectProperties?.FullPath}, Configuration: {projectProperties.Configuration}"); solution?.SolutionBuild.BuildProject( solution.SolutionBuild.ActiveConfiguration.Name, project?.UniqueName, WaitForBuildToFinish: true); @@ -336,7 +340,7 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, // these can cause conflicts when we invoke [dotnet] below to // publish the project. - Log.Info($"Publishing: {projectProperties?.FullPath}"); + Log.Info($"Publishing Started: {projectProperties?.FullPath}, Runtime: {projectProperties.Runtime}"); const string allowedVariableNames = """ @@ -444,7 +448,7 @@ private static async Task PublishProjectAsync(DTE2 dte, Solution solution, if (response.ExitCode == 0) { - Log.Info("Publish succeeded"); + Log.Info("Publish Succeeded"); return true; } @@ -615,13 +619,33 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro return null; } + var fileInfo = new FileInfo( + Path.Combine(projectProperties.OutputFolder, projectProperties.OutputFileName)); + + bool shouldUploadProgram = + LastUploadedFileInfo == null || + LastUploadedFileInfo.FullName != fileInfo.FullName || + LastUploadedFileInfo.LastWriteTime != fileInfo.LastWriteTime; + + if (!shouldUploadProgram) + { + Log.Info($"Skipping upload of {fileInfo.FullName}, {fileInfo.LastWriteTime}"); + + return connection; + } + + Log.Info($"Uploading {fileInfo.FullName}, {fileInfo.LastWriteTime}"); + // Upload the program binaries. if (await connection.UploadProgramAsync( - projectProperties?.Name, + projectProperties?.Name, projectProperties?.AssemblyName, - projectProperties?.PublishFolder)) + projectProperties?.PublishFolder)) + { + LastUploadedFileInfo = fileInfo; return connection; + } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); diff --git a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs index 5cf734e..30dc4a9 100644 --- a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs +++ b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs @@ -513,7 +513,7 @@ private static List ParseArgs(string commandLine) /// /// Returns the name of the output binary file. /// - private string OutputFileName { get; set; } + public string OutputFileName { get; private set; } /// /// Indicates whether Raspberry debugging is enabled for this project. From cb055a3aec0b6c14fbf3a170f267fdb82f089b7d Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Fri, 15 Sep 2023 15:06:04 -0400 Subject: [PATCH 11/37] Create a Raspberry Debugger specific Output Window Pane Writing log information to the Debug pane is lost as soon as the debugger launches because VS clears that pane. Create a specific pane for the extension so that the log is retained until the next command. --- .../Commands/DebugStartCommand.cs | 2 ++ RaspberryDebugger/Log.cs | 28 +++++++++++-------- RaspberryDebugger/PackageHelper.cs | 7 +---- RaspberryDebugger/RaspberryDebuggerPackage.cs | 18 ++++++++---- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/RaspberryDebugger/Commands/DebugStartCommand.cs b/RaspberryDebugger/Commands/DebugStartCommand.cs index ae71e63..d3196c8 100644 --- a/RaspberryDebugger/Commands/DebugStartCommand.cs +++ b/RaspberryDebugger/Commands/DebugStartCommand.cs @@ -108,6 +108,8 @@ private async void Execute(object sender, EventArgs e) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + Log.Clear(); + if (!await DebugHelper.EnsureOpenSshAsync()) { return; diff --git a/RaspberryDebugger/Log.cs b/RaspberryDebugger/Log.cs index 155853e..84f1999 100644 --- a/RaspberryDebugger/Log.cs +++ b/RaspberryDebugger/Log.cs @@ -16,7 +16,6 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; - using Task = System.Threading.Tasks.Task; namespace RaspberryDebugger @@ -27,6 +26,14 @@ namespace RaspberryDebugger /// internal static class Log { + /// + /// Clear the debug pane + /// + public static void Clear() + { + RaspberryDebuggerPackage.LogClear(); + } + /// /// Writes text to the debug pane. /// @@ -42,7 +49,7 @@ public static void Write(string text) /// Optionally specifies the log text. public static void WriteLine(string text = "") { - RaspberryDebuggerPackage.Log(text + "\n"); + RaspberryDebuggerPackage.Log(text + Environment.NewLine); } /// @@ -51,7 +58,7 @@ public static void WriteLine(string text = "") /// The information text. public static void Info(string text) { - WriteLine($"[{PackageHelper.LogName}]: INFO: {text}"); + WriteLine($"INFO: {text}"); } /// @@ -60,7 +67,7 @@ public static void Info(string text) /// The error text. public static void Error(string text) { - WriteLine($"[{PackageHelper.LogName}]: ERROR: {text}"); + WriteLine($"ERROR: {text}"); } /// @@ -69,7 +76,7 @@ public static void Error(string text) /// The error text. public static void Warning(string text) { - WriteLine($"[{PackageHelper.LogName}]: WARNING: {text}"); + WriteLine($"[WARNING: {text}"); } /// @@ -87,21 +94,18 @@ public static void Exception(Exception e, string message = null) // We're going to build a multi-line message to reduce pressure // on the task/threading in [RaspberryDebugPackage.Log()]. - var sb = new StringBuilder(); - - sb.Append("\n"); + var sb = new StringBuilder().AppendLine(); if (string.IsNullOrEmpty(message)) { - sb.Append($"EXCEPTION: {e.GetType().FullName}: {e.Message}\n"); + sb.AppendLine($"EXCEPTION: {e.GetType().FullName}: {e.Message}"); } else { - sb.Append($"EXCEPTION: {e.GetType().FullName}: {message} {e.Message}\n"); + sb.AppendLine($"EXCEPTION: {e.GetType().FullName}: {message} {e.Message}"); } - sb.Append(e.StackTrace); - sb.Append("\n"); + sb.AppendLine(e.StackTrace); RaspberryDebuggerPackage.Log(sb.ToString()); } diff --git a/RaspberryDebugger/PackageHelper.cs b/RaspberryDebugger/PackageHelper.cs index 9b85983..26e5a52 100644 --- a/RaspberryDebugger/PackageHelper.cs +++ b/RaspberryDebugger/PackageHelper.cs @@ -63,11 +63,6 @@ internal static class PackageHelper /// private static readonly string ConnectionsPath; - /// - /// The name used to prefix logged output and status bar text. - /// - public const string LogName = "raspberry"; - /// /// Directory on the Raspberry Pi where .NET Core SDKs will be installed along with the /// vsdbg remote debugger. @@ -689,7 +684,7 @@ public static async Task ExecuteWithProgressAsync(string descr szWaitMessage: description, szProgressText: null, varStatusBmpAnim: null, - szStatusBarText: $"[{LogName}]{description}", + szStatusBarText: $"[Raspberry Debugger]{description}", iDelayToShowDialog: 0, fIsCancelable: false, fShowMarqueeProgress: true); diff --git a/RaspberryDebugger/RaspberryDebuggerPackage.cs b/RaspberryDebugger/RaspberryDebuggerPackage.cs index f362e4d..3088222 100644 --- a/RaspberryDebugger/RaspberryDebuggerPackage.cs +++ b/RaspberryDebugger/RaspberryDebuggerPackage.cs @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // FILE: RaspberryDebuggerPackage.cs // CONTRIBUTOR: Jeff Lill // COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. @@ -23,7 +23,6 @@ using EnvDTE; using EnvDTE80; -using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Shell.Interop; using RaspberryDebugger.Commands; @@ -129,6 +128,16 @@ public static void Log(string text) }); } + /// + /// Clear the log output pane + /// + public static void LogClear() + { + if (Instance == null || _debugPane == null) return; // Logging hasn't been initialized yet. + + _debugPane.Clear(); + } + //--------------------------------------------------------------------- // Instance members @@ -168,10 +177,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke } // Initialize the log panel. - var debugWindow = Package.GetGlobalService(typeof(SVsOutputWindow)) as IVsOutputWindow; - var generalPaneGuid = VSConstants.GUID_OutWindowDebugPane; - - debugWindow?.GetPane(ref generalPaneGuid, out _debugPane); + _debugPane = GetOutputPane( Guid.NewGuid(), "Raspberry Debugger" ); // VS version var devenvInfo = FileVersionInfo.GetVersionInfo(dte.FullName); From 73b7aefb96cca2ac29cd2f6f4c52ebc097534c01 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Wed, 20 Sep 2023 14:20:32 -0400 Subject: [PATCH 12/37] Allow the system to install/manage multiple dotnet SDKs. Use the project's required SDK and the PiStatus to determine if the needed SDK is installed. If not, then add. --- RaspberryDebugger/Connection/Connection.cs | 64 +++++++------------ RaspberryDebugger/Connection/Sdk.cs | 51 --------------- RaspberryDebugger/Connection/Status.cs | 4 +- RaspberryDebugger/DebugHelper.cs | 2 +- .../Models/VisualStudio/ProjectProperties.cs | 4 +- RaspberryDebugger/RaspberryDebugger.csproj | 1 - 6 files changed, 28 insertions(+), 98 deletions(-) delete mode 100644 RaspberryDebugger/Connection/Sdk.cs diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index 0a7c4fe..55a46bf 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -447,7 +447,7 @@ chmod 755 /lib/dotnet } // Convert the comma separated SDK names into a [PiSdk] list. - var sdks = new List(); + var sdks = new List(); foreach (var sdkName in sdkLine .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) @@ -458,7 +458,7 @@ chmod 755 /lib/dotnet if (sdkCatalogItem != null) { - sdks.Add(new Sdk(sdkName, osBitness)); + sdks.Add(sdkCatalogItem); } else { @@ -560,14 +560,29 @@ exit 0 /// Download and install actual (latest) SDK /// /// true if successful - public async Task SetupSdkAsync() + public async Task SetupSdkAsync(string projectSdkVersion) { - if (IsSdkPresent()) return true; + var sdkRequiredByProject = + PackageHelper.SdkCatalog.Items + .OrderByDescending(item => item.Name) + .FirstOrDefault( + sdk => sdk.Name == projectSdkVersion && sdk.Architecture == PiStatus.Architecture ); - var targetSdk = ReadActualSdkCatalogItem(); - return await DownloadSdkAsync(targetSdk) && - await InstallSdkAsync(targetSdk); + if ( sdkRequiredByProject == null ) + { + // project requires something not available... + return false; + } + + if ( this.PiStatus.InstalledSdks.Any( sdk => sdk.Name == projectSdkVersion ) ) + { + // project sdk is already installed. + return true; + } + + return await DownloadSdkAsync(sdkRequiredByProject) && + await InstallSdkAsync(sdkRequiredByProject); } /// @@ -705,7 +720,7 @@ exit 0 if (response.ExitCode == 0) { // Add the newly installed SDK to the list of installed SDKs. - PiStatus.InstalledSdks.Add(new Sdk(targetSdk.Name, targetSdk.Architecture)); + PiStatus.InstalledSdks.Add(targetSdk); return await Task.FromResult(true); } else @@ -722,39 +737,6 @@ exit 0 }); } - /// - /// Is any .NET Core SDK installed on the Raspberry Pi. - /// The Raspberry architecture is driving the installation - the newest .NET Core version is taken - /// - /// true on success. - private bool IsSdkPresent() - { - var sdkOnPi = PiStatus.InstalledSdks - .OrderByDescending(name => name.Name) - .FirstOrDefault(); - - var sdkOnPiVersion = sdkOnPi?.Name ?? string.Empty; - var sdkOnPiArchitecture = sdkOnPi?.Architecture ?? PiStatus.Architecture; - - return PiStatus.InstalledSdks.Any(sdk => sdk.Name == sdkOnPiVersion && - sdk.Architecture == sdkOnPiArchitecture); - } - - /// - /// Read actual (latest) SDK from catalog - /// - /// Latest target SDK - private SdkCatalogItem ReadActualSdkCatalogItem() - { - // Locate the standalone SDK for the request .NET version. - // Figure out the latest SDK version - Microsoft versioning: the highest number - var targetSdk = PackageHelper.SdkCatalog.Items - .OrderByDescending(item => item.Name) - .FirstOrDefault(item => item.Architecture == PiStatus.Architecture); - - return targetSdk; - } - /// /// Installs the vsdbg debugger on the Raspberry if it's not already installed. /// diff --git a/RaspberryDebugger/Connection/Sdk.cs b/RaspberryDebugger/Connection/Sdk.cs deleted file mode 100644 index fd2aba5..0000000 --- a/RaspberryDebugger/Connection/Sdk.cs +++ /dev/null @@ -1,51 +0,0 @@ -//----------------------------------------------------------------------------- -// FILE: Sdk.cs -// CONTRIBUTOR: Jeff Lill -// COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -using System; -using System.Diagnostics.Contracts; -using RaspberryDebugger.Models.Sdk; - -namespace RaspberryDebugger.Connection -{ - /// - /// Holds information about a .NET Core SDK installed on a Raspberry Pi. - /// - internal class Sdk - { - /// - /// Constructor. - /// - /// The SDK name. - /// The SDK bitness architecture. - public Sdk(string name, SdkArchitecture architecture = SdkArchitecture.Arm32) - { - Covenant.Requires(!string.IsNullOrEmpty(name), nameof(name)); - - this.Name = name; - this.Architecture = architecture; - } - - /// - /// Returns the name of the SDK (like 3.1.402). - /// - public string Name { get; } - - /// - /// The raspberry pi architecture - /// - public SdkArchitecture Architecture { get; } - } -} diff --git a/RaspberryDebugger/Connection/Status.cs b/RaspberryDebugger/Connection/Status.cs index 4e35a4f..656ae57 100644 --- a/RaspberryDebugger/Connection/Status.cs +++ b/RaspberryDebugger/Connection/Status.cs @@ -46,7 +46,7 @@ public Status( bool hasUnzip, bool hasLsof, bool hasDebugger, - IEnumerable installedSdks, + IEnumerable installedSdks, string model, string revision, SdkArchitecture architecture) @@ -95,7 +95,7 @@ public Status( /// /// Returns information about the .NET Core SDKs installed. /// - public List InstalledSdks { get; } + public List InstalledSdks { get; } /// /// Returns the Raspberry board model. diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index e819f18..1289245 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -569,7 +569,7 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro } // Ensure that the SDK is installed. - if (!await connection.SetupSdkAsync()) + if (!await connection.SetupSdkAsync(projectProperties.SdkVersion)) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); diff --git a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs index 30dc4a9..5c60573 100644 --- a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs +++ b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs @@ -100,7 +100,7 @@ public static ProjectProperties CopyFrom(Solution solution, EnvDTE.Project proje var versionRegex = new Regex(@"(?[0-9\.]+)$"); var netVersion = SemanticVersion.Parse(versionRegex.Match(monikers[1]).Groups["version"].Value); - var targetSdk = (RaspberryDebugger.Connection.Sdk)null; + var targetSdk = (RaspberryDebugger.Models.Sdk.SdkCatalogItem)null; var targetSdkVersion = (SemanticVersion)null; foreach (var sdkItem in PackageHelper.SdkCatalog.Items) @@ -116,7 +116,7 @@ public static ProjectProperties CopyFrom(Solution solution, EnvDTE.Project proje continue; targetSdkVersion = sdkVersion; - targetSdk = new RaspberryDebugger.Connection.Sdk(sdkItem.Name, sdkItem.Architecture); + targetSdk = sdkItem; } var sdkName = targetSdk?.Name; diff --git a/RaspberryDebugger/RaspberryDebugger.csproj b/RaspberryDebugger/RaspberryDebugger.csproj index e037e24..82a904f 100644 --- a/RaspberryDebugger/RaspberryDebugger.csproj +++ b/RaspberryDebugger/RaspberryDebugger.csproj @@ -67,7 +67,6 @@ - Form From 08229aff3b9c2245c69c230bd1dbbfebb89c6bd6 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Thu, 21 Sep 2023 08:21:21 -0400 Subject: [PATCH 13/37] Fix: Track output directory to determine upload behavior Suspicion confirmed, output file isn't enough, but it appears that tracking the directory might work. --- RaspberryDebugger/DebugHelper.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index 1289245..3f85dac 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -49,7 +49,7 @@ internal static class DebugHelper /// /// Track the last output file that was uploaded. /// - private static FileInfo LastUploadedFileInfo { get; set; } + private static DirectoryInfo LastUploadedDirInfo { get; set; } /// /// Ensures that the native Windows OpenSSH client is installed, prompting @@ -619,22 +619,23 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro return null; } - var fileInfo = new FileInfo( - Path.Combine(projectProperties.OutputFolder, projectProperties.OutputFileName)); + var dirInfo = new DirectoryInfo(projectProperties.OutputFolder); bool shouldUploadProgram = - LastUploadedFileInfo == null || - LastUploadedFileInfo.FullName != fileInfo.FullName || - LastUploadedFileInfo.LastWriteTime != fileInfo.LastWriteTime; + LastUploadedDirInfo == null || + LastUploadedDirInfo.FullName != dirInfo.FullName || + LastUploadedDirInfo.LastWriteTime != dirInfo.LastWriteTime; + var outputFileName = Path.Combine( projectProperties.OutputFolder, projectProperties.OutputFileName ); + if (!shouldUploadProgram) { - Log.Info($"Skipping upload of {fileInfo.FullName}, {fileInfo.LastWriteTime}"); + Log.Info($"Skipping upload of {outputFileName}, {dirInfo.LastWriteTime}"); return connection; } - Log.Info($"Uploading {fileInfo.FullName}, {fileInfo.LastWriteTime}"); + Log.Info($"Uploading {outputFileName}, {dirInfo.LastWriteTime}"); // Upload the program binaries. if (await connection.UploadProgramAsync( @@ -642,7 +643,7 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro projectProperties?.AssemblyName, projectProperties?.PublishFolder)) { - LastUploadedFileInfo = fileInfo; + LastUploadedDirInfo = dirInfo; return connection; } From 03998254b4191f4fb298ba4efff58c0bc7ece2ed Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Mon, 2 Oct 2023 09:16:59 -0400 Subject: [PATCH 14/37] Use MS install scripts to install the .NET SDKs Use the Microsoft based install scripts to install the needed SDK. This removes the need for the SDK catalog updates. As is used now this will cause the most up to date .NET SDK to be installed. TODO: Call this script at least once per session so that the SDK can be updated, Or, possibly track to the Project's global.json file to make sure the required is installed. --- RaspberryDebugger/Connection/Connection.cs | 152 +-- RaspberryDebugger/Connection/Status.cs | 4 +- RaspberryDebugger/DebugHelper.cs | 8 +- RaspberryDebugger/Models/Sdk/SdkCatalog.cs | 33 - .../Models/Sdk/SdkCatalogItem.cs | 73 -- .../Models/VisualStudio/ProjectProperties.cs | 34 +- RaspberryDebugger/PackageHelper.cs | 85 -- RaspberryDebugger/RaspberryDebugger.csproj | 3 - RaspberryDebugger/sdk-catalog.json | 1124 ----------------- 9 files changed, 58 insertions(+), 1458 deletions(-) delete mode 100644 RaspberryDebugger/Models/Sdk/SdkCatalog.cs delete mode 100644 RaspberryDebugger/Models/Sdk/SdkCatalogItem.cs delete mode 100644 RaspberryDebugger/sdk-catalog.json diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index 55a46bf..f1cda79 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -447,24 +447,10 @@ chmod 755 /lib/dotnet } // Convert the comma separated SDK names into a [PiSdk] list. - var sdks = new List(); - - foreach (var sdkName in sdkLine - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .Select(sdk => sdk.Trim())) - { - var sdkCatalogItem = PackageHelper.SdkCatalog.Items - .SingleOrDefault(item => item.Link.Contains(sdkName) && item.Architecture == osBitness); - - if (sdkCatalogItem != null) - { - sdks.Add(sdkCatalogItem); - } - else - { - LogWarning($".NET SDK [{sdkName}] is present on [{Name}] but is not known to the RaspberryDebugger extension. Consider updating the extension."); - } - } + var sdks = sdkLine + .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(sdk => new Version(sdk.Trim())) + .ToList(); PiStatus = new Status( processor: processor, @@ -560,29 +546,27 @@ exit 0 /// Download and install actual (latest) SDK /// /// true if successful - public async Task SetupSdkAsync(string projectSdkVersion) + public async Task SetupSdkAsync(Version projectSdkVersion) { - var sdkRequiredByProject = - PackageHelper.SdkCatalog.Items - .OrderByDescending(item => item.Name) - .FirstOrDefault( - sdk => sdk.Name == projectSdkVersion && sdk.Architecture == PiStatus.Architecture ); - - - if ( sdkRequiredByProject == null ) + // .NET 3.1, 6 and 7 are supported. When 8 arrives this should work. + if (projectSdkVersion.Major != 3 && + projectSdkVersion.Major < 6 ) { // project requires something not available... return false; } - if ( this.PiStatus.InstalledSdks.Any( sdk => sdk.Name == projectSdkVersion ) ) + if ( this.PiStatus.InstalledSdks.Any( sdk => sdk.Major == projectSdkVersion.Major && + sdk.Minor == projectSdkVersion.Minor) ) { // project sdk is already installed. return true; } - return await DownloadSdkAsync(sdkRequiredByProject) && - await InstallSdkAsync(sdkRequiredByProject); + LogInfo($"The project requires .NET SDK {projectSdkVersion} which is not installed."); + + return await this.InstallSdkPrerequsitesAsync() && + await InstallSdkAsync(projectSdkVersion); } /// @@ -590,29 +574,14 @@ public async Task SetupSdkAsync(string projectSdkVersion) /// The Raspberry architecture is driving the installation - the newest .NET Core version is taken /// /// true on success. - private async Task DownloadSdkAsync(SdkCatalogItem targetSdk) + private async Task InstallSdkPrerequsitesAsync() { - if (targetSdk == null) - { - LogError("RasberryDebug is unaware of .NET Core SDK."); - LogError("Try updating the RasberryDebug extension or report this issue at:"); - LogError("https://github.com/nforgeio/RaspberryDebugger/issues"); - - return await Task.FromResult(false); - } - else - { - LogInfo($".NET Core SDK [v{targetSdk.Release}] is not installed."); - } - // Install the SDK. - LogInfo($"Downlaoding SDK v{targetSdk.Release}"); - - var downloadSdkInfo = - $"Download SDK for .NET v{targetSdk.Release} " + - $"({targetSdk.Architecture.GetAttributeOfType().Value}) on Raspberry..."; + LogInfo($"Ensure that the packages required by .NET are installed"); - return await PackageHelper.ExecuteWithProgressAsync(downloadSdkInfo, + // https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu#dependencies + return await PackageHelper.ExecuteWithProgressAsync( + $"Setup prerequsites for .NET SDK on Raspberry {this.connectionInfo.Host}...", async () => { var downloadScript = @@ -627,17 +596,6 @@ exit 1 exit 1 fi - # Remove any existing SDK download. This might be - # present if a previous installation attempt failed. - if ! rm -f /tmp/dotnet-sdk.tar.gz ; then - exit 1 - fi - - # Download the SDK installation file to a temporary file. - if ! wget --quiet -O /tmp/dotnet-sdk.tar.gz {targetSdk.Link} ; then - exit 1 - fi - exit 0 """; @@ -647,6 +605,7 @@ exit 0 if (response.ExitCode == 0) { + LogInfo(response.AllText); return await Task.FromResult(true); } else @@ -663,64 +622,51 @@ exit 0 }); } + /// + /// Don't care about value, ToString result is important! + /// + enum SdkQuality + { + preview, + + // The final stable releases of the .NET SDK and Runtime. Intended for public use as well as production support. + GA + } + /// /// Installs the .NET Core SDK on the Raspberry if it's not already installed. /// The Raspberry architecture is driving the installation - the newest .NET Core version is taken /// /// true on success. - private async Task InstallSdkAsync(SdkCatalogItem targetSdk) + private async Task InstallSdkAsync(Version targetSdk) { + var sdkQuality = SdkQuality.GA; + // Install the SDK. - LogInfo($"Installing SDK v{targetSdk.Release}"); - - var installSdkInfo = - $"Install SDK for .NET v{targetSdk.Release} " + - $"({targetSdk.Architecture.GetAttributeOfType().Value}) on Raspberry..."; + LogInfo($"Installing .NET SDK {targetSdk}"); - return await PackageHelper.ExecuteWithProgressAsync(installSdkInfo, + // Use the install script to install the latest version of the .NET SDK rather than use the + // PackageHelper.SdkCatalog list which must be updated manually. It doesn't require looking + // up the link to the SDK install package. + // TODO? Should this be run every time to update? + // TODO? Use a JSON file to control updates + // see: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script + var installCommand = + $"""curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel {targetSdk.ToString(2)} --quality {sdkQuality} --install-dir {PackageHelper.RemoteDotnetFolder}"""; + + return await PackageHelper.ExecuteWithProgressAsync( + $"Installing .NET SDK {targetSdk} on Raspberry {this.connectionInfo.Host}...", async () => { - var installScript = - $""" - export DOTNET_ROOT={PackageHelper.RemoteDotnetFolder} - - # Verify the SHA512. - orgDir=$cwd - cd /tmp - - if ! echo '{targetSdk.Sha512} dotnet-sdk.tar.gz' | sha512sum --check - ; then - cd $orgDir - exit 1 - fi - - cd $orgDir - - # Make sure the installation directory exists. - if ! mkdir -p $DOTNET_ROOT ; then - exit 1 - fi - - # Unpack the SDK to the installation directory. - if ! tar -zxf /tmp/dotnet-sdk.tar.gz -C $DOTNET_ROOT --no-same-owner ; then - exit 1 - fi - - # Remove the temporary installation file. - if ! rm /tmp/dotnet-sdk.tar.gz ; then - exit 1 - fi - - exit 0 - """; - try { - var response = SudoCommand(CommandBundle.FromScript(installScript)); + var response = SudoCommand(installCommand); if (response.ExitCode == 0) { // Add the newly installed SDK to the list of installed SDKs. - PiStatus.InstalledSdks.Add(targetSdk); + //PiStatus.InstalledSdks.Add(targetSdk); + LogInfo(response.AllText); return await Task.FromResult(true); } else diff --git a/RaspberryDebugger/Connection/Status.cs b/RaspberryDebugger/Connection/Status.cs index 656ae57..0439bb7 100644 --- a/RaspberryDebugger/Connection/Status.cs +++ b/RaspberryDebugger/Connection/Status.cs @@ -46,7 +46,7 @@ public Status( bool hasUnzip, bool hasLsof, bool hasDebugger, - IEnumerable installedSdks, + IEnumerable installedSdks, string model, string revision, SdkArchitecture architecture) @@ -95,7 +95,7 @@ public Status( /// /// Returns information about the .NET Core SDKs installed. /// - public List InstalledSdks { get; } + public List InstalledSdks { get; } /// /// Returns the Raspberry board model. diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index 3f85dac..2af7ceb 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -172,7 +172,7 @@ public static Project GetTargetProject(DTE2 dte) return null; } - if (string.IsNullOrEmpty(projectProperties.SdkVersion)) + if ( projectProperties.SdkVersion == null ) { MessageBox.Show( @"The .NET Core SDK version could not be identified.", @@ -183,12 +183,10 @@ public static Project GetTargetProject(DTE2 dte) return null; } - var sdkVersion = Version.Parse(projectProperties.SdkVersion); - if (!projectProperties.IsSupportedSdkVersion) { MessageBox.Show( - $@"The .NET Core SDK [{sdkVersion}] is not currently supported. Only .NET Core versions [v3.1] or later will ever be supported + $@"The .NET Core SDK [{projectProperties.SdkVersion}] is not currently supported. Only .NET Core versions [v3.1] or later will ever be supported Note that we currently support only official SDKs (not previews or release candidates) and we check for new .NET Core SDKs every week or two. Submit an issue if you really need support for a new SDK ASAP: https://github.com/nforgeio/RaspberryDebugger/issues", @@ -574,7 +572,7 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); MessageBoxEx.Show( - $"Cannot install the .NET SDK [v{connection.PiStatus}] on the Raspberry.\r\n\r\nCheck the Debug Output for more details.", + $"Installation of the .NET SDK {projectProperties.SdkVersion} on the Raspberry was unsuccessful.\r\n\r\nCheck the Debug Output for more details.", "SDK Installation Failed", MessageBoxButtons.OK, MessageBoxIcon.Error); diff --git a/RaspberryDebugger/Models/Sdk/SdkCatalog.cs b/RaspberryDebugger/Models/Sdk/SdkCatalog.cs deleted file mode 100644 index a79d8a3..0000000 --- a/RaspberryDebugger/Models/Sdk/SdkCatalog.cs +++ /dev/null @@ -1,33 +0,0 @@ -//----------------------------------------------------------------------------- -// FILE: SdkCatalog.cs -// CONTRIBUTOR: Jeff Lill -// COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace RaspberryDebugger.Models.Sdk -{ - /// - /// Describes the available .NET Core SDK binary downloads for ARM. - /// - internal class SdkCatalog - { - /// - /// The list of SDK catalog items. - /// - [JsonProperty(PropertyName = "Items", Required = Required.Always)] - public List Items { get; set; } = new List(); - } -} diff --git a/RaspberryDebugger/Models/Sdk/SdkCatalogItem.cs b/RaspberryDebugger/Models/Sdk/SdkCatalogItem.cs deleted file mode 100644 index 9a305f6..0000000 --- a/RaspberryDebugger/Models/Sdk/SdkCatalogItem.cs +++ /dev/null @@ -1,73 +0,0 @@ -//----------------------------------------------------------------------------- -// FILE: SdkCatalogItem.cs -// CONTRIBUTOR: Jeff Lill -// COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -using Newtonsoft.Json; - -namespace RaspberryDebugger.Models.Sdk -{ - /// - /// Describes an .NET Core SDK download. - /// - internal class SdkCatalogItem - { - /// - /// The SDK name (like "3.1.402"). - /// - [JsonProperty(PropertyName = "Name", Required = Required.Always)] - public string Name { get; set; } - - /// - /// The SDK Release (like "6.0.301"). - /// - [JsonProperty(PropertyName = "Release", Required = Required.Always)] - public string Release { get; set; } - - /// - /// Specifies the 32-bit or 64-bit version of the SDK. - /// - [JsonProperty(PropertyName = "Architecture", Required = Required.Always)] - public SdkArchitecture Architecture { get; set; } - - /// - /// The URL to the binary download. - /// - [JsonProperty(PropertyName = "Link", Required = Required.Always)] - public string Link { get; set; } - - /// - /// The SHA512 hash expected for the download.z - /// - [JsonProperty(PropertyName = "SHA512", Required = Required.Always)] - public string Sha512 { get; set; } - - /// - /// SdkCatalog Item Constructor - /// - /// SDK Name - /// SDK Release number - /// SDK type - /// Link for download - /// Checksum for download - public SdkCatalogItem(string name, string release, SdkArchitecture sdk, string link, string sha512) - { - Name = name; - Architecture = sdk; - Release = release; - Link = link; - Sha512 = sha512; - } - } -} diff --git a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs index 5c60573..4c3cb37 100644 --- a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs +++ b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs @@ -99,28 +99,7 @@ public static ProjectProperties CopyFrom(Solution solution, EnvDTE.Project proje // Extract the version from the moniker. This looks like: "Version=v5.0" var versionRegex = new Regex(@"(?[0-9\.]+)$"); var netVersion = SemanticVersion.Parse(versionRegex.Match(monikers[1]).Groups["version"].Value); - - var targetSdk = (RaspberryDebugger.Models.Sdk.SdkCatalogItem)null; - var targetSdkVersion = (SemanticVersion)null; - - foreach (var sdkItem in PackageHelper.SdkCatalog.Items) - { - var sdkVersion = SemanticVersion.Parse(sdkItem.Name); - - if (sdkVersion.Major != netVersion.Major || - sdkVersion.Minor != netVersion.Minor) - continue; - - if (targetSdkVersion != null && - sdkVersion <= targetSdkVersion) - continue; - - targetSdkVersion = sdkVersion; - targetSdk = sdkItem; - } - - var sdkName = targetSdk?.Name; - + // Load [Properties/launchSettings.json] if present to obtain the command line // arguments and environment variables as well as the target connection. Note // that we're going to use the profile named for the project and ignore any others. @@ -267,12 +246,7 @@ string SetLaunchUrl(JObject profileObject) // Determine whether the referenced .NET Core SDK is currently supported. // The bitness is not important for this - we need only the SDK version - var sdk = sdkName == null - ? null - : PackageHelper.SdkCatalog.Items.Find(item => - SemanticVersion.Parse(item.Name) == SemanticVersion.Parse(sdkName)); - - var isSupportedSdkVersion = sdk != null; + var isSupportedSdkVersion = netVersion.Major == 3 || netVersion.Major >= 6; // Determine whether the project is Raspberry compatible. var isRaspberryCompatible = isNetCore && @@ -300,7 +274,7 @@ string SetLaunchUrl(JObject profileObject) Guid = projectGuid, Configuration = project.ConfigurationManager.ActiveConfiguration.ConfigurationName, IsNetCore = isNetCore, - SdkVersion = sdk?.Name, + SdkVersion = new Version( netVersion.Major, netVersion.Minor), OutputFolder = Path.Combine(projectFolder, project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString()), OutputFileName = (string)project.Properties.Item("OutputFileName").Value, IsExecutable = outputType == 1, // 1=EXE @@ -467,7 +441,7 @@ private static List ParseArgs(string commandLine) /// just the major and minor versions of the SDK. This may also return null /// if the SDK version could not be identified. /// - public string SdkVersion { get; private set; } + public Version SdkVersion { get; private set; } /// /// Returns true if the project references a supported .NET Core SDK version. diff --git a/RaspberryDebugger/PackageHelper.cs b/RaspberryDebugger/PackageHelper.cs index 26e5a52..d00e596 100644 --- a/RaspberryDebugger/PackageHelper.cs +++ b/RaspberryDebugger/PackageHelper.cs @@ -51,8 +51,6 @@ namespace RaspberryDebugger /// internal static class PackageHelper { - private static SdkCatalog _cachedSdkCatalog; - /// /// The path to the folder holding the Raspberry SSH private keys. /// @@ -98,89 +96,6 @@ public static string RemoteDebugBinaryRoot(string username) return LinuxPath.Combine("/", "home", username, "vsdbg"); } - /// - /// Returns information about the all good .NET Core SDKs, including the unusable ones. - /// - public static SdkCatalog SdkCatalog - { - get - { - if (_cachedSdkCatalog != null) return _cachedSdkCatalog; - - // read newest .net sdks - if(!ReadSdkCatalogToCache()) - { - // if no SDKs present show a message - MessageBoxEx.Show( - "Cannot find any SDK on page: https://dotnet.microsoft.com/en-us/download/dotnet", - "No SDK found", - MessageBoxButtons.OK, - MessageBoxIcon.Error); - } - - return _cachedSdkCatalog; - } - } - - /// - /// Read SDK links from hosted service - /// with fallback to sdk-catalog.json entries - /// - /// true if SDKs present - private static bool ReadSdkCatalogToCache() - { - using (new CursorWait()) - { - try - { - // try to get the catalog thru version feed service - _cachedSdkCatalog = JsonConvert.DeserializeObject( - ThreadHelper.JoinableTaskFactory.Run(async () => - await new VersionsService.Feed() - .ReadAsync() - .WithTimeout(TimeSpan.FromSeconds(2)))); - } - catch (Exception) - { - _cachedSdkCatalog = new SdkCatalog(); - } - - if (_cachedSdkCatalog?.Items.Any() == true) return true; - - _cachedSdkCatalog = ReadIntegratedCatalog(); - } - - return true; - } - - /// - /// Read assembly integrated catalog json - /// - /// SdkCatalog with SDK items - private static SdkCatalog ReadIntegratedCatalog() - { - try - { - // try to get the catalog thru own fetch - using var catalogStream = Assembly - .GetExecutingAssembly() - .GetManifestResourceStream("RaspberryDebugger.sdk-catalog.json"); - - var jsonSerializerSettings = new JsonSerializerSettings(); - jsonSerializerSettings.Converters.Add(new StringEnumConverter()); - - return JsonConvert.DeserializeObject( - new StreamReader(catalogStream!).ReadToEnd(), - jsonSerializerSettings); - } - catch (Exception) - { - _cachedSdkCatalog = new SdkCatalog(); - } - - return _cachedSdkCatalog; - } - /// /// Static constructor. /// diff --git a/RaspberryDebugger/RaspberryDebugger.csproj b/RaspberryDebugger/RaspberryDebugger.csproj index 82a904f..2c3942f 100644 --- a/RaspberryDebugger/RaspberryDebugger.csproj +++ b/RaspberryDebugger/RaspberryDebugger.csproj @@ -96,8 +96,6 @@ - - @@ -121,7 +119,6 @@ SettingsDialog.cs - Always true diff --git a/RaspberryDebugger/sdk-catalog.json b/RaspberryDebugger/sdk-catalog.json deleted file mode 100644 index 4ee5213..0000000 --- a/RaspberryDebugger/sdk-catalog.json +++ /dev/null @@ -1,1124 +0,0 @@ -{ - "items": [ - { - "name": "3.1", - "release": "3.1.425", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/17fc9caa-076e-41c0-907c-f027140b081f/ac9ba7784bf06b63185ead3a2aa2f4f4/dotnet-sdk-3.1.425-linux-arm.tar.gz", - "sha512": "ca1d9e119dd72e3ed1afafd12b7e6b01ae98c1b5146008dff937d577426ff27069fcb912ab93bcbd064115eb69aca9ebc07b2fd84fccbed051c4f7c90a994df6" - }, - { - "name": "3.1", - "release": "3.1.424", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/abae2803-1012-48e2-a720-355795f80d79/47650a0b203a6f28019fe6f68215528e/dotnet-sdk-3.1.424-linux-arm.tar.gz", - "sha512": "4ca319e7cdfcd318cb0d649d83a93f1ac87a7a777f454a0a71ff7e87bae1ef8020e789edb4bfa172c091edc66b1e5dce0faa0950cb95a93953863c76721ce11f" - }, - { - "name": "3.1", - "release": "3.1.423", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/8f81b133-220b-4831-abe6-e8be161fd9a2/1af75b5e2ca89af2a31cf9981a976832/dotnet-sdk-3.1.423-linux-arm.tar.gz", - "sha512": "6b615ec6c1d66280c44ff28de0532ff6a4c21c77caf188101b04bdd58e8935436cb2b049ad9d831799476d421e25795184615c7e1caff8e550855e2f6ed5efd9" - }, - { - "name": "3.1", - "release": "3.1.422", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/e5ec7845-008a-4b7d-a247-c314f2407b8d/9117e05fa19f0217a030666df6b6eb9d/dotnet-sdk-3.1.422-linux-arm.tar.gz", - "sha512": "9cbccaf303f693657f797ae81eec2bd2ea55975b7ae71a8add04175a0104545208fa2f9c536b97d91fa48c6ea890678eb0772a448977bce4acbc97726ac47f83" - }, - { - "name": "3.1", - "release": "3.1.421", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/564f08f3-230e-4476-8ebe-7e1f02dceae4/9da37442bde3f45300c65e9f71e1b24a/dotnet-sdk-3.1.421-linux-arm.tar.gz", - "sha512": "412b30ee45554de69844e4297354680fdc5111c270b5e41af73db212117ee101878b87eb4592bda4c314ec0d7406ba8ab449d83466267f78198ce09fc32ef425" - }, - { - "name": "3.1", - "release": "3.1.420", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/78abce54-388a-418f-85e0-cf3c6a0e7d35/98d1ee575a0369c97c3d14ee0e1085a8/dotnet-sdk-3.1.420-linux-arm.tar.gz", - "sha512": "d61cc1a5dc345d4c32bb06bcce1e50d603103294783460c811a87635eb14fc51c58869456f3326cfb689fdb7b379d2410f5db5bf63332aff173814035a319c28" - }, - { - "name": "3.1", - "release": "3.1.419", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/077c85dd-4bb4-45d9-8cc7-4913ab0307d1/444453aee99210cbd2b966fba8c11cb6/dotnet-sdk-3.1.419-linux-arm.tar.gz", - "sha512": "a89d857200f5ce4d65f662f1acd70f0d8a6eb7fda0ae7ca904cf7b50a6772378a42c7d11ce0dac27c522d642fee0ad67c9da64ce0e7edbe27f28df776b4a45d8" - }, - { - "name": "3.1", - "release": "3.1.418", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/c2bd849e-394c-48b0-9955-0d625d0aca50/60549bead15b74667ffc76f18aa05641/dotnet-sdk-3.1.418-linux-arm.tar.gz", - "sha512": "a5edf84b01740767cd0ed2d7e8f84ed66bd786fc61bc93065d3125c8eac123e6c383e7155e5ead31e344b691e23788b240f812d5a5759fa0d764c0e336f2cc22" - }, - { - "name": "3.1", - "release": "3.1.417", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/36a601f0-b88e-41ea-910b-4dde7b083e73/61ec8564d50fb391f9e3a10b226fdd0d/dotnet-sdk-3.1.417-linux-arm.tar.gz", - "sha512": "d68f9b130f4a516cb199c9010a42acdda0c9e8c705bce0e72e9854587ee54f5a017b1cea5b84f15dae057531a8a619cffffa1e79f3413d376ba7d7226407574c" - }, - { - "name": "3.1", - "release": "3.1.416", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/1b2a2fb1-b04b-485b-8a25-caed97ebe601/0c6024a3814f664558dc39fc85b34192/dotnet-sdk-3.1.416-linux-arm.tar.gz", - "sha512": "33a6d64f466839cc30adef87909a2ff98ecdf6bb763b82a7951314ee8eded7dc210297f914d4aa0b9c0b101aa0c33da97cb15ff64c5f83f08b212b885d662e90" - }, - { - "name": "3.1", - "release": "3.1.415", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/e401b906-4681-437b-a1c5-21a2d7e0f83c/824371926ae334ac264b91d8234b350c/dotnet-sdk-3.1.415-linux-arm.tar.gz", - "sha512": "b738f0b4455b926b8fafa9699525cebbf51eaad7bbe0e77267640a3fe33645ab4901552008de0a9916f55d0eff1de61c22ebd432a5a1fb5099f0cfa1b33a5e75" - }, - { - "name": "3.1", - "release": "3.1.414", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/cefd43b6-16ac-4435-bcc6-594ebb0441cf/7d064f0f61c4174f620eafe97484e6cb/dotnet-sdk-3.1.414-linux-arm.tar.gz", - "sha512": "08c93b7948151fbe3db9fa105ed02bfefb510e437aa9ad418c60ba96b41a7e25f891a1d4308f51595a9aa385d4e9ca05cab8a803e75728fb70aa9bae30f37b67" - }, - { - "name": "3.1", - "release": "3.1.413", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/40edd52f-b1ca-4f0c-8d50-34433202ce9d/2b8f5b881c239a706f271f010e56159c/dotnet-sdk-3.1.413-linux-arm.tar.gz", - "sha512": "31f395b1e48e9ba53d4dc63db7ff1ea38bdcb612a1d54b483cde22a009c48fbae0303779f42cee32db0e51bd953c8abfdaa1620a43a7fd84e1f8e937b6675d59" - }, - { - "name": "3.1", - "release": "3.1.412", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/5aef7e5d-2112-4868-8d7c-4c82f04363c5/e4fe30dc136634001cf357f26c825506/dotnet-sdk-3.1.412-linux-arm.tar.gz", - "sha512": "3c66abcdef095db393ecd25501ba1e13c5a78b79ce65e6bd9ddcc3a559528eab21b0a95b39acb86e5f7f8565ae7a799e6c7e6d723121132110f93eb868cf81eb" - }, - { - "name": "3.1", - "release": "3.1.411", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/c36515e8-b5eb-4501-bfda-555c16938673/4faa9e8f1e1f84f020e85ab3dbd4c306/dotnet-sdk-3.1.411-linux-arm.tar.gz", - "sha512": "a684155eb088e280ea4e8612e06b3ccd3d00a58ecd84d0971ee96ac0ec80c1d7333acf929590a886be5759eec33890bfd126152f740657fb9bbea09e9f96e97a" - }, - { - "name": "3.1", - "release": "3.1.410", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/9f93cdf3-2f04-461b-8c42-dbd84b624878/e69a16b86c90ddaa52775673bde765f4/dotnet-sdk-3.1.410-linux-arm.tar.gz", - "sha512": "139c9b41a89af44bef74de27df31d4bf50e56e5edd2d76e501bcaab7fc39764c1d74ef142fdd4f077a21c84b550b65038a642a4c65bbe65c0e38c6ce7fb7ac25" - }, - { - "name": "3.1", - "release": "3.1.409", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/58d0ebb7-c06d-4d9a-a69f-22dac06fb278/0ae7881b7007c13a8e325d54a8f87657/dotnet-sdk-3.1.409-linux-arm.tar.gz", - "sha512": "4908a84951a93acac80c6e7d2dff88b40b90fa079bfc0a02678a70c412a45f1146a3d344c218791edef4bb972d549accadcbfcdc721be0478b07db3a3336cf6d" - }, - { - "name": "3.1", - "release": "3.1.408", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/614983bc-78eb-4673-b1ff-fe876660ae21/03523848937d401293a7abdb56a6a0e2/dotnet-sdk-3.1.408-linux-arm.tar.gz", - "sha512": "05335636d61067c647e15ced618ca3ba2460b5aaa76e1713281fda2995740ee49fe9d63ae71fa8ac51786653b2ea7da83f540cec742628f78201206e142de609" - }, - { - "name": "3.1", - "release": "3.1.407", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/12a5b3f4-4960-4e1a-a82c-c782138807b2/62f01a300ac1007d2b62612fa1aa3f3d/dotnet-sdk-3.1.407-linux-arm.tar.gz", - "sha512": "a60a272673842470ec3b32addd2ce2c3528b36315ba9c0b4237847b7e0b34914cb56b4b2f62410de2ccf231656327a7a3bbe2afa5c14672f1808df5cb4f9b8d8" - }, - { - "name": "3.1", - "release": "3.1.406", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/9863a55b-2577-49d3-9888-ab853a4201cb/3110704f3265713f8d82aab157a23ed2/dotnet-sdk-3.1.406-linux-arm.tar.gz", - "sha512": "b978d8f8dd6af16abb16f42b8c36c356d18e6e88309967ae9faa9a8009245e4a94183a4c2a6acad48ba342a7429de8055e4e32aca79f0c1d2f2c3bca1a318530" - }, - { - "name": "3.1", - "release": "3.1.405", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/2178c8a1-ad48-4e51-9ddd-4e3ab64d1f0e/68746abefadf62be43ca525653c915a1/dotnet-sdk-3.1.405-linux-arm.tar.gz", - "sha512": "110f595a835ebc5c974fcb24e5ed7b81461288ddcf6b3a0dcead3f22b6995698dab767304e0bd98d3c450a297db8f04b185bbaa0d310fc9f1d3f9c3157fdac06" - }, - { - "name": "3.1", - "release": "3.1.404", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/2ebe1f4b-4423-4694-8f5b-57f22a315d66/4bceeffda88fc6f19fad7dfb2cd30487/dotnet-sdk-3.1.404-linux-arm.tar.gz", - "sha512": "0aaed20c96c97fd51b8e0f525caf75ab95c5a51de561e76dc89dad5d3c18755c0c773b51be6f1f5b07dda02d2bb426c5b9c45bb5dd59914beb90199f41e5c59e" - }, - { - "name": "3.1", - "release": "3.1.403", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/8a2da583-cac8-4490-bcca-2a3667d51142/6a0f7fb4b678904cdb79f3cd4d4767d5/dotnet-sdk-3.1.403-linux-arm.tar.gz", - "sha512": "9f1293ef8f3abf5c6a8da7f963de4408d5aed6a9ee29a2c84655871574041980d8a4bb5b608ea129b1bd392890dc577d11c138bd54ce91745cb4960be697cb4e" - }, - { - "name": "3.1", - "release": "3.1.402", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/8f0dffe3-18f0-4d32-beb0-dbcb9a0d91a1/abe9a34e3f8916478f0bd80402b01b38/dotnet-sdk-3.1.402-linux-arm.tar.gz", - "sha512": "b4ada8bff572d39262c952506661d6f328d22dd963903ed81a1c7646e1dfbd54e8f6897e0ff189bfae29f69b76b3ddecc17001b5df1ddd9e8da4cf9eebdd22d7" - }, - { - "name": "3.1", - "release": "3.1.401", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/a92a6358-52c3-472b-ad6d-d2d80abdcef4/37a7551a4e2c9e455caed5ef777a8983/dotnet-sdk-3.1.401-linux-arm.tar.gz", - "sha512": "2c84d8442fd872aafbdff7a1f131c4bacfb75ca69426d2aa2b9f3cf05a8e3a365923c14f7eb732113dd7a9fdc674c955e70817fb355aaabca25b79ed33356a15" - }, - { - "name": "3.1", - "release": "3.1.302", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/56691c4c-341a-4bca-9869-409803d23cf8/d872d7a0c27a6c5e9b812e889de89956/dotnet-sdk-3.1.302-linux-arm.tar.gz", - "sha512": "eccb9ba89eb745282cb749e505fcf2209e3b56f41d5ddbb383dbeae04eb58a9b367560d743bc78600c8adab4abb93bbabccaae33613b9d3fec2b150fca5dffc4" - }, - { - "name": "3.1", - "release": "3.1.301", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/dbf4ea18-70bf-4b0f-ae9c-65c8c88bcadd/115e84fb95170ddeeaf9bdb9222c964d/dotnet-sdk-3.1.301-linux-arm.tar.gz", - "sha512": "732364b93caaa94ee96dfe24ed42e63ae59862afd0691760557c22019c67139f92db28cc5e730618a630c45a96b2468676867345e54ae93004567b470edf5f47" - }, - { - "name": "3.1", - "release": "3.1.300", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/f2e1cb4a-0c70-49b6-871c-ebdea5ebf09d/acb1ea0c0dbaface9e19796083fe1a6b/dotnet-sdk-3.1.300-linux-arm.tar.gz", - "sha512": "510de2931522633e5a35cfbaebac255704bb2a282e4980e7597c924531564b1a2f769cf67b3d1f196442ceca3d0d9a53e0a6dcb12adc9b0c6c1500742e7b1ee5" - }, - { - "name": "3.1", - "release": "3.1.202", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/647e322c-e198-4bff-ba2a-a1a5b8477033/87b7b0af543dba7048a57ee2ab5a31ee/dotnet-sdk-3.1.202-linux-arm.tar.gz", - "sha512": "6a978081468458fb08f405e11d39067f2dab3ec1b9ed9d033f7e74ddf8e700eb15c9c3d86d8fba5dbcf44f03b06c7f4a5d84b531e7d57a75d7a4f4cdc7f98992" - }, - { - "name": "3.1", - "release": "3.1.201", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/ccbcbf70-9911-40b1-a8cf-e018a13e720e/03c0621c6510f9c6f4cca6951f2cc1a4/dotnet-sdk-3.1.201-linux-arm.tar.gz", - "sha512": "f37d0e55c9f593c6951bea5a6bb1ea3194486956efe08a2a0f266b419d912cdcbf4ac279358976f0bfa1fe560c333ca5d5437f8e8c718bb5963991e4395e0cd7" - }, - { - "name": "3.1", - "release": "3.1.200", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/21a124fd-5bb7-403f-bdd2-489f9d21d695/b58fa90d19a5a5124d21dea94422868c/dotnet-sdk-3.1.200-linux-arm.tar.gz", - "sha512": "5e8a5e5899cd3c635a4278c6c57b9f9c75ffee81734ccf85feaacf1c3799cc135fd24d401abb7e8783db40e2072769a1d2a012f3317ed39cc019d69712243266" - }, - { - "name": "3.1", - "release": "3.1.120", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/ff0c5ae3-2b4d-422c-8619-2121a6fac5bc/a38c89439845fc4ef076b7232141e9c0/dotnet-sdk-3.1.120-linux-arm.tar.gz", - "sha512": "b82c36dac8a6aeba87e7015775bdffb1ed381abc86ed51a251d508f670015b8c720e65781b39566931dd7948f56735175c176445efb14ef36b82f7b620219746" - }, - { - "name": "3.1", - "release": "3.1.119", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/2b395979-32e6-4154-bd52-007fb7b58ea1/a7558832505d59d3f0c444e2081304ae/dotnet-sdk-3.1.119-linux-arm.tar.gz", - "sha512": "1e8c67c0036d49c57d4525f256d422b40d315dc434dca9aad7ae6f164a17168d74ebd6cda81b974798bd4008b78b41eb5bd81a7092b2efd6ebb96feea3eac5e2" - }, - { - "name": "3.1", - "release": "3.1.118", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/64a1b7b0-e5ca-4454-abfb-058b91b5a975/979872728452ea321d067351e526f08e/dotnet-sdk-3.1.118-linux-arm.tar.gz", - "sha512": "e7fe87cf3d5a4d4f20c2f1b7b4e0e8ae99bd14ece3113e9bcf83ab54cc93b40ee4458b7eb76d9f78f153a8b1aed5cab62398577e6fc4aa204f8827551112cb08" - }, - { - "name": "3.1", - "release": "3.1.117", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/56bbadc1-12ad-4885-95e6-a52760aa4786/d5bc16bac8471d8c8a978c9dc6154bb0/dotnet-sdk-3.1.117-linux-arm.tar.gz", - "sha512": "c7a781fb1cccb308788d5b04c3acf822c3d0fd8df31a2882090b238a7d04ce9bf059b4153a0f6e0cc7e6468ff8fbe89ae3456b6303dcb8292157e7470f71442d" - }, - { - "name": "3.1", - "release": "3.1.116", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/351c3281-43d6-4f2f-8936-6ba4f0ae9e0e/159e36b534b01a6ee8dd13d2e53680a8/dotnet-sdk-3.1.116-linux-arm.tar.gz", - "sha512": "3fd1a4842067a7dca2a6730865884b607dcf5bdd40406a9950448ccf1d12941446a2d753521c124b6ee6b9adb8cc4076da4a9b2f548f5afce52cbc96f8a9613e" - }, - { - "name": "3.1", - "release": "3.1.115", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/31ccb908-2638-4fa1-8ed4-2e90ca89e42e/30dc805ef1b30c277b0a63a553439d41/dotnet-sdk-3.1.115-linux-arm.tar.gz", - "sha512": "00da62d108784d6fb09a9be418479ca695b99f4ef5f65c56a700f61bbe7eac8cb83cadd596fb4577c77a434b435493fa32b889b1c23375c82c391dce1385d004" - }, - { - "name": "3.1", - "release": "3.1.114", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/09c1545d-dd80-4629-ad2d-90a69723cb0b/06fd6210be9220099d4a506c0323c7c1/dotnet-sdk-3.1.114-linux-arm.tar.gz", - "sha512": "3357a7a3192583b8478364d684e3c93e8dea894628b6fa9cffaba6fc9daabf9c8aada4f5cc423a56041d01e95fc9e703109f3ba6b320dc52ea3055f555e932fa" - }, - { - "name": "3.1", - "release": "3.1.113", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/d0cb55c6-1731-4c64-aaa9-3e87cad0c890/515de52bd97e8d78bb837c3d19c54061/dotnet-sdk-3.1.113-linux-arm.tar.gz", - "sha512": "c27d63b171dda1e7513137c625ebb5897f7b9b10b4d213f49dd32e353913f18d112469eb19f739b8186d02a7f5cc47f050b38c000b109ca1233982b9556c3b87" - }, - { - "name": "3.1", - "release": "3.1.112", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/d720b6ef-d5c3-4403-a87e-e371c33fbc08/3cbf4e48b65cb9f9dc9f8db0959eed1c/dotnet-sdk-3.1.112-linux-arm.tar.gz", - "sha512": "a7e639a7432ce4ef404ab8bbc66f42128571a1b7de70989c6aca26dd83a43d036db985f31992a62d707d7986eb00a30b03b67ed28e1f5048a76bb9954fbf97de" - }, - { - "name": "3.1", - "release": "3.1.111", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/127a8331-eb7c-423e-b326-fa2227c159bb/c5d9c46055e41b1b2486a2e289b382f7/dotnet-sdk-3.1.111-linux-arm.tar.gz", - "sha512": "67b9aa755b208a9594d73b3964721521976963e05abc6cfc95add271d6c09a0848555a04d0aa1531d900d67aa3fb7414dc704af74ec5d733ee18b6267f3ca460" - }, - { - "name": "3.1", - "release": "3.1.110", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/b4b0a624-a046-4ad5-a19b-82dd26c1ccdb/28af71681b300f3a8b7aa0841cce45cc/dotnet-sdk-3.1.110-linux-arm.tar.gz", - "sha512": "af345605f4f795d90ca469b70ded4a62d8d3536cc1cf8856a856b576a438c1faff9f8b652c4657d7ca211306266d78f80da6ea1286e00812314bd742786d72d4" - }, - { - "name": "3.1", - "release": "3.1.109", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/d9a0b670-88f8-44ac-a6b1-9020c783c518/8bbec2b438275789bc1dbc95b8f89adf/dotnet-sdk-3.1.109-linux-arm.tar.gz", - "sha512": "035b00adc3aecc365017db44771a30300b0858c6eb480f7358fa5c9b931a1d7d2a8d3e44d88a3e7ef59efbdf1cfab1c9dbd52e8c31694a1fa9419805134e2b52" - }, - { - "name": "3.1", - "release": "3.1.108", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/52fb935e-f2b3-42c3-9695-d53e7c693baa/6c38b8ac3bc97ea2f09a03a60cdacdc5/dotnet-sdk-3.1.108-linux-arm.tar.gz", - "sha512": "b2f074cb6820f8859c61e04a355087828028f5c11912e0d1bcb0f93c5f3597eb60774542b0f3f3955f81fb459784036f2d4a9bcfcc0ba06965d671ed004e52ab" - }, - { - "name": "3.1", - "release": "3.1.107", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/41775681-e8a1-4cdd-b1d2-967c25d2b5d6/7b968b58d157f7159ec4b6466c76ff02/dotnet-sdk-3.1.107-linux-arm.tar.gz", - "sha512": "e36f8192127c6d52c34fe15dabc23d4b9cb6e48d88a44355f687d974b13fe4a56dcb142fcacd9d959e67469cc31455b10b1fad8a5fdebbfc3f6cebc99d63dc5d" - }, - { - "name": "3.1", - "release": "3.1.106", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/ad10d24d-9823-42fc-bf2a-1d598d8999c6/80f944ded4c6d3fd73cd6a00f6ae660f/dotnet-sdk-3.1.106-linux-arm.tar.gz", - "sha512": "05830f3b9924706d40b9a310e5dc334029f7be080b0e69aaef17e470b9845e1cc708e52652537c2ead98ca4209fda4d53a0cd5200c6b7727ce42f808c54d50f6" - }, - { - "name": "3.1", - "release": "3.1.105", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/52f61afc-0897-4bc7-abf4-f936f9c6f637/8fca0abb8c378a32d966c1b762524c0d/dotnet-sdk-3.1.105-linux-arm.tar.gz", - "sha512": "a5e7531445c5efc5d647a6dca3725bc13b92df19aa87b63163b01518de5eb29e22f02c124807f29edc5f07ab31c56b675a6c34a1eae50e090c4ddf930fb4bd9f" - }, - { - "name": "3.1", - "release": "3.1.104", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/74e61bc8-e8b1-4728-9c56-7d978010e4dd/a3c8533ed97dcfea09fe64e6969cd60c/dotnet-sdk-3.1.104-linux-arm.tar.gz", - "sha512": "18120f948651558f8b075017d42f075b97454c386ec9c7985f68169755a9b059110b5b52edebe8763ab0178ffd1bc453a70d9231d61213170b386ff899fc6463" - }, - { - "name": "3.1", - "release": "3.1.103", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/7eb8b77b-e7e9-44ea-8a4e-e560ef639958/ee3565807f13ea0cf62e7a6bd8a58221/dotnet-sdk-3.1.103-linux-arm.tar.gz", - "sha512": "7b646a0e62b781f658862f3e6e2ada2e3ce5a3529b835d8c7fc1931c1b6654de89a152a7a033a3dc23352880684bd149bd4f6fda180a6da66d860ac25b578174" - }, - { - "name": "3.1", - "release": "3.1.102", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/349f13f0-400e-476c-ba10-fe284b35b932/44a5863469051c5cf103129f1423ddb8/dotnet-sdk-3.1.102-linux-arm.tar.gz", - "sha512": "b279185fd245c3a254f4bbdd4f743d4309fcf8e2d3a1eb42df2f464e40df9954257209a666287ad3d924f863ca09d0cd8638d394da9f990477a2fc6d71198550" - }, - { - "name": "3.1", - "release": "3.1.101", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/d52fa156-1555-41d5-a5eb-234305fbd470/173cddb039d613c8f007c9f74371f8bb/dotnet-sdk-3.1.101-linux-arm.tar.gz", - "sha512": "bd68786e16d59b18096658ccab2a662f35cd047065a6c87a9c6790a893a580a6aa81b1338360087e58d5b5e5fdca08269936281e41a7a7e7051667efb738a613" - }, - { - "name": "3.1", - "release": "3.1.100", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/67766a96-eb8c-4cd2-bca4-ea63d2cc115c/7bf13840aa2ed88793b7315d5e0d74e6/dotnet-sdk-3.1.100-linux-arm.tar.gz", - "sha512": "9f4848b4bca649cc6131032de4b0115549a3dafb6bf90250930794aa69f7939bba82cedda67578348a83b50b7057e452846a400589bb4e9d4a2d1b33ce57c71c" - }, - { - "name": "3.1", - "release": "3.1.425", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/d4a8d050-e3d0-4f07-b222-5cadb21320f2/05d4d832757a78ec88fb56d8f9f4cc65/dotnet-sdk-3.1.425-linux-arm64.tar.gz", - "sha512": "f3c18acc094c19f3887f6598c34c9a2e1cfa94055f77aa4deae7e51e8d760ca87af7185cc9ed102e08f04d35f9a558894f04f7a44fa56b91232ccc895f4e5a5c" - }, - { - "name": "3.1", - "release": "3.1.424", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/dfe62f78-d4c1-4190-9d9d-44249e83a0c5/1fb0e84fb45e4e5d3207de6db85d99c3/dotnet-sdk-3.1.424-linux-arm64.tar.gz", - "sha512": "3bfd29233a3e0dfdbdc967f07808d4e239651f0f4f23f7c9e74f09271c9ded8044539ea4278bad070504ad782c4638a493bd9026ddbc97bbc657c5c12c27ccd2" - }, - { - "name": "3.1", - "release": "3.1.423", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/11abab07-d7a2-46b0-9ab5-19d5db67212f/783196073ecbd9fd64378fec412affbe/dotnet-sdk-3.1.423-linux-arm64.tar.gz", - "sha512": "ba4f82e939be43ed863f059f69cdfb80b6dfe7cf99638bd6e787b060c2c1c4934440b599c133f61e3a0995f73675ae5d927bb047597cdd6a15b9074891dfd62e" - }, - { - "name": "3.1", - "release": "3.1.422", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/fdf76122-e9d5-4f66-b96f-4dd0c64e5bea/d756ca70357442de960db145f9b4234d/dotnet-sdk-3.1.422-linux-arm64.tar.gz", - "sha512": "3eb7e066568dfc0135f2b3229d0259db90e1920bb413f7e175c9583570146ad593b50ac39c77fb67dd3f460b4621137f277c3b66c44206767b1d28e27bf47deb" - }, - { - "name": "3.1", - "release": "3.1.421", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/3aa1ef77-157e-4c54-bdc6-1cf589f3e3d1/590f24f95d808144bc18caa0c45b7d9f/dotnet-sdk-3.1.421-linux-arm64.tar.gz", - "sha512": "c584642469343c2c54fa02a7157009fa36bae9b304512db0a2b0069f71593ee2ba47070896212def0541460f37bf1b0a478b914e08a2c78b985cb2981e5ab6c6" - }, - { - "name": "3.1", - "release": "3.1.420", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/a84bf296-ee6e-4e66-9694-90d3da7af2b4/b00b2efe2432938e5a19c45d3759d80f/dotnet-sdk-3.1.420-linux-arm64.tar.gz", - "sha512": "ac66b1544fe178153bb85c2e5be584464374ce4c036fc95720547c231c2730312018fbdfc735f9071579749415bc54e1f6b8f080cc2b08d5799a0da941e8a5f5" - }, - { - "name": "3.1", - "release": "3.1.419", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/6aaec6b7-3d0c-4f00-a8a0-a53c4844525b/e932447b5c2e854bcae25942a2113af2/dotnet-sdk-3.1.419-linux-arm64.tar.gz", - "sha512": "94f398c09b53c10dc3e4ed1f624eee19b18770734956ebb0cb4ac9d789c1a79a891c1934e7c4c3a2bed5326ee1a0417ee89816695ab2436b3db7076328a40b77" - }, - { - "name": "3.1", - "release": "3.1.418", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/1533613a-1a50-48d0-bffe-341276bf95b3/d20d99d497f07b40f655b888319de311/dotnet-sdk-3.1.418-linux-arm64.tar.gz", - "sha512": "8c3f1254a27991f116f499b11aa389266bc63b93a85ab7103b398bdf14225755277499ccb8297012f572732e5e521c23d02fe3d99b552ecadf8af2867456ebc5" - }, - { - "name": "3.1", - "release": "3.1.417", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/5da6dffe-5c27-4d62-87c7-a3fca48be9bd/967bd7ddc7bbcaef20671175f7b26ee3/dotnet-sdk-3.1.417-linux-arm64.tar.gz", - "sha512": "28ea17c3c8e57721fdafcdf8339a175d4d7c29616597d7dac60362fe4ac8c3a8493612865a37e985729b3d3953caae7fed2f8a11a0d0bb1dd24b1d816d6b6abf" - }, - { - "name": "3.1", - "release": "3.1.416", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/d3aaa7cc-a603-4693-871b-53b1537a4319/5981099ca17a113b3ce1c080462c50ef/dotnet-sdk-3.1.416-linux-arm64.tar.gz", - "sha512": "0065c7afb129b1a0e0c11703309f3b45cf9a3c0ea156247f7cc61555f21c37054f215eb77add509dad77b1d388a4e6c585f8a8016109f31c5b64184b25e2c407" - }, - { - "name": "3.1", - "release": "3.1.415", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/4a78a923-e891-40fe-88d2-4bff2c90519f/126bee4399caeabde4f34f4ace7f44e3/dotnet-sdk-3.1.415-linux-arm64.tar.gz", - "sha512": "7a5b9922988bcbde63d39f97e283ca1d373d5521cca0ab8946e2f86deaef6e21f00244228a0d5d8c38c2b9634b38bc7338b61984f0e12dd8fdb8b2e6eed5dd34" - }, - { - "name": "3.1", - "release": "3.1.414", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/040f982b-bd08-496f-ae52-a60361a79546/7d572611a4177c48d868e0516ac192dc/dotnet-sdk-3.1.414-linux-arm64.tar.gz", - "sha512": "42b526d4ae914a0f1b04cbefe70b2c052eae9791dce54431ee5aff2e1bba5dbd08f49505a835319dab0551e9e9788f239e53ac154760cc8c0a85512cbe568408" - }, - { - "name": "3.1", - "release": "3.1.413", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/dfd0ad22-3e47-432f-9aa1-f65b11a2ced2/d096c5d1561732c1658543fa8fb7a31f/dotnet-sdk-3.1.413-linux-arm64.tar.gz", - "sha512": "39f198f07577faf81f09ca621fb749d5aac38fc05e7e6bd6226009679abc7d001454068430ddb34b320901955f42de3951e2707e01bce825b5216df2bc0c8eca" - }, - { - "name": "3.1", - "release": "3.1.412", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/f9f54199-f0b3-43ac-badd-f9ef6867641c/50bd985f26c59f5d63f29f571f7f89e5/dotnet-sdk-3.1.412-linux-arm64.tar.gz", - "sha512": "bfc6f58cb0b87b0a2cf42d91494b914ab0997c91289599cce1704ee33fac9773e5b37b48d40c2d0fc53709c7f94cc37c26533ef7d0eb90f6db05680b2b603da0" - }, - { - "name": "3.1", - "release": "3.1.411", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/3dc91205-b4b2-4b90-bd5d-899b85c79454/6831ad89fe379c5ed01dbd362cbd4cac/dotnet-sdk-3.1.411-linux-arm64.tar.gz", - "sha512": "c9b03b858e6063fc200a103930fb5a3b03ae35b89b884bb461bad36ce34f14fa84c4e98edc7082bcf5b132fbd31d8d58192e62ae055e757d064ed98e4ec5c600" - }, - { - "name": "3.1", - "release": "3.1.410", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/0d0ad29d-da90-42ce-a88d-94f47f9ddc09/bbfafc31b9a7e36140a74e0e157e9e3e/dotnet-sdk-3.1.410-linux-arm64.tar.gz", - "sha512": "58400007d55b122becb229a45d0fa8676890e16e818e229a9b6f5684e6d9133a22e4cb144f3a1af351c01fe9cc70056d43ab8164dca2b841cbdfae96fd7b02db" - }, - { - "name": "3.1", - "release": "3.1.409", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/df1fe0a4-487f-4803-b541-4abb2f08ef2d/c905bb3ccc7f584963a45e32d7361d74/dotnet-sdk-3.1.409-linux-arm64.tar.gz", - "sha512": "edc011e5ee64fc76e8004aa73d439e7cea922ab00be6c70250c5f73cf6838b1935f5d3d3c9aa65f83bfd3923751bc1a6d92be3fba64a0a09a4acb4fd8d6db4c7" - }, - { - "name": "3.1", - "release": "3.1.408", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/8aca4221-54b6-421d-9be0-f25e4b799463/b70cca6f2acddc5361f97dc7f77a8ddf/dotnet-sdk-3.1.408-linux-arm64.tar.gz", - "sha512": "5d69cb6d5f088452a6cc3a3635d5f6102e0217f3d5fa680287be9e67c211b0720fe493f05280ab4d2c1a905afe78e8ba9cb28151453172e7fcf10b0d9553e2d2" - }, - { - "name": "3.1", - "release": "3.1.407", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/94a88a85-be1e-464a-8cdd-6eb23d8559a1/b715559dd50aec6097db76ca50e2154b/dotnet-sdk-3.1.407-linux-arm64.tar.gz", - "sha512": "4ae1c92bd4cdf0ea459591e87aea0e2f560df9d2c406e68dcf6667576ebf7761817683b565d42aeca74a6f03cdb8342d3fd1f9c81a4657a78043a5f765dc549c" - }, - { - "name": "3.1", - "release": "3.1.406", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/fc9051ee-4071-4808-9e71-82d69328ab47/32ae2b7177d082fc52d89774e4f127fa/dotnet-sdk-3.1.406-linux-arm64.tar.gz", - "sha512": "e460ac35329e572dbf4005254129b9799c897f19261d01ea77a0aa196b9e0fecf804996b1157cea92731e30e08b5827ccb0c2d280ea9ab2b04b46492ed5e12a3" - }, - { - "name": "3.1", - "release": "3.1.405", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/ebb398e7-06d1-48f9-94e7-ddae049b704f/6bb78627f0337b980ece2a3181963fbd/dotnet-sdk-3.1.405-linux-arm64.tar.gz", - "sha512": "e720b7c6497da52ce4a927b1a29df5c180fbf5b4f800185de61a31092c0bfa18a78bb9c2fee744fabc78214c5be6e9277f3dc14ae1426b55274f9726997fc733" - }, - { - "name": "3.1", - "release": "3.1.404", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/de47cbe2-f75f-44c5-8250-7960a36d6591/76cfdbfb7bf17cce27378a9fddd969a6/dotnet-sdk-3.1.404-linux-arm64.tar.gz", - "sha512": "b22b60a06f4a1a409eb8eb8f5aec26454ff393bef9677294f0a9d61367caeb2a55fff1e4e282af5250365d27cee3b5cf7c31db8ff1c224f1c7225263b0e4a9aa" - }, - { - "name": "3.1", - "release": "3.1.403", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/7a027d45-b442-4cc5-91e5-e5ea210ffc75/68c891aaae18468a25803ff7c105cf18/dotnet-sdk-3.1.403-linux-arm64.tar.gz", - "sha512": "c0f5070deca932d67a80b06268a69146ca403f1657e49d509513b5fe15cb5224cdfb5bec9cd2e63db6c83a48f3cb64d23d8cc30fcd98c620d9936544dbb6ce0b" - }, - { - "name": "3.1", - "release": "3.1.402", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/186257d9-bca2-4dda-be74-006205965ec9/b2b63d45482701473d9731abc41ecc2a/dotnet-sdk-3.1.402-linux-arm64.tar.gz", - "sha512": "1704fb88a04cb5a00de5a22da4ad68237a7cce9aeaac608166f85082a4bfc86ba360b1d81c5ceb40c906cf7407e365aed73fa68a735d4ba90b334ab01a3a8455" - }, - { - "name": "3.1", - "release": "3.1.401", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/8c39349a-23d0-46b0-8206-8b573a404709/b42fd441c1911acc90aaddaa58d7103f/dotnet-sdk-3.1.401-linux-arm64.tar.gz", - "sha512": "ab9afd226b920dce24bcd372cccb1965163829c26d1f11f1df3d8f9be5afb1d87f26b23e5fbeb58cf4ddaa040b8228fa00a786c379a454b9d99c2964197ab4cd" - }, - { - "name": "3.1", - "release": "3.1.302", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/5ee48114-19bf-4a28-89b6-37cab15ec3f2/f5d1f54ca93ceb8be7d8e37029c8e0f2/dotnet-sdk-3.1.302-linux-arm64.tar.gz", - "sha512": "c2bebb673f217d9e7afb80b2b032c6f850d93e2419b5c0f9aa22676114a5c4fa91550a89b46757012fb9535405c1bb7902f0927f093769d4d055a8de84cfc5d8" - }, - { - "name": "3.1", - "release": "3.1.301", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/fe5c0663-3ed1-4a93-95e1-fd068b89215b/14d1caad8fd2859d5f3514745a9bf6b3/dotnet-sdk-3.1.301-linux-arm64.tar.gz", - "sha512": "834dc5829730ea7abcf5adfca5557458d5de534597933dbdcec99abbd7eff00f3e1d0084b7f3572de80b4d333dee6d32cffa2d1ead022faad3957c95e5a920a0" - }, - { - "name": "3.1", - "release": "3.1.300", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/e5e70860-a6d4-48cf-b0d1-eeba32657d80/2da3c605aaa65c7e4ac2ad0507a2e429/dotnet-sdk-3.1.300-linux-arm64.tar.gz", - "sha512": "b1d806dd719e61ae27297515d26e6ef12e615da131db4fd1c29b2acc4d6a68a6b0e4ce94ead4f8f737c203328d596422068c78495eba331a5759f595ed9ed149" - }, - { - "name": "3.1", - "release": "3.1.202", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/15434752-2803-4722-b406-9a62d3e089d5/159bd7713f8a7ff82d7b2f756ae87f4f/dotnet-sdk-3.1.202-linux-arm64.tar.gz", - "sha512": "b570a423522de777d05de67410cea7d6d54461b7e2b82a18f4ca21093897836447f215b2737df909ee581508fbd1a61993f3ea1d9856b9a883caed3f7086f0a6" - }, - { - "name": "3.1", - "release": "3.1.201", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/98a2e556-bedd-46c8-b3fa-96a9f1eb9556/09f60d50e3cbba0aa16d48ceec9dcb0b/dotnet-sdk-3.1.201-linux-arm64.tar.gz", - "sha512": "2f4f6b7ae55802b0beaf5d62bcb64f23ce132c9e08d8ce0f0af8d9b0b1b2c2629b1d4e805e83f831575c9968a86d1495dfa5292d2592af0cd1ae4a385daf42e7" - }, - { - "name": "3.1", - "release": "3.1.200", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/781cb53b-046c-45fb-b18e-97ad65ff61a0/5c6ce7f4e031dad7cca0fdd5bcf4335b/dotnet-sdk-3.1.200-linux-arm64.tar.gz", - "sha512": "66ec47514d5bd5739db54c4469250e637f99e5792bca758783eb46722cab3a09920b02f7fe3873b1c430cd3ddea85075ce5e62e6f922a9be0c5f367ddf475b64" - }, - { - "name": "3.1", - "release": "3.1.120", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/ead118ce-f9f9-4d0b-ac65-d90e330383a5/d673a7c4f7576e84bf778b5205b8a7ba/dotnet-sdk-3.1.120-linux-arm64.tar.gz", - "sha512": "507c5cade364a71b52c7c9c45ab4ee098b56ec24676ce960a092ba8497a10cacdd4d48184d24d88fd20c20698cf8bb9d0d409b02e706a7440351b37ebbc7de26" - }, - { - "name": "3.1", - "release": "3.1.119", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/4b7053fb-c474-49b7-9064-64b5de935646/20148106c1aa427854d815112d844e8e/dotnet-sdk-3.1.119-linux-arm64.tar.gz", - "sha512": "943de9f6d4f46193cda08e4a149550a0490495ea19ff0a99119070b0d1d16a2c315ea0d05c04bdbfb742db993637ac9e264e7f1e00db4d99184d2874ec55e0ca" - }, - { - "name": "3.1", - "release": "3.1.118", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/22ce33f1-b2b8-400f-b18f-7db499d8cb5d/448893643f3ec460e6cabc4e8053115f/dotnet-sdk-3.1.118-linux-arm64.tar.gz", - "sha512": "c79d4ca598caf3cc0f90e3b3b8b36bfc792b849f4cae538a6b1258c06f79b61d7c93c235e0fb80cae369a1b05a4a0132c7b45f3d862c1829fa356cbafb22e880" - }, - { - "name": "3.1", - "release": "3.1.117", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/af36f11d-46b3-4adf-8d39-bd8607c58edb/2d2fe413f311e55cb729b86c49a214c2/dotnet-sdk-3.1.117-linux-arm64.tar.gz", - "sha512": "6c474b38dbaf6b55cb2f5ce27a98b50f3cb18c1fc1b15448785baf20c371fa42973eeafcf667ab42c7b840ddfde35a6b3fc819c06f9d76963617e74c34220c70" - }, - { - "name": "3.1", - "release": "3.1.116", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/3279c2d9-9604-4c36-9c33-c7f23d16befa/a7593d4f3381a6679cda1864a8cfe0f4/dotnet-sdk-3.1.116-linux-arm64.tar.gz", - "sha512": "3a8f3744290899b860be9a2456df58d84101dbaf8c7383acc89a3c6daaaf03e5f708fe52d67f79bc7da5f3b0bfc4e0731add1ee59ed31b7e4efea40aa0d328d7" - }, - { - "name": "3.1", - "release": "3.1.115", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/5ddeff0d-46d7-4688-ba7b-9b0b1eca68ff/2fcf0dde34749a46ec7dbd92eb255934/dotnet-sdk-3.1.115-linux-arm64.tar.gz", - "sha512": "325a8c43f74ab30b2a6ae52476f37853b361bc862b77eeb74007a3bdf44245615a0bbfaab0971fe6542b24d0a806aa1526869a62e5640635480c8110a024ae57" - }, - { - "name": "3.1", - "release": "3.1.114", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/99d10374-6d9f-4f7d-b79c-c7de5530a082/17105b38223a2bdb340775162dc96e65/dotnet-sdk-3.1.114-linux-arm64.tar.gz", - "sha512": "822ce83c1fe1d5dd4cfbe7cde8cd68dc29db54ef673582e3c9e6423d252592317bb1a579d0f3598b4b967cd30ff015023400382f447a48ec1292649ba47cfadc" - }, - { - "name": "3.1", - "release": "3.1.113", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/313e05b5-61c3-4644-b594-54ecc19c0544/81c3d5179e264f8adc28cc073cbacee2/dotnet-sdk-3.1.113-linux-arm64.tar.gz", - "sha512": "d25ddb029c5ca469895ec97b4d88f8b8ded157aeb51ff20106d53d428851ff8d146e3acd10e869e486f21cdea5d40aef2ba62d1a6586b8bbd4291179df9882b5" - }, - { - "name": "3.1", - "release": "3.1.112", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/9b242a62-b203-44fe-9fb8-964f705b0c6d/ba9802acf2096e4832cb0aecfdc1519c/dotnet-sdk-3.1.112-linux-arm64.tar.gz", - "sha512": "0044bc449af04e0c6d349d0cb9c35a9f30e7e13bb906951e077911a49a5de88faede9f1f798625d10b6cdf8f35695f22e61623570b72f00324005b90d3b6c47d" - }, - { - "name": "3.1", - "release": "3.1.111", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/3e6d3a57-eba8-4036-af2f-257cc4e7c5ff/5307347389772eb8a9b60bbee6a808fa/dotnet-sdk-3.1.111-linux-arm64.tar.gz", - "sha512": "0ea4d5a65d78ca09dcfd558e15accde34ca99647873ffd3584733e79d80ac4df493f466ce2434847bec4dddf2907e247522a5751fd05bd1eb3c82f6023f1e41f" - }, - { - "name": "3.1", - "release": "3.1.110", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/af40aa01-90f9-47cb-8ed6-a186de459e6c/0cb13fba48e467e7788b1ccad83a5358/dotnet-sdk-3.1.110-linux-arm64.tar.gz", - "sha512": "ad20fb6d23ce9967cbd88390510c8207172854ea9ef5a3eae78cfd04dd73b6e312aaaa2f999ce81542c15021b4c313238e9ec01c1b7fb5f39b086848d39a244f" - }, - { - "name": "3.1", - "release": "3.1.109", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/27fdcb48-766c-4f0e-8032-9f2afa40d3af/f2c6dac373046fa2d70e9a41b4a7dadf/dotnet-sdk-3.1.109-linux-arm64.tar.gz", - "sha512": "c3675edda58a8dc8ae9132fb1c5cea0b2a764d5c93ce2f94de0109676d4ef64f21f886d4354a10c441c522a2a8f13493c49501d62fc2c9e7a2f480eaff93cf56" - }, - { - "name": "3.1", - "release": "3.1.108", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/572d9a06-dd1e-4349-a443-702b5382605c/dbe9647eceb84dea786af91cd11a9e3e/dotnet-sdk-3.1.108-linux-arm64.tar.gz", - "sha512": "b83513ffcfcddaca679edbd731ec4dbe8d653c46e626f0e1dcb700559a16effe0859d8c9a9b4a5e79e3de23521e0f37f8794e493075018c0fd7b8df7bc889d54" - }, - { - "name": "3.1", - "release": "3.1.107", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/6e1897f2-8de1-41f2-828e-f2651d6448f9/c25e59f180ffb6a31d5e3f0a163391a0/dotnet-sdk-3.1.107-linux-arm64.tar.gz", - "sha512": "80f980455452b3d63c55585b8009a5475331202dc60c2d8b6990bf4ef367a652e07dd29d1e2d879042f65f90ecebadd4178042f3446186dfbdf530c8e39237a5" - }, - { - "name": "3.1", - "release": "3.1.106", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/026fec12-345b-4c61-8731-1c0184594fc3/1738a6c43d2739dc6c2a9ec5caf0c41f/dotnet-sdk-3.1.106-linux-arm64.tar.gz", - "sha512": "aa2cb7ce94a013b1204dd9523e4fa0051dd43545b5a881647e44f1cf998dd1aafc7e1c709f603306c25bcf064ffbd8295cb17e17fb974e9dfa469e2ecf991f92" - }, - { - "name": "3.1", - "release": "3.1.105", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/a2de5fc2-1c17-4ea2-bf3f-77c404e9263e/f9c79b6067afc819656ba9f6e6a4ed73/dotnet-sdk-3.1.105-linux-arm64.tar.gz", - "sha512": "10c13928f8f3b4a7bd0c782d3579e417b526f3497cb59deeef4ae9e7fae3228df2ecddfeb1c66f9c2d329204a62fa0c4bb759e2954a0e26ac00419b3efd6017e" - }, - { - "name": "3.1", - "release": "3.1.104", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/7148dc66-dc70-4d6f-ae3d-c65aa8443259/734885b4dafa4097c0b264ca20be7e26/dotnet-sdk-3.1.104-linux-arm64.tar.gz", - "sha512": "a8bd5535af395dff4130d47e288837bda036b73a074f84755d1224d2c703304bcd36593dda5eb3f139a051060030a100516b5e8a2fd2fcdbb192eb04c1a341a8" - }, - { - "name": "3.1", - "release": "3.1.103", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/2231ea64-1835-4e2f-bcff-f611bd803786/3e492dc64e6c3e6ca977e1e2abace10a/dotnet-sdk-3.1.103-linux-arm64.tar.gz", - "sha512": "f146fb6678262fa9214f02a0567a2bde2b2e56511fc9c2953b64aa4cfef11d9ef9a834324f21c64a497bdf347435db644eae999bc102c328bfbc1aaac062f24d" - }, - { - "name": "3.1", - "release": "3.1.102", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/2ea7ea69-6110-4c39-a07c-bd4df663e49b/5d60f17a167a5696e63904f7a586d072/dotnet-sdk-3.1.102-linux-arm64.tar.gz", - "sha512": "7ad682935158599aeff1f04228df65ce99aa7d34fbe096422a55d6b0c6b38a7de4b9d0af1b667f63728b051d355f0c69526ffa90bb4c4d8ded53fb4ba63233c9" - }, - { - "name": "3.1", - "release": "3.1.101", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/cf54dd72-eab1-4f5c-ac1e-55e2a9006739/d66fc7e2d4ee6c709834dd31db23b743/dotnet-sdk-3.1.101-linux-arm64.tar.gz", - "sha512": "03ea4cc342834a80f29b3b59ea1d7462e1814311dc6597bf2333359061b9b24f5ce98ed6ebf8d7ca05d42db31baba8ed8d4dec30a576fd818b3c0041c86d2937" - }, - { - "name": "3.1", - "release": "3.1.100", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/5a4c8f96-1c73-401c-a6de-8e100403188a/0ce6ab39747e2508366d498f9c0a0669/dotnet-sdk-3.1.100-linux-arm64.tar.gz", - "sha512": "93634c555698ca5c3392332a93551b1548fa103328401c5c25e8955f085124b887b73736b70a139fc8eb8d622e47fcfc0aa25210b73a8f851906b32eaa8a9887" - }, - { - "name": "6.0", - "release": "6.0.403", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/10cadabb-4cb4-4cca-94db-67cb31cb6f3a/5b3d102b4198da0a25ed12d83ae5633d/dotnet-sdk-6.0.403-linux-arm.tar.gz", - "sha512": "b07423700a92e3cc79f4e9e02c40e923352c09958e3307fd2ce7fc882509460c65a4404e8080f1b3852af98458512699ba43b37683916756666b4e2532cc8f46" - }, - { - "name": "6.0", - "release": "6.0.402", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/7be1dda3-3412-4f9a-88f2-e6a8e5f118ff/7bd57a63288994da06e7a1b9a4e407e3/dotnet-sdk-6.0.402-linux-arm.tar.gz", - "sha512": "98b275af781ac7be20e22736d601ea667161640703b9d430340e517fb2c1bdcd6d06d5eb4f374cab1f6e29c9135005050ec89dd8dcf0ec97e7b0d9912e52f988" - }, - { - "name": "6.0", - "release": "6.0.401", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/451f282f-dd26-4acd-9395-36cc3a9758e4/f5399d2ebced2ad9640db6283aa9d714/dotnet-sdk-6.0.401-linux-arm.tar.gz", - "sha512": "7d3c32f510a7298b8e4c32a95e7d3c9b0475d94510732a405163c7bff589ffda8964f2e9336d560bd1dc37461e6cb3da5809337a586da0288bdcc71496013ba0" - }, - { - "name": "6.0", - "release": "6.0.400", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/5a24144e-0d7d-4cc9-b9d8-b4d32d6bb084/e882181e475e3c66f48a22fbfc7b19c0/dotnet-sdk-6.0.400-linux-arm.tar.gz", - "sha512": "a72aa70bfb15e21a20ddd90c2c3e37acb53e6f1e50f5b6948aac616b28f80ac81e1157e8db5688e21dc9a7496011ef0fcf06cdca74ddc7271f9a1c6268f4b1b2" - }, - { - "name": "6.0", - "release": "6.0.306", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/a752d876-ddea-41a9-b8c6-5326b48791e3/ade6f4c1672c5357f140c44bba1b9acd/dotnet-sdk-6.0.306-linux-arm.tar.gz", - "sha512": "9ea0273b8e9a7ba0650aa6d989933d959a75f0c6c2cae46b1e6ba23913ddd25c6546275d9a21d540b760a9202fa802a484f713cacd0312405345142dfe452c6e" - }, - { - "name": "6.0", - "release": "6.0.305", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/2f5729be-273f-45fd-a1ec-f91695951839/a26275ca2b4abf646c7783c5a409ff31/dotnet-sdk-6.0.305-linux-arm.tar.gz", - "sha512": "ae7ab7920e1ba2833ce55c44116e4400fdebd8ce48d3b193b590b938e25909a647a34706f32dd4fe2a8468ff61a8bc962d7c8dfde5404293b6254c5e980f46a6" - }, - { - "name": "6.0", - "release": "6.0.304", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/32139893-1030-4515-a6a6-e3392685e9af/5f4b8acdaabe97f6d6d105e38a5c1557/dotnet-sdk-6.0.304-linux-arm.tar.gz", - "sha512": "4cbcb1fe9d9c3be643d3d0247e5cb4eff95778429a4eeae38060d268b3d31ef4c51cd47357c03a4d4281c5eb20feaa07ac140d430ffe4270c0f37aba3af546b4" - }, - { - "name": "6.0", - "release": "6.0.303", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/89e0bd36-57eb-41e4-95c9-4e35569e0f6b/1e7b6862caa6488465ab74d7c44bf130/dotnet-sdk-6.0.303-linux-arm.tar.gz", - "sha512": "444b8055f6814d5282e320ae243244fa27fe8afe76356c7d06e03a399ae2d41806cefc523a7bf12f36931931da88964d6797f1758a9cf23671aae318f41d3167" - }, - { - "name": "6.0", - "release": "6.0.302", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/f35557f7-d5e1-43be-93b6-e59ee8bd823c/9dd2c25a4d7351412ff5902c355732ca/dotnet-sdk-6.0.302-linux-arm.tar.gz", - "sha512": "0d31c7e8ccf02c8dea92d7b60bcb15e15912d74e7ee2ab8fd88ee03c4fbd8f292c356357d08ec23c2aedc5e3e0803d42ce16f3fff36245739d0cac6634bc3387" - }, - { - "name": "6.0", - "release": "6.0.301", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/a218e3b9-941b-43be-bfb1-615862777457/80954de34ab68729981ed372a8d25b46/dotnet-sdk-6.0.301-linux-arm.tar.gz", - "sha512": "ef7d028b80eaaae18b71195e89e00dea2186d455f7b72f373fc0a57074e8320c8e9245167c06e30a2ddade4ab21ad5e8b05d04a6ea11c1de68b7c9a6f9807d25" - }, - { - "name": "6.0", - "release": "6.0.300", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/ef1d4f88-cbe9-47c2-9fb3-e7e772be1a4c/4fbbf2a11cee4f52a478a46b1a69ed03/dotnet-sdk-6.0.300-linux-arm.tar.gz", - "sha512": "362e09bbe36a827beacbf36af6d66f7a6eb6da92e002e9a466a597f2fc181754e8893840c68c67a6c5e94b39e2dec1da360c72814bd904b325171ff7d06c56eb" - }, - { - "name": "6.0", - "release": "6.0.203", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/88fefcd9-70aa-4bca-80f8-4a78d6b8b53c/7ee6202e44cea4fa104f5f788425fcaf/dotnet-sdk-6.0.203-linux-arm.tar.gz", - "sha512": "e6cb656e4acf450023413cd0e155e9c4f294887dec1fb6c87d4e9951eb29d0ad697f50719e42fe3dbea0a34f9d297dce9261c541a7e43e6e4a359c8db215390d" - }, - { - "name": "6.0", - "release": "6.0.202", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/e41a177d-9f0b-4afe-97a4-53587cd89d00/c2c897aa6442d49c1d2d86abb23c20b2/dotnet-sdk-6.0.202-linux-arm.tar.gz", - "sha512": "8c2d56256f4bebe58caee7810b7689408ff023b1f2e68f99fa375f0115db41ef0c3eb160b9ab84dc2764443a045801a4b03f6bc9090e0c1583fca2587ea0d9d6" - }, - { - "name": "6.0", - "release": "6.0.201", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/eefec3fa-c4c3-454d-bd7d-8fda31d15e5f/62668641ffc94db5fa11187f14a981f8/dotnet-sdk-6.0.201-linux-arm.tar.gz", - "sha512": "5a683430325a90dd1d8e0071a1868939fb01268f9eb389ca1dc40956fde6b9f45bec086553ad3333139e530dfe5afae48195bcdfec388b0b568989924a1f1dd7" - }, - { - "name": "6.0", - "release": "6.0.200", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/4cfcfa53-f421-4257-8cd2-d4078f9ffe90/008804a5475fa0d46b9e8f03cb78bfcd/dotnet-sdk-6.0.200-linux-arm.tar.gz", - "sha512": "c2950d5da671a50c955d07997b288c02076b1d69014d3ac3f5941179e29a67b4d56fc5acbde85fe13ffd46efa95ead05b39d90dc577d2a668f637e6a9547944a" - }, - { - "name": "6.0", - "release": "6.0.111", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/f8693beb-cb52-4d0b-9362-c93f47f2e0f5/7fa339566925e191039a6db91de3d547/dotnet-sdk-6.0.111-linux-arm.tar.gz", - "sha512": "44388611a84620e09e3adea7ada8ce4e04ef675d54c3a6ef12017bbed25e7c5d100089a700c503e9edc8605f9c0f48995f3b4595bd3179910a6cf4e2c11b1a53" - }, - { - "name": "6.0", - "release": "6.0.110", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/ec48c241-aa98-44fb-8e9e-f8ec91f048ec/8c9b79c23058a1c0ad7b3e0fdc340d41/dotnet-sdk-6.0.110-linux-arm.tar.gz", - "sha512": "ed8a0a3c5edc42b6e82dc925c35ebd3ba0ddf94b98c97febb0f4ffa758b369b2c063935fa62cc5e18c1f26e64e0618daf2600d8a9946a0d44f6103d725d99091" - }, - { - "name": "6.0", - "release": "6.0.109", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/743cf42d-f201-4dd6-ada8-37bd46cef977/d3508390013604f9023dab6698492aea/dotnet-sdk-6.0.109-linux-arm.tar.gz", - "sha512": "b757ffdef4b87a9394ce0a367f5563b2900e9720eba6b071ce22e454eaddcb7983bde182d90ef552b5b903c2b5505af5ab642190c982dfc18649ea8ee8657886" - }, - { - "name": "6.0", - "release": "6.0.108", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/69439f13-034e-4961-b0ba-1ef3b7dfeada/b3afee58e324bcd2c0e2a124b7472635/dotnet-sdk-6.0.108-linux-arm.tar.gz", - "sha512": "c3726e053b447e7baec21e015a91dddb884a79a483c7d2a247f2fe143a5cff25e5d7e822944c6b12f0b030d39b4e71c1da437e2ee4c094dd1bcdeccad3c44568" - }, - { - "name": "6.0", - "release": "6.0.107", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/e69db7cd-ea5c-40ea-87cd-cc567cbd6c3f/0765ead789975a5f4359fe44e3e7596a/dotnet-sdk-6.0.107-linux-arm.tar.gz", - "sha512": "05364e5f3c3be3f66420310c1fe26550d639c6e95b43ed004ea79017ee8c973d73349ff87c5eca4c560f80fea55a435c1c22f3889d5c015b85474533395245f4" - }, - { - "name": "6.0", - "release": "6.0.106", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/cba88c45-5ea4-43ed-b495-099d9925b561/af8f6468186950a4f87e932f888434a8/dotnet-sdk-6.0.106-linux-arm.tar.gz", - "sha512": "9973fa26f7129e4f148e65123512ba02644b78b47a7d4b1fbeeafd09038beac66664b285ace5e228a7818f0c35a357d31ff1d580795182c872c514fdb3b90e35" - }, - { - "name": "6.0", - "release": "6.0.105", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/e3c5dfe0-e6ba-4660-a73e-d6edacfdc894/4fba777299a959a5e3125a955866c49a/dotnet-sdk-6.0.105-linux-arm.tar.gz", - "sha512": "edfb33b0956cf1398f460847505cebd8571b82ae870f64e48de54b67d5cbdb5d3cdcfe2328ce9f096d665751bae844eb5a1f66fb707da2ad888d694016444adb" - }, - { - "name": "6.0", - "release": "6.0.104", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/4a905b9c-e97e-4ab6-a258-d9dd9d41564f/af30654ab6af793527e9652dfa29c817/dotnet-sdk-6.0.104-linux-arm.tar.gz", - "sha512": "96c3af8b9c920b542a4e9fc3ce26242a0d193404d74b7e88d223d44b2e597da83d44892d89f7fed5385acad1ff5f787bbd81381f01c3cd1b0d89888d14688750" - }, - { - "name": "6.0", - "release": "6.0.103", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/3324d5ae-3b19-4906-a5be-c088c08d4bae/b95253ada2fc9ad129c58a66db09f3ab/dotnet-sdk-6.0.103-linux-arm.tar.gz", - "sha512": "e1ad50651dbd80cd9a089a5032f32c110b47b74935813aa3cbd8a8473ef65f139e5bed61f4952c9ff4ff95fff11c51a12095dd33e228733208222c13c95034c5" - }, - { - "name": "6.0", - "release": "6.0.102", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/2509d293-6a9f-4108-8fe1-10e78341c5df/18f693729320bdbb5e8d936460dd0e2b/dotnet-sdk-6.0.102-linux-arm.tar.gz", - "sha512": "a72a0e81c62478b0dc662ef0aaeb7f96e7dd534e90b3ac1bdab1ca98dd93a4605881dba6e9ed2315781fdf71f5b33acb1aa5e28090c7a1693405bebed5853094" - }, - { - "name": "6.0", - "release": "6.0.101", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/72888385-910d-4ef3-bae2-c08c28e42af0/59be90572fdcc10766f1baf5ac39529a/dotnet-sdk-6.0.101-linux-arm.tar.gz", - "sha512": "f9e212dc4cccbe665d9aac23da6bdddce4957ae4e4d407cf3f1d6da7e79784ebd408c3a59b3ecc6ceaa930b37cf01a4a91c6b38517970d49227e96e50658cc46" - }, - { - "name": "6.0", - "release": "6.0.100", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/1f85b038-9917-4d0a-8485-5dc86510eec7/a7555924fe292c6c2140893f066abe65/dotnet-sdk-6.0.100-linux-arm.tar.gz", - "sha512": "c1e555893c48c4f4256d3e6b1d36b31d8a4d7763a6e958fb63dd31436c660648d481612b5e25d79a613e84a1954f5eac2c9c2b740bf410958172780f7bbeaeb3" - }, - { - "name": "6.0", - "release": "6.0.403", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/67ca3f83-3769-4cd8-882a-27ab0c191784/bf631a0229827de92f5c026055218cc0/dotnet-sdk-6.0.403-linux-arm64.tar.gz", - "sha512": "fe62f6eca80acb6774f0a80c472dd02851d88f7ec09cc7f1cadd9981ec0ee1ceb87224911fc0c544cb932c7f5a91c66471a0458b50f85c899154bc8c3605a88e" - }, - { - "name": "6.0", - "release": "6.0.402", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/234daf6a-5e12-4fa3-a73b-b12db44a3154/df7c012e5e4e2cc510de9226425dad88/dotnet-sdk-6.0.402-linux-arm64.tar.gz", - "sha512": "2f5351192e87c2dd196d975e7618bd7b0b542034d0b1bc932fe944d8cbabb0ed2599e98e88d9757e68f198559961ab3350d8eddfacc2951df00fbf6a7e44f244" - }, - { - "name": "6.0", - "release": "6.0.401", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/a567a07f-af9d-451a-834c-a746ac299e6b/1d9d74b54cf580f93cad71a6bf7b32be/dotnet-sdk-6.0.401-linux-arm64.tar.gz", - "sha512": "8c05f9e02e0a48fcc3e4534fa7225fe5b974c07f1a4788c46207e18e94031194e1c881e40452ee6c432764e92331c50ae47305d4aec5afa363fab3a8a6727cdf" - }, - { - "name": "6.0", - "release": "6.0.400", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/901f7928-5479-4d32-a9e5-ba66162ca0e4/d00b935ec4dc79a27f5bde00712ed3d7/dotnet-sdk-6.0.400-linux-arm64.tar.gz", - "sha512": "a21010f9e0e091bf0a4df9dfc4ec9893c056c2b07b10be093ea392a4fa5c8a38bad9535f66e570b45dc25165b685199fb729434b845bcfb35f8b79cceb22c632" - }, - { - "name": "6.0", - "release": "6.0.306", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/fb258146-ac1b-480d-99b2-fecb7a607705/66e827540def06412bf11da9e6accb61/dotnet-sdk-6.0.306-linux-arm64.tar.gz", - "sha512": "cc49223db9c6309c4f0f7e208dfa07a1e9bdde032c2047b9aa2711e03d8aa0da91da22d728b332c2c9adbc54f423bb7e1dcdcb3888ed9ceef899d6e74bd308b2" - }, - { - "name": "6.0", - "release": "6.0.305", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/031e2cdb-71ae-4f10-8862-e2883ff82f03/fdbd377c5d84c1c07c4b8d1c87cca6bc/dotnet-sdk-6.0.305-linux-arm64.tar.gz", - "sha512": "0d7eb35dc1b2ee8c31710bab2eeb1f6871819168bcdf7aff257074cd0c4eafc3ad52875a45cec38ad799a12e8c81bddc6267f6b608aadfd9607d435cb3e6ba6f" - }, - { - "name": "6.0", - "release": "6.0.304", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/6d879cce-4273-42d6-b39d-0cc4d3ab198e/3a63185d3aa4685be69aa395a0986f24/dotnet-sdk-6.0.304-linux-arm64.tar.gz", - "sha512": "69dbd86331002990d7f6c915b0fb832c5d8ba55bb4dacbd6a4065ca7d59e92902fb5052f6cd905a453e42355a655d526b5c12be8fb5d12255af2d345d5b12846" - }, - { - "name": "6.0", - "release": "6.0.303", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/625d6cbb-7d21-41ab-a474-3ba603770d1d/7016fc39dc1eb5c8c7c5e2cc36440212/dotnet-sdk-6.0.303-linux-arm64.tar.gz", - "sha512": "b6eed880882873a35fdda99f8cc4a3d7b72851004244cd9a2e8656b475c4e766da78cfb33e0f034e742da39200b583ae9970c284e1401f1a4645c9d9d4429282" - }, - { - "name": "6.0", - "release": "6.0.302", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/33389348-a7d7-41ae-850f-ec46d3ca9612/36bad11f948b05a4fa9faac93c35e574/dotnet-sdk-6.0.302-linux-arm64.tar.gz", - "sha512": "26e98a63665d707b1a7729f1794077316f9927edd88d12d82d0357fe597096b0d89b64a085fcdf0cf49807a443bbfebb48e10ea91cea890846cf4308e67c4ea5" - }, - { - "name": "6.0", - "release": "6.0.301", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/06c4ee8e-bf2c-4e46-ab1c-e14dd72311c1/f7bc6c9677eaccadd1d0e76c55d361ea/dotnet-sdk-6.0.301-linux-arm64.tar.gz", - "sha512": "978dd04f78ac3d6b594c47f1482bba0abe93f0b37379c1c46a2b9b33bdf5188576b055250546295de39bb22cba93ea9b31c31bb026a319ad1b3fc507db44481f" - }, - { - "name": "6.0", - "release": "6.0.300", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/7c62b503-4ede-4ff2-bc38-50f250a86d89/3b5e9db04cbe0169e852cb050a0dffce/dotnet-sdk-6.0.300-linux-arm64.tar.gz", - "sha512": "67eb088ccad197a39f104af60f3e6d12ea9b17560e059c0f7c8e956005d919d00bf0f3e487b06280be63ad57aa8895f16ebc8c92107c5019c9cf47bd620ea925" - }, - { - "name": "6.0", - "release": "6.0.203", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/c7d9ebd1-16cd-44d5-b406-177ad676c630/1a46912f74a71117bee6077ad3b832df/dotnet-sdk-6.0.203-linux-arm64.tar.gz", - "sha512": "552448b13cc77fc1e6189f4954eab16e8a87822189f3e488e6bc73ac099a8fbe6f34b667dabee637522e35edad30661ba32cdd4b94d57bb5cea9441e2f4abf19" - }, - { - "name": "6.0", - "release": "6.0.202", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/952f5525-7227-496f-85e5-09cadfb44629/eefd0f6eb8f809bfaf4f0661809ed826/dotnet-sdk-6.0.202-linux-arm64.tar.gz", - "sha512": "2d0021bb4cd221ffba6888dbd6300e459f45f4f9d3cf7323f3b97ee0f093ef678f5a36d1c982296f4e15bbcbd7275ced72c3e9b2fc754039ba663d0612ffd866" - }, - { - "name": "6.0", - "release": "6.0.201", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/33c6e1e3-e81f-44e8-9de8-91934fba3c94/9105f95a9e37cda6bd0c33651be2b90a/dotnet-sdk-6.0.201-linux-arm64.tar.gz", - "sha512": "2ea443c27ab7ca9d566e4df0e842063642394fd22fe2a8620371171c8207ae6a4a72c8c54fc6af5b6b053be25cf9c09a74504f08b963e5bd84544619aed9afc2" - }, - { - "name": "6.0", - "release": "6.0.200", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/ad60a07c-d4f0-4225-9154-c3a2ec0f34cf/a588cd2b94db2214f6e5dcd02c4aa37a/dotnet-sdk-6.0.200-linux-arm64.tar.gz", - "sha512": "4e2b8f65f4cd9d1e54233b377e7efef5202eee3fa5e4592131ff03ecab032bfccdc91f4e8c806064fb769c48f946634bf1e420afecd7fcd2d981d40eeec5a881" - }, - { - "name": "6.0", - "release": "6.0.111", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/f83d8e86-8cc1-4787-b6a7-b318d19d9582/9eca68b2392ba2798b70d598d49837ec/dotnet-sdk-6.0.111-linux-arm64.tar.gz", - "sha512": "7473eef3715c83ff399adaaf2605ae28f0144186024e3a4a5661ca978cc376262203147d77c51476cd88b5d7bdd7b3700221f214083eb77838a41a1357766b7c" - }, - { - "name": "6.0", - "release": "6.0.110", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/1a0faccb-a85e-43b7-b2a6-78ee8b975855/572b91765e7db29d33887cf4b87bc86c/dotnet-sdk-6.0.110-linux-arm64.tar.gz", - "sha512": "da312773a6def29612ea6898c489b86b2546e5e52c7c890134712c64fb3c0e52dfab88d8589858f9a9b39c3d2c9fc39406d6da251e3cfca399eb93df0c9ad5c6" - }, - { - "name": "6.0", - "release": "6.0.109", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/5da20803-1c48-4e54-a87c-88cda79efd77/4e6cd608eca3e34540d89e1ec3df5e6b/dotnet-sdk-6.0.109-linux-arm64.tar.gz", - "sha512": "eb4a42a45cbf8a92d2f78d4299ec34ab11d6d8dbc28dcab9dbe95648e40895a0dc56675a99b4df9e1f5a42ab0f3368322ae17381810d9bac5cb8623066120b80" - }, - { - "name": "6.0", - "release": "6.0.108", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/f3162067-d239-4518-9423-32559f4b6ebe/e944b933ee94602074678b2ea1374b6e/dotnet-sdk-6.0.108-linux-arm64.tar.gz", - "sha512": "95f5c47fb27882f5554b0ee0befb813357875d6bfd19447c7c902ce225ed394bbb6cd945c5f7d5233fe0d3a16a1c006f47eba9d6be51cf8578fc5fbeba2806f0" - }, - { - "name": "6.0", - "release": "6.0.107", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/dd4f49ba-39b0-4358-bd82-18cb5b1350d1/ec891910fd6f13c22448a8162fe1f017/dotnet-sdk-6.0.107-linux-arm64.tar.gz", - "sha512": "946b43f0da3e5d94d20163d6a94fc4fcef66c1c18d6fa02530e769201d96c9e2125c0f35532ea87e0c5b4f3a491daa6d4b8d6dd23f4eb9da32625ca0a4065e14" - }, - { - "name": "6.0", - "release": "6.0.106", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/3a8c5d20-21ac-40cf-b3c5-2efd29a88870/b6f62cff4a13924832a81574e5ef5a80/dotnet-sdk-6.0.106-linux-arm64.tar.gz", - "sha512": "86fabee178d16dcf9b5ff3d2f786c72be6bea5838b69c9e02d3a356703799378094a87f3ae4cc3ed6564f2c762a1837c4d8f91a228ba94cf58546d5ba7363f8f" - }, - { - "name": "6.0", - "release": "6.0.105", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/54abc3c4-4ed6-4d0e-804f-71372f91051e/6dc0cc5cbf2052e6ace42248473464f3/dotnet-sdk-6.0.105-linux-arm64.tar.gz", - "sha512": "e995bf3da74b2b9b0cb17339be5cd34299e2d5471cd72e923919e9ac22badde369d23357f09c3dbc121c10da366f6650ee8721adec3a11911ef5fed223b9accd" - }, - { - "name": "6.0", - "release": "6.0.104", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/e61cf583-1e44-4ac5-a04f-5b59fda42ea7/df3853bb318af131f7eafa61f2b839b8/dotnet-sdk-6.0.104-linux-arm64.tar.gz", - "sha512": "91fa1114a656173a988aafd65c657c9498c34ef9145eac60b6feacc8a08f68538defeb38af472e2626ffd0669eb62140fdb1408771db0e2b63501baf2a646f29" - }, - { - "name": "6.0", - "release": "6.0.103", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/84b9132d-f18e-4f54-bd34-ed4ffcbfa1f7/8a4cc6ca1d60a58963a1866a2b1857fe/dotnet-sdk-6.0.103-linux-arm64.tar.gz", - "sha512": "e9efdbbb36a064b2cddcadc7b8c3a92dabc0da5c9491a6a39580720739d9a7517fee8e9ea2073d2dbfc91685f093a950bcb80713ba77413da07c17cddbbbfe55" - }, - { - "name": "6.0", - "release": "6.0.102", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/93dd8d1e-f2af-45b1-8e86-9b8c3d58f4d2/b3fc3ef9da1db691043387fcb56f4d6f/dotnet-sdk-6.0.102-linux-arm64.tar.gz", - "sha512": "790cbf322ca8fed32eaf574f19d0bdc05656c5a88a65aa4dba8269cfce1443cd7cdeecdd3a40e353c368f055490b70592ca7f15f981a66c5b3a9517d0b09e4cb" - }, - { - "name": "6.0", - "release": "6.0.101", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/d43345e2-f0d7-4866-b56e-419071f30ebe/68debcece0276e9b25a65ec5798cf07b/dotnet-sdk-6.0.101-linux-arm64.tar.gz", - "sha512": "04cd89279f412ae6b11170d1724c6ac42bb5d4fae8352020a1f28511086dd6d6af2106dd48ebe3b39d312a21ee8925115de51979687a9161819a3a29e270a954" - }, - { - "name": "6.0", - "release": "6.0.100", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/adcd9310-5072-4179-9b8b-16563b897995/15a7595966f488c74909e4a9273c0e24/dotnet-sdk-6.0.100-linux-arm64.tar.gz", - "sha512": "e5983c1c599d6dc7c3c7496b9698e47c68247f04a5d0d1e3162969d071471297bce1c2fd3a1f9fb88645006c327ae79f880dcbdd8eefc9166fd717331f2716e7" - }, - { - "name": "7.0", - "release": "7.0.100", - "architecture": "Arm32", - "link": "https://download.visualstudio.microsoft.com/download/pr/fd193b5b-f171-436e-8783-5eb77a7ad5ee/2a0af2a874f3c4f7da0199dc64996829/dotnet-sdk-7.0.100-linux-arm.tar.gz", - "sha512": "11c1150357a0a79095b563671bc038085f8bbbc678a47681c4decade22fcb18504e60732518e681a5688008e7ffbad69933a8ff3bd91c09ff4df66a80a596809" - }, - { - "name": "7.0", - "release": "7.0.100", - "architecture": "Arm64", - "link": "https://download.visualstudio.microsoft.com/download/pr/47337472-c910-4815-9d9b-80e1a30fcf16/14847f6a51a6a7e53a859d4a17edc311/dotnet-sdk-7.0.100-linux-arm64.tar.gz", - "sha512": "0a332df58891e808c9adc2b785e9b0e658b29b494963c8d501b0f8806ff5d3daad4614886349cbba86af638ed7ac76e78a2d05aeca13bac25d5f45fbe62b8251" - } - ] -} \ No newline at end of file From 88b2e38a9af0bd077fb8d0290689754c7376bfde Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Mon, 2 Oct 2023 15:55:40 -0400 Subject: [PATCH 15/37] Fix: MS .NET SDK install scripts don't pick up on arm (32bit) OS. Force the --architecture flag on the .NET SDK download/install ops. --- RaspberryDebugger/Connection/Connection.cs | 15 ++++++++++----- RaspberryDebugger/DebugHelper.cs | 2 +- .../Models/VisualStudio/ProjectProperties.cs | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index f1cda79..5115f5b 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -546,7 +546,7 @@ exit 0 /// Download and install actual (latest) SDK /// /// true if successful - public async Task SetupSdkAsync(Version projectSdkVersion) + public async Task SetupSdkAsync(Version projectSdkVersion, Status piStatus ) { // .NET 3.1, 6 and 7 are supported. When 8 arrives this should work. if (projectSdkVersion.Major != 3 && @@ -566,7 +566,7 @@ public async Task SetupSdkAsync(Version projectSdkVersion) LogInfo($"The project requires .NET SDK {projectSdkVersion} which is not installed."); return await this.InstallSdkPrerequsitesAsync() && - await InstallSdkAsync(projectSdkVersion); + await InstallSdkAsync(projectSdkVersion, piStatus); } /// @@ -638,9 +638,14 @@ enum SdkQuality /// The Raspberry architecture is driving the installation - the newest .NET Core version is taken /// /// true on success. - private async Task InstallSdkAsync(Version targetSdk) + private async Task InstallSdkAsync(Version targetSdk, Status piStatus) { - var sdkQuality = SdkQuality.GA; + var verbose = string.Empty;// "--verbose"; + var sdkQuality = SdkQuality.GA; + + var arch = piStatus.Architecture == SdkArchitecture.Arm64 ? + "arm64" : + "arm"; // Install the SDK. LogInfo($"Installing .NET SDK {targetSdk}"); @@ -652,7 +657,7 @@ private async Task InstallSdkAsync(Version targetSdk) // TODO? Use a JSON file to control updates // see: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script var installCommand = - $"""curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel {targetSdk.ToString(2)} --quality {sdkQuality} --install-dir {PackageHelper.RemoteDotnetFolder}"""; + $"""curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --architecture {arch} --channel {targetSdk.ToString(2)} --quality {sdkQuality} --install-dir {PackageHelper.RemoteDotnetFolder} {verbose}"""; return await PackageHelper.ExecuteWithProgressAsync( $"Installing .NET SDK {targetSdk} on Raspberry {this.connectionInfo.Host}...", diff --git a/RaspberryDebugger/DebugHelper.cs b/RaspberryDebugger/DebugHelper.cs index 2af7ceb..8842e0b 100644 --- a/RaspberryDebugger/DebugHelper.cs +++ b/RaspberryDebugger/DebugHelper.cs @@ -567,7 +567,7 @@ public static ConnectionInfo GetDebugConnectionInfo(ProjectProperties projectPro } // Ensure that the SDK is installed. - if (!await connection.SetupSdkAsync(projectProperties.SdkVersion)) + if (!await connection.SetupSdkAsync(projectProperties.SdkVersion, connection.PiStatus)) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); diff --git a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs index 4c3cb37..bdb3c6d 100644 --- a/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs +++ b/RaspberryDebugger/Models/VisualStudio/ProjectProperties.cs @@ -257,6 +257,7 @@ string SetLaunchUrl(JObject profileObject) .Item( "PlatformTarget" ).Value; // For the time being make linux-arm64 the default. + // linux-arm64 //var runtime = string.IsNullOrEmpty( platformTarget ) ? platformTarget : $"linux-{platformTarget}"; var runtime = string.IsNullOrEmpty(platformTarget) ? "linux-arm64" : $"linux-{platformTarget}"; From 330d93c46b6e8ec51c15c86471f8628bf3fbb35a Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Tue, 3 Oct 2023 08:34:35 -0400 Subject: [PATCH 16/37] Fix: NullReferenceException on new Raspian image. Pass the projectsettings object into the connect retry to prevent exception on subsequent operations. Also add arch to text for SDK install. --- RaspberryDebugger/Connection/Connection.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RaspberryDebugger/Connection/Connection.cs b/RaspberryDebugger/Connection/Connection.cs index 5115f5b..f5f0362 100644 --- a/RaspberryDebugger/Connection/Connection.cs +++ b/RaspberryDebugger/Connection/Connection.cs @@ -125,7 +125,7 @@ public static async Task ConnectAsync(ConnectionInfo connectionInfo, try { - var connection = await ConnectAsync(connectionInfo, usePassword: true); + var connection = await ConnectAsync(connectionInfo, usePassword: true, projectSettings); // Append the public key to the user's [authorized_keys] file if it's // not already present. @@ -648,7 +648,7 @@ private async Task InstallSdkAsync(Version targetSdk, Status piStatus) "arm"; // Install the SDK. - LogInfo($"Installing .NET SDK {targetSdk}"); + LogInfo($"Installing .NET SDK {targetSdk} {arch}"); // Use the install script to install the latest version of the .NET SDK rather than use the // PackageHelper.SdkCatalog list which must be updated manually. It doesn't require looking @@ -660,7 +660,7 @@ private async Task InstallSdkAsync(Version targetSdk, Status piStatus) $"""curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --architecture {arch} --channel {targetSdk.ToString(2)} --quality {sdkQuality} --install-dir {PackageHelper.RemoteDotnetFolder} {verbose}"""; return await PackageHelper.ExecuteWithProgressAsync( - $"Installing .NET SDK {targetSdk} on Raspberry {this.connectionInfo.Host}...", + $"Installing .NET SDK {targetSdk} {arch} on Raspberry {this.connectionInfo.Host}...", async () => { try From 157c0827a97b0012af62cfa1daeb4885bc5cb690 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Mon, 28 Oct 2024 13:19:43 -0400 Subject: [PATCH 17/37] Update: Update Nuget packages. Update to the latest available packages on all references. --- RaspberryDebugger/Dialogs/ConnectionDialog.cs | 580 +++++++++--------- RaspberryDebugger/RaspberryDebugger.csproj | 452 +++++++------- 2 files changed, 516 insertions(+), 516 deletions(-) diff --git a/RaspberryDebugger/Dialogs/ConnectionDialog.cs b/RaspberryDebugger/Dialogs/ConnectionDialog.cs index b7827be..b07d3e3 100644 --- a/RaspberryDebugger/Dialogs/ConnectionDialog.cs +++ b/RaspberryDebugger/Dialogs/ConnectionDialog.cs @@ -1,290 +1,290 @@ -//----------------------------------------------------------------------------- -// FILE: ConnectionDialog.cs -// CONTRIBUTOR: Jeff Lill -// COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Windows.Forms; -using Neon.Net; -using RaspberryDebugger.Models.Connection; - -namespace RaspberryDebugger.Dialogs -{ - /// - /// Implements the Add/Remove connection dialogs. - /// - internal partial class ConnectionDialog : Form - { - private const char PasswordChar = '•'; - - private readonly List existingConnections; - - /// - /// Constructor. - /// - /// The information for the connection being created or edited. - /// Pass true when editing, false for creating a new connection. - /// The existing connection. - public ConnectionDialog(ConnectionInfo connectionInfo, bool edit, List existingConnections) - { - InitializeComponent(); - - this.ConnectionInfo = connectionInfo; - this.Text = edit ? "Edit Raspberry Connection" : "New Raspberry Connection"; - this.existingConnections = existingConnections; - - // Initialize the controls on load. - this.Load += (s, a) => - { - hostTextBox.Text = connectionInfo.Host; - portTextBox.Text = connectionInfo.Port.ToString(); - userTextBox.Text = connectionInfo.User; - passwordTextBox.Text = connectionInfo.Password; - passwordTextBox.PasswordChar = PasswordChar; - showPasswordCheckBox.Checked = false; - instructionsTextBox.Visible = string.IsNullOrEmpty(connectionInfo.PrivateKeyPath); - }; - } - - public sealed override string Text - { - get => base.Text; - set => base.Text = value; - } - - /// - /// Returns the connection being created or edited. - /// - private ConnectionInfo ConnectionInfo { get; } - - /// - /// Handles the OK button. - /// - /// The sender. - /// The arguments. -#pragma warning disable VSTHRD100 - private async void okButton_Click(object sender, EventArgs args) -#pragma warning restore VSTHRD100 - { - //----------------------------------------------------------------- - // Validate the host - - var hostText = hostTextBox.Text.Trim(); - - if (hostText == string.Empty) - { - hostTextBox.Focus(); - hostTextBox.SelectAll(); - MessageBoxEx.Show(this, "You must specify a host name or IP address.", "Connection Error", MessageBoxButtons.OK); - return; - } - - if (!IPAddress.TryParse(hostText, out _) && !NetHelper.IsValidHost(hostText)) - { - portTextBox.Focus(); - portTextBox.SelectAll(); - MessageBoxEx.Show(this, $"[{hostText}] is not a valid IPv4 address or host name.", "Connection Error", MessageBoxButtons.OK); - return; - } - - //----------------------------------------------------------------- - // Validate the SSH port. - - var portText = portTextBox.Text.Trim(); - - if (portText == string.Empty) - { - portTextBox.Focus(); - portTextBox.SelectAll(); - MessageBoxEx.Show(this, "You must specify the SSH port.", "Connection Error", MessageBoxButtons.OK); - return; - } - - if (!int.TryParse(portText, out var port) || !NetHelper.IsValidPort(port)) - { - portTextBox.Focus(); - portTextBox.SelectAll(); - MessageBoxEx.Show(this, $"[{portText}] is not a valid SSH port.", "Connection Error", MessageBoxButtons.OK); - return; - } - - //----------------------------------------------------------------- - // Validate the username. - - var userText = userTextBox.Text.Trim(); - - if (userText == string.Empty) - { - userTextBox.Focus(); - userTextBox.SelectAll(); - MessageBoxEx.Show(this, "You must specify a username.", "Connection Error", MessageBoxButtons.OK); - return; - } - - var hasWhitespace = false; - var hasQuote = false; - - foreach (var ch in userText) - { - if (char.IsWhiteSpace(ch)) - { - hasWhitespace = true; - break; - } - else if (ch == '\'' || ch == '"') - { - hasQuote = true; - break; - } - } - - if (hasWhitespace) - { - userTextBox.Focus(); - userTextBox.SelectAll(); - MessageBoxEx.Show(this, "Username may not include whitespace.", "Connection Error", MessageBoxButtons.OK); - return; - } - - if (hasQuote) - { - userTextBox.Focus(); - userTextBox.SelectAll(); - MessageBoxEx.Show(this, "Username may not include single or double quotes.", "Connection Error", MessageBoxButtons.OK); - return; - } - - //----------------------------------------------------------------- - // Validate the password. - - var passwordText = passwordTextBox.Text.Trim(); - - if (passwordText == string.Empty && string.IsNullOrEmpty(ConnectionInfo.PrivateKeyPath)) - { - passwordTextBox.Focus(); - passwordTextBox.SelectAll(); - MessageBoxEx.Show(this, "You must specify a password until a SSH key has been created automatically for this connection.", "Connection Error", MessageBoxButtons.OK); - return; - } - - foreach (var ch in passwordText) - { - if (char.IsWhiteSpace(ch)) - { - hasWhitespace = true; - break; - } - else if (ch == '\'' || ch == '"') - { - hasQuote = true; - break; - } - } - - if (hasWhitespace) - { - passwordTextBox.Focus(); - passwordTextBox.SelectAll(); - MessageBoxEx.Show(this, "Password may not include whitespace.", "Connection Error", MessageBoxButtons.OK); - return; - } - - if (hasQuote) - { - passwordTextBox.Focus(); - passwordTextBox.SelectAll(); - MessageBoxEx.Show(this, "Password may not include single or double quotes.", "Connection Error", MessageBoxButtons.OK); - return; - } - - //----------------------------------------------------------------- - // Connection name needs to be unique. - - var connectionName = $"{userText}@{hostText}"; - - if (existingConnections.Any(connection => connection != this.ConnectionInfo && connection.Name == connectionName)) - { - portTextBox.Focus(); - portTextBox.SelectAll(); - MessageBoxEx.Show(this, $"Another connection already exists for [{connectionName}].", "Connection Error", MessageBoxButtons.OK); - return; - } - - //----------------------------------------------------------------- - // The properties look OK, so establish a connection to verify. - - var testConnectionInfo = new ConnectionInfo() - { - Host = hostText, - Port = port, - User = userText, - Password = passwordText, - PrivateKeyPath = ConnectionInfo.PrivateKeyPath, - PublicKeyPath = ConnectionInfo.PublicKeyPath - }; - - try - { - using (await Connection.Connection.ConnectAsync(testConnectionInfo)) { } - } - catch - { - MessageBoxEx.Show( - this, - $"Unable to connect to: {hostText}\r\n\r\nMake sure your Raspberry is turned on and verify your username and password.", - "Connection Failed", - MessageBoxButtons.OK, - MessageBoxIcon.Error); - - return; - } - - //----------------------------------------------------------------- - // Everything looks good, so update the connection and return. - - ConnectionInfo.Host = hostText; - ConnectionInfo.Port = port; - ConnectionInfo.User = userText; - ConnectionInfo.Password = passwordText; - ConnectionInfo.PrivateKeyPath = testConnectionInfo.PrivateKeyPath; - ConnectionInfo.PublicKeyPath = testConnectionInfo.PublicKeyPath; - - DialogResult = DialogResult.OK; - } - - /// - /// Handles the CANCEL button. - /// - /// The sender. - /// The arguments. - private void cancelButton_Click(object sender, EventArgs args) - { - DialogResult = DialogResult.Cancel; - } - - /// - /// Shows/hides the password. - /// - /// The sender. - /// The arguments. - private void showPasswordCheckBox_CheckedChanged(object sender, EventArgs args) - { - passwordTextBox.PasswordChar = showPasswordCheckBox.Checked ? (char)0 : PasswordChar; - } - } -} +//----------------------------------------------------------------------------- +// FILE: ConnectionDialog.cs +// CONTRIBUTOR: Jeff Lill +// COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows.Forms; +using Neon.Net; +using RaspberryDebugger.Models.Connection; + +namespace RaspberryDebugger.Dialogs +{ + /// + /// Implements the Add/Remove connection dialogs. + /// + internal partial class ConnectionDialog : Form + { + private const char PasswordChar = '•'; + + private readonly List existingConnections; + + /// + /// Constructor. + /// + /// The information for the connection being created or edited. + /// Pass true when editing, false for creating a new connection. + /// The existing connection. + public ConnectionDialog(ConnectionInfo connectionInfo, bool edit, List existingConnections) + { + InitializeComponent(); + + this.ConnectionInfo = connectionInfo; + this.Text = edit ? "Edit Raspberry Connection" : "New Raspberry Connection"; + this.existingConnections = existingConnections; + + // Initialize the controls on load. + this.Load += (s, a) => + { + hostTextBox.Text = connectionInfo.Host; + portTextBox.Text = connectionInfo.Port.ToString(); + userTextBox.Text = connectionInfo.User; + passwordTextBox.Text = connectionInfo.Password; + passwordTextBox.PasswordChar = PasswordChar; + showPasswordCheckBox.Checked = false; + instructionsTextBox.Visible = string.IsNullOrEmpty(connectionInfo.PrivateKeyPath); + }; + } + + public sealed override string Text + { + get => base.Text; + set => base.Text = value; + } + + /// + /// Returns the connection being created or edited. + /// + private ConnectionInfo ConnectionInfo { get; } + + /// + /// Handles the OK button. + /// + /// The sender. + /// The arguments. +#pragma warning disable VSTHRD100 + private async void okButton_Click(object sender, EventArgs args) +#pragma warning restore VSTHRD100 + { + //----------------------------------------------------------------- + // Validate the host + + var hostText = hostTextBox.Text.Trim(); + + if (hostText == string.Empty) + { + hostTextBox.Focus(); + hostTextBox.SelectAll(); + MessageBoxEx.Show(this, "You must specify a host name or IP address.", "Connection Error", MessageBoxButtons.OK); + return; + } + + if (!IPAddress.TryParse(hostText, out _) && !NetHelper.IsValidDnsHost(hostText)) + { + portTextBox.Focus(); + portTextBox.SelectAll(); + MessageBoxEx.Show(this, $"[{hostText}] is not a valid IPv4 address or host name.", "Connection Error", MessageBoxButtons.OK); + return; + } + + //----------------------------------------------------------------- + // Validate the SSH port. + + var portText = portTextBox.Text.Trim(); + + if (portText == string.Empty) + { + portTextBox.Focus(); + portTextBox.SelectAll(); + MessageBoxEx.Show(this, "You must specify the SSH port.", "Connection Error", MessageBoxButtons.OK); + return; + } + + if (!int.TryParse(portText, out var port) || !NetHelper.IsValidPort(port)) + { + portTextBox.Focus(); + portTextBox.SelectAll(); + MessageBoxEx.Show(this, $"[{portText}] is not a valid SSH port.", "Connection Error", MessageBoxButtons.OK); + return; + } + + //----------------------------------------------------------------- + // Validate the username. + + var userText = userTextBox.Text.Trim(); + + if (userText == string.Empty) + { + userTextBox.Focus(); + userTextBox.SelectAll(); + MessageBoxEx.Show(this, "You must specify a username.", "Connection Error", MessageBoxButtons.OK); + return; + } + + var hasWhitespace = false; + var hasQuote = false; + + foreach (var ch in userText) + { + if (char.IsWhiteSpace(ch)) + { + hasWhitespace = true; + break; + } + else if (ch == '\'' || ch == '"') + { + hasQuote = true; + break; + } + } + + if (hasWhitespace) + { + userTextBox.Focus(); + userTextBox.SelectAll(); + MessageBoxEx.Show(this, "Username may not include whitespace.", "Connection Error", MessageBoxButtons.OK); + return; + } + + if (hasQuote) + { + userTextBox.Focus(); + userTextBox.SelectAll(); + MessageBoxEx.Show(this, "Username may not include single or double quotes.", "Connection Error", MessageBoxButtons.OK); + return; + } + + //----------------------------------------------------------------- + // Validate the password. + + var passwordText = passwordTextBox.Text.Trim(); + + if (passwordText == string.Empty && string.IsNullOrEmpty(ConnectionInfo.PrivateKeyPath)) + { + passwordTextBox.Focus(); + passwordTextBox.SelectAll(); + MessageBoxEx.Show(this, "You must specify a password until a SSH key has been created automatically for this connection.", "Connection Error", MessageBoxButtons.OK); + return; + } + + foreach (var ch in passwordText) + { + if (char.IsWhiteSpace(ch)) + { + hasWhitespace = true; + break; + } + else if (ch == '\'' || ch == '"') + { + hasQuote = true; + break; + } + } + + if (hasWhitespace) + { + passwordTextBox.Focus(); + passwordTextBox.SelectAll(); + MessageBoxEx.Show(this, "Password may not include whitespace.", "Connection Error", MessageBoxButtons.OK); + return; + } + + if (hasQuote) + { + passwordTextBox.Focus(); + passwordTextBox.SelectAll(); + MessageBoxEx.Show(this, "Password may not include single or double quotes.", "Connection Error", MessageBoxButtons.OK); + return; + } + + //----------------------------------------------------------------- + // Connection name needs to be unique. + + var connectionName = $"{userText}@{hostText}"; + + if (existingConnections.Any(connection => connection != this.ConnectionInfo && connection.Name == connectionName)) + { + portTextBox.Focus(); + portTextBox.SelectAll(); + MessageBoxEx.Show(this, $"Another connection already exists for [{connectionName}].", "Connection Error", MessageBoxButtons.OK); + return; + } + + //----------------------------------------------------------------- + // The properties look OK, so establish a connection to verify. + + var testConnectionInfo = new ConnectionInfo() + { + Host = hostText, + Port = port, + User = userText, + Password = passwordText, + PrivateKeyPath = ConnectionInfo.PrivateKeyPath, + PublicKeyPath = ConnectionInfo.PublicKeyPath + }; + + try + { + using (await Connection.Connection.ConnectAsync(testConnectionInfo)) { } + } + catch + { + MessageBoxEx.Show( + this, + $"Unable to connect to: {hostText}\r\n\r\nMake sure your Raspberry is turned on and verify your username and password.", + "Connection Failed", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + + return; + } + + //----------------------------------------------------------------- + // Everything looks good, so update the connection and return. + + ConnectionInfo.Host = hostText; + ConnectionInfo.Port = port; + ConnectionInfo.User = userText; + ConnectionInfo.Password = passwordText; + ConnectionInfo.PrivateKeyPath = testConnectionInfo.PrivateKeyPath; + ConnectionInfo.PublicKeyPath = testConnectionInfo.PublicKeyPath; + + DialogResult = DialogResult.OK; + } + + /// + /// Handles the CANCEL button. + /// + /// The sender. + /// The arguments. + private void cancelButton_Click(object sender, EventArgs args) + { + DialogResult = DialogResult.Cancel; + } + + /// + /// Shows/hides the password. + /// + /// The sender. + /// The arguments. + private void showPasswordCheckBox_CheckedChanged(object sender, EventArgs args) + { + passwordTextBox.PasswordChar = showPasswordCheckBox.Checked ? (char)0 : PasswordChar; + } + } +} diff --git a/RaspberryDebugger/RaspberryDebugger.csproj b/RaspberryDebugger/RaspberryDebugger.csproj index 2c3942f..c0345f0 100644 --- a/RaspberryDebugger/RaspberryDebugger.csproj +++ b/RaspberryDebugger/RaspberryDebugger.csproj @@ -1,227 +1,227 @@ - - - - 16.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - false - - - latest - - - latest - - - - Debug - AnyCPU - 2.0 - {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {80D6A0E0-A145-488C-976D-CE34A16D8533} - Library - Properties - RaspberryDebugger - RaspberryDebugger - v4.7.2 - true - true - true - false - false - true - true - Program - $(DevEnvDir)devenv.exe - /rootsuffix Exp - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - CS0414 - latest - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - CS0414 - latest - - - - - - - - - - - - - Form - - - ConnectionDialog.cs - - - Form - - - KeysDialog.cs - - - - Form - - - SettingsDialog.cs - - - - - - - - - - - - - - - UserControl - - - ConnectionsPanel.cs - - - Component - - - - - - - - - KeysDialog.cs - - - SettingsDialog.cs - - - Always - true - - - - Designer - - - - - - - - - - - - - - - - - - - - - 15.0.6142705 - - - 17.5.33428.366 - - - 15.8.243 - - - compile; build; native; contentfiles; analyzers; buildtransitive - - - 17.7.37355 - - - 16.3.42 - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - 2.18.2 - - - 2.18.2 - - - 2.18.2 - - - 13.0.3 - - - 2.9.1 - - - 7.2.4 - - - 2.16.36 - - - - - Menus.ctmenu - - - - - ConnectionsPanel.cs - - - ConnectionDialog.cs - - - - - - - - - - - Always - true - - - - - - + + + + 16.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + false + + + latest + + + latest + + + + Debug + AnyCPU + 2.0 + {82b43b9b-a64c-4715-b499-d71e9ca2bd60};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {80D6A0E0-A145-488C-976D-CE34A16D8533} + Library + Properties + RaspberryDebugger + RaspberryDebugger + v4.7.2 + true + true + true + false + false + true + true + Program + $(DevEnvDir)devenv.exe + /rootsuffix Exp + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + CS0414 + latest + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + CS0414 + latest + + + + + + + + + + + + + Form + + + ConnectionDialog.cs + + + Form + + + KeysDialog.cs + + + + Form + + + SettingsDialog.cs + + + + + + + + + + + + + + + UserControl + + + ConnectionsPanel.cs + + + Component + + + + + + + + + KeysDialog.cs + + + SettingsDialog.cs + + + Always + true + + + + Designer + + + + + + + + + + + + + + + + + + + + + 15.0.6142705 + + + 17.10.40152 + + + 17.9.380 + + + compile; build; native; contentfiles; analyzers; buildtransitive + + + 17.11.40262 + + + 16.3.73 + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + 4.0.12 + + + 4.0.12 + + + 4.0.12 + + + 13.0.3 + + + 2.9.1 + + + 8.4.2 + + + 2.19.27 + + + + + Menus.ctmenu + + + + + ConnectionsPanel.cs + + + ConnectionDialog.cs + + + + + + + + + + + Always + true + + + + + + \ No newline at end of file From 0433a015459c2df725489e77565a5b3c27b99858 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Tue, 11 Mar 2025 14:37:49 -0400 Subject: [PATCH 18/37] Fix: Thread Access issues correct "Accessing "DTE2" should only be done on the main thread." warnings. --- RaspberryDebugger/Commands/DebugStartCommand.cs | 4 +++- RaspberryDebugger/RaspberryDebuggerPackage.cs | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/RaspberryDebugger/Commands/DebugStartCommand.cs b/RaspberryDebugger/Commands/DebugStartCommand.cs index d3196c8..6ca77d5 100644 --- a/RaspberryDebugger/Commands/DebugStartCommand.cs +++ b/RaspberryDebugger/Commands/DebugStartCommand.cs @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // FILE: DebugStartCommand.cs // CONTRIBUTOR: Jeff Lill // COPYRIGHT: Copyright (c) 2021 by neonFORGE, LLC. All rights reserved. @@ -176,6 +176,8 @@ private async void Execute(object sender, EventArgs e) await NeonHelper.WaitForAsync(async () => { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + // The developer must have stopped debugging before the // ASPNET application was able to begin servicing requests. if (dte.Mode != vsIDEMode.vsIDEModeDebug) return true; diff --git a/RaspberryDebugger/RaspberryDebuggerPackage.cs b/RaspberryDebugger/RaspberryDebuggerPackage.cs index 3088222..1096b7d 100644 --- a/RaspberryDebugger/RaspberryDebuggerPackage.cs +++ b/RaspberryDebugger/RaspberryDebuggerPackage.cs @@ -135,7 +135,12 @@ public static void LogClear() { if (Instance == null || _debugPane == null) return; // Logging hasn't been initialized yet. - _debugPane.Clear(); + _ = Instance.JoinableTaskFactory.RunAsync( + async () => + { + await Instance.JoinableTaskFactory.SwitchToMainThreadAsync( Instance.DisposalToken ); + _debugPane.Clear(); + } ); } //--------------------------------------------------------------------- @@ -210,11 +215,6 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke //--------------------------------------------------------------------- // DEBUG Command interceptors - /// - /// Returns true if the IDE in debug mode. - /// - private bool IsDebugging => dte.Mode == vsIDEMode.vsIDEModeDebug; - /// /// Executes a command by command set GUID and command ID. /// @@ -282,7 +282,7 @@ private void DebugStartCommandEvent_BeforeExecute(string guid, int id, object cu { ThreadHelper.ThrowIfNotOnUIThread(); - if (IsDebugging) + if ( dte.Mode == vsIDEMode.vsIDEModeDebug) { return; } From 88ce3af6cc2cf19d720d5f3a15fe6e1bafa3d9fd Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Tue, 11 Mar 2025 14:57:21 -0400 Subject: [PATCH 19/37] Fix VS Support warnings, Update NuGet packages Remove VS NuGet references which were causing "The extension is incompatible with the targeted version of Visual Studio" Update various other packages. --- RaspberryDebugger/RaspberryDebugger.csproj | 25 +++------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/RaspberryDebugger/RaspberryDebugger.csproj b/RaspberryDebugger/RaspberryDebugger.csproj index c0345f0..b7dfc82 100644 --- a/RaspberryDebugger/RaspberryDebugger.csproj +++ b/RaspberryDebugger/RaspberryDebugger.csproj @@ -145,28 +145,9 @@ - - 15.0.6142705 - - - 17.10.40152 - - - 17.9.380 - - + compile; build; native; contentfiles; analyzers; buildtransitive - - 17.11.40262 - - - 16.3.73 - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - 4.0.12 @@ -183,10 +164,10 @@ 2.9.1 - 8.4.2 + 8.5.2 - 2.19.27 + 2.21.10 From c6bc7a076bbec4e3e9e9471ad34fc39adf93b6a8 Mon Sep 17 00:00:00 2001 From: Bryan Roth Date: Tue, 11 Mar 2025 16:30:27 -0400 Subject: [PATCH 20/37] **HACK** - Fix: MissingMethodException using PrivateKeys Using Private Key access results in an exception in VS2022 when MAUI workloads are installed because they force the Neon.SSH component to use the newest version (loaded by VS). Updates to Neon.SSH are beyond our control, so hack a solution: Clone Neon.SSH in an adjacent dir to this project, reference the Neon components specifically, and force the update of SSH.NET that's required to avoid the exception. The update forces a single line change for a nullable at present. Otherwise, it's just a recompile to pick up on the introduction of an Interface. --- RaspberryDebugger.sln | 158 ++++++++++++--------- RaspberryDebugger/RaspberryDebugger.csproj | 18 ++- 2 files changed, 106 insertions(+), 70 deletions(-) diff --git a/RaspberryDebugger.sln b/RaspberryDebugger.sln index 1cf3839..a44e384 100644 --- a/RaspberryDebugger.sln +++ b/RaspberryDebugger.sln @@ -1,67 +1,91 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32505.173 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub", "GitHub", "{177F60A0-B1B9-45D1-9CB1-8F06A6ED2AB5}" - ProjectSection(SolutionItems) = preProject - .gitignore = .gitignore - buildenv.cmd = buildenv.cmd - LICENSE = LICENSE - README.md = README.md - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RaspberryDebugger", "RaspberryDebugger\RaspberryDebugger.csproj", "{80D6A0E0-A145-488C-976D-CE34A16D8533}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{5A14B2C0-0606-433A-AE9C-9E33C7B2BA27}" - ProjectSection(SolutionItems) = preProject - Doc\DEVELOPER.md = Doc\DEVELOPER.md - MAINTAIN.md = MAINTAIN.md - Doc\RELEASE-TEMPLATE.md = Doc\RELEASE-TEMPLATE.md - Doc\RELEASE.md = Doc\RELEASE.md - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Images", "Images", "{642CFDE5-32E6-46EB-B79E-8E380CCE0237}" - ProjectSection(SolutionItems) = preProject - Doc\Images\RaspberryDebugSettings.png = Doc\Images\RaspberryDebugSettings.png - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ToolBin", "ToolBin", "{15A5F928-90D4-421A-850D-8A09842DA012}" - ProjectSection(SolutionItems) = preProject - ToolBin\archive.cmd = ToolBin\archive.cmd - ToolBin\archive.ps1 = ToolBin\archive.ps1 - ToolBin\builder.cmd = ToolBin\builder.cmd - ToolBin\builder.ps1 = ToolBin\builder.ps1 - ToolBin\openssl.exe = ToolBin\openssl.exe - ToolBin\PathTool.exe = ToolBin\PathTool.exe - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{21D869D2-B357-485A-89C0-6A18B8886432}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blinky", "Blinky", "{C7EA532F-BE47-4993-9599-66168340E980}" - ProjectSection(SolutionItems) = preProject - Test\Blinkie\Blinky.sln = Test\Blinkie\Blinky.sln - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {80D6A0E0-A145-488C-976D-CE34A16D8533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {80D6A0E0-A145-488C-976D-CE34A16D8533}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80D6A0E0-A145-488C-976D-CE34A16D8533}.Release|Any CPU.ActiveCfg = Release|Any CPU - {80D6A0E0-A145-488C-976D-CE34A16D8533}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {642CFDE5-32E6-46EB-B79E-8E380CCE0237} = {5A14B2C0-0606-433A-AE9C-9E33C7B2BA27} - {C7EA532F-BE47-4993-9599-66168340E980} = {21D869D2-B357-485A-89C0-6A18B8886432} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {52E13CDA-74D0-400C-83D8-417CC3C113D6} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.2.32505.173 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub", "GitHub", "{177F60A0-B1B9-45D1-9CB1-8F06A6ED2AB5}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + buildenv.cmd = buildenv.cmd + LICENSE = LICENSE + README.md = README.md + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RaspberryDebugger", "RaspberryDebugger\RaspberryDebugger.csproj", "{80D6A0E0-A145-488C-976D-CE34A16D8533}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{5A14B2C0-0606-433A-AE9C-9E33C7B2BA27}" + ProjectSection(SolutionItems) = preProject + Doc\DEVELOPER.md = Doc\DEVELOPER.md + MAINTAIN.md = MAINTAIN.md + Doc\RELEASE-TEMPLATE.md = Doc\RELEASE-TEMPLATE.md + Doc\RELEASE.md = Doc\RELEASE.md + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Images", "Images", "{642CFDE5-32E6-46EB-B79E-8E380CCE0237}" + ProjectSection(SolutionItems) = preProject + Doc\Images\RaspberryDebugSettings.png = Doc\Images\RaspberryDebugSettings.png + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ToolBin", "ToolBin", "{15A5F928-90D4-421A-850D-8A09842DA012}" + ProjectSection(SolutionItems) = preProject + ToolBin\archive.cmd = ToolBin\archive.cmd + ToolBin\archive.ps1 = ToolBin\archive.ps1 + ToolBin\builder.cmd = ToolBin\builder.cmd + ToolBin\builder.ps1 = ToolBin\builder.ps1 + ToolBin\openssl.exe = ToolBin\openssl.exe + ToolBin\PathTool.exe = ToolBin\PathTool.exe + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{21D869D2-B357-485A-89C0-6A18B8886432}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blinky", "Blinky", "{C7EA532F-BE47-4993-9599-66168340E980}" + ProjectSection(SolutionItems) = preProject + Test\Blinkie\Blinky.sln = Test\Blinkie\Blinky.sln + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neon.BuildInfo", "..\neonSDK\Lib\Neon.BuildInfo\Neon.BuildInfo.csproj", "{62AEE7BF-2F8B-297E-4BDA-DB9289DE49AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neon.Common", "..\neonSDK\Lib\Neon.Common\Neon.Common.csproj", "{7B3C9089-7DCC-90DC-A824-B0EECD7C511C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neon.Cryptography", "..\neonSDK\Lib\Neon.Cryptography\Neon.Cryptography.csproj", "{C0E0FD22-0AB6-6B0B-8571-C5F4D6EDD7B8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neon.SSH", "..\neonSDK\Lib\Neon.SSH\Neon.SSH.csproj", "{030C5DD8-990D-0DD3-2886-02CB01C171CB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {80D6A0E0-A145-488C-976D-CE34A16D8533}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80D6A0E0-A145-488C-976D-CE34A16D8533}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80D6A0E0-A145-488C-976D-CE34A16D8533}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80D6A0E0-A145-488C-976D-CE34A16D8533}.Release|Any CPU.Build.0 = Release|Any CPU + {62AEE7BF-2F8B-297E-4BDA-DB9289DE49AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {62AEE7BF-2F8B-297E-4BDA-DB9289DE49AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {62AEE7BF-2F8B-297E-4BDA-DB9289DE49AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {62AEE7BF-2F8B-297E-4BDA-DB9289DE49AA}.Release|Any CPU.Build.0 = Release|Any CPU + {7B3C9089-7DCC-90DC-A824-B0EECD7C511C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B3C9089-7DCC-90DC-A824-B0EECD7C511C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B3C9089-7DCC-90DC-A824-B0EECD7C511C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B3C9089-7DCC-90DC-A824-B0EECD7C511C}.Release|Any CPU.Build.0 = Release|Any CPU + {C0E0FD22-0AB6-6B0B-8571-C5F4D6EDD7B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C0E0FD22-0AB6-6B0B-8571-C5F4D6EDD7B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C0E0FD22-0AB6-6B0B-8571-C5F4D6EDD7B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C0E0FD22-0AB6-6B0B-8571-C5F4D6EDD7B8}.Release|Any CPU.Build.0 = Release|Any CPU + {030C5DD8-990D-0DD3-2886-02CB01C171CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {030C5DD8-990D-0DD3-2886-02CB01C171CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {030C5DD8-990D-0DD3-2886-02CB01C171CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {030C5DD8-990D-0DD3-2886-02CB01C171CB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {642CFDE5-32E6-46EB-B79E-8E380CCE0237} = {5A14B2C0-0606-433A-AE9C-9E33C7B2BA27} + {C7EA532F-BE47-4993-9599-66168340E980} = {21D869D2-B357-485A-89C0-6A18B8886432} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {52E13CDA-74D0-400C-83D8-417CC3C113D6} + EndGlobalSection +EndGlobal diff --git a/RaspberryDebugger/RaspberryDebugger.csproj b/RaspberryDebugger/RaspberryDebugger.csproj index b7dfc82..dbcba95 100644 --- a/RaspberryDebugger/RaspberryDebugger.csproj +++ b/RaspberryDebugger/RaspberryDebugger.csproj @@ -148,7 +148,7 @@ compile; build; native; contentfiles; analyzers; buildtransitive - + 13.0.3 @@ -169,6 +169,9 @@ 2.21.10 + + 2024.2.0 + @@ -195,7 +198,16 @@ true - + + + {7b3c9089-7dcc-90dc-a824-b0eecd7c511c} + Neon.Common + + + {030c5dd8-990d-0dd3-2886-02cb01c171cb} + Neon.SSH + + - 13.0.3 + 13.0.4 2.9.1 - 8.5.2 + 8.6.5 - 2.21.10 + 2.22.23 - 2024.2.0 + 2025.1.0