尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Inno Setup如何调用C DLL?HS2-HF_Patch的DllExport与stdcall导出机制深度剖析

Inno Setup如何调用C DLL?HS2-HF_Patch的DllExport与stdcall导出机制深度剖析 Inno Setup如何调用C# DLLHS2-HF_Patch的DllExport与stdcall导出机制深度剖析【免费下载链接】HS2-HF_PatchAutomatically translate, uncensor and update HoneySelect2!项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch在开源项目 HS2-HF_PatchHF Patch for HoneySelect2一款自动翻译、去审查并更新 HoneySelect2 的补丁工具中安装器由 Inno Setup 编写而复杂的文件校验、权限修复、插件备份等逻辑全部放在一个 C# DLL 里完成。本文带你弄清 Inno Setup 调用 C# DLL 的完整机制DllExport 属性导出 stdcall 调用约定声明以及这个真实项目中 12 个导出函数是怎么串起来的。为什么安装器要用 C# DLL 干活HF Patch 的安装过程需要不少重活校验安装器自身和分卷文件的 MD5 哈希防止下载损坏从注册表、Steam 目录、全盘扫描三级查找游戏安装位置用takeown/icacls修复游戏目录权限把 BepInEx 插件打包成带时间戳的 zip 备份Inno Setup 自带的 Pascal Script 做这些事比较吃力没有现成的哈希库、zip 压缩、Steam 探测等于是作者把逻辑写成 .NET 程序集HelperLib见 HelperLib/HelperLib.csproj让 Inno Setup 脚本像调用普通 Win32 函数一样调用它。第一步用 DllExport 把静态方法变成导出函数普通 .NET 程序集没有导出表无法被LoadLibrary直接调用。项目的解决方案是 NuGet 包UnmanagedExportsDllExport在 HelperLib/packages.config 中只引用了一个包package idUnmanagedExports version1.2.7 targetFrameworknet45它需要两处配合见 HelperLib/HelperLib.csproj引用RGiesecke.DllExport.Metadata.dll提供DllExport特性导入构建脚本packages/UnmanagedExports.1.2.7/tools/RGiesecke.DllExport.targets编译后自动为标记的方法生成导出表。之后在方法上加一个特性即可对外导出例如 HelperLib/HelperLib.cs 中的[DllExport(FindInstallLocation, CallingConvention CallingConvention.StdCall)] public static void FindInstallLocation(..., out string strout)注意几个硬性要求方法必须是static没有实例可传参数必须全部是托管友好的类型字符串、数字、bool、out 参数返回值建议用out参数传递结果而不是 return。第二步stdcall 调用约定两边必须一致这是最容易踩的坑。x86 上 stdcall 与 cdecl 的栈清理方不同约定不一致会导致栈指针错乱、安装器当场崩溃。C# 侧在特性里指定CallingConvention.StdCall见 HelperLib/HelperLib.csInno Setup 侧在 patch.iss 中用external声明末尾必须写stdcallprocedure FindInstallLocation(path: String; gameName: String; gameNameSteam: String; out strout: WideString); external FindInstallLocationfiles:HelperLib.dll stdcall;声明格式是函数名DLL路径 调用约定。files:HelperLib.dll表示取安装器文件所在目录里的 DLL。整个 patch.iss 一共以这种方式声明了 12 个函数FindInstallLocation、VerifyFiles、SetConfigDefaults、WriteVersionFile、FixConfig、FixPermissions、CreateBackup、RemoveModsExceptModpacks、RemoveSideloaderDuplicates、RemoveNonstandardListfiles、PostInstallCleanUp、RemoveJapaneseCards。字符串怎么传字符集必须对齐Inno Setup 的String内部是 UTF-16 宽字符C# 侧若按 ANSI 解析就会乱码。项目的做法是输入字符串统一标注[MarshalAs(UnmanagedType.LPWStr)]即宽字符串指针输出参数用[MarshalAs(UnmanagedType.BStr)] out string即 COM BSTRPascal Script 侧对应out strout: WideString。以自动探测安装目录为例HelperLib/HelperLib.csFindInstallLocation按顺序尝试三级策略先查注册表Software\illusion\{游戏名}上次打补丁时写入的INSTALLDIR_HFP再查 Steam 各steamapps/common目录实现见 HelperLib/Steam.cs最后对 Program Files 和所有磁盘根目录做暴力扫描。调用点就在 patch.iss 的GetDefaultDirName通过DefaultDirName{code:GetDefaultDirName}让安装向导的目录框直接填好正确路径。一个亮点DLL 根本没打包进安装器patch.iss 中 HelperLib.dll 的 Files 条目带了dontcopy标志Source: HelperLib.dll; DestDir: {app}; Flags: dontcopy意思是编译时把 DLL 塞进安装器但安装到游戏目录时不释放它——它留在安装器临时目录供files:HelperLib.dll在运行期加载任务结束后随临时文件一起消失。这样游戏目录里不会残留一个无用的 DLL卸载时也无从删起。12 个导出函数在流程中的分工阶段函数作用选择目录FindInstallLocation三级探测游戏安装位置安装前VerifyFiles校验 exe 末尾嵌入的 MD5 哈希表HelperLib/Verifier.cs安装前FixPermissions生成批处理执行 takeown/icacls安装前CreateBackup把 BepInEx、scripts、DHH_Data 打包成 zip安装前RemoveModsExceptModpacks旧 Mod 移入备份目录安装后FixConfig校验 setup.xml损坏则重写为安全默认值安装后WriteVersionFile写隐藏的版本记录文件其中VerifyFiles的设计很巧妙哈希表就嵌在安装器 exe 的最后 1000 字节里标记为|HASHES|C# 代码先截取尾部读出期望哈希再对主体重新计算 MD5 比对HelperLib/Verifier.cs。Inno Setup 侧在PrepareToInstall中调用它返回非空错误信息时安装向导自动中止patch.iss。新手最容易踩的 5 个坑调用约定不一致C# 侧StdCall、Inno Setup 侧漏写stdcall表现为安装器莫名崩溃或返回垃圾值字符集不匹配忘了LPWStr标注路径含中文或空格时参数被截断导出非 static 方法DllExport 编译期直接报错异常穿透到非托管C# 异常抛回 Inno Setup 会导致未处理崩溃所以项目里每个导出函数都整包try/catch错误写入HF_Patch_log.txtHelperLib/HelperLib.cs目标机器缺 .NET 4.5DLL 是 .NET 程序集机器上没有对应框架就会加载失败HF Patch 面向的游戏用户环境基本都有但自己项目要评估。小结Inno Setup 调用 C# DLL 的完整链路可以浓缩为四步NuGet 安装UnmanagedExports在 csproj 中引用元数据程序集并导入 targets方法上加[DllExport(导出名, CallingConvention.StdCall)]Inno Setup 中procedure ...; external 导出名files:xxx.dll stdcall;字符串统一宽字符LPWStr/WideString输出走BStr或宽字符串指针。想深入看完整实现推荐按顺序阅读 patch.iss声明与调用、HelperLib/HelperLib.cs导出函数实现和 HelperLib/Verifier.cs哈希校验再对照 README.md 了解这套机制服务的整体补丁流程。【免费下载链接】HS2-HF_PatchAutomatically translate, uncensor and update HoneySelect2!项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表