开发者

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

开发者 https://www.devze.com 2023-04-01 01:57 出处:网络
Due to issues with merging 开发者_如何学Goetc, we have lots of project files that don’t contain all source code files that are within their folders.

Due to issues with merging 开发者_如何学Goetc, we have lots of project files that don’t contain all source code files that are within their folders.

Before I write a little tool, that checks that every *.cs file is included in a project file, I wish to make sure that no-body else has already done that before.

(We have close to 100 project files, and 1000s of C# files)

-------------------

Clearly the support that visual studio now has for using wildcards to include all “*.cs” files from a given directory in the project is the best solution to this problem. In that there is then no need to update project files when “.cs” files are added, renamed ete. However it is only in VS2017 that this become usable from the UI.


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


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.


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 ;)).


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


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();
        }
    }
}


None of the previous solutions worked for me as the project I was attempting to add files to was a "Web Site Project"(WSP). When selecting the project in the solution explorer the "Project" menu item converted to "Website" and there was no "Show all Files" option.

This is because for WSP(link):

"all files are already shown in the Solution Explorer."

Except in my case they weren't... I resolved the issue by simply closing and reopening Visual Studio 2015(VS) and reloading the project. I think VS only detects the addition of new files when the Web Site is re-loaded, not when those files are added outside of VS.


We had a similar situation which resulted in failed compiles due to missing files. I stumbled upon this post linked below, which helped me. It describes writing a Visual Studio macro that runs when a build is started.

Report error/warning if missing files in project/solution in Visual Studio


(Assuming that Team Foundation Server is your source control): If the file has been added to the project and shows up in Source Control Explorer, but does NOT show up in Solution Explorer, you must manually add it to Source Control Explorer by selecting "Add", "Existing Item". This is an annoying Visual Studio/TFS bug that I just spend 2 hours trying to figure out.


I wrote a tool for this some time ago. Available here.


Another possibility: Sometimes the file is selectively not added to the source control. To resolve this, right-click the project and select "Add Items to Folder".

Any files not shown in the source control explorer that you see in their source folders should be here and can be selectively added.


I know this has already been answered, but here is what I use.

using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;

namespace ProjectReferenceChecker
{
    class Program
    {
        static void Main(string[] args)
        {
            if (string.IsNullOrEmpty(args[0]))
                throw new Exception("Project file must be specified using in argument");

            var projectFile = new FileInfo(args[0]);

            var text = File.ReadAllText(projectFile.FullName);
            var regex = new Regex("<(Compile|Content|None) Include=\"([^\"]*)\".*>");

            foreach (Match match in regex.Matches(text))
            {
                var relativePath = match.Groups[2].ToString();
                relativePath = HttpUtility.HtmlDecode(relativePath);
                relativePath = HttpUtility.UrlDecode(relativePath);
                var targetPath = Path.Combine(projectFile.Directory.FullName, relativePath);
                if (!new FileInfo(targetPath).Exists)
                {
                    Console.WriteLine(relativePath);
                }
            }
        }
    }
}

To call this from a command line (windows):

  1. Publish the console app
  2. Move that folder to C:\Program Files\[Your App Name]
  3. Open start menu and look for "edit the system environment variables"
  4. At the bottom of the "Advanced" tab click "Environment Variables"
  5. Either in the top box for just your variables or bottom box for system wide variables find the "path" variable. Double click it to open the edit window.
  6. Click "New" then enter "C:\Program Files\[Your App Name]". Press okay and back all the way out. Close any CMD or powershell sessions you have open.
  7. Reopen a new cmd/ps and you should be able the following from anywhere:
    [Your App Name].exe "C:\path\to\project.csproj"


If anyone has the error File Not Included the first response dated 2011 still works on VS 2017 Version 15.8.5 on .NET Framework Version 4.7.03056 Windows 10 with latest updates. Closing and reopening VS shows all files.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号