microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
160.77k stars 28.18k forks source link

"Run VS Code outside the Developer Command Prompt" instructions fail if opened file's basename and/or dirname contains space characters #158615

Open casadan opened 1 year ago

casadan commented 1 year ago

This is actually a reproduction of issue #135994 which was closed due to insufficient information to consistently recreate it. Hopefully, this new report will shed more light on the problem.

Steps to Reproduce

  1. If necessary, configure VS Code for Microsoft C++ (see Prerequisites section in this tutorial).
  2. Follow this guide to create a tasks.json configuration for running VS Code outside the Developer Command Prompt for Visual Studio.
  3. Create a C/C++ source file containing at least one space character in its basename or dirname.
  4. Attempt to build the source file using the task created in step 2.

Expected Result The integrated shell opens and the build is successfully completed, e.g. building c:\Test\test.c results in this terminal output:

*  Executing task: cl.exe /Zi /EHsc /Fe: c:\Test\test.exe c:\Test\test.c 

**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.3.0
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
Microsoft (R) C/C++ Optimizing Compiler Version 19.33.31629 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 14.33.31629.0    
Copyright (C) Microsoft Corporation.  All rights reserved.

/debug
/out:c:\Test\test.exe
test.obj
 *  Terminal will be reused by tasks, press any key to close it. 

Actual Result The terminal process terminates with exit code 1, apparently because the double quotes enclosing the second shell argument string in tasks.json are being internally dropped, thus attempting to build c:\Test\test file.c yields:

 *  Executing task: cl.exe /Zi /EHsc /Fe: "c:\Test\test file.exe" "c:\Test\test file.c" 

'C:/Program' is not recognized as an internal or external command,
operable program or batch file.

 *  The terminal process "cmd.exe /C "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat" && cl.exe /Zi /EHsc /Fe: "c:\Test\test file.exe" "c:\Test\test file.c"" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Additional Info For reference, here is what my tasks.json file looks like:

