如何在C#控制台应用中运行MSBuild命令?遇权限及项目文件错误
问题
在Visual Studio 2017命令提示符中执行msbuild /t:scmclean可正常运行,但在C#控制台应用中执行失败,目标工作目录为D:/Git/abc/Build/Tools(该目录下存在被命令调用的csproj文件)。
已尝试的代码
CliWrap实现
var result = await Cli.Wrap("C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe") .WithArguments("/t:scmclean") .WithWorkingDirectory("D:\git\abc\Build\Tools") .WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutCO)) .WithStandardErrorPipe(PipeTarget.ToStringBuilder(stdErrCO)) .ExecuteBufferedAsync(); var stdOut1 = stdOutCO.ToString(); var stdErr1 = stdErrCO.ToString(); Console.WriteLine("Build Info:"); Console.WriteLine(stdOut1); Console.WriteLine(stdErr1);
Process.Start实现
Process.Start("C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe", "/t:scmclean");
遇到的错误
- CliWrap执行时:出现权限拒绝错误,但通过
System.Security.Principal.WindowsIdentity.GetCurrent().Name检查显示当前为超级用户。 - Process.Start执行时:
MSBUILD : error MSB1003: Specify a project or solution file. The current working directory does not contain a project or solution file.
解决方案
1. 修复路径字符串转义问题
C#中字符串内的\需要转义为\\,或使用@前缀的逐字字符串,否则路径会被解析错误,导致找不到MSBuild程序或权限异常。例如将MSBuild路径改为:
@"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"
工作目录路径同理改为:
@"D:\git\abc\Build\Tools"
2. Process.Start需指定工作目录
默认情况下Process.Start的工作目录是控制台应用的输出目录,而非目标目录,需显式设置WorkingDirectory,同时重定向输出流以获取执行结果:
var processStartInfo = new ProcessStartInfo { FileName = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe", Arguments = "/t:scmclean", WorkingDirectory = @"D:\git\abc\Build\Tools", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (var process = Process.Start(processStartInfo)) { string stdOut = process.StandardOutput.ReadToEnd(); string stdErr = process.StandardError.ReadToEnd(); process.WaitForExit(); Console.WriteLine("Build Info:"); Console.WriteLine(stdOut); Console.WriteLine(stdErr); }
3. CliWrap正确实现(含结果输出)
修复路径后,CliWrap可直接通过ExecuteBufferedAsync的返回结果获取输出,无需手动维护StringBuilder:
var msbuildPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe"; var workDir = @"D:\git\abc\Build\Tools"; var result = await Cli.Wrap(msbuildPath) .WithArguments("/t:scmclean") .WithWorkingDirectory(workDir) .ExecuteBufferedAsync(); Console.WriteLine("Build Info:"); Console.WriteLine(result.StandardOutput); Console.WriteLine(result.StandardError);
4. 权限问题排查
- 尝试以管理员身份运行控制台应用,避免UAC权限限制。
- 检查
D:\git\abc\Build\Tools目录的写入权限(scmclean命令需要清理文件,需对应权限)。
关于进程执行结果输出
无论是使用Process.Start还是CliWrap,核心是重定向标准输出和错误流,读取流内容后输出到控制台:
Process.Start需设置RedirectStandardOutput = true和RedirectStandardError = true,通过StandardOutput.ReadToEnd()和StandardError.ReadToEnd()获取内容。- CliWrap的
ExecuteBufferedAsync()返回的结果对象直接包含StandardOutput和StandardError属性,可直接读取输出。
内容的提问来源于stack exchange,提问作者madhurima
相关产品推荐
相关产品推荐

