.NET 將 .config 文件嵌入到程序集
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/Iron_Ye/article/details/83979628
.NET 將 .config 文件嵌入到程序集
最近,團隊中的一位同事實現了一個小程序,供主程序調用。為了小程序分發的方便性,使用了 Costura.Fody
dll
都嵌入到了 exe
中。但是,其中的 log4net.dll
又需要一個 *.config
文件才能正常工作,而 Costura.Fody
又不支持此類文件的嵌入。
我們先來復現一下問題場景,關於 Costura.Fody
和 log4net
的使用可以參考:
- .NET 合並程序集(將 dll 合並到 exe 中)
- log4net 詳解
首先,在一個 C#
控制臺程序中通過 NuGet
引用 log4net
和 Costura.Fody
兩個組件,然後在程序的 App.config
文件中添加如下配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<root>
<level value="WARN" />
<appender-ref ref="LogFileAppender" />
</root>
<logger name="mylogger">
<level value="ALL"/>
</logger>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender" >
<param name="File" value="log-file.txt" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout"/>
</appender>
</log4net>
</configuration>
這些配置用於指定 log4net
如何工作,需要在程序的入口處加載這些配置信息:
static void Main(string[] args)
{
// 從默認的配置文件(App.config)中讀取配置信息
log4net.Config.XmlConfigurator.Configure();
var logger = LogManager.GetLogger("mylogger");
logger.Info("Starting...");
Console.ReadLine();
}
然後,為 Costura.Fody
添加一個 FodyWeavers.xml
文件,文件內容如下:
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<Costura/>
</Weavers>
最後,編譯此項目。你會發現 log4net.dll
並未出現在生成目錄中,而是被合並到了 MyConsoleApp.exe
中。同時,生成目錄中還有一個 MyConsoleApp.exe.config
文件(App.config
)生成的。如果刪除該文件,MyConsoleApp.exe
中的 log4net
不能正常工作。
因此,如果要實現 MyConsoleApp.exe
單文件分發,就要將 App.config
嵌入到該 exe
中,並且 log4net
要能識別嵌入的文件。
Embedded Resource
好在 Visual Studio
支持將項目中的某個文件的 Build Action
設置為 Embedded Resource(嵌入資源)
,這樣一來,文件將作為資源被嵌入到程序集中。
並且,可以在運行時通過 Assembly.GetManifestResourceStream()
方法取文件內容:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "MyCompany.MyProduct.MyFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
這只是其中一種將文件作為資源嵌入到程序集的方法,欲了解更多方法,可參考 Various Build Actions in Visual Studio 。
Configure(Stream configStream)
查資料發現,log4net
支持從 Stream
中加載配置文件:
log4net.Config.XmlConfigurator.Configure(Stream configStream);
那麽,結合 Embedded Resource
,問題就非常簡單了:
static void Main(string[] args)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "MyConsoleApp.App.config";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
// 從 Stream 中讀取 log4net 的配置信息
log4net.Config.XmlConfigurator.Configure(stream);
}
var logger = LogManager.GetLogger("mylogger");
logger.Info("Starting...");
Console.ReadLine();
}
再次編譯項目,MyConsoleApp.exe.config
也從生成目錄中消失了,單獨的一個 MyConsoleApp.exe
也能正常運行了。
總結
本文只是以 *.config
文件為例來說明如何將文件作為資源嵌入到程序集中,其它格式的文件也是支持的,並且還有其它的嵌入方式,感興趣的可以通過 Build Action
去探索更多的方法。
參考資料
- How to read embedded resource text file
- Various Build Actions in Visual Studio
- What are the various
Build Action
settings in Visual Studio …
.NET 將 .config 文件嵌入到程序集