2012-06-18 21 views
2

我在我的WPF程序中使用了一個通用實用dll文件。我的程序做的第一件事是檢查一個更新的dll文件並將其複製到正在執行的目錄 - 所有這些都不需要引用dll中的任何方法或屬性。DLL加載時間在Visual Studio與EXE文件中有所不同

當我從Visual Studio(v10)編譯並運行程序時,所有內容都按預期工作。該程序啓動,檢查dll文件,如果需要複製,然後繼續使用程序集。

如果我從Windows資源管理器運行編譯後的.exe文件,它看起來第一件事就是加載Util.dll程序集。這將鎖定文件,並且不允許我更新它。

有沒有人有一些洞察力,爲什麼程序會在Visual Studio vs .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

僅供參考因爲大多數IT管理員會忽視這種做法(非常不安全),所以這在產品環境中將無法使用。 – tsells

回答

6

這通常是一件有風險的事情,當需要爲方法生成機器代碼時,程序集會被即時編譯器加載。你可能不會指望的是代碼內聯,這是一個重要的優化,在發佈版本中啓用。當您使用調試器運行時,該優化是off

在你的代碼片段中,可能從「util.dll」加載哪種類型並不明顯。但一定要重構代碼,以便來自util.dll的所有類型都在遠離UpdateUtil()調用的單獨方法中。使用方法上的[MethodImpl(MethodImplOptions.NoInlining)]屬性抑制內聯。

到目前爲止,最好的方法是使用一個小引導程序.exe文件進行測試,然後啓動主要的.exe。但請記住,當您在用戶機器上運行此代碼時,您無疑會再次碰壁,無法將DLL複製到沒有UAC提升的c:\ program files中。這實際上是一個安裝程序任務,它不應該在您的代碼中。

+0

Util.dll在MainWindow類中使用,這就是我從應用程序加載中檢查/更新的原因。我看到的問題是編譯設置爲發佈版本。我意識到這個過程並不理想,但我缺乏經驗去做得更好。這是爲我工作的小公司,並且將有一個有限的用戶羣。 –

+0

好吧,在一個單獨的方法中移動使用MainWindow的最後兩行併爲其賦予[MethodImpl]屬性。 –

+0

內聯優化是問題所在。感謝您的幫助。 –

1

檢查其中的文件正在被複制。我可能錯了,但Visual Studio可能會使用項目文件夾作爲當前文件夾,而從Explorer啓動時,可執行文件的位置將用作工作目錄。

您可以嘗試輸出destFileName的值(如帶有消息框)。我不是dot net的專家,但通常使用延遲加載的規則DLL。有可能在this page上有用。但我再一次不知道點網。

+0

我使用應用程序的基本目錄,所以我知道它總是複製到正確的位置。不過謝謝你的建議。 –

0

如果您需要查找更新的文件,那麼您可能需要在基本框架中使用插件。概念是你在一個目錄中尋找某個特定名字的所有文件 - 然後將它們加載到程序中。使用接口防止程序啓動後立即編譯它們。

相關問題