57

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

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

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

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

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

4

12 回答 12

66

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

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

我找到了“显示 VS 2019 的缺失文件”Visual Studio 扩展。它将在构建后的“错误列表”窗口中显示项目文件中缺少未引用的列表。

对于较旧的 Visual Studio,请使用“显示 VS 2013-2017 的缺失文件”扩展名。

于 2016-10-06T04:10:25.523 回答
9

在阅读 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的。

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

    gulp checkVSIncludes

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

于 2015-07-12T20:14:17.480 回答
7

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

对于 VS 2013+,我使用博客文章中的 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
于 2015-09-21T16:18:13.933 回答
4

一个小型的 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();
        }
    }
}
于 2016-01-29T13:26:03.897 回答
2

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

这是因为对于 WSP(链接):

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

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

于 2016-05-26T14:31:09.293 回答
0

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

于 2014-01-23T19:09:23.597 回答
0

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

如果 Visual Studio 中的项目/解决方案中缺少文件,则报告错误/警告

于 2012-10-11T18:28:34.883 回答
0

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

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

于 2017-03-06T19:47:24.853 回答
0

我前段时间为此写了一个工具。在这里可用。

于 2016-12-16T10:07:33.907 回答
0

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

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"
于 2021-02-25T14:45:58.687 回答
-2

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

于 2018-10-13T14:04:36.813 回答