Макрос Visual Studio: Найти файлы, которые не включены в проект? - PullRequest
8 голосов
/ 04 января 2010

Я хотел бы написать макрос для обхода файлов в каталоге моего проекта и поиска файлов, которые не включены в проект.

Играя с объектом DTE, я вижу, что у объекта Project есть ProjectItems; если ProjectItem представляет каталог, то у него есть собственная коллекция ProjectItems. Это дает мне все файлы, которые включены в проект.

Таким образом, я мог бы рекурсивно сканировать каждую коллекцию ProjectItems, и для каждого ProjectItem, являющегося каталогом, проверить, есть ли в файловой системе файлы, которые не имеют соответствующего ProjectItem. Это кажется неуклюжим, хотя.

Есть какие-нибудь идеи о более простом подходе к этому?

Ответы [ 4 ]

11 голосов
/ 27 февраля 2012

Вот версия вашего кода на C #:

public static void IncludeNewFiles()
{
    int count = 0;
    EnvDTE80.DTE2 dte2;
    List<string> newfiles;

    dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");

    foreach (Project project in dte2.Solution.Projects)
    {
        if (project.UniqueName.EndsWith(".csproj"))
        {
            newfiles = GetFilesNotInProject(project);

            foreach (var file in newfiles)
                project.ProjectItems.AddFromFile(file);

            count += newfiles.Count;
        }
    }
    dte2.StatusBar.Text = String.Format("{0} new file{1} included in the project.", count, (count == 1 ? "" : "s"));
}

public static List<string> GetAllProjectFiles(ProjectItems projectItems, string extension)
{
    List<string> returnValue = new List<string>();

    foreach(ProjectItem projectItem in projectItems)
    {
        for (short i = 1; i <= projectItems.Count; i++)
        {
            string fileName = projectItem.FileNames[i];
            if (Path.GetExtension(fileName).ToLower() == extension)
                returnValue.Add(fileName);
        }
        returnValue.AddRange(GetAllProjectFiles(projectItem.ProjectItems, extension));        
    }

    return returnValue;
}

public static List<string> GetFilesNotInProject(Project project)
{
    List<string> returnValue = new List<string>();
    string startPath = Path.GetDirectoryName(project.FullName);
    List<string> projectFiles = GetAllProjectFiles(project.ProjectItems, ".cs");

    foreach (var file in Directory.GetFiles(startPath, "*.cs", SearchOption.AllDirectories))
        if (!projectFiles.Contains(file)) returnValue.Add(file);

    return returnValue;
}
8 голосов
/ 04 января 2010

Спасибо @JaredPar и @lpthnc за указание в правильном направлении.В итоге я использовал подход, очень похожий на тот, что описал @JaredPar выше.Вот мой рабочий макрос FWIW.

Imports System.IO
Imports System.Collections.Generic
Imports EnvDTE

Public Module Main

    Sub IncludeNewFiles()
        Dim Count As Integer = 0
        For Each Project As Project In DTE.Solution.Projects
            If Project.UniqueName.EndsWith(".vbproj") Then
                Dim NewFiles As List(Of String) = GetFilesNotInProject(Project)
                For Each File In NewFiles
                    Project.ProjectItems.AddFromFile(File)
                Next
                Count += NewFiles.Count
            End If
        Next
        DTE.StatusBar.Text = String.Format("{0} new file{1} included in the project.", Count, If(Count = 1, "", "s"))
    End Sub

    Private Function GetAllProjectFiles(ByVal ProjectItems As ProjectItems, ByVal Extension As String) As List(Of String)
        GetAllProjectFiles = New List(Of String)
        For Each ProjectItem As ProjectItem In ProjectItems
            For i As Integer = 1 To ProjectItem.FileCount
                Dim FileName As String = ProjectItem.FileNames(i)
                If Path.GetExtension(fileName).ToLower = Extension Then
                    GetAllProjectFiles.Add(fileName)
                End If
            Next
            GetAllProjectFiles.AddRange(GetAllProjectFiles(ProjectItem.ProjectItems, Extension))
        Next
    End Function

    Private Function GetFilesNotInProject(ByVal Project As Project) As List(Of String)
        Dim StartPath As String = Path.GetDirectoryName(Project.FullName)
        Dim ProjectFiles As List(Of String) = GetAllProjectFiles(Project.ProjectItems, ".vb")
        GetFilesNotInProject = New List(Of String)
        For Each file In Directory.GetFiles(StartPath, "*.vb", SearchOption.AllDirectories)
            If Not ProjectFiles.Contains(file) Then GetFilesNotInProject.Add(file)
        Next
    End Function

End Module
2 голосов
/ 04 января 2010

Я бы выбрал подход к

  1. Перечислить файловую систему, ищущую все файлы
  2. Проверьте и посмотрите, имеет ли данный файл связанный элемент проекта.

Вот небольшой пример кода

Function ContainsItem(p as Project, fileName as String) As Boolean
  Try
    Return p.ProjectItems.Item(fileName)
  Catch ex As ArgumentException
    Return False
  End Try
End Function

Function CotainsItem(dte as DTE, fileName as String) As Boolean
  For Each p As Project in dte.Solution.Projects
    Return ContainsItem(p, fileName)
  Next
End Function

Function GetFilesNotInProject(dte as DTE, startPath as String) as List(Of String)
  Dim list As New List(Of String)
  Dim files = Directory.GetFiles(startPath, "*.cs", SearchOPtions.AllDirectories)
  For Each file in files 
    If Not ContainsItem(dte, file) Then
      list.Add(file)
    End If
  Next
  Return list
End Function
0 голосов
/ 02 мая 2014

Я бы пошел с PowerShell. Сценарий PowerShell в моем другом посте сделает это за вас. Сценарий получит список включенных файлов из файла проекта и сравнит его с файлами на диске. Вы получите набор файлов, которые находятся на диске, но не включены в проект. Вы можете удалить их или считать их удаляемыми для TFS.

https://stackoverflow.com/a/23420956/846428

...