【问题标题】:How do I find files that are missing from visual studio projects?如何查找 Visual Studio 项目中缺少的文件?
【发布时间】:2011-11-08 10:41:50
【问题描述】:

由于合并等问题,我们有很多项目文件不包含其文件夹中的所有源代码文件。

在我编写一个小工具之前,它会检查每个 *.cs 文件是否包含在项目文件中,我希望确保之前没有其他人已经这样做过。

(我们有近 100 个项目文件和 1000 个 C# 文件)

-------

很明显,Visual Studio 现在支持使用通配符来包含项目中给定目录中的所有“*.cs”文件,这是解决此问题的最佳方法。因为在添加“.cs”文件时不需要更新项目文件,重命名为 ete。然而,只有在 VS2017 中才能从 UI 中使用它。

【问题讨论】:

    标签: visual-studio visual-studio-2010 visual-studio-2019 projects-and-solutions


    【解决方案1】:

    有了这么多文件和项目,听起来您可能想要更自动化的东西。但是,有一种手动方法(不确定您是否已经知道):

    1. 在解决方案资源管理器窗格中选择项目
    2. 项目菜单 -> 显示所有文件
    3. 在项目下,不属于项目的文件将显示为“幽灵”图标
    4. 选择您想要的文件并从上下文菜单中选择“包含在项目中”

    【讨论】:

    • 这个选项的外观似乎取决于个别项目。这适用于我拥有的一个解决方案,但“显示所有文件”选项不会出现在另一个解决方案中。仍在努力确定差异。 (与 2013 年相比)。
    • 啊,无需编写任何内容即可添加到 VS 2015 的解决方案。像我这样的人无法弄清楚为什么我无法将此文件添加到 VS 2015 项目中。它在 Windows 资源管理器中。项目工作,但你只是无法在 VS 2015 中看到或访问文件。现在一切都很好。谢谢!
    • 小提示:如果您发现上下文菜单中的“包含在项目中”选项是灰色的,那么您可能正在运行/调试它 - 所以按“停止”按钮,然后选项将变为可用。
    • 如果只有几个子文件夹可以查看并看到“幻影”文件,这很好,但在我的情况下,有数百个子文件夹,似乎没有任何实用的方法来找到所有丢失的文件。通过 Nuget 升级 3rd 方 JS 和 CSS 库后,这是一个巨大的问题。如果这些新版本带有新文件,您必须手动找到它们并将它们“包含”到您的项目中。这是一个巨大的痛苦。 Visual Studio 需要更好的解决方案。
    【解决方案2】:

    我找到了“Show missing files for VS 2019”Visual Studio 扩展。它将在构建后的“错误列表”窗口中显示项目文件中的 missingnot referenced 列表。

    对于较旧的 Visual Studio,请使用“Show missing files for VS 2013-2017”扩展名。

    【讨论】:

    • 这解决了从文件系统中不存在的项目文件引用文件的相反问题。我们在文件系统中有很多没有从项目文件中引用的源文件(测试)。 ——
    • 也解决了直接问题。此扩展在“错误列表”中添加了两种类型的“错误”。第一个显示未添加到项目中的现有文件。第二个显示添加到项目中的文件(存在于项目树中),但在磁盘上找不到。
    • 这是一个很好的解决方案。 JohnD 目前最受欢迎的解决方案确实有效——但这消除了对每个文件夹进行目视检查的需要。
    【解决方案3】:

    在阅读 Stack Overflow 上没有通用解决方案后,我在这个周末创建了一个 NodeJS 模块来解决这个问题:

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

    这是非常通用的,所以我希望这对其他人也有帮助。它使我在每次部署时都无需手动检查 70 多个文件夹(500 多个文件)。如果我有时间,我希望改进一些东西,比如文档……但现在让我举一个简单的例子。

    简单示例

    1. 安装 nodeJS(在 Windows 上也很好用)
    2. npm install check-vs-includes

    3. 为其添加任务并指定要检查的文件。

    例如,将gulpfile.js 添加到您的项目中:

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

    此示例检查指定文件夹中的所有.js.less 文件是否包含在您的项目文件中。请注意,您可以使用glob's。

    1. 运行检查;对于 GULP 示例:

      gulp checkVSIncludes

    查看源代码以获取更多选项,都在GitHub 上(欢迎贡献;))。

    【讨论】:

    • 有趣的是,包括将检查作为构建的一部分,对我来说是行不通的,因为它需要 20 多人在他们的机器上安装软件。我在大合并等之后使用了我的“hack”,检查项目文件是否正常,它最终没有进入自动构建脚本。
    • 我还担心添加检查的项目文件更改会因合并而丢失。项目文件只是不能很好地合并。
    • @IanRingrose 您确实可以将此检查添加到您的构建过程中。即使在“监视”中,也可以在目标文件的每次更改后进行检查。有时间我可能会为此添加一个 GULP 插件,以进一步简化它。但是该模块可以正常工作。我目前在部署期间手动运行它。所以我会注意到它是否从 package.json 中消失了。该任务取代了我之前必须做的打开 77 个文件夹(和 500 多个文件)的手动检查:) 存在节点依赖性,但在我当前的项目中,所有开发人员已经安装了节点。不应该每个人都有Node吗?已经是 2015 年了:P
    【解决方案4】:

    在为此寻找解决方案时,我遇到了this VS Extension,但它仅适用于 VS 2012。它也在Github

    对于 VS 2013+,我使用在 this 博客文章中找到的 Powershell 脚本。请注意,它仅适用于 C# 项目,但您可以针对 VB 项目进行修改。

    #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 ##############'
    

    使用示例(应从 NuGet 控制台运行):

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

    【讨论】:

    • PowerShell 脚本(包括该 repo 中的插件)在 VS2015 之前运行良好,即使扩展程序没有。
    • 值得一提的是,ps1 应该在 sln 打开的情况下从 powerhell 控制台(工具 > 包管理器 > nuget 控制台)中运行。我从一个普通的控制台运行它并从不同的 sln 得到结果,这很奇怪。
    【解决方案5】:

    一个小的 C# 控制台应用程序,它查找某个根文件夹下的项目文件引用的所有 cs 文件(递归),并与同一根文件夹下的文件系统中的文件进行比较。可以适用于不同的文件扩展名,不同的项目文件结构(我已经针对VS2008进行了测试)。它可能需要一些修改以适应其他需求,但应该提供一个有用的基础。

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

    【讨论】:

    • 感谢稍作改动,我能够将其用于数据库项目。
    【解决方案6】:

    以前的解决方案都不适合我,因为我尝试向其中添加文件的项目是“网站项目”(WSP)。在解决方案资源管理器中选择项目时,“项目”菜单项转换为“网站”,并且没有“显示所有文件”选项。

    这是因为对于 WSP(link):

    “所有文件都已显示在解决方案资源管理器中。”

    除了在我的情况下,它们不是...我通过简单地关闭并重新打开 Visual Studio 2015(VS) 并重新加载项目来解决问题。我认为 VS 仅在重新加载网站时检测到新文件的添加,而不是在将这些文件添加到 VS 之外时检测到。

    【讨论】:

      【解决方案7】:

      我们遇到过类似的情况,由于缺少文件而导致编译失败。我偶然发现了下面链接的这篇文章,这对我有帮助。它描述了编写一个在构建开始时运行的 Visual Studio 宏。

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

      【讨论】:

      • 这解决了从文件系统中不存在的项目文件引用文件的相反问题。我们在文件系统中有很多没有从项目文件中引用的源文件(测试)。
      【解决方案8】:

      (假设 Team Foundation Server 是您的源代码管理):如果文件已添加到项目并显示在源代码管理资源管理器中,但未显示在解决方案资源管理器中,您必须手动将其添加到源代码管理资源管理器通过选择“添加”、“现有项目”。这是一个烦人的 Visual Studio/TFS 错误,我只花了 2 个小时试图弄清楚。

      【讨论】:

      • 似乎与 Q 无关,而且如果它被添加到项目中,它怎么会不在解决方案中?
      【解决方案9】:

      我前段时间为此编写了一个工具。可用here

      【讨论】:

      • 仅链接的答案最好是评论。否则,请随时将该链接中的相关信息添加到此处的答案中,因为链接可能会更改或损坏。谢谢。
      【解决方案10】:

      另一种可能性:有时文件被选择性地不添加到源代码管理中。要解决此问题,请右键单击项目并选择“将项目添加到文件夹”。

      您在其源文件夹中看到的任何未显示在源代码管理资源管理器中的文件都应该在此处,并且可以有选择地添加。

      【讨论】:

        【解决方案11】:

        我知道这已经得到了回答,但这是我使用的。

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

        从命令行调用它(windows):

        1. 发布控制台应用
        2. 将该文件夹移至 C:\Program Files\[Your App Name]
        3. 打开开始菜单并查找“编辑系统环境变量”
        4. 在“高级”选项卡底部单击“环境变量”
        5. 在仅用于变量的顶部框中或在系统范围变量的底部框中找到“路径”变量。双击打开编辑窗口。
        6. 单击“新建”,然后输入“C:\Program Files\[Your App Name]”。按确定并完全退出。关闭您打开的所有 CMD 或 powershell 会话。
        7. 重新打开一个新的 cmd/ps,您应该可以在任何地方执行以下操作:
          [Your App Name].exe "C:\path\to\project.csproj"

        【讨论】:

          【解决方案12】:

          如果有人遇到错误文件未包含,则日期为 2011 年的第一个响应仍然适用于 .NET Framework 版本 4.7.03056 Windows 10 上的 VS 2017 版本 15.8.5,并具有最新更新。关闭并重新打开 VS 会显示所有文件。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-11-25
            • 1970-01-01
            • 1970-01-01
            • 2011-05-04
            • 2017-10-25
            • 1970-01-01
            • 2011-04-30
            相关资源
            最近更新 更多