Repository: conan-io/conan

Issue:
MSBuild().build(build_type=x)  - Automatically enclose x in Quotes
Conan 1.5.2

When using a custom Visual Studio "Configuration" with spaces in it, quotes must be used around the name:

`MSBuild(self).build(build_type='"Release DLL"')`

Otherwise, it goes through like this: 

`msbuild vssharedbuffer.sln /p:Configuration=Release DLL /p:UseEnv=true /p:Platform="x64"`

Which fails due to this error: 

```
MSBUILD : error MSB1008: Only one project can be specified.
Switch: DLL
```
Since Conan is already enclosing the 'Platform' parameter in quotes automatically (as shown in the line above), perhaps the same could be done for `build_type`. 

Incidentally, when manually enclosing with quotes, an incorrect warning is displayed, which doesn't seem to account for the quotes. 

`WARN: ***** The configuration "Release DLL"|x64 does not exist in this solution *****`


- [x] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [x] I've specified the Conan version, operating system version and any tool that can be relevant.
- [x] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.




Discussion:

Resolving patch:
diff --git a/conans/client/build/msbuild.py b/conans/client/build/msbuild.py
--- a/conans/client/build/msbuild.py
+++ b/conans/client/build/msbuild.py
@@ -49,7 +49,7 @@ def get_command(self, project_file, props_file_path=None, targets=None, upgrade_
         command = []
 
         if upgrade_project and not get_env("CONAN_SKIP_VS_PROJECTS_UPGRADE", False):
-            command.append("devenv %s /upgrade &&" % project_file)
+            command.append('devenv "%s" /upgrade &&' % project_file)
         else:
             self._output.info("Skipped sln project upgrade")
 
@@ -60,7 +60,7 @@ def get_command(self, project_file, props_file_path=None, targets=None, upgrade_
         if not arch:
             raise ConanException("Cannot build_sln_command, arch not defined")
 
-        command.append("msbuild %s /p:Configuration=%s" % (project_file, build_type))
+        command.append('msbuild "%s" /p:Configuration="%s"' % (project_file, build_type))
         msvc_arch = {'x86': 'x86',
                      'x86_64': 'x64',
                      'armv7': 'ARM',
@@ -96,7 +96,7 @@ def get_command(self, project_file, props_file_path=None, targets=None, upgrade_
             command.append("/target:%s" % ";".join(targets))
 
         if toolset:
-            command.append("/p:PlatformToolset=%s" % toolset)
+            command.append('/p:PlatformToolset="%s"' % toolset)
 
         if props_file_path:
             command.append('/p:ForceImportBeforeCppTargets="%s"' % props_file_path)


Test patch:
diff --git a/conans/test/build_helpers/msbuild_test.py b/conans/test/build_helpers/msbuild_test.py
--- a/conans/test/build_helpers/msbuild_test.py
+++ b/conans/test/build_helpers/msbuild_test.py
@@ -43,9 +43,8 @@ def without_runtime_test(self):
         self.assertNotIn("<RuntimeLibrary>", template)
 
     @attr('slow')
+    @unittest.skipUnless(platform.system() == "Windows", "Requires MSBuild")
     def build_vs_project_test(self):
-        if platform.system() != "Windows":
-            return
         conan_build_vs = """
 from conans import ConanFile, MSBuild
 
@@ -111,10 +110,9 @@ def package(self):
         self.assertIn("Debug|x86", client.user_io.out)
         self.assertIn("Copied 1 '.exe' file: MyProject.exe", client.user_io.out)
 
+    @unittest.skipUnless(platform.system() == "Windows", "Requires MSBuild")
     def reuse_msbuild_object_test(self):
         # https://github.com/conan-io/conan/issues/2865
-        if platform.system() != "Windows":
-            return
         conan_build_vs = """
 from conans import ConanFile, MSBuild
 
diff --git a/conans/test/util/build_sln_command_test.py b/conans/test/util/build_sln_command_test.py
--- a/conans/test/util/build_sln_command_test.py
+++ b/conans/test/util/build_sln_command_test.py
@@ -37,7 +37,7 @@ def no_configuration_test(self):
         tools.set_global_instances(ConanOutput(new_out), None)
         command = build_sln_command(Settings({}), sln_path=path, targets=None, upgrade_project=False,
                                     build_type='Debug', arch="x86", parallel=False)
-        self.assertIn('/p:Configuration=Debug /p:Platform="x86"', command)
+        self.assertIn('/p:Configuration="Debug" /p:Platform="x86"', command)
         self.assertIn("WARN: ***** The configuration Debug|x86 does not exist in this solution *****",
                       new_out.getvalue())
         # use platforms
@@ -45,7 +45,7 @@ def no_configuration_test(self):
         tools.set_global_instances(ConanOutput(new_out), None)
         command = build_sln_command(Settings({}), sln_path=path, targets=None, upgrade_project=False,
                                     build_type='Debug', arch="x86", parallel=False, platforms={"x86": "Win32"})
-        self.assertIn('/p:Configuration=Debug /p:Platform="Win32"', command)
+        self.assertIn('/p:Configuration="Debug" /p:Platform="Win32"', command)
         self.assertNotIn("WARN", new_out.getvalue())
         self.assertNotIn("ERROR", new_out.getvalue())
 
@@ -62,18 +62,18 @@ def no_build_type_test(self):
     def positive_test(self):
         command = build_sln_command(Settings({}), sln_path='dummy.sln', targets=None, upgrade_project=False,
                                     build_type='Debug', arch='x86', parallel=False)
-        self.assertIn('msbuild dummy.sln', command)
+        self.assertIn('msbuild "dummy.sln"', command)
         self.assertIn('/p:Platform="x86"', command)
-        self.assertNotIn('devenv dummy.sln /upgrade', command)
+        self.assertNotIn('devenv "dummy.sln" /upgrade', command)
         self.assertNotIn('/m:%s' % cpu_count(), command)
         self.assertNotIn('/target:teapot', command)
 
     def upgrade_test(self):
         command = build_sln_command(Settings({}), sln_path='dummy.sln', targets=None, upgrade_project=True,
                                     build_type='Debug', arch='x86_64', parallel=False)
-        self.assertIn('msbuild dummy.sln', command)
+        self.assertIn('msbuild "dummy.sln"', command)
         self.assertIn('/p:Platform="x64"', command)
-        self.assertIn('devenv dummy.sln /upgrade', command)
+        self.assertIn('devenv "dummy.sln" /upgrade', command)
         self.assertNotIn('/m:%s' % cpu_count(), command)
         self.assertNotIn('/target:teapot', command)
 
@@ -81,9 +81,9 @@ def upgrade_test(self):
             command = build_sln_command(Settings({}), sln_path='dummy.sln', targets=None,
                                         upgrade_project=True,
                                         build_type='Debug', arch='x86_64', parallel=False)
-            self.assertIn('msbuild dummy.sln', command)
+            self.assertIn('msbuild "dummy.sln"', command)
             self.assertIn('/p:Platform="x64"', command)
-            self.assertNotIn('devenv dummy.sln /upgrade', command)
+            self.assertNotIn('devenv "dummy.sln" /upgrade', command)
             self.assertNotIn('/m:%s' % cpu_count(), command)
             self.assertNotIn('/target:teapot', command)
 
@@ -91,23 +91,23 @@ def upgrade_test(self):
             command = build_sln_command(Settings({}), sln_path='dummy.sln', targets=None,
                                         upgrade_project=True,
                                         build_type='Debug', arch='x86_64', parallel=False)
-            self.assertIn('devenv dummy.sln /upgrade', command)
+            self.assertIn('devenv "dummy.sln" /upgrade', command)
 
     def parallel_test(self):
         command = build_sln_command(Settings({}), sln_path='dummy.sln', targets=None, upgrade_project=True,
                                     build_type='Debug', arch='armv7', parallel=False)
-        self.assertIn('msbuild dummy.sln', command)
+        self.assertIn('msbuild "dummy.sln"', command)
         self.assertIn('/p:Platform="ARM"', command)
-        self.assertIn('devenv dummy.sln /upgrade', command)
+        self.assertIn('devenv "dummy.sln" /upgrade', command)
         self.assertNotIn('/m:%s' % cpu_count(), command)
         self.assertNotIn('/target:teapot', command)
 
     def target_test(self):
         command = build_sln_command(Settings({}), sln_path='dummy.sln', targets=['teapot'], upgrade_project=False,
                                     build_type='Debug', arch='armv8', parallel=False)
-        self.assertIn('msbuild dummy.sln', command)
+        self.assertIn('msbuild "dummy.sln"', command)
         self.assertIn('/p:Platform="ARM64"', command)
-        self.assertNotIn('devenv dummy.sln /upgrade', command)
+        self.assertNotIn('devenv "dummy.sln" /upgrade', command)
         self.assertNotIn('/m:%s' % cpu_count(), command)
         self.assertIn('/target:teapot', command)
 
@@ -120,9 +120,10 @@ def toolset_test(self):
                                     sln_path='dummy.sln', targets=None,
                                     upgrade_project=False, build_type='Debug', arch='armv7',
                                     parallel=False, toolset="v110")
-        self.assertTrue(command.startswith('msbuild dummy.sln /p:Configuration=Debug '
+        print(command)
+        self.assertTrue(command.startswith('msbuild "dummy.sln" /p:Configuration="Debug" '
                                            '/p:Platform="ARM" '
-                                           '/p:PlatformToolset=v110 '
+                                           '/p:PlatformToolset="v110" '
                                            '/p:ForceImportBeforeCppTargets='), command)
 
     def properties_file_test(self):
@@ -134,7 +135,7 @@ def properties_file_test(self):
                                     sln_path='dummy.sln', targets=None,
                                     upgrade_project=False, build_type='Debug', arch='armv7',
                                     parallel=False)
-        self.assertTrue(command.startswith('msbuild dummy.sln /p:Configuration=Debug '
+        self.assertTrue(command.startswith('msbuild "dummy.sln" /p:Configuration="Debug" '
                                            '/p:Platform="ARM" '
                                            '/p:ForceImportBeforeCppTargets='), command)
         path_tmp = command.split("/p:ForceImportBeforeCppTargets=")[1][1:-1]  # remove quotes
diff --git a/conans/test/util/tools_test.py b/conans/test/util/tools_test.py
--- a/conans/test/util/tools_test.py
+++ b/conans/test/util/tools_test.py
@@ -553,7 +553,7 @@ def msvc_build_command_test(self):
         settings.compiler.version = "14"
         # test build_type and arch override, for multi-config packages
         cmd = tools.msvc_build_command(settings, "project.sln", build_type="Debug", arch="x86")
-        self.assertIn('msbuild project.sln /p:Configuration=Debug /p:Platform="x86"', cmd)
+        self.assertIn('msbuild "project.sln" /p:Configuration="Debug" /p:Platform="x86"', cmd)
         self.assertIn('vcvarsall.bat', cmd)
 
         # tests errors if args not defined
@@ -566,7 +566,7 @@ def msvc_build_command_test(self):
         # successful definition via settings
         settings.build_type = "Debug"
         cmd = tools.msvc_build_command(settings, "project.sln")
-        self.assertIn('msbuild project.sln /p:Configuration=Debug /p:Platform="x86"', cmd)
+        self.assertIn('msbuild "project.sln" /p:Configuration="Debug" /p:Platform="x86"', cmd)
         self.assertIn('vcvarsall.bat', cmd)
 
     @unittest.skipUnless(platform.system() == "Windows", "Requires vswhere")