为整个解决方案运行自定义工具

时间:2009-12-16 10:24:51

标签: visual-studio customtool

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

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

4 个答案:

答案 0 :(得分:16)

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

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

答案 1 :(得分:11)

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

如果您只需要再次运行所有 T4 模板,那么自VS2012以来, Build 菜单中有转换所有T4 。< / p>

对于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

答案 2 :(得分:5)

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

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

“转换所有T4模板”应该可以提供您想要的内容。

答案 3 :(得分:2)

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

  1. 在Visual Studio的“解决方案资源管理器”中选择要运行的模板。请注意,您应该选择实际文件 - 不是包含它们的文件夹
  2. 右键单击其中一个选定的模板文件,然后从上下文菜单中选择Run Custom Tool