2

We work here in a csproj, commiting, updating and deleting files. Sometimes csproj is commited in subversion repository, but its content references to files that don't exist in disk anymore.

I was thinking about creating a unit test to check if content files referenced really exist in disk, for example:

\Styles\main.css - PASSED
\Styles\main.ie7.css - FAILED -> it does not exist in disk
\Styles\main.ie8.css - PASSED

is there a C# sample, any free tool or batch file that does this job?

Cameron S
  • 2,251
  • 16
  • 18
Junior Mayhé
  • 16,144
  • 26
  • 115
  • 161

3 Answers3

3

I created a unit testing to check the files. This can be put in a continuous integration server to check if files do exist in hard drive. Hopefully this can help somebody facing the same issue when working in a development team:

this sample runs a test in a file located at D:\YourProject\Solution\My.Website

a helper to deal with file IO in your test project (suppose it is on D:\YourProject\Solution\My.Website.Tests)

internal sealed class IOHelper
{
    /// <summary>
    /// get list of files described in csproj
    /// </summary>
    /// <param name="filename"></param>
    /// <returns></returns>
    public static List<string> GetFilesInCSPROJ(string filename)
    {
        var list = new List<string>();
        var lines = File.ReadLines(filename);
        foreach (string line in lines)
        {
            if (line.Contains("<Content Include="))
                list.Add(Regex.Matches(line, "(?:[^\"]+|\\.)*")[2].Value);

        }
        return list;

    }
}

in your test project (suppose it is on D:\YourProject\Solution\My.Website.Tests)

/// <summary>
/// Tests for CSPROJ
/// </summary>
[TestClass]
public class TestCSPROJ
{

    /// <summary>
    /// check if CSPROJ content files exist in disk
    /// </summary>
    [TestMethod]
    public void CsProj_Files_Exist_In_Disk()
    {
        string root = Environment.CurrentDirectory.Substring(0, Environment.CurrentDirectory.IndexOf("\\Solution\\TestResults"))
            + "\\Website\\My.Website\\";
        string websiteProj = root + "My.Website.csproj";
        var list = IOHelper.GetFilesInCSPROJ(websiteProj);
        Assert.IsTrue(list != null, "there are no content files added in Portal6.Website.csproj");
        foreach (var item in list)
        {
            Assert.IsTrue(System.IO.File.Exists(root + item), "FAILED - file not found in disk: " + root + item);
        }

    }
}
Junior Mayhé
  • 16,144
  • 26
  • 115
  • 161
3

Here is an MsBuild solution: http://www.neovolve.com/2013/01/11/causing-a-vs-web-project-to-fail-compilation-when-content-is-missing/

I improved this solution to add checks for files with Build Action set to Embedded Resource in addition to those with Content:

<Target Name="BeforeBuild">
  <ItemGroup>
    <MissingContentFiles Include="@(Content)" Condition="!Exists(%(Content.FullPath))" />
    <MissingResourceFiles Include="@(EmbeddedResource)" Condition="!Exists(%(EmbeddedResource.FullPath))" />
  </ItemGroup>

  <Message Text="Content file: %(Content.FullPath)" />
  <Message Text="Missing content file: %(MissingContentFiles.FullPath)" Condition="'@(MissingContentFiles)' != ''" />
  <Error Text="Content file '%(MissingContentFiles.FullPath)' was not found." Condition="'@(MissingContentFiles)' != ''" ContinueOnError="true" />
  <Error Text="One or more content files are missing." Condition="'@(MissingContentFiles)' != ''" />

  <Message Text="Embedded resource: %(EmbeddedResource.FullPath)" />
  <Message Text="Missing embedded resource: %(MissingResourceFiles.FullPath)" Condition="'@(MissingResourceFiles)' != ''" />
  <Error Text="Embedded resource file '%(MissingResourceFiles.FullPath)' was not found." Condition="'@(MissingResourceFiles)' != ''" ContinueOnError="true" />
  <Error Text="One or more embedded resource files are missing." Condition="'@(MissingResourceFiles)' != ''" />
</Target>
Fabrice
  • 3,094
  • 3
  • 28
  • 31
  • Is there a way to show the line number of each file? It keeps showing the line of the log command only. Otherwise works like a charm. – Eugene Aug 17 '16 at 17:34
1

Your project is unlikely to build if a source file is missing.

If you wanted to prevent check-ins of *.csproj file unless the related source file already exists in source control, you'd probably want to write a trigger in your source control system that would examine the *.csproj file and verify that all its related source files exist in source control, rejecting the check-in if the constraint isn't met.

Of course, then you'll have the edge case where the user has added a new source file and is checking in both the new source file and the updated *.csproj file in the same atomic check-in.

Doing any of this sort of thing is highly dependent upon the source control system in use.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135