18

有没有办法为整个解决方案“运行自定义工具”?

为什么?自定义工具正在开发中,当进行更改时,我需要刷新所有使用它的项目以确保没有任何问题。

4

4 回答 4

18

在 Visual Studio 2010 中,解决方案导航器的图标栏中有一个按钮,它将运行解决方案中的所有 t4 模板。

在 Visual Studio 2012 中显示“构建”工具栏。该工具栏中有一个按钮,可以运行解决方案中的所有 t4 模板。

于 2012-12-13T05:33:47.377 回答
12

因为我需要一个答案并且必须自己做,所以这里是“运行自定义工具”的解决方案。

如果您只需要再次运行所有T4模板,那么从 VS2012 开始,在Build菜单中有Transform all T4 。

对于 VS2017,他们已删除宏,因此请按照https://msdn.microsoft.com/en-us/library/cc138589.aspx并使用您的菜单项制作插件。例如,将您的命令命名为 RefreshAllResxFiles,并将此文件粘贴到(默认命令集不包括 VSLangProj 的 dll,因此只需在 NuGet 中找到适当的包):

internal sealed class RefreshAllResxFiles
{
  public const int CommandId = 0x0100;
  public static readonly Guid CommandSet = new Guid(copy the guid from guidRefreshAllResxFilesPackageCmdSet from the vsct file);
  private readonly Package _package;
  private readonly DTE2 _dte;

  /// <summary>
  /// Initializes a new instance of the <see cref="RefreshAllResxFiles"/> class.
  /// Adds our command handlers for menu (commands must exist in the command table file)
  /// </summary>
  /// <param name="package">Owner package, not null.</param>
  private RefreshAllResxFiles(Package package)
  {
     _package = package ?? throw new ArgumentNullException(nameof(package));

     var commandService = ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
     if (commandService != null)
     {
        var menuCommandId = new CommandID(CommandSet, CommandId);
        var menuItem = new MenuCommand(MenuItemCallback, menuCommandId);
        commandService.AddCommand(menuItem);
     }
     _dte = ServiceProvider.GetService(typeof(DTE)) as DTE2;
  }

  public static RefreshAllResxFiles Instance { get; private set; }
  private IServiceProvider ServiceProvider => _package;

  public static void Initialize(Package package)
  {
     Instance = new RefreshAllResxFiles(package);
  }

  /// <summary>
  /// This function is the callback used to execute the command when the menu item is clicked.
  /// See the constructor to see how the menu item is associated with this function using
  /// OleMenuCommandService service and MenuCommand class.
  /// </summary>
  private void MenuItemCallback(object sender, EventArgs e)
  {
     foreach (Project project in _dte.Solution.Projects)
        IterateProjectFiles(project.ProjectItems);
  }

  private void IterateProjectFiles(ProjectItems projectProjectItems)
  {
     foreach (ProjectItem file in projectProjectItems)
     {
        var o = file.Object as VSProjectItem;
        if (o != null)
           ProcessFile(o);
        if (file.SubProject?.ProjectItems != null)
           IterateProjectFiles(file.SubProject.ProjectItems);
        if (file.ProjectItems != null)
           IterateProjectFiles(file.ProjectItems);
     }

  }

  private void ProcessFile(VSProjectItem file)
  {
     if (file.ProjectItem.Name.EndsWith(".resx"))
     {
        file.RunCustomTool();
        Log(file.ProjectItem.Name);
     }
  }
  public const string VsWindowKindOutput = "{34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3}";

  private void Log(string fileName)
  {
     var output = _dte.Windows.Item(VsWindowKindOutput);
     var pane = ((OutputWindow)output.Object).OutputWindowPanes.Item("Debug");
     pane.Activate();
     pane.OutputString(fileName);
     pane.OutputString(Environment.NewLine);
  }
}

宏的旧解决方案:

Option Strict Off
Option Explicit Off
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports VSLangProj
Imports System.Diagnostics

Public Module RecordingModule
    Sub IterateFiles()
        Dim solution As Solution = DTE.Solution
        For Each prj As Project In solution.Projects
            IterateProjectFiles(prj.ProjectItems)
        Next
    End Sub

    Private Sub IterateProjectFiles(ByVal prjItms As ProjectItems)
        For Each file As ProjectItem In prjItms
            If file.Object IsNot Nothing AndAlso TypeOf file.Object Is VSProjectItem Then
                AddHeaderToItem(file.Object)
            End If
            If file.SubProject IsNot Nothing AndAlso file.SubProject.ProjectItems IsNot Nothing AndAlso file.SubProject.ProjectItems.Count > 0 Then
                IterateProjectFiles(file.SubProject.ProjectItems)
            End If
            If file.ProjectItems IsNot Nothing AndAlso file.ProjectItems.Count > 0 Then
                IterateProjectFiles(file.ProjectItems)
            End If
        Next
    End Sub

    Private Sub AddHeaderToItem(ByVal file As VSProjectItem)
        If file.ProjectItem.Name.EndsWith(".resx") Then
            file.RunCustomTool()
            Log(file.ProjectItem.Name)
        End If
    End Sub
    Private Sub Write(ByVal name As String, ByVal message As String)
        Dim output As Window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
        Dim window As OutputWindow = output.Object
        Dim pane As OutputWindowPane = window.OutputWindowPanes.Item(name)
        pane.Activate()
        pane.OutputString(message)
        pane.OutputString(Environment.NewLine)
    End Sub
    Private Sub Log(ByVal message As String, ByVal ParamArray args() As Object)
        Write("Debug", String.Format(message, args))
    End Sub

    Private Sub Log(ByVal message As String)
        Write("Debug", message)
    End Sub

End Module
于 2011-07-13T08:55:35.920 回答
6

您可以在 Visual Studio 2010 的解决方案中执行所有 T4 模板。右键单击上方工具栏空间并启用“构建”工具栏。这将添加一个工具栏,其中包含以下内容:

  • 构建选择
  • 构建解决方案
  • 转换所有 T4 模板
  • 取消

“转换所有 T4 模板”应该给你你想要的。

于 2013-08-14T12:50:07.300 回答
2

对于开始使用其他答案中提供的解决方案但发现运行解决方案中的所有模板花费的时间太长的任何人 - 如果模板的一个子集就足够了 - 那么可以使用以下方法运行多个模板脚步。

  1. 选择您希望在 Visual Studio 的解决方案资源管理器中运行的模板。请注意,您应该选择的是实际文件,而不是包含它们的文件夹
  2. 右键单击选定的模板文件之一,然后Run Custom Tool从上下文菜单中选择。
于 2016-03-10T16:30:50.897 回答