{
    "version": "2.0.0",
    "windows": {
      "options": {
        "shell": {
          "executable": "cmd.exe",
          "args": [
            "/C",
            // The path to VsDevCmd.bat depends on the version of Visual Studio you have installed.
            "\"C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat\"",
            "&&"
          ]
        }
      }
    },
    "tasks": [
        {
            "type": "shell",
            "label": "cl.exe build active file",
            "command": "cl.exe",
            "args": [
                "/Zi",
                "/EHsc",
                "/Fe:",
                "${fileDirname}\\${fileBasenameNoExtension}.exe",
                "${file}"
            ],
            "problemMatcher": [
                "$msCompile"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
  }

Current Workarounds

Does this issue occur when all extensions are disabled?: Yes

meganrogge commented 1 year ago

@alexr00 has this ever been supported?

alexr00 commented 1 year ago

@meganrogge We try to handle escaping/quoting well, but it's been a losing battle to do it correctly on every platfom+shell combination. the quoting property (a sub-property of command in the json schema) also tries to help with this.

@casadan does it work if you try one of the other shell quoting options? Ex:

{
...
  "command": {
    "value": "cl.exe",
    "quoting": "escape"
}
...
casadan commented 1 year ago

@alexr00 I tried building c:\Test\test file.c with this tasks.json:

{
    "version": "2.0.0",
    "windows": {
      "options": {
        "shell": {
          "executable": "cmd.exe",
          "args": [
            "/C",
            // The path to VsDevCmd.bat depends on the version of Visual Studio you have installed.
            "\"C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat\"",
            "&&"
          ]
        }
      }
    },
    "tasks": [
        {
            "type": "shell",
            "label": "cl.exe build active file",
            "command": {
                "value": "cl.exe /Zi /EHsc /Fe: ${fileDirname}\\${fileBasenameNoExtension}.exe ${file}",
                "quoting": "escape"
            },

            "problemMatcher": [
                "$msCompile"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
  }

This time the Developer Command Prompt for Visual Studio is successfully run but then the compiler fails due to the unescaped space characters in cl.exe's /Fe argument:

 *  Executing task: cl.exe /Zi /EHsc /Fe: c:\Test\test file.exe c:\Test\test file.c 

**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.3.3
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
Microsoft (R) C/C++ Optimizing Compiler Version 19.33.31629 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

cl : Command line warning D9024 : unrecognized source file type 'file.exe', object file assumed    
cl : Command line warning D9024 : unrecognized source file type 'c:\Test\test', object file assumed
file.c
c1: fatal error C1083: Cannot open source file: 'file.c': No such file or directory

 *  The terminal process "cmd.exe /C "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat" && cl.exe /Zi /EHsc /Fe: c:\Test\test file.exe c:\Test\test file.c" terminated with exit code: 2. 
 *  Terminal will be reused by tasks, press any key to close it. 

Again, removing the space character from the file name (e.g. c:\Test\test.c) works as expected:

 *  Executing task: cl.exe /Zi /EHsc /Fe: c:\Test\test.exe c:\Test\test.c 

**********************************************************************
** Visual Studio 2022 Developer Command Prompt v17.3.3
** Copyright (c) 2022 Microsoft Corporation
**********************************************************************
Microsoft (R) C/C++ Optimizing Compiler Version 19.33.31629 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.c
Microsoft (R) Incremental Linker Version 14.33.31629.0    
Copyright (C) Microsoft Corporation.  All rights reserved.

/debug
/out:c:\Test\test.exe
test.obj
 *  Terminal will be reused by tasks, press any key to close it. 

Switching the quoting style from escape to strong breaks the task regardless of the file name:

 *  Executing task: "cl.exe /Zi /EHsc /Fe: c:\Test\test.exe c:\Test\test.c" 

'C:/Program' is not recognized as an internal or external command,
operable program or batch file.

 *  The terminal process "cmd.exe /C "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat" && "cl.exe /Zi /EHsc /Fe: c:\Test\test.exe c:\Test\test.c"" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Adding escaped double quotes to the /Fe argument does not work either regardless of the quoting style or the file name, e.g.:

            "command": {
                "value": "cl.exe /Zi /EHsc /Fe: \"${fileDirname}\\${fileBasenameNoExtension}.exe\" \"${file}\"",
                "quoting": "escape"
            },

Results in:

 *  Executing task: cl.exe /Zi /EHsc /Fe: "c:\Test\test.exe" "c:\Test\test.c" 

'C:/Program' is not recognized as an internal or external command,
operable program or batch file.

 *  The terminal process "cmd.exe /C "C:/Program Files/Microsoft Visual Studio/2022/Community/Common7/Tools/VsDevCmd.bat" && cl.exe /Zi /EHsc /Fe: "c:\Test\test.exe" "c:\Test\test.c"" terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 
lijingjian001 commented 6 months ago

I solved this problem by using the pwsh.exe terminal, which may be because the cmd.exe terminal is too old

There are several key points that may need attention:

  1. The type of the task is shell, not cppbuild

  2. It is not necessary to use the shell of the Windows option on the outermost layer of tasks.json, but the shell of the current task's option can also be used

  3. The Bat script file needs to be replaced with a ps1 script file (if you feel that the path is too long, you can create a soft link to a folder you often use, of course, this folder is in the environment variable Path)

  4. Another benefit of using pwsh.exe is that you don't have to worry about garbled code

Below is my tasks.json

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: gcc.exe 生成活动文件",
            "command": "G:\\msys64\\ucrt64\\bin\\gcc.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${file}",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "G:\\msys64\\ucrt64\\bin"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": false
            },
            "detail": "调试器生成的任务。"
        },
        {
            "type": "shell",
            "label": "msvc cl.exe 生成活动文件",
            "command": "cl.exe",
            "args": [
                "/source-charset:utf-8",
                "/execution-charset:gbk",
                "/Zi",
                "/EHsc",
                "/nologo",
                "/Fe${fileDirname}\\${fileBasenameNoExtension}.exe",
                "${file}",
                "User32.Lib"
            ],
            "options": {
                "cwd": "${fileDirname}",
                "shell": {
                    "executable": "pwsh.exe",
                    "args": [
                        "-c",
                        "msvc",/*msvc is soft link*/
                        "&&"
                    ],
                }
            },
            "problemMatcher": [
                "$msCompile"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "shared",
                "showReuseMessage": false,
                "clear": false
            }
        }
    ],
    "version": "2.0.0"
}

image