VS2012:文件属性;如何按文件类型指定默认自定义工具

时间:2014-07-02 16:23:04

标签: c# visual-studio-2012 razor apache-spark

我正在寻找一些机制来在向VS2012项目添加特定类型的新文件时自动应用文件属性的值(如VS属性窗口中所示)。

例如,如果有人添加了*.cshtml文件,我希望默认情况下将自定义工具设置为“RazorGenerator”,因为它可能很麻烦,确保在所有剃刀文件中手动指定。< / p>

类似于*.spark,其中Build Action必须始终设置为Content(或CI构建中断)。

似乎没有任何VS2012内置的配置默认文件属性的设置,那么人们正在做些什么来解决这个问题,这对于开发团队来说效果很好?

我正在寻找选择。

1 个答案:

答案 0 :(得分:0)

ANTLR 4 C#目标要求在添加到项目中的 *。g4 文件时采取类似的操作。

  • 构建操作设置为Antlr4
  • 将其他几个属性设置为默认值
  • 通过自定义Visual Studio
  • 中的属性窗口来显示多个自定义属性

根据您的提问,我会专注于只有第一项

为文件类型

提供默认构建操作

这实际上是ANTLR Language Support扩展程序中提供的一项功能。当具有特定扩展名的文件添加到项目时,扩展会执行操作。有关行为的详细信息,请参阅OnAfterAddFilesEx开头的注释。此代码来自扩展Package并实现IVsTrackProjectDocumentsEvents2的类。此接口的其余方法的实现只返回VSConstants.E_NOTIMPL。请注意,此代码可能使用我的解决方案中其他位置定义的自定义扩展方法。该代码不是为了直接使用,而是仅作为希望通过自己的扩展执行类似操作的人的指南。

private static readonly Guid CSharpProjectTypeGuid = Guid.Parse(PrjKind.prjKindCSharpProject);

private uint _trackDocumentsEventsCookie;

protected override void Initialize()
{
    base.Initialize();

    IVsTrackProjectDocuments2 trackDocuments2 = serviceProvider.GetTrackProjectDocuments2();
    trackDocuments2.AdviseTrackProjectDocumentsEvents(this, out _trackDocumentsEventsCookie);
}

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        if (_trackDocumentsEventsCookie != 0)
        {
            var serviceProvider = this.AsVsServiceProvider();
            IVsTrackProjectDocuments2 trackDocuments = serviceProvider.GetTrackProjectDocuments2();
            trackDocuments.UnadviseTrackProjectDocumentsEvents(_trackDocumentsEventsCookie);
            _trackDocumentsEventsCookie = 0;
        }
    }

    base.Dispose(disposing);
}

public int OnAfterAddFilesEx(int cProjects, int cFiles, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, VSADDFILEFLAGS[] rgFlags)
{
    /* need to make the following alterations:
        *  1. set the Build Action of *.g and *.g3 to Antlr3
        *  2. set the Build Action of *.g4 to Antlr4
        *  3. set the Custom Tool of *.g, *.g3, and *.g4 to MSBuild:Compile
        *  4. set the Custom Tool Namespace of *.g4 to $(RootNamespace) + relative folder path
        */

    for (int i = 0; i < cProjects; i++)
    {
        IVsProject project = rgpProjects[i];
        int projectFiles = (i == cProjects - 1) ? cFiles : rgFirstIndices[i + 1];
        projectFiles -= rgFirstIndices[i];

        if (!IsCSharpProject(project))
            continue;

        for (int j = 0; j < projectFiles; j++)
        {
            string currentFile = rgpszMkDocuments[rgFirstIndices[i] + j];
            if (string.IsNullOrEmpty(currentFile))
                continue;

            bool grammarFile =
                currentFile.EndsWith(".tokens", StringComparison.OrdinalIgnoreCase)
                || currentFile.EndsWith(".g", StringComparison.OrdinalIgnoreCase)
                || currentFile.EndsWith(".g3", StringComparison.OrdinalIgnoreCase)
                || currentFile.EndsWith(".g4", StringComparison.OrdinalIgnoreCase);

            if (grammarFile)
            {
                OnAfterAddedGrammarFile(project, currentFile);
            }
        }
    }

    return VSConstants.S_OK;
}

private static bool IsCSharpProject(IVsProject project)
{
    IVsAggregatableProject aggregatableProject = project as IVsAggregatableProject;
    if (aggregatableProject == null)
        return false;

    string guidsString = null;
    if (ErrorHandler.Failed(ErrorHandler.CallWithCOMConvention(() => aggregatableProject.GetAggregateProjectTypeGuids(out guidsString))))
        return false;

    if (string.IsNullOrWhiteSpace(guidsString))
        return false;

    string[] guids = guidsString.Split(';');
    foreach (var guidString in guids)
    {
        Guid guid;
        if (Guid.TryParse(guidString, out guid) && guid == CSharpProjectTypeGuid)
            return true;
    }

    return false;
}

