首页 / 资讯中心 / 文章详情

ArcGIS Engine 程序打包部署:闪退排查与一体化安装包

ArcGIS Engine 程序打包部署:闪退排查与一体化安装包 ★ FEATURED ARTICLE
简介这份资源面向使用 ArcGIS Engine 开发桌面地理信息系统的初中级开发者聚焦应用程序交付环节的打包与部署问题帮助开发者把自行开发的 Engine 程序连同运行环境一起做成可交付的安装包。资源包内为 1 个 docx 文档压缩后约 2.24MB内容以图文步骤为主覆盖 .NET Framework 3.5 SP1 与 ArcGIS Engine 10 Runtime 的单独安装、在 Visual Studio 2008 中通过安装项目模板制作 Setup、排除 Esri 组件引用并创建桌面与开始菜单快捷方式以及借助 InstallShield 将运行库与应用程序一并封装的两类方案并单列打包过程中的常见问题。文档还对比了 Project Assistant 向导与 Installation Designer 两种制作方式的适用场景便于读者按需选择。已有 657 人学习适合需要把 Engine 工程整理成规范安装包的开发者参考。1. ArcGIS Engine 程序在客户机上闪退多半栽在打包这一环去年收尾一个管线巡检的模拟项目开发机上跑得好好的 ArcGIS Engine 程序拷到客户那台刚做完系统的机器上双击图标转半秒就没了连个报错框都不给。翻事件查看器才看到一条运行库加载失败的记录。这种翻车在 ArcGIS Engine 应用交付里太常见了ArcGIS Engine 应用程序打包从来不是把 exe 和一堆 dll 压个压缩包扔过去而是要把 .NET Framework 3.5 SP1、ArcGIS Engine 10 Runtime、授权文件、快捷方式和安装顺序在安装包里排明白。装漏一样程序就变成双击没反应的玄学故障。这篇按我实际走过的顺序写从版本对照、单独安装、VS 2008 的 Setup 项目到 InstallShield 一体化包最后落到怎么在一台干净机器上验证跑通。2. 版本对齐.NET Framework 3.5 SP1 与 ArcGIS Engine 10 Runtime 谁先装这一章先把「装什么」定死。ArcGIS Engine 10 那个年代的托管程序集编译目标基本是 .NET 2.0/3.5 这一代Runtime 本身只提供 32 位版本所以整条链路上的版本选择没有太多自由度装错一个后面全是连锁反应。2.1 四个组件的版本对照表先把依赖关系摊开。下面这张表是我在模拟项目 A 上实际用过的一套组合装之前建议照着核一遍别在客户现场才发现版本对不上。组件版本作用装在哪.NET Framework3.5 SP1Engine 托管程序集的运行时底座目标机ArcGIS Engine Runtime10提供运行库 dll 与许可校验目标机授权文件单机 ecp 或浮动 License Manager让 Runtime 认得出授权目标机打包工具Visual Studio 2008 Setup 项目 / InstallShield生成 msi exe开发机最容易被忽略的是第一行。很多人看到目标机是 Win10系统里已经带了 .NET Framework 4.x就觉得 3.5 不用管了。这是个典型的版本坑.NET 4.x 和 3.5 是并行安装的两套运行时4.x 装得再全也不会替 3.5 顶班。以 3.5 为目标编译的 Engine 程序在只有 4.x 的机器上加载程序集时会直接失败表现就是进程起来又瞬间退出。我一般会在动手打包前先在目标机上跑一条查询确认 3.5 的状态省得后面排查方向跑偏:: 查询 .NET Framework 3.5 是否已启用Install1 表示已装 reg query HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5 /v Install :: 顺带看一眼 Service Pack 级别SP1 才是我们要的 reg query HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5 /v SPInstall的值为0x1才说明 3.5 本体在SP为1表示打了 SP1。两条都满足才算过关。如果第一条直接报「系统找不到指定的注册表项」那就别纠结了先把 3.5 装上再谈打包。Win10/Win11 上补装 3.5 的常见做法是走系统功能而不是去下离线安装包:: 在线启用 .NET Framework 3.5 功能无需重启前先备份现场 DISM /Online /Enable-Feature /FeatureName:NetFx3 /All :: 如果目标机不能上网用系统安装镜像里的 sxs 目录做离线源 DISM /Online /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:D:\sources\sxs/Online指操作当前运行的系统/All会把父功能一起启用/LimitAccess是告诉 DISM 别去 Windows Update 找文件/Source指向镜像里解出来的sources\sxs。离线那条命令里的盘符要换成实际挂载位置这一步很多人抄错盘符然后得到一个 0x800f081f 的错误码。2.2 单独安装路线Runtime 和应用程序分开装原材料里给的方案其实是两条Runtime 和应用程序分开安装或者一起打包。分开装适合内部环境、机器数量少、装机的人懂点技术的场景。它的好处是排错边界清晰——Runtime 出问题就查 Runtime程序出问题就查程序不会互相甩锅。我一般按这个顺序走顺序错了会多绕很多路装 .NET Framework 3.5 SP1装完重启一次。装 ArcGIS Engine 10 Runtime安装过程中不要改默认安装路径。打开授权配置工具把 ecp 授权文件注册进去确认状态为可用。最后装应用程序本身装完从开始菜单启动不要直接从安装目录双击 exe。第三步是最容易漏的。Runtime 装完不等于授权完成没有授权的 Runtime 在启动时会静默失败连个对话框都不弹新手很容易把它当成程序 bug 去查代码。单机授权用 ecp 文件在授权管理界面里注册浮动授权则要在客户端填 License Manager 的机器名两条路的操作入口不同别混。装完之后可以用卸载注册表项反查版本确认 Runtime 真的落地了:: 在卸载列表里搜 ArcGIS Engine Runtime 的显示名和版本 reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s /f ArcGIS Engine Runtime | findstr /i DisplayName DisplayVersion :: 32 位程序在 64 位系统上会落到 WOW6432Node两个位置都查一遍 reg query HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall /s /f ArcGIS Engine Runtime | findstr /i DisplayName DisplayVersion/s是递归搜索子键/f指定要匹配的字符串findstr /i忽略大小写只留下关心的两行。为什么要查两个位置因为 ArcGIS Engine 10 是 32 位程序在 64 位系统上它的卸载信息会写进WOW6432Node这个重定向节点只查第一处很可能什么都搜不到然后误判成没装。2.3 目标平台必须锁 x86这一条经常被放到最后一章讲但它属于版本对齐的一部分我提前说。ArcGIS Engine 10 Runtime 只有 32 位所以你的应用程序在编译时目标平台必须显式设成x86不能用AnyCPU。AnyCPU编出来的 exe 在 64 位系统上会以 64 位进程启动进程一加载 32 位的 Engine 运行库就直接崩报的是BadImageFormatException或者干脆没有异常。这个坑的血泪经验在于开发机如果是 32 位系统AnyCPU跑起来毫无问题你会以为一切正常等装到 64 位客户机上才开始翻车。在 VS 2008 里改的地方是项目属性 → 生成 → 目标平台选x86或者在解决方案配置管理器里给所有项目统一建一个x86平台。改完之后重新生成用任务管理器看一眼进程32 位进程后面会带*32标记算是肉眼确认。3. Visual Studio 2008 打包Setup 项目从建到出 msi这条路线的前提是目标机上已经装好了 Runtime安装包只负责搬应用程序本体。它的产物就是一个setup.exe加一个setup.msi体积小做内部交付足够用。3.1 新建安装项目并挂主输出在现有的解决方案里加一个安装项目不要另开一个解决方案。原因是安装项目要引用应用程序项目的输出同一个解决方案里才能直接选到「主输出」这个节点。命名我一般就叫Setup别用中文名后面命令行构建会省很多麻烦。建完项目后右键「应用程序文件夹」→ 添加 → 项目输出项目选你的 Engine 应用程序输出选「主输出」。这一步做完中间的窗口里会刷出一堆 dll其中绝大多数是 Engine 的运行库。关键判断在这里这些运行库不该打进安装包。Runtime 已经装在目标机上了包里再带一份装完之后两份版本打架表现是程序有时能开有时开不了非常难查。所以下一步不是继续加文件而是做减法。3.2 排除运行库 dll 而不是删掉在安装项目的「检测到的依赖项」里把 Engine 相关的 dll 一个一个设成「排除」。注意是排除不是从「应用程序文件夹」里删掉——删掉的话VS 下次重新生成依赖检测又会把它们加回来你会陷入反复删除的循环。排除之后被排除的项在列表里会显示一个排除标记并且不会进 msi。这个操作背后的原理是安装项目的依赖检测只是「发现」了这些 dll而是否「分发」由排除标记控制。分清这两件事就不会在打包体积和运行冲突之间反复横跳。哪些留、哪些排除我按这个原则判断类型处理理由Engine 运行库 dll排除Runtime 已提供重复分发会版本冲突你自己的业务 dll保留这些 Runtime 里没有第三方小控件保留除非 Runtime 明确包含.NET 框架程序集排除由系统或前置安装提供第三方控件要不要打进去得看它是否随 Runtime 一起装了。拿不准的时候在干净机器上只装 Runtime把业务 dll 拷过去试跑能跑的就说明不用打。3.3 快捷方式和安装位置在「应用程序文件夹」里对着主输出右键 → 创建主输出的快捷方式然后把它挪到「用户的桌面」或者「用户的程序菜单」目录下。两个目录都放一份是常见做法用户从哪进都行。快捷方式有两个属性必须改默认值基本都不能用Name改成用户看得懂的名字Target保持指向主输出别手动改成绝对路径。改成绝对路径之后如果用户改了安装目录快捷方式就指向一个不存在的位置双击报「找不到项目」。安装目录同理。默认是[ProgramFilesFolder][Manufacturer]\[ProductName]其中的厂商和产品名来自安装项目的属性面板。我一般把Manufacturer填成团队名ProductName填程序名别留默认值否则会装到一个叫「默认公司名」的目录里。3.4 生成产物与命令行构建在解决方案配置里选Release右键安装项目 → 生成输出目录下会出现setup.exe和setup.msi。setup.exe是个引导程序负责检查 .NET 之类的前置条件setup.msi是真正的安装数据库。发给客户的时候两个都要给只给 msi 会丢掉前置检查。要接自动化构建可以用命令行调 devenv:: 用 VS2008 的 devenv 构建安装项目输出到指定目录 devenv D:\Work\SimProjectA\Setup\Setup.vdproj /build Release /out D:\Work\build.log :: 静默安装记录详细日志便于排查 msiexec /i D:\Work\SimProjectA\Setup\Release\Setup.msi /qn /norestart /l*v %TEMP%\setup_install.log第一条里/build后面跟的是解决方案配置名必须和你在 IDE 里建的那个配置完全一致大小写也别错/out把构建日志单独存一份构建失败时先看这个文件而不是 IDE 的输出窗口。第二条里/qn是完全静默、不弹任何界面/norestart禁止安装程序自己重启机器/l*v写详细日志到指定路径。/qn在调试阶段不建议用出错了什么都看不到等安装包稳定了再用它做批量部署。安装日志是这东西的黑匣子。客户现场装不上先让他把%TEMP%下那份setup_install.log发过来返回码 1603 是脚本自定义动作失败1605 是产品没装过所以卸不掉1638 是已经装了另一个版本。看懂这几个码一半的现场问题不用远程。4. InstallShield 一体化包把 Runtime 和 .NET 一起塞进去分开装的方案在内部好用一旦要发给外部用户就不行了——你没法要求对方先自己去装 Runtime。这时候就得上 InstallShield把 .NET、Runtime、授权、程序本体打进一个安装流程里。4.1 先用 Project Assistant 搭骨架新建工程类型选 InstallScript MSI 或者 Basic MSI 都行我习惯 Basic MSI。建完之后 InstallShield 默认进 Project Assistant就是那个「上一步、下一步」的向导。这个向导只适合把骨架搭起来复杂一点的编排它做不了所以我的做法是向导走一遍把必要信息填掉然后立刻切到 Installation Designer。向导里要填的几项Application Information产品名、版本号、公司名。版本号一定要认真填后面升级安装靠它判断新旧。Installation Architecture安装架构默认即可。Application Files这里先空着等会儿到 Designer 里摆。填完直接切到 Installation Designer 的 Files and Folders 视图。4.2 在 Designer 里摆文件Application Target Folder 与 temp 目录Designer 的 Files and Folders 界面分左右两栏左边Source computers folders是你本机的目录右边Destination computers folders是目标机上的目录结构。要做的第一件事把你的应用程序输出文件夹从左边拖到右边的Application Target Folder下。这个目录对应目标机上的安装路径。第二件事在Application Target Folder上右键新建一个temp子目录然后把准备好的 Runtime 安装目录整个拖进这个 temp 里。这个目录里应该同时包含 Runtime 的安装程序和授权文件缺一不可。之所以叫 temp是因为它只在安装过程中被用到装完可以清掉名字上有提示作用。这一步的目录结构直接决定后面自定义动作里的路径怎么写。装到这个位置之后安装过程中 Runtime 安装程序的完整路径大致是[INSTALLDIR]temp\...\setup.msi其中[INSTALLDIR]是 InstallShield 的属性变量会展开成用户实际选的安装目录。写死盘符是常见错误用户改了安装盘就崩。4.3 开始菜单与快捷方式重命名回到向导的 Shortcuts 页点 New 选你的 exe。InstallShield 会给一个默认名字通常是launch 你的工程名.exe这种必须改掉——这个名字会原样出现在开始菜单里用户看着莫名其妙。改完名字还可以到 Designer 的 Shortcuts 视图做更细的调整比如再复制一份放到桌面、设置快捷方式的图标、指定工作目录。工作目录这一项容易被跳过但它是相对路径解析的基准如果你的程序要读同目录下的配置文件工作目录没设对就会读不到。4.4 用自定义动作按顺序拉起 Runtime 安装这是整个一体化包里最核心的一步。文件塞进去了还得让安装程序在合适的时机去执行它。在 Designer 里进 Behavior and Logic → Custom Actions新建一个「Exe 或 Command Line」类型的动作命令行写:: 在安装过程中静默拉起 Runtime 安装并单独记日志 msiexec /i [INSTALLDIR]temp\ArcEngine10\setup.msi /qn /norestart /l*v [INSTALLDIR]temp\aeruntime.log[INSTALLDIR]会在运行时展开成实际安装路径/qn保证用户看不到第二个安装向导弹出来/norestart防止中途重启打断整个流程/l*v把 Runtime 的安装日志也留在 temp 目录里出问题时一次性取证。动作建好之后要设三个属性Sequence 设成After InstallFiles意思是文件都拷贝完了再执行Return Processing 设成「检查返回码」返回码非 0 就中止安装Execute 设成「Deferred」让它以提升后的权限运行——这一步不做普通用户权限下装 Runtime 会失败。顺序很重要。放在After InstallFiles之前temp 目录里还没有文件命令必然找不到路径放在After SetupCompleteSuccess之后用户可能已经在点「完成」了弹出来的权限框会让人以为装出问题。如果还想让安装包自动补 .NET 3.5可以在 Installation Requirements 里把它加成先决条件Prerequisite路径指向你准备好的离线安装包。这样整个流程变成检查 .NET → 装 .NET → 拷文件 → 装 Runtime → 注册授权 → 建快捷方式用户只点一次下一步。授权注册这一步如果 Runtime 安装目录里有可用的命令行工具也可以串一个自定义动作进去没有的话就在安装完成后弹一个说明页让用户手工导入 ecp。后者虽然土但至少不会静默失败。5. 打包避坑五个把安装包做废的细节这一章全是我自己或者身边人被咬过的记录按「现象 → 原因 → 解决」写遇到对应症状可以直接对号入座。5.1 装完双击没反应进程一闪就没现象安装顺利完成快捷方式也在双击之后鼠标转半秒什么都没有任务管理器里进程出现过又消失。原因目标机只有 .NET Framework 4.x没有 3.5。Engine 程序加载托管程序集失败异常在进程启动阶段就被吞掉了所以看不到任何提示。解决按第 2 章那两条 reg query 确认 3.5 状态缺就用 DISM 补上。补完之后不用重装应用程序直接再双击即可。要验证是不是这个原因可以在命令行里带| more跑一遍或者直接看事件查看器里应用程序日志的 .NET Runtime 错误。5.2 安装包一百多兆装完还偶发崩溃现象安装包体积远大于预期装完之后程序时好时坏重启一次可能又正常。原因把 Engine 运行库 dll 一起打进包了。Runtime 装在系统目录包里又往安装目录塞了一份进程加载时到底用哪一份取决于搜索路径顺序于是产生随机崩溃。解决回到安装项目的依赖检测里把这些 dll 设成排除重新生成。判断标准很简单安装包体积应该是几兆到十几兆量级如果上百兆八成是把运行库打进去了。顺便说一句这类问题在开发机上永远复现不了因为开发机上 Runtime 装得全搜索路径顺序刚好对。5.3 快捷方式指向一个不存在的路径现象安装到自定义目录后桌面快捷方式双击提示找不到文件。原因创建快捷方式时手改了 Target写成了开发机上的绝对路径而不是指向安装目录里的相对目标。解决删掉重建Target 保持指向主输出节点不要手工编辑路径。如果确实需要指定用[INSTALLDIR]这类属性变量而不是盘符路径。改完在测试机上装到 D 盘验证一遍别只在 C 盘默认路径下测。5.4 装到 Program Files 下程序读不到配置现象装在默认目录下程序启动报配置读取失败装在 D 盘根目录就正常。原因Program Files有 UAC 保护普通权限进程不能往安装目录写文件。程序如果试图在自身目录下写配置或者日志就会被重定向或者直接失败。解决把可写内容挪到%ProgramData%或者用户目录下安装时用 InstallShield 建好目录并设置权限实在改不动代码就在安装包里把安装目录的写权限放开但这属于治标。这条坑在 Win7 之后一直存在只是很多人开发时用管理员账号跑感觉不到。5.5 换了台机器就提示授权无效现象同一套安装包A 机器装完能用B 机器装完提示没有授权。原因ecp 授权文件只对特定机器有效或者 Runtime 装完但授权从没注册过。也有一种情况是安装时用管理员账号注册了授权普通用户登录后读不到。解决先确认授权类型。单机 ecp 需要每台机器单独申请并注册浮动授权则要保证客户端能连到 License Manager 并且机器名填对。注册完用授权管理界面确认状态别只看安装程序有没有报错。6. 装完怎么验证在一台干净机器上走完整链路安装包做完最有价值的动作不是再检查一遍代码而是找一台从没装过任何相关组件的机器跑一遍。虚拟机最合适装完系统打个快照测完回滚下次改包还能复用。我一般会在这台机器上按下面的顺序过一遍任何一步不对就停下别往下走。步骤检查内容通过标准1.NET Framework 3.5 SP1注册表 Install1 且 SP12Runtime 是否落地卸载列表能查到 ArcGIS Engine Runtime3授权状态授权管理界面显示可用4安装过程无报错弹窗日志无 16035快捷方式桌面与开始菜单各一份均能启动6业务流程打开一个真实数据完成一次导出第 6 步是关键。前面五步全过程序也可能在真正加载数据的时候崩因为那才会走到 Engine 的图形和几何模块。所以验证不能停在「窗口能打开」一定要跑一个真实的业务动作哪怕只是一个很小的示例数据。装完之后我还会做一件事把安装日志和 Runtime 日志都留一份到固定目录命名带上日期和版本号。:: 归档安装日志文件名带版本和日期方便回溯 set LOGDIRD:\ReleaseLogs\%DATE:~0,4%%DATE:~5,2%%DATE:~8,2% mkdir %LOGDIR% copy %TEMP%\setup_install.log %LOGDIR%\setup.log copy C:\Program Files\SimProjectA\temp\aeruntime.log %LOGDIR%\runtime.log%DATE:~0,4%这类写法是截取系统日期的年月日拼成目录名不同区域设置下%DATE%的格式不一样正式脚本里最好换成不依赖区域格式的取法。这么做的好处是半年后客户报「当时装的时候就有问题」你能立刻把当次日志翻出来而不是靠回忆。还有一个习惯每改一次安装包版本号必须往上走哪怕是只改了一个快捷方式名字。安装项目的ProductCode要保持每次构建都变UpgradeCode要保持永远不变。前者让系统把新包当成新产品后者让新包能找到旧版本并执行升级而不是并排安装。这两项搞混用户机器上会出现两个同名程序卸载一个另一个还在。从那以后我每次发版前都强制走一遍干净机器验证不管改动多小哪怕只是换了张图标。因为在开发机上一切正常这件事从来不能说明安装包没问题。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站