Issue 1:
Environment

Windows build number: 10.0.18362.175
Windows Terminal version (if applicable): 0.2.1715.0

Any other software: Visual Studio 2017 (I guess it fails with other VS versions)

Steps to reproduce

Add this entry to profile.json:

{
"acrylicOpacity" : 0.75,
"closeOnExit" : true,
"colorScheme" : "Campbell",
"commandline" : "cmd.exe /k \"%PROGRAMFILES(X86)%\\Microsoft Visual Studio\\2017\\Community\\Common7\\Tools\\VsDevCmd.bat\"",
"cursorColor" : "#FFFFFF",
"cursorShape" : "bar",
"fontFace" : "Consolas",
"fontSize" : 10,
"guid" : "{1748ecca-abdd-4aa4-bcc4-9fca0d045be5}",
"historySize" : 9001,
"icon" : "ms-appx:///ProfileIcons/{0caa0dad-35be-5f56-a8ff-afceeeaa6101}.png",
"name" : "VS cmd",
"padding" : "0, 0, 0, 0",
"snapOnInput" : true,
"startingDirectory" : "%USERPROFILE%",
"useAcrylic" : true
},

Expected behavior

Initializes the Developer Command prompt for visual studio

Actual behavior

The batch script does not executes and fails like this:

'C:\Program' is not recognized as an internal or external command,

operable program or batch file.

Issue 2:
Environment

Windows build number: [run "ver" at a command prompt]
Windows Terminal version (if applicable):

Any other software?

Today I modified the Windows Terminal configuration file and wanted to create a Pwsh with the emoji title. However, I encountered some confusion in this process. I checked the task manager and found that conhost did not escape when the process was started, causing the command line to parse the exception.

Steps to reproduce

Expected behavior

I need to start pwsh by the following command line (note that the following command line is in cmd, or you can start pwsh normally using CreateProcessW.)

"C:\Program Files\PowerShell\7-preview\pwsh.exe" -NoExit -Command "$Host.UI.RawUI.WindowTitle=\"Windows Pwsh 💙 (7 Preview)\""

Here is the Windows Terminal configuration file (the command line has been properly escaped):

{
"startingDirectory": "C:\\Users\\CharlieInc",
"guid": "{08a0be98-ff68-4e3a-a054-0fbd3969d3bb}",
"name": "Windows Pwsh 💙 (7 Preview)",
"colorscheme": "Campbell",
"historySize": 9001,
"snapOnInput": true,
"cursorColor": "#FFFFFF",
"cursorShape": "bar",
"commandline": "\"C:\\Program Files\\PowerShell\\7-preview\\pwsh.exe\" -NoExit -Command \"$Host.UI.RawUI.WindowTitle=\\\"Windows Pwsh 💙 (7 Preview)\\\"\"",
"fontFace": "Consolas",
"fontSize": 12,
"acrylicOpacity": 0.75,
"useAcrylic": true,
"closeOnExit": false,
"padding": "0, 0, 0, 0",
"icon": "ms-appdata:///roaming/pwsh-32.png"
}

Actual behavior

As expected, Pwsh should set the title correctly, but pwsh reported the error:

Let's take a look at the command line:

When you see the red line, the command line that pwsh starts is incorrect, and when you start conhost, the command line is still correct!

Currently I have found a suspicious code, most likely this code caused an error:

terminal/src/host/ConsoleArguments.cpp

Lines 263 to 288
in
71e19cd

HRESULT ConsoleArguments::_GetClientCommandline(_Inout_ std::vector<std::wstring>& args, const size_t index, const bool skipFirst)

{

auto start = args.begin()+index;

// Erase the first token.

// Used to get rid of the explicit commandline token "--"

if (skipFirst)

{

// Make sure that the arg we're deleting is "--"

FAIL_FAST_IF(!(CLIENT_COMMANDLINE_ARG == start->c_str()));

args.erase(start);

}

_clientCommandline = L"";

size_t j = 0;

for (j = index; j < args.size(); j++)

{

_clientCommandline += args[j];

if (j+1 < args.size())

{

_clientCommandline += L" ";

}

}

args.erase(args.begin()+index, args.begin()+j);

return S_OK;

In this code, command line composition is simply a simple connection rather than a concatenated string. If the string contains spaces, this will result in an incorrect command line.

Below is a code for the command line escaping, which may be useful：

inline std::wstring escape_argument(std::wstring_view ac) {
if (ac.empty()) {
return L"\"\"";
}
bool hasspace = false;
auto n = ac.size();
for (auto c : ac) {
switch (c) {
case L'"':
case L'\\':
n++;
break;
case ' ':
case '\t':
hasspace = true;
break;
default:
break;
}
}
if (hasspace) {
n += 2;
}
if (n == ac.size()) {
return std::wstring(ac.data(), ac.size());
}
std::wstring buf;
if (hasspace) {
buf.push_back(L'"');
}
size_t slashes = 0;
for (auto c : ac) {
switch (c) {
case L'\\':
slashes++;
buf.push_back(L'\\');
break;
case L'"': {
for (; slashes > 0; slashes--) {
buf.push_back(L'\\');
}
buf.push_back(L'\\');
buf.push_back(c);
} break;
default:
slashes = 0;
buf.push_back(c);
break;
}
}
if (hasspace) {
for (; slashes > 0; slashes--) {
buf.push_back(L'\\');
}
buf.push_back(L'"');
}
return buf;
}