控制台应用调用MSBuild跳过编译且未启用VS2017命令行的问题
问题解决:MSBuild跳过编译+控制台调用VS2017命令行环境
一、让控制台应用调用VS2017命令行环境
你在VS终端设置的默认命令行仅对VS内置终端生效,控制台应用启动进程时不会自动加载VsDevCmd.bat的环境变量。需要修改RunMSBuild方法,先加载VS开发环境变量再执行MSBuild:
修改后的RunMSBuild方法代码:
private static bool RunMSBuild(string msBuildPath, string arguments = null) { try { string vsDevCmdPath = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat"; if (!File.Exists(vsDevCmdPath)) throw new Exception($"Error: VsDevCmd.bat not found ({vsDevCmdPath})"); string msBuildFilename = Path.Combine(msBuildPath, "MSBuild.exe"); if (!File.Exists(msBuildFilename)) throw new Exception($"Error: MSBuild.exe not found ({msBuildFilename})"); // 构造cmd命令:先加载VS环境,再执行MSBuild string cmdArguments = $"/c \"\"{vsDevCmdPath}\" && \"{msBuildFilename}\" {arguments}\""; ProcessStartInfo startInfo = new ProcessStartInfo("cmd.exe") { CreateNoWindow = true, RedirectStandardError = true, RedirectStandardOutput = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Normal, Arguments = cmdArguments }; using (Process p = new Process() { StartInfo = startInfo, EnableRaisingEvents = true }) { p.ErrorDataReceived += (sender, e) => { if (!String.IsNullOrEmpty(e.Data)) { Console.WriteLine("Error: " + e.Data); Debug.WriteLine("Error: " + e.Data); } }; p.OutputDataReceived += (sender, e) => { if (!String.IsNullOrEmpty(e.Data)) { Console.WriteLine("Output: " + e.Data); Debug.WriteLine("Output: " + e.Data); } }; p.Start(); p.BeginErrorReadLine(); p.BeginOutputReadLine(); p.WaitForExit(); p.CancelErrorRead(); p.CancelOutputRead(); // 检查进程退出码,0表示执行成功 return p.ExitCode == 0; } } catch (Exception ex) { Console.WriteLine("Error {0}", ex.Message); return false; } }
关键改动:
- 先指定VsDevCmd.bat路径,通过
cmd.exe /c执行环境加载脚本,再调用MSBuild - 增加进程退出码检查,确保MSBuild执行成功才返回true
二、解决MSBuild提示"输出文件已最新跳过编译"
这个提示是MSBuild的正常逻辑:当所有输入文件(源码、配置等)的修改时间早于输出文件(dll、exe等)时,会跳过编译以提升效率。如果需要强制重新编译,可以:
- 在调用RunMSBuild时添加
/t:Clean;Build参数(先清理再编译),示例:retvalue = RunMSBuild(msBuildPath, "/t:Clean;setup"); retvalue = RunMSBuild(msBuildPath, "/t:Clean;debug;pbuild"); - 或者添加
/p:ForceRebuild=true参数强制重建目标,示例:retvalue = RunMSBuild(msBuildPath, "/t:debug;pbuild /p:ForceRebuild=true");
额外注意点
你的代码中string RMSolution = ResourceManagerPath;存在未定义变量问题,应改为string RMSolution = RMPath;,否则会编译报错。
内容的提问来源于stack exchange,提问作者madhurima
相关产品推荐
相关产品推荐

