How do I find files that are missing from visual studio projects?

Solution 1:

With that number of files and projects, it sounds like you might want something more automated. However, there is a manual approach (not sure if you are already aware of it):

  1. Select the project in Solution Explorer pane
  2. Project menu -> Show all Files
  3. Under the project, files which are not part of the project will show up as "ghost" icons
  4. Select the file(s) you want and pick "Include In Project" from the context menu

Solution 2:

I've found the "Show missing files for VS 2019" Visual Studio extension. It will show the list both missing and not referenced from project files in the "Error list" window after the build.

For the older Visual Studio use "Show missing files for VS 2013-2017" extension.

Solution 3:

After reading there is no generic solution for this here on Stack Overflow, I created a NodeJS module this weekend to solve this problem:

https://www.npmjs.com/package/check-vs-includes

This is pretty generic, so I hope this helps others as well. It saves me a manual check of over 70 folders (500+ files) on every deploy. If I have some time I hope to improve some things, like documentation... But let me give a simple example right now.

Simple example

  1. Install nodeJS (Works great on Windows too)
  2. npm install check-vs-includes

  3. Add a task for it and specify the files to check for.

For instance add a gulpfile.js to your project:

gulp.task('checkVSIncludes', function(cb) {
    checkVSIncludes(['/Content/**/*.less', '/app/**/*.js']);
});

This example checks that all .js and .less files in the specified folders are included in your project file. Notice that you can use glob's.

  1. Run the check; for the GULP example:

    gulp checkVSIncludes

Check the source code for more options, it's all on GitHub (contributions are welcome ;)).

Solution 4:

In my search for a solution for this, I ran into this VS Extension, but it only works with VS 2012. It's also on Github.

For VS 2013+ I use a Powershell script found on this blog post. Note that it only works for C# projects, but you can modify it for VB projects.

#Author: Tomasz Subik http://tsubik.com
#Date: 8/04/2012 7:35:55 PM
#Script: FindProjectMissingFiles
#Description: Looking for missing references to files in project config file
Param(
    [parameter(Mandatory=$false)]
    [alias("d")]
    $Directory,
    [parameter(Mandatory=$false)]
    [alias("s")]
    $SolutionFile
)


Function LookForProjectFile([System.IO.DirectoryInfo] $dir){
    [System.IO.FileInfo] $projectFile = $dir.GetFiles() | Where { $_.FullName.EndsWith(".csproj") } | Select -First 1

    if ($projectFile){
        $projectXmlDoc = [xml][system.io.file]::ReadAllText($projectFile.FullName)
        #[xml]$projectXmlDoc = Get-Content $projectFile.FullName
        $currentProjectPath = $projectFile.DirectoryName+"\"
        Write-Host "----Project found: "  $projectFile.Name

        $nm = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $projectXmlDoc.NameTable
        $nm.AddNamespace('x', 'http://schemas.microsoft.com/developer/msbuild/2003')
        [System.Collections.ArrayList]$filesListedInProjectFile = $projectXmlDoc.SelectNodes('/x:Project/x:ItemGroup/*[self::x:Compile or self::x:Content or self::x:None]/@Include', $nm) | Select-Object Value

        CheckProjectIntegrity $dir $currentProjectPath $filesListedInProjectFile;
    }
    else { $dir.GetDirectories() | ForEach-Object { LookForProjectFile($_); } }
}

Function CheckProjectIntegrity([System.IO.DirectoryInfo] $dir,[string] $currentProjectPath,  [System.Collections.ArrayList] $filesListedInProjectFile ){
    $relativeDir = $dir.FullName -replace [regex]::Escape($currentProjectPath)
    $relativeDir = $relativeDir +"\"
    #check if folder is bin obj or something
    if ($relativeDir -match '(bin\\|obj\\).*') { return }

    $dir.GetFiles()  | ForEach-Object {
        $relativeProjectFile = $_.FullName -replace [regex]::Escape($currentProjectPath)
        $match = $false
        if(DoWeHaveToLookUpForThisFile($relativeProjectFile))
        {
            $idx = 0
            foreach($file in $filesListedInProjectFile)
            {
                if($relativeProjectFile.ToLower().Trim() -eq $file.Value.ToLower().Trim()){
                    $match = $true
                    break
                }
                $idx++
            }
            if (-not($match))
            {
                Write-Host "Missing file reference: " $relativeProjectFile -ForegroundColor Red
            }
            else
            {
                $filesListedInProjectFile.RemoveAt($idx)
            }
        }
    }
    #lookup in sub directories
    $dir.GetDirectories() | ForEach-Object { CheckProjectIntegrity $_ $currentProjectPath $filesListedInProjectFile }
}

Function DoWeHaveToLookUpForThisFile($filename)
{
    #check file extensions
    if ($filename -match '^.*\.(user|csproj|aps|pch|vspscc|vssscc|ncb|suo|tlb|tlh|bak|log|lib|sdf)$') { return $false }
    return $true    
}

Write-Host '######## Checking for missing references to files started ##############'
if($SolutionFile){
    [System.IO.FileInfo] $file = [System.IO.FileInfo] $SolutionFile
    $Directory = $file.Directory
}
LookForProjectFile($Directory)
Write-Host '######## Checking for missing references to files ends ##############'

Example usage (should be run from the NuGet console):

./FindProjectMissingFiles.ps1 -s $dte.Solution.FileName

Solution 5:

A small C# console application that finds all cs files referred from project files under a certain root folder (recursively), and compares with files in the file system under the same root folder. Can be applied to different file extensions, and different project file structures (I have tested it for VS2008). It may need some modifications to suit other needs, but should provide a useful base.

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

namespace CompareProjectFilesWithFileSystem
{
    class Program
    {
        static void Main(string[] args)
        {
            string ext = "cs";
            string rootProjectFolder = @"C:\MySolutionRootFolder";
            Regex projectFileReferenceRegEx = new Regex(@"<(Compile|Content|None) Include=\""([^\""]+." + ext + @")\""( /)?>");

            // Files in file system:
            List<string> filesInFileSystem = new List<string>();
            filesInFileSystem.AddRange(Directory.GetFiles(rootProjectFolder, "*." + ext, SearchOption.AllDirectories));

            // Files referred from project files:
            string[] projectFilePaths = Directory.GetFiles(rootProjectFolder, "*.csproj", SearchOption.AllDirectories);
            List<string> filesReferredInProjectFiles = new List<string>();
            foreach (string projectFilePath in projectFilePaths)
            {
                string[] lines = File.ReadAllLines(projectFilePath);
                foreach (string line in lines)
                {
                    Match match = projectFileReferenceRegEx.Match(line);
                    if (match.Success)
                    {
                        filesReferredInProjectFiles.Add(Path.Combine(Path.GetDirectoryName(projectFilePath), match.Result("$2")));
                    }
                }
            }

            // Finding files referred from project files that are not contained in file system. And reversely.
            var list1 = filesReferredInProjectFiles.Except(filesInFileSystem).ToList();
            var list2 = filesInFileSystem.Except(filesReferredInProjectFiles).ToList();
        }
    }
}