2012-06-18 3 views
2

У меня есть общий DLL-файл служебной программы, используемый в моей программе WPF. Первое, что делает моя программа, - проверить обновленный файл dll и скопировать его в исполняемый каталог - все без ссылки на какие-либо методы или свойства из dll.Время загрузки DLL в Visual Studio vs EXE-файл

Когда я компилирую и запускаю программу изнутри Visual Studio (v10), все работает так, как ожидалось. Программа запускается, проверяет файл dll, копирует, если необходимо, а затем переходит к использованию сборки.

Если я запустил скомпилированный файл .exe из Проводника Windows, кажется, первое, что он делает, это загрузить сборку Util.dll. Это заблокирует файл и не позволит мне его обновить.

У кого-нибудь есть представление о том, почему программа будет работать по-разному в Visual Studio по сравнению с .exe-файлом? Любые мысли о отслеживании того, что вызывает сборку при загрузке .exe-файла?

Вот фрагмент кода запуска программы:

void AppLoad(object sender, StartupEventArgs e) 
{ 

    //Used to see what assemblies are loaded. 
    System.Text.StringBuilder sb = new System.Text.StringBuilder(); 
    foreach (var item in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
    sb.AppendLine(item.FullName.ToString()); 
    } 
    System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "test.txt", sb.ToString()); 


    //Check for the latest Util dll. 
    if (!UpdateUtil()) 
    { 
    //Shutdown. 
    Application.Current.Shutdown(); 
    return; 
    } 

    //Start the main window. 
    MainWindow m = new MainWindow(); 
    m.Show(); 
} 

bool UpdateUtil() 
{ 
    //Verify network path. 
    if (!Directory.Exists(_componentPath)) 
    { 
    MessageBox.Show("The program encountered an error.\r\rPlease contact your Program Administrator with the following information:\r\r" + 
     "Program Name - Genesis Admin\r\r" + 
     "Error Message - Network Component path not found.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); 
    return false; 
    } 
    //Verify file existance. 
    string sourceFileName = _componentPath + "Util.dll"; 
    if (!File.Exists(sourceFileName)) 
    { 
    MessageBox.Show("The program encountered an error.\r\rPlease contact your Program Administrator with the following information:\r\r" + 
     "Program Name - Genesis Admin\r\r" + 
     "Error Message - Network Util file not found.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); 
    return false; 
    } 

    string destFileName = AppDomain.CurrentDomain.BaseDirectory + "Util.dll"; 
    if (!File.Exists(destFileName) || File.GetLastWriteTime(sourceFileName) > File.GetLastWriteTime(destFileName)) 
    File.Copy(sourceFileName, destFileName, true); 

    return true; 
} 
+1

FYI это никогда не будет работать в производственной среде, так как большинство ИТ-администраторов могут отказаться от этой практики (очень небезопасно). – tsells

ответ

6

Это, как правило, очень рискованно, сборка загружается компилятором «точно вовремя», когда ему нужно сгенерировать машинный код для метода. Вероятно, вы не рассчитываете на код, который получает inlined - важную оптимизацию, включенную в сборку выпуска. Эта оптимизация выключена при запуске с отладчиком.

Это не очевидно в вашем фрагменте, который может быть загружен из «util.dll». Но не забудьте перестроить свой код, чтобы все типы, принадлежащие util.dll, находятся в разных методах, удаленных от вызова UpdateUtil(). Подавить вложение с атрибутом [MethodImpl (MethodImplOptions.NoInlining)] в методе.

На самом деле лучший способ сделать это с помощью небольшого загрузочного файла .exe, который выполняет тест, а затем запускает основной файл .exe. Но имейте в виду, что вы, несомненно, снова столкнетесь с стеной, когда вы запустите этот код на машине пользователя, вы не сможете скопировать DLL в файлы c: \ program без выравнивания UAC. Это действительно задача установщика, она не должна быть в вашем коде.

+0

Util.dll используется в классе MainWindow, поэтому я проверял/обновлял приложение. Проблема, которую я вижу, - это когда компиляция настроена на сборку Release. Я понимаю, что этот процесс не идеален, но мне не хватает опыта, чтобы сделать это лучше. Это для небольшой компании, в которой я работаю, и будет иметь ограниченную базу пользователей. –

+0

Ну, переместите последние две строки, которые используют MainWindow в отдельном методе и придают ему атрибут [MethodImpl]. –

+0

Проблема была в развернутой оптимизации. Спасибо вам за помощь. –

1

Проверьте, где файл копируется. Возможно, я ошибаюсь, но Visual Studio может использовать папку проекта в качестве текущей папки, а при запуске из проводника местоположение вашего исполняемого файла используется как рабочий каталог.

Не могли бы вы попытаться вывести значение destFileName (например, с помощью окна сообщения). Я не эксперт в сети точек, но обычно используется отложенная загрузка для обычных DLL. Может быть что-то полезное на this page. Но еще раз я не знаю точки сети.

+0

Я использую базовый каталог приложения, поэтому я знаю, что он всегда копирует в нужное место. Благодарю вас за предложение. –

0

Если вам нужно найти обновленные файлы, вы можете использовать плагин в базовой структуре. Концепция заключается в том, что вы ищете все файлы по определенному имени в каталоге, а затем загружаете их в программу. Используйте интерфейсы для предотвращения их компиляции сразу после запуска программы.

Смежные вопросы