Powershell: Finding items in a Visual Studio project

In the Macaw Solutions Factory we execute a lot of PowerShell code in the context of Visual Studio, meaning that we can access the Visual Studio object model directly from our PowerShell code.

There is a great add-in for Visual Studio that provides you with a PowerShell console within Visual Studio that also allows you to access the Visual Studio object model to play with VSX (Visual Studio Extensibility). This add-in is called Power Console.

If you paste the function below in this Power Console, you can find a (selection of) project items in a specified Visual Studio project.

For example:

FindProjectItems -SolutionRelativeProjectFile 'Business.ServiceInterfaces\Business.ServiceInterfaces.csproj' -Pattern '.asmx' | select-object RelativeFileName

returns:

RelativeFileName                                                                                                                                ----------------
Internal\AnotherSoapService.asmx
SampleSoapService.asmx

What I do is that I extend the standard Visual Studio ProjectItem objects with two fields: FileName (this is the full path to the item) and RelativeFileName (this is the path to the item relative to the project folder (line 53-55). I return a collection of Visual Studio project items, with these additional fields.

A great way of testing out this kind of code is by editing it in Visual Studio using the PowerGuiVSX add-in (which uses the unsurpassed PowerGui script editor), and copying over the code into the Power Console.

Find project items
  1. function FindProjectItems
  2. {
  3.     param
  4.     (
  5.         $SolutionRelativeProjectFile,
  6.         $Pattern = ''
  7.     )
  8.     
  9.     function FindProjectItemsRecurse
  10.     {
  11.         param
  12.         (
  13.             $AbsolutePath,
  14.             $RelativePath = '',
  15.             $ProjectItem,
  16.             $Pattern
  17.         )
  18.  
  19.         $projItemFolder = '{6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C}' # Visual Studio defined constant
  20.         
  21.         if ($ProjectItem.Kind -eq $projItemFolder)
  22.         {
  23.             if ($ProjectItem.ProjectItems -ne $null)
  24.             {
  25.                 if ($RelativePath -eq '')
  26.                 {
  27.                     $relativeFolderPath = $ProjectItem.Name
  28.                 }
  29.                 else
  30.                 {
  31.                     $relativeFolderPath = Join-Path -Path $RelativePath -ChildPath $ProjectItem.Name
  32.                 }
  33.                 $ProjectItem.ProjectItems | ForEach-Object {
  34.                     FindProjectItemsRecurse -AbsolutePath $AbsolutePath -RelativePath $relativeFolderPath -ProjectItem $ -Pattern $Pattern
  35.                 }
  36.             }
  37.         }
  38.         else
  39.         {
  40.             if ($ProjectItem.Name -like $pattern)
  41.             {
  42.                 if ($RelativePath -eq '')
  43.                 {
  44.                     $relativeFileName = $ProjectItem.Name
  45.                 }
  46.                 else
  47.                 {
  48.                     if ($RelativePath -eq $null) { Write-Host "Relative Path is NULL" }
  49.                     $relativeFileName = Join-Path -Path $RelativePath -ChildPath $ProjectItem.Name
  50.                 }
  51.                 $fileName = Join-Path -Path $AbsolutePath -ChildPath $relativeFileName;
  52.                 
  53.                 $ProjectItem |
  54.                     Add-Member -MemberType NoteProperty -Name RelativeFileName -Value $relativeFileName -PassThru |
  55.                     Add-Member -MemberType NoteProperty -Name FileName -Value $fileName -PassThru
  56.             }
  57.         }
  58.     }
  59.     
  60.     $proj = $DTE.Solution.Projects.Item($SolutionRelativeProjectFile)
  61.     $projPath = Split-Path -Path $proj.FileName -Parent
  62.     if ($proj -eq $null) { throw "No project '$SolutionRelativeProjectFile' found in current solution" }
  63.     $proj.ProjectItems | ForEach-Object {
  64.         FindProjectItemsRecurse -AbsolutePath $projPath -ProjectItem $ -Pattern $Pattern
  65.     }
  66. }

No Comments