• Jobs
  • Bootcamp
  • About Us
  • For professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
    • Bootcamp
  • For business
    • Home
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

270
Views
System.IO.Directory.Exists fails inside LINQ statement, but not in a foreach loop

.Net Framework 4.7.2

That was a very surprisingly issue...

I have this routine to get all available Inventor templates from local disk, no matter which version it is:

private static IEnumerable<string> GetInventorTemplates_FAILS()
{
    var publicPath = Environment.GetEnvironmentVariable("PUBLIC");
    var autodeskPath = Path.Combine(publicPath, "Documents", "Autodesk");
    var inventorPaths = Directory.GetDirectories(autodeskPath, "*Inventor*");
    var templatePaths = inventorPaths.Select(path => Path.Combine(path, "Templates"));
    var templates = templatePaths.Where(Directory.Exists).SelectMany(path => Directory.GetFiles(path, "*.*", SearchOption.AllDirectories));
    //                     throws error ^^^^^^^^^^^^^^^^

    return templates;
}

If I run this code, I got this error:

System.Linq.SystemCore_EnumerableDebugView`1[System.String].get_Items() calls into native method Microsoft.Win32.Win32Native.GetFullPathName(char*, int, char*, System.IntPtr). Evaluation of native methods in this context is not supported.  

What makes it more crazy is if I rewrite the code, to manually call Directory.Exists and it works!!!

private static IEnumerable<string> GetInventorTemplates_WORKS()
{
    var publicPath = Environment.GetEnvironmentVariable("PUBLIC");
    var autodeskPath = Path.Combine(publicPath, "Documents", "Autodesk");
    var inventorPaths = Directory.GetDirectories(autodeskPath, "*Inventor*");
    var templatePaths = inventorPaths.Select(path => Path.Combine(path, "Templates"));

    foreach (var path in templatePaths)
        if (Directory.Exists(path)) // <- no exception!!!
            foreach (var template in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories))
                yield return template;
}

You'll get the same result if you just check via QuickWatch:

templatePaths.Where(Directory.Exists) via QuickWatch dialog

Directory.Exists(templatePaths.First()) via QuickWatch dialog

For now I can use the rewrited version, but I was a lot curious if I'm the lucky one... :-)

12 months ago · Santiago Trujillo
1 answers
Answer question

0

That's not a .NET problem. The code will run fine, you don't have to change anything. The debugger says it can't safely execute the query in the watch window so it can't display any results. The error explains that

Evaluation of native methods in this context is not supported.

template isn't a list of documents, it's a query that hasn't been executed yet. The debugger would have to execute that query to retrieve and the results.

This is neither a problem nor uncommon. There are several cases where the debugger can't execute a LINQ query or enumerate an IEnumerable safely and display the results. If you want to inspect the results, execute the query explicitly eg with ToList.

PS

It's probably a good idea to use a globbing library like Glob (3M NuGet downloads) to replace all this code with :

var root = new DirectoryInfo(autodeskPath);
var templates = root.GlobFileSystemInfos("*Inventor*/Templates/**/*.*");

.NET Core itself uses file globbing through the Microsoft.Extensions.FileSystemGlobbing package.

Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*Inventor*/Templates/**/*.*" });

foreach (string file in matcher.GetResultsInFullPath(autodeskPath))
{
    Console.WriteLine(file);
}
12 months ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post job Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2023 PeakU Inc. All Rights Reserved.