Visual Studio 2010:在单个文件上运行自定义构建工具时指定工作目录

Posted

技术标签:

【中文标题】Visual Studio 2010:在单个文件上运行自定义构建工具时指定工作目录【英文标题】:Visual Studio 2010: Specify working directory when running custom build tools on individual files 【发布时间】:2014-05-08 23:01:57 【问题描述】:

我有一个 Visual Studio 2010 C++ 项目,其中包含需要使用生成 C++ 代码的内部自定义构建工具处理的文件。

我已经完成了为每个文件添加自定义构建工具的步骤。在自定义构建工具命令行中,使用“调用”来确保自定义构建工具在编译 C++ 代码之前针对所有这些文件运行。

唯一的问题是自定义构建工具需要从文件所在的目录运行,而不是从 Visual Studio 解决方案的位置运行。

我现在看到了一些可能的选择,但没有一个是理想的:

    将第一个文件上的自定义构建工具命令行更改为:“cd workingdir && call custom-tool ...”我不喜欢这个,因为它很脆弱——如果我在第一个文件之前添加一个按字母顺序排列的新文件,我必须记住,它需要自定义构建步骤中的这个特殊步骤。 创建一个批处理文件来更改工作目录,调用自定义构建工具,然后更改回来。从 Visual Studio 调用此批处理文件。 使用“start”而不是“call”来调用自定义构建工具。这带来了为每个文件打开一个命令 shell 的缺点(看起来这些命令 shell 需要手动关闭)。

在工作目录中的文件上运行自定义构建工具是否有更好的选择?

谢谢。

【问题讨论】:

由于该工具是内部制作的,是否可以将其更改为将相关文件的完整路径作为参数,cd 到其工作目录,然后在那里执行任何操作? 我会使用我认为的批处理文件。 谢谢!我们最终可能会更改构建工具,但遗憾的是对于我的项目来说还不够快。 当您查看使用 Start 时,我假设使用其 /D 选项,您是否尝试包含其 /B 和必要时 /Wait 选项?例如Start ["Title"] [/D Path] [/Wait] [/B] [Command/Program] [Parameters]. 【参考方案1】:

Visual Studio 项目文件是 MSBuild 文件。因此,您可以在 VS 中构建项目时手动修改项目文件并执行其他操作。

为此:

    创建一个简单的 MSbuild 文件,命名为 e.g. MyCustomtool.target。此文件“覆盖”MSBuild 目标并调用您的自定义工具。

这里是示例文件:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="BeforeBuild">
    <Message Text="Calling custom tool for %(ClCompile.Identity)"/>
    <Exec Command="customtool.exe %(ClCompile.Identity)" WorkingDirectory="$(ProjectDir)" />
  </Target>
</Project>

这个文件: “覆盖”目标名称“BeforeBuild”,并为组“ClCompile”中定义的每个文件显示文本消息并执行 customtool.exe,名称为已编译的 .cpp 文件作为参数。

    您必须修改您的 .vcxproj 文件并在最后一行包含 &lt;/Project&gt; 之前导入您的文件添加一行:

&lt;Import Project="MyCustomtool.target"/&gt;

在此之后,Visual Studio 将为项目中的每个文件执行您的自定义工具。

一些cmets:

因为我没有安装 VS 2010,所以我不能 100% 确定可以使用哪个目标名称。我认为“BeforeBuild”应该对 VS 2010 有效(在 VS 2017 中我使用的是“BeforeBuildGenerateSources”)。

您可以将选项“工具/选项/项目和解决方案/构建和运行/MSBuild 项目构建输出详细程度”更改为“详细”,查看构建过程的详细输出并检查目标名称。

文件组“ClCompile”包含所有 *.cpp 文件。您可以检查 .vcxproj 文件中的文件组名称。 您可以为您的自定义工具设置工作目录(如上)。如果您需要在 MSBuild 文件中使用 $(ProjectDir)、$(OutDir) 等 VisualStudio 宏。

【讨论】:

【参考方案2】:

您可以创建一个简单的调用程序应用程序来更改工作目录并将构建工具作为子进程调用。您使用 Visual Studio,所以我想您的平台是 Windows。在这种情况下,应用程序的代码可以简单如下(它是 C 语言,基于 MSDN 中的示例)

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

int _tmain(int argc, TCHAR *argv[])

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    if (argc < 3)
    
        printf("Usage: %s working_directory !cmdline\n", argv[0]);
        return 1;
    

    if (!SetCurrentDirectory(argv[1]))
    
        printf("SetCurrentDirectory failed (%d)\n", GetLastError());
        return 1;
    

    LPTSTR commandLine = GetCommandLine();
    while (*commandLine && *commandLine != '!')
        ++commandLine;
    ++commandLine;

    if (!CreateProcess(NULL, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
    
        printf("CreateProcess failed (%d).\n", GetLastError());
        return 1;
    

    // Wait until child process exits.
    WaitForSingleObject(pi.hProcess, INFINITE);
    DWORD exitCode = 0;
    GetExitCodeProcess(pi.hProcess, &exitCode);

    // Close process and thread handles. 
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return exitCode;

它接收新的工作目录作为第一个参数,然后搜索!在命令行中并将其后的所有内容视为子进程命令行。这非常方便,因为您无需费心引用引号等。例如

cdandcall.exe C:\Windows !python -c "import os; print(os.path.abspath('.'))"

将在输出中打印C:\Windows。 (当然,如果您将应用程序编译为cdandcall.exe,则在您的PATH 上有python,并且存在C:\Windows 文件夹。

【讨论】:

以上是关于Visual Studio 2010:在单个文件上运行自定义构建工具时指定工作目录的主要内容,如果未能解决你的问题,请参考以下文章

visual studio 2010编译c的设置方法

Visual Studio 2010 性能测试

Visual Studio 2010错误#U1095,NMAKE

visual studio 2010 一个解决方案里有多个c++源文件 怎么只执行其中一个?

Visual Studio 2010 发布配置文件——它们存储在哪里?

打开 .sql 文件时,Visual Studio 2010 挂断