Directory.EnumerateFiles и File.Exists игнорируют собственные файлы DLL - PullRequest
4 голосов
/ 09 февраля 2012

Среда: C #, .NET 4.0 и смешанный режим.

У меня сложное приложение с несколькими сторонними зависимостями. Когда мы получили некоторые сообщения о сбое приложения, мы добавили некоторые проверки работоспособности, чтобы убедиться, что все зависимости существуют, путем обхода зависимостей сборки. К сожалению, это не проверяет наличие собственных файлов DLL, используемых нашим приложением. Наше предполагаемое решение состоит в том, чтобы перебрать все имена DLL и убедиться, что есть хотя бы файл с этим именем в качестве проверки работоспособности.

Проблема

Оба Directory.EnumerateFiles () и File.Exists () также не могут видеть эти собственные библиотеки DLL. Код для воспроизведения этой проблемы так же прост, как и учебник «Как составить список файлов»:

foreach(string file in
        Directory.EnumerateFiles(Environment.CurrentDirectory, "*.dll"))
{
    string entry = Path.GetFileName(file);
    if (! RequiredFiles.Contains(entry))
    {
        /* Do error handling */
    }
}

Находясь в каталоге, в котором я перечислял файлы, я мог видеть файлы, которые хотел обнаружить. Они никак не помечаются как системные файлы. Тем не менее, независимо от того, был ли у меня текст фильтра или нет, были перечислены только файлы .NET DLL. Я подумал переписать часть кода более напрямую и разочарованно получил те же результаты:

foreach(string dependency in RequiredFiles)
{
    string fileName = Environment.CurrentDirectory + '\\' + dependency;
    if(! File.Exists(fileName))
    { /* do error handling */ }
}

Я получил точно такие же результаты. Все нативные файлы DLL казались невидимыми для .NET.

Вопрос

Что вызывает это? И что еще более важно, как я могу определить, существуют ли собственные файлы DLL, если я даже не вижу их в файловой системе?

Ответы [ 3 ]

2 голосов
/ 10 февраля 2012

Вы уверены, что ваш рабочий каталог правильный? В противном случае Environment.CurrentDirectory не будет указывать на то, что вы ожидаете. Если файлы DLL находятся в той же директории, что и исполняемый код, вы можете вместо этого сделать:

Assembly.GetExecutingAssembly().Location
2 голосов
/ 10 февраля 2012
  • Создайте имя для своей собственной DLL, например, MySuperNiftyLibrary.dll. Это может быть просто переименованный текстовый файл. Положите его в папку, которую вы смотрите. Запустите код еще раз. Посмотрите, есть ли это имя в списке. Если это вас не убеждает, создайте небольшой проект библиотеки классов .NET с отличительным именем и поместите его в каталог.

    Нет никаких причин, по которым Directory.EnumerateFiles будет фильтровать библиотеки DLL .NET, в отличие от других типов библиотек DLL, поэтому вы не можете искать правильный каталог.

  • Но если да, то подумайте, находятся ли искомые библиотеки DLL в каталоге верхнего уровня или в подкаталоге. По умолчанию EnumerateFiles отображает только файлы в каталоге верхнего уровня . Чтобы вывести список всех файлов во всех подкаталогах, вам нужно использовать эту перегрузку EnumerateFiles:

Directory.EnumerateFiles(directory, "*.dll", SearchOption.AllDirectories)

0 голосов
/ 09 февраля 2012

Затем используйте оболочку, что-то вроде этого должно работать:

            Shell32.Shell shl = null;
            Shell32.Folder folder = null;
            try
            {
                shl = new Shell32.Shell();
                folder = shl.NameSpace(Environment.CurrentDirectory);
                foreach (Shell32.FolderItem file in folder.Items())
                {
                    if (!RequiredFiles.Contains(file.path))
                    {/* do error handling */}
                }
            }
            catch
            { }
            finally
            {
                if (folder != null)
                {
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(folder);
                    folder = null;
                }
                if (shl != null)
                {
                    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shl);
                    shl = null;
                }
            }

ОБНОВЛЕНИЕ: если вы собираетесь использовать это как на XP, так и на более новых ОС, вам нужно сослаться на Shell32.dll (элементы управления и автоматизация Microsoft Shell) на XP и скомпилируйте там один раз, чтобы такая dll была скопирована в ваш проект.Потому что DLL из Vista или 7 не будет работать на XP, и наоборот.Это более простой подход, основанный на сценариях Shell.В противном случае вы можете напрямую взаимодействовать с Shell API, но это сложнее ...

...