从用于远程 CLR 安装的 MSI 自定义操作读取文件数据

Read File data from MSI custom action for remote CLR installation

我们需要能够在 MSI 安装期间将程序集安装到远程 SQL 服务器数据库。为了做到这一点,我们有一个带有替换标记的 SQL 脚本,程序集数据(用 0x 前缀编码的十六进制)应该放在那里。现在我需要弄清楚如何使自定义操作从 MSI 文件中读取程序集的二进制文件数据,并将十六进制内容放入 InstallShield 的 "SQL Scripts" 操作可以替换为 属性 的 SQL脚本。

我卡在了需要从 MSI 文件读取二进制文件数据的位置。我可以等到延迟上下文在安装后从文件系统中读取文件数据,但这似乎不是 MSI "wants" 的操作方式,因为它如何使在延迟上下文中访问属性变得如此困难动作上下文。我什至不确定那时我是否仍然能够修改 SQL 脚本 - 可能为时已晚。我认为 "right" 的方法是在延迟操作阶段开始之前确定要执行的 SQL 脚本。

我正在寻找一个比我的备份计划更好的解决方案,即让构建过程在构建时替换 SQL 脚本中的内容(因为这意味着我们实际上提供了文件的两个副本,一个用于 reference/maintenance 目的,另一个包含在 SQL 脚本中)。

那么我如何读取 MSI 将从自定义操作安装的文件的二进制内容,或者是否有更好的方法将 CLR 的程序集安装到远程 SQL 服务器?

我会建议做你试图避免做的事情 ;-),那就是让构建过程创建 SQL 脚本,其中包含 CREATE ASSEMBLY [name] FROM 0x....

I'm looking for a solution better than my backup plan of having the build process replace the content in the SQL script at build time (because that means we essentially deliver two copies of the file, one for reference/maintenance purposes, and the other included in SQL script).

我不同意这里的结论。您只需要其中包含 FROM 0x.... 的脚本。您不需要保留一个引用 DLL 路径的文件。这不是很便携,即使在 MSI 安装程序场景之外也是如此。从 SDLC("Software Development Life Cycle" 对于那些想知道该首字母缩略词的人)的角度来看,最好有一个独立的发布脚本:对文件系统某处的 DLL 没有外部依赖性。从 "reference" 的角度来看,除了可能使用 ILSpy or Red Gate's .NET Reflector 查看其代码之外,让 DLL 没有太多好处,那只是验证什么是 "shipped",因为你有实际源代码。

我唯一一次使用 DLL 是为了演示、演示和文章。当谈到将某些东西集成到构建过程中时,我只是将 DLL 读入一串十六进制代码,在每第 N 个字符处用反斜杠 (\) 作为该行的最后一个字符断开,因为那是T-SQL 行继续符。一个例子是 Pastebin.com 上的以下 SQL 脚本:

SQLCLR Meta-data function for cross-database IndexName()

该脚本安装一个程序集并创建一个函数作为我在此 DBA.StackExchange 答案中发布的代码的工作示例:

Central stored procedure to execute in calling database context

我想我附近有一篇关于这个主题的博客文章。

我已经编写了很多具有数据库要求的安装程序,并且我几乎得出了不尝试对远程数据库执行脚本的结论。可能出错的地方太多了,当它是另一台或多台机器时,MSI 对 "installed" 的理解就会不同步。

有几次我决定将数据库功能拆分到它自己的 MSI 中,然后 运行 直接在数据层服务器上。现在,应用程序层仅获取连接字符串、验证兼容性并配置应用程序以使用它。

只是一个想法。