private void OnAfterAddedGrammarFile(IVsProject project, string currentFile)
{
    int found;
    VSDOCUMENTPRIORITY[] priority = new VSDOCUMENTPRIORITY[1];
    uint itemId;
    if (ErrorHandler.Failed(project.IsDocumentInProject(currentFile, out found, priority, out itemId)))
        return;

    if (found == 0 || priority[0] != VSDOCUMENTPRIORITY.DP_Standard)
        return;

    string desiredItemType = "Antlr3";
    if (string.Equals(Path.GetExtension(currentFile), ".tokens", StringComparison.OrdinalIgnoreCase))
        desiredItemType = "AntlrTokens";
    else if (string.Equals(Path.GetExtension(currentFile), ".g4", StringComparison.OrdinalIgnoreCase))
        desiredItemType = "Antlr4";

    IVsHierarchy hierarchy = project as IVsHierarchy;
    if (hierarchy != null)
    {
        object browseObject = null;
        PropertyDescriptorCollection propertyDescriptors = null;
        int hr = ErrorHandler.CallWithCOMConvention(() => hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_BrowseObject, out browseObject));
        if (ErrorHandler.Succeeded(hr))
            propertyDescriptors = TypeDescriptor.GetProperties(browseObject);

        object obj;
        hr = hierarchy.GetProperty(itemId, (int)__VSHPROPID4.VSHPROPID_BuildAction, out obj);
        if (ErrorHandler.Succeeded(hr))
        {
            string buildAction = obj != null ? obj.ToString() : null;
            if (string.IsNullOrWhiteSpace(buildAction) || string.Equals(buildAction, "None", StringComparison.OrdinalIgnoreCase))
            {
                hr = ErrorHandler.CallWithCOMConvention(() => hierarchy.SetProperty(itemId, (int)__VSHPROPID4.VSHPROPID_BuildAction, desiredItemType));
            }
        }

        if (ErrorHandler.Failed(hr) && propertyDescriptors != null)
        {
            PropertyDescriptor itemTypeDescriptor = propertyDescriptors["ItemType"] ?? propertyDescriptors["BuildAction"];
            if (itemTypeDescriptor != null)
            {
                obj = itemTypeDescriptor.GetValue(browseObject);
                string buildAction = (string)itemTypeDescriptor.Converter.ConvertToInvariantString(obj);
                if (string.IsNullOrWhiteSpace(buildAction) || string.Equals(buildAction, "None", StringComparison.OrdinalIgnoreCase))
                {
                    try
                    {
                        obj = itemTypeDescriptor.Converter.ConvertFromInvariantString(desiredItemType);
                        itemTypeDescriptor.SetValue(browseObject, obj);
                    }
                    catch (NotSupportedException)
                    {
                    }
                }
            }
        }

        if (propertyDescriptors != null)
        {
            PropertyDescriptor customToolDescriptor = propertyDescriptors["CustomTool"];
            if (customToolDescriptor != null)
            {
                obj = customToolDescriptor.GetValue(browseObject);
                string customTool = customToolDescriptor.Converter.ConvertToInvariantString(obj);
                if (string.IsNullOrWhiteSpace(customTool))
                {
                    try
                    {
                        obj = customToolDescriptor.Converter.ConvertToInvariantString("MSBuild:Compile");
                        customToolDescriptor.SetValue(browseObject, obj);
                    }
                    catch (NotSupportedException)
                    {
                    }
                }
            }

            PropertyDescriptor customToolNamespaceDescriptor = propertyDescriptors["CustomToolNamespace"];
            if (customToolNamespaceDescriptor != null)
            {
                object defaultNamespace;
                hr = hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_DefaultNamespace, out defaultNamespace);
                if (ErrorHandler.Succeeded(hr) && !string.IsNullOrEmpty(defaultNamespace as string))
                {
                    obj = customToolNamespaceDescriptor.GetValue(browseObject);
                    string customToolNamespace = customToolNamespaceDescriptor.Converter.ConvertToInvariantString(obj);
                    if (string.IsNullOrWhiteSpace(customToolNamespace))
                    {
                        try
                        {
                            obj = customToolNamespaceDescriptor.Converter.ConvertToInvariantString(defaultNamespace);
                            customToolNamespaceDescriptor.SetValue(browseObject, obj);
                        }
                        catch (NotSupportedException)
                        {
                        }
                    }
                }
            }
        }
    }
}