From 0c0830b2f2b9791d8d9e9e79da31df5115ad869c Mon Sep 17 00:00:00 2001 From: Don-Vito Date: Tue, 10 Nov 2020 00:55:45 +0200 Subject: [PATCH] Azure: fall back to powershell when no preferred shell is set (#8197) I am still not sure what is the full set of scenarios that the problem might occur, but for me it occurred for an "old" cloud shell account, and didn't reproduce since I have reconfigured it. These behavior might be explained by the fact that "preferred shell type" did not exist in the API originally and thus was not set. In such case, Terminal succeeds to retrieve to the settings but then crashes when reading the missing field. To fix it, I handle the case where the field is missing and fallback to PowerShell. ## Validation Steps Performed * Tested manually, only once. Closes #7056 --- .../TerminalConnection/AzureConnection.cpp | 23 +++++++++++++++++-- .../TerminalConnection/AzureConnection.h | 2 ++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/cascadia/TerminalConnection/AzureConnection.cpp b/src/cascadia/TerminalConnection/AzureConnection.cpp index b8c5e31a0b9..9bddedb958b 100644 --- a/src/cascadia/TerminalConnection/AzureConnection.cpp +++ b/src/cascadia/TerminalConnection/AzureConnection.cpp @@ -687,6 +687,25 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _state = AzureState::TermConnecting; } + // Method description: + // - Helper function to parse the preferred shell type from user settings returned by cloud console API. + // We need this function because the field might be missing in the settings + // created with old versions of cloud console API. + std::optional AzureConnection::_ParsePreferredShellType(const web::json::value& settingsResponse) + { + if (settingsResponse.has_object_field(L"properties")) + { + const auto userSettings = settingsResponse.at(L"properties"); + if (userSettings.has_string_field(L"preferredShellType")) + { + const auto preferredShellTypeValue = userSettings.at(L"preferredShellType"); + return preferredShellTypeValue.as_string(); + } + } + + return std::nullopt; + } + // Method description: // - helper function to connect the user to the Azure cloud shell void AzureConnection::_RunConnectState() @@ -706,9 +725,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation _WriteStringWithNewline(RS_(L"AzureSuccess")); // Request for a terminal for said cloud shell - const auto shellType = settingsResponse.at(L"properties").at(L"preferredShellType").as_string(); + const auto shellType = _ParsePreferredShellType(settingsResponse); _WriteStringWithNewline(RS_(L"AzureRequestingTerminal")); - const auto socketUri = _GetTerminal(shellType); + const auto socketUri = _GetTerminal(shellType.value_or(L"pwsh")); _TerminalOutputHandlers(L"\r\n"); // Step 8: connecting to said terminal diff --git a/src/cascadia/TerminalConnection/AzureConnection.h b/src/cascadia/TerminalConnection/AzureConnection.h index 4db0a9619b4..b2afd99ab2e 100644 --- a/src/cascadia/TerminalConnection/AzureConnection.h +++ b/src/cascadia/TerminalConnection/AzureConnection.h @@ -95,6 +95,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation std::optional _ReadUserInput(InputMode mode); web::websockets::client::websocket_client _cloudShellSocket; + + static std::optional _ParsePreferredShellType(const web::json::value& settingsResponse); }; }