I've been working on this about 14 hours now. It is totally driving me crazy.
Without referencing any custom dlls I want to walk $dte.Solution.Projects
for either projects or projectitems to check if
$SourceControl = get-interface $dte.SourceControl ([EnvDTE.SourceControl])
$SourceControl.IsItemUnderScc()
Things like solution folders get in the way. I've done this just fine in C# repeatedly (and in F#), I just can't seem to do it in powershell. I have done it both (C#) via Dte.Solution
and UIHierarchy
My C# walking code is in a T4 Nuget Package as an example, but all my linqpad samples currently use UIHierarchy
Here's a sample from that c# that doesn't seem to work in powershell:
C# Projects projects = dte.Solution.Projects;
Powershell $Projects= [EnvDTE.Projects]$dte.Solution.Projects
which fails with Cannot convert the "System.__ComObject" value of type "System.__ComObject#{e3ec0add-31b3-461f-8303-8a5e6931257a}" to type "EnvDTE.Projects".
Using the code provided later in this answer calling it for just the first project in your solution would be GetUnversionedFiles(GetProjectFiles((GetSolutionProjects).get_Item(1)))
to run this code GetUnversionedFiles(GetProjectFiles((GetSolutionProjects).get_Item(0)))
Get the projects in the solution
function GetSolutionProjects(){
$projects = get-interface $dte.Solution.Projects ([EnvDTE.Projects])
write-debug "projects=$projects"
$result = new-object "System.Collections.Generic.List[EnvDTE.Project]"
foreach($project in $projects.GetEnumerator()) {
if($project -eq $null){
continue;
}
write-debug "yay project or solution folder! $project $project.Kind"
if($project.Kind -eq [EnvDTE80.ProjectKinds]::vsProjectKindSolutionFolder){
write-debug ("Solution folder "+$project.Name)
foreach($solutionFolderProject in RecurseSolutionFolderProjects($project)){
$result+=$solutionFolderProject
}
} else {
write-debug ("else " +$project.Name + " " + $project.Kind
$result+=$project
}
}
return $result
}
recurse down solution folders
function RecurseSolutionFolderProjects(){
param($solutionFolder = $(throw "Please specify a solutionFolder"))
$projectList = @()
for($i = 1; $i -le $solutionFolder.ProjectItems.Count; $i++){
$subProject = $solutionFolder.ProjectItems.Item($i).subProject
if($subProject -eq $null){
continue;
}
if($subProject.Kind -eq [EnvDTE80.ProjectKinds]::vsProjectKindSolutionFolder)
{
$projectList += RecurseSolutionFolderProjects($subProject)
} else {
$projectList += $subProject
}
}
return $projectList
}
walk down projectItems
function RecurseDescendants(){
param($source = $(throw "Please specify a source"))
write-debug "starting RecurseDescendants"
$result = new-object "System.Collections.Generic.List[EnvDTE.ProjectItem]"
foreach($s in $source){
#write-host "working on " $s.Kind $s.Name $s.FileNames(0)
$pi = $s.Object -as [EnvDTE.ProjectItem]
$result+=$s
$children=$s.ProjectItems
foreach($child in RecurseDescendants($children)){
$result+=$child
}
write-debug "inner for each stopped"
}
write-debug "outer for each finished"
return $result
}
walk project for files within
function GetProjectFiles(){
param($project = $(throw "Please specify a project"))
write-debug ("getting project files for " + $project.Name + " "+ $project.ProjectName)
$projectItems = RecurseDescendants($project.ProjectItems)
return $projectItems | Where-Object {$_.Kind -ne [EnvDTE.Constants]::vsProjectItemKindPhysicalFolder}
}
Check found files for being in version control
function GetUnversionedFiles(){
param($items = $(throw "Please specify items"))
write-host "checking for unversioned files"
$SourceControl = get-interface $dte.SourceControl ([EnvDTE.SourceControl])
return $items | Where-Object {$SourceControl.IsItemUnderSCC($_.FileNames(0)) -eq $FALSE }
}
walk project for items within
function GetProjectItems(){
param($project = $(throw "Please specify a project"))
if($project.ProjectItems.count -gt 0){
write-debug "getting project items for '$project.Name' '$project.ProjectName'"
}
#example: GetProjectItems((GetSolutionProjects).get_Item(1))
$result =RecurseDescendants($project.ProjectItems)
return $result
}
the most current version is at https://github.com/ImaginaryDevelopment/config/blob/master/My%20Documents/WindowsPowerShell/NuGet_profile.ps1