如何查找visual studio项目中缺少的文件?

时间:2011-09-01 14:03:57

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

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

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

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

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

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

12 个答案:

答案 0 :(得分:49)

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

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

答案 1 :(得分:17)

我找到了" Show missing files" Visual Studio扩展。它将在"错误列表"中显示丢失文件的列表。构建后的窗口。

答案 2 :(得分:9)

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

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

这是非常通用的,所以我希望这也有助于其他人。它为我节省了每次部署超过70个文件夹(500多个文件)的手动检查。如果我有一些时间,我希望改进一些事情,比如文档......但是现在让我举一个简单的例子。

简单示例

  1. 安装nodeJS(在Windows上也很棒)
  2.   

    npm install check-vs-includes

  3. 为其添加任务并指定要检查的文件。
  4. 例如,在项目中添加gulpfile.js

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

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

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

      gulp checkVSIncludes

    2. 检查源代码以获取更多选项,它全部在GitHub上(欢迎提供;)。

答案 3 :(得分:7)

在我为此寻找解决方案时,我遇到了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

答案 4 :(得分: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();
        }
    }
}

答案 5 :(得分:2)

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

这是因为对于WSP(link):

  

&#34;所有文件都已显示在解决方案资源管理器中。&#34;

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

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

答案 10 :(得分: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\[您的应用程序名称]
  3. 打开开始菜单并查找“编辑系统环境变量”
  4. 在“高级”选项卡底部,点击“环境变量”
  5. 在顶部框中的变量或系统范围变量的底部框中找到“路径”变量。双击它打开编辑窗口。
  6. 单击“新建”,然后输入“C:\Program Files\[您的应用程序名称]”。按确定并返回。关闭您打开的所有 CMD 或 powershell 会话。
  7. 重新打开一个新的 cmd/ps,您应该可以从任何地方执行以下操作:
    [Your App Name].exe "C:\path\to\project.csproj"

答案 11 :(得分:-1)

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