Avalonia 制作 AOT 單文件
本文提供的方法在 11.3.2 的 Avalonia 版本實(shí)驗(yàn)成功,支持 Windows x86 應(yīng)用程序 AOT 發(fā)布為完全單文件。預(yù)期對 windows x64 也能成功 AOT 發(fā)布完全單文件
實(shí)現(xiàn)方式如下
先正常對應(yīng)用項(xiàng)目進(jìn)行 AOT 發(fā)布,發(fā)布之后,預(yù)期會多出以下幾個 DLL 文件:
- av_libglesv2.dll
- libHarfBuzzSharp.dll
- libSkiaSharp.dll
將這幾個 DLL 文件拷貝出來,隨便找個文件夾放。如我這里就放在 C:\lindexi\Library\Avalonia_win-x86\ 文件夾里
回到項(xiàng)目里面,修改 csproj 項(xiàng)目文件,添加對存放的 DLL 文件的引用,設(shè)置為嵌入程序集資源,大概代碼如下
<ItemGroup>
<EmbeddedResource Include="C:\lindexi\Library\Avalonia_win-x86\*.dll" LinkBase="Assets\win-x86" />
</ItemGroup>
如果不知道這部分代碼怎么寫,可以在本文末尾獲取本文所有代碼的下載方法,拉取我的代碼了解具體的代碼
接著修改 Program.cs 的 Main 函數(shù),將原本寫在 Main 函數(shù)里面的 Avalonia 調(diào)用抽一個獨(dú)立的方法。如我這里放在 RunAvalonia 方法里面。獨(dú)立方法的作用是防止在進(jìn)入 Main 時立刻碰到 Avalonia 類型,導(dǎo)致類型快速初始化,類型快速初始化時可能會碰到某些基礎(chǔ)庫引用,此時基礎(chǔ)庫還沒被釋放出來,就可能導(dǎo)致異常
再編寫一個名為 LoadNativeLib 的方法,方法代碼如下
private static void LoadNativeLib()
{
var assembly = typeof(Program).Assembly;
var manifestResourceNames = assembly.GetManifestResourceNames();
var platform = "win_x86";
var platformResource = $"CibairfejeballChecekayral.Desktop.Assets.{platform}.";
var folder = Directory.CreateDirectory(Path.Join(AppContext.BaseDirectory, platform));
foreach (var manifestResourceName in manifestResourceNames)
{
if (manifestResourceName.StartsWith(platformResource))
{
using var manifestResourceStream = assembly.GetManifestResourceStream(manifestResourceName)!;
var fileName = manifestResourceName[platformResource.Length..];
var file = Path.Join(folder.FullName, fileName);
if (!File.Exists(file))
{
using var fileStream = File.OpenWrite(file);
manifestResourceStream.CopyTo(fileStream);
}
NativeLibrary.Load(file);
}
}
}
通過以上代碼可以看到核心實(shí)現(xiàn)就是將嵌入程序集里面的幾個 DLL 釋放出來,我這里只處理了 x86 的情況,其他情況還請大家自行判斷處理。從程序集里面取出 DLL 寫入到文件之后,調(diào)用 NativeLibrary.Load 方法即可執(zhí)行加載
完成之后,再次進(jìn)行 AOT 發(fā)布,此時只取發(fā)布出來的 exe 一個文件放在另一個空白文件夾里面雙擊運(yùn)行,可見此時可以成功正常運(yùn)行
通過如此方式即可實(shí)現(xiàn)在 Avalonia 里面進(jìn)行獨(dú)立 AOT 成單個文件,非常方便小工具的分發(fā)
本文代碼放在 github 和 gitee 上,可以使用如下命令行拉取代碼。我整個代碼倉庫比較龐大,使用以下命令行可以進(jìn)行部分拉取,拉取速度比較快
先創(chuàng)建一個空文件夾,接著使用命令行 cd 命令進(jìn)入此空文件夾,在命令行里面輸入以下代碼,即可獲取到本文的代碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 21d0bbfbb70ff2274d74357b90c80ea32656c727
以上使用的是國內(nèi)的 gitee 的源,如果 gitee 不能訪問,請?zhí)鎿Q為 github 的源。請?jiān)诿钚欣^續(xù)輸入以下代碼,將 gitee 源換成 github 源進(jìn)行拉取代碼。如果依然拉取不到代碼,可以發(fā)郵件向我要代碼
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 21d0bbfbb70ff2274d74357b90c80ea32656c727
獲取代碼之后,進(jìn)入 AvaloniaIDemo/CibairfejeballChecekayral 文件夾,即可獲取到源代碼
更多技術(shù)博客,請參閱 博客導(dǎo)航
博客園博客只做備份,博客發(fā)布就不再更新,如果想看最新博客,請?jiān)L問 https://blog.lindexi.com/
如圖片看不見,請?jiān)跒g覽器開啟不安全http內(nèi)容兼容

本作品采用知識共享署名-非商業(yè)性使用-相同方式共享 4.0 國際許可協(xié)議進(jìn)行許可。歡迎轉(zhuǎn)載、使用、重新發(fā)布,但務(wù)必保留文章署名[林德熙](http://www.rzrgm.cn/lindexi)(包含鏈接:http://www.rzrgm.cn/lindexi ),不得用于商業(yè)目的,基于本文修改后的作品務(wù)必以相同的許可發(fā)布。如有任何疑問,請與我[聯(lián)系](mailto:lindexi_gd@163.com)。

浙公網(wǎng)安備 33010602011771號