[.NET]要如何由程式設定DLL參考目錄及Config File的位置?

要如何由程式設定DLL參考目錄及Config File的位置?
讓執行目錄只有一個執行檔呢?

朋友梅梅子問「如何改變執行時參考目錄?」,直覺想到可以設定在config中設定,可以參考「將共用的DLL放在同一個目錄之中」。

但這位朋友想要連config檔也移走,這樣程式執行起來就找不到設定檔了!

所以建立一個簡單的測試程式(Windows Form程式呼叫一個DLL的Class(ClassLibrary2.Class1),而該Class取得Config檔appSettings中某個項目值),來試看看!

ClassLibrary2.Class1的內容


namespace ClassLibrary2
{
    public class Class1
    {
        public string ConfigAppsettingValue { get; set; }

        public Class1()
        {
            string configValue = System.Configuration.ConfigurationManager.AppSettings["Test"];
            ConfigAppsettingValue = configValue;
        }
    }
}

Windows Form程式(app.config)


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <appSettings>
    <add key="Test" value="Class Test"/>
  </appSettings>
</configuration>

Windows Form程式(button的Click)


private void button1_Click(object sender, EventArgs e)
{
	string configValue = System.Configuration.ConfigurationManager.AppSettings["Test"];
	MessageBox.Show("ConfigValue:" + configValue);
	ClassLibrary2.Class1 c1 = new ClassLibrary2.Class1();
	MessageBox.Show("c1 ConfigValue:" + c1.ConfigAppsettingValue);
}

當exe, exe.config, dll都在同一個目錄下,運作都正常。如下,

image

 

可是如果將除了exe之外的檔案都搬到files的子目錄之中,程式就會發生錯誤!

image

 

想說可以透過AppDomain.CurrentDomain.SetupInformation.ConfigurationFile來指定config檔,如下,


AppDomain.CurrentDomain.SetupInformation.ConfigurationFile="myCustConfigFile";

但卻沒有效果!

後來有找到使用 AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "myCustConfigFile") 可以改變Config檔的位置,而在config檔中加入 probing 的設定。

執行程式,還是會出現DLL找不到的錯誤!

看來還是要在程式中指定才PrivatePath才行!

所以就在 Main() Method中多設定 PrivatePath ,如下,


static void Main()
{
	string custFolderName = @"files";
	string configFile = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), custFolderName, Path.GetFileName(Application.ExecutablePath) + ".config");
	if (File.Exists(configFile) == true)
	{
		//檔案存在才執行
		AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configFile);
		AppDomain.CurrentDomain.AppendPrivatePath(custFolderName);
	}
	Application.EnableVisualStyles();
	Application.SetCompatibleTextRenderingDefault(false);
	Application.Run(new Form1());
}

image

 

那如果您使用的是VB.NET那段程式碼要加在那裡呢?

您可以新增一個Module如下,


Module App

    <STAThread()> _
    Public Sub Main()
        Dim custFolderName As String = "files"
        Dim configFile As String = Path.Combine(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), custFolderName), Path.GetFileName(Application.ExecutablePath) & ".config")
        If File.Exists(configFile) Then
            '檔案存在才執行
            AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", configFile)
            AppDomain.CurrentDomain.AppendPrivatePath(custFolderName)
        End If
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        Application.Run(New Form1())
 
    End Sub

End Module

然後在專案屬性中設定啟動的物件為Sub Main,如下,

appProp

設定完成後,重新建罝專案後就可以了哦!

image

 

 

註:朋友梅梅子有說可以在Form的New 建構子中去設定,但筆者測試起來雖然沒有問題,但是卻會有取不到config檔appSettings中的值,而在Sub Main()中測試則是沒問題的!

另外,「代码控制PrivateBinPath和ConfigurationFile的位置」這篇所使用的方式也是可以的! 只是Code比較長一點!

以上方式,希望對大家有所幫助,有更好的方式,也請讓我知道哦!

 

參考資料

代码控制PrivateBinPath和ConfigurationFile的位置

指定組件的位置

將共用的DLL放在同一個目錄之中

Relocating app.config file to a custom path

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^