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),仅供参考
企业数字化 ERP 产品动态
相关推荐
通用Agent大赛脑洞炸裂!用TaoToken统一Key打通OpenManus与Flowith的配置实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:26:11
抖音无水印批量下载手把手指南:3条命令存档任意创作者全部作品 抖音无水印批量下载手把手指南:3条命令存档任意创作者全部作品 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallba… · 2026/9/25 2:26:11
Breach 3靶场实战:从环境搭建到信息收集拿下第一个入口 最近在复盘vulnhub上的Breach 3靶场,把它当成一次完整的实战前演练。说实话,这几年带人入门安全测试,最常被问到的问题不是“漏洞怎么利用”,而是“我连入口都找不到,接下来干什么”。DVWA和Pikachu这类靶场练的是漏洞… · 2026/9/25 3:32:27
机房管理系统源码包复现:反编译、重建数据库与运行排坑 简介:机房管理系统代码文件.zip是一套基于Java的机房管理信息系统源码包,面向需要开发或学习设备管理、上机统计、故障处理等场景的开发者与学生。压缩包共140个文件,体积约5MB,包含30个Java源文件、54个class编译文件、3个SQL脚本… · 2026/9/25 3:32:27
urql populateExchange 深度指南:用 @populate 指令自动填充 Mutation 查询字段 前端 【免费下载链接】urql The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow. 项目地址: https://gitcode.com/gh_mirrors/ur/urql 点击查看 免费下载 populateExchange 是 urql 生态中… · 2026/9/25 3:32:21
全域智能管控平台权限管理:RBAC模型落地与安全管控实践 聊到权限管理,很多人第一反应就是"给谁开通什么功能",似乎建个用户列表再打个勾就完事了。但真正做过安防平台、物联网管控平台或者企业内部中台的人都会明白,权限管理从来不是界面交互问题,而是整个系统的安全底座。尤… · 2026/9/25 3:32:21
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37