2010-01-04 9 views
8

Ich möchte ein Makro schreiben, um durch die Dateien in meinem Projektverzeichnis zu crawlen und Dateien zu finden, die nicht im Projekt enthalten sind.Visual Studio-Makro: Suchen Sie Dateien, die nicht im Projekt enthalten sind?

Beim Herumspielen mit dem DTE-Objekt, sehe ich, dass das Project Objekt hat ProjectItems; Wenn ein ProjectItem ein Verzeichnis darstellt, hat es seine eigene ProjectItems Sammlung. Das gibt mir alle Dateien, die in dem Projekt enthalten sind.

So konnte ich rekursiv durch jede ProjectItems-Auflistung crawlen und für jedes ProjectItem, das ein Verzeichnis ist, überprüfen, ob Dateien im Dateisystem vorhanden sind, die kein entsprechendes ProjectItem haben. Das scheint jedoch plump zu sein.

Irgendwelche Ideen für einen einfacheren Weg, dies zu erreichen?

+0

eine Liste aller beteiligten Verzeichnissen, jede Datei in ihnen finden, ihre vollständigen Pfade in einen Satz Datenstruktur speichern. Jetzt gehen Sie durch alle Dateien in Ihrem Projekt und entfernen Sie sie aus der Menge (den richtigen Pfad voranstellen). Dann überprüfen Sie, was Sie übrig haben ... –

+0

Danke - warum nicht nur dies als Antwort posten? –

Antwort

8

Dank @JaredPar und @lpthnc für mich in der richtigen Richtung. Ich benutzte einen Ansatz, der dem ähnlich war, was @JaredPar oben skizziert hat. Hier ist mein Arbeitsmakro 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 
+0

Funktioniert dies für die gesamte Lösung? Ich habe viele ausgeschlossene Dateien, die ich löschen möchte. –

+0

@SohamDasgupta - Sie müssen wahrscheinlich nacheinander die Projekte der Lösung durchgehen und tun dies für jeden einzelnen. –

+0

Scheint, dass [Makros in Visual Studio 2012 nicht mehr verfügbar sind] (http://www.dzone.com/articles/missing-macros-visual-studio). Eine mögliche Lösung für VS 2012? –

2

Der Ansatz, den ich nehmen würde, ist zu

  1. das Dateisystem Aufzählen für alle Dateien suchen
  2. prüfen und sehen, ob die angegebene Datei ein zugehöriges Projektelement hat.

Hier ist ein kurzes Stück Beispielcode

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

Danke - das hat sehr geholfen. Es funktioniert nicht so wie es ist, weil 'p.ProjectItems' nur Elemente im Stammverzeichnis des Projekts enthält; Sie müssen nacheinander jede ProjectItems-Auflistung von ProjectItem recursen. In dem Code, den ich gepostet habe, erstelle ich eine Liste der vorhandenen Dateien und benutze diese, um zu sehen, was nicht enthalten ist. –

11

Hier ist der C# -Version Code:

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; 
} 
0

ich mit Powershell gehen würde. Das PowerShell-Skript in meinem anderen Beitrag wird dies für Sie tun. Das Skript ruft die Liste der enthaltenen Dateien aus der Projektdatei ab und vergleicht sie mit den Dateien auf der Festplatte. Sie erhalten die Dateien, die sich auf der Festplatte befinden, aber nicht im Projekt enthalten sind. Sie können sie entweder löschen oder als Löschvorgänge für TFS anhängen.

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