如何从Java(8)应用中访问Wix构建的MSI公共属性?
我来一步步帮你实现这个需求,核心思路是让MSI接收命令行参数,把参数值存到注册表(或者你偏好的存储位置),然后Java应用从这个存储位置读取值就行。
1. 修改你的自定义WXS文件
首先得在WXS里做两处关键修改:让MSI能接收FOO参数,然后把这个参数值写到注册表。
1.1 定义可接收的命令行属性
在你的src/main/deploy/package/windows/<<APPNAME>>.wxs的<Product>标签里,加一行定义FOO属性,这样安装时传的FOO=BAR才能被MSI识别:
<Property Id="FOO" Value="" /> <!-- 空值是默认值,安装时可以用命令行覆盖 -->
1.2 把FOO的值写到注册表
接下来要把这个值存到注册表,这样Java应用能读到。找到你现有注册表相关的代码块(或者新增一个组件),添加存储FOO的注册表项:
<DirectoryRef Id="APPLICATIONFOLDER"> <Component Id="AppRegistryConfig" Guid="这里生成一个新的GUID哦"> <RegistryKey Root="REGISTRY_ROOT" Key="SOFTWARE\APPLICATION_VENDOR\APPLICATION_NAME" Action="createAndRemoveOnUninstall"> <!-- 保留你原来的Path注册表项,这是你之前代码里有的 --> <RegistryValue Name="Path" Type="string" Value="[APPLICATIONFOLDER]" KeyPath="yes" /> <!-- 新增这行,把FOO的值存进去 --> <RegistryValue Name="FOO" Type="string" Value="[FOO]" /> </RegistryKey> </Component> </DirectoryRef>
1.3 确保组件被安装
别忘记把这个新的注册表组件加到<Feature>里,不然安装时不会执行这个组件的逻辑:
<Feature Id="MainApplication" Title="Main Application" Level="1"> <ComponentRef Id="AppRegistryConfig" /> <!-- 这里保留你原来的其他ComponentRef,比如主程序文件的引用 --> </Feature>
可选:解决参数传递问题(如果遇到的话)
如果安装后发现FOO的值没存进去,可以试试把FOO加入安全属性列表,确保参数能在安装流程中传递:
<Property Id="SecureCustomProperties" Value="FOO" />
2. 重新打包MSI
用javafxpackager重新构建你的MSI包,确保自定义WXS被正确加载:
javafxpackager -deploy -native msi -srcdir dist -srcfiles your-app.jar -outdir target -outfile YourApp -name "YourApp" -vendor "YourVendor" -version 1.0.0
3. 在JavaFX应用里读取FOO的值
现在就可以在应用里通过Java的Preferences类读取注册表的值了,根据你的安装范围(全局/当前用户)选择对应的读取方式:
3.1 全局安装(InstallScope="perMachine",对应注册表HKLM)
import java.util.prefs.Preferences; public class AppConfig { public static String getFooValue() { // 对应注册表路径:HKEY_LOCAL_MACHINE\SOFTWARE\你的厂商名\你的应用名 Preferences systemPrefs = Preferences.systemRoot() .node("/SOFTWARE/APPLICATION_VENDOR/APPLICATION_NAME"); // 如果没找到FOO的值,就返回"default"作为默认值 return systemPrefs.get("FOO", "default"); } // 在你的应用初始化时调用这个方法就行 public static void main(String[] args) { System.out.println("FOO的值是:" + getFooValue()); } }
3.2 当前用户安装(InstallScope="perUser",对应注册表HKCU)
只需要把上面的Preferences.systemRoot()换成Preferences.userRoot():
Preferences userPrefs = Preferences.userRoot() .node("/SOFTWARE/APPLICATION_VENDOR/APPLICATION_NAME");
注意32位/64位兼容性
如果你的JRE是32位,而MSI是64位(或者反过来),注册表会自动映射到Wow6432Node目录下,这时候要调整路径:
// 32位JRE读取64位MSI的注册表 Preferences systemPrefs = Preferences.systemRoot() .node("/SOFTWARE/Wow6432Node/APPLICATION_VENDOR/APPLICATION_NAME");
测试一下
安装的时候用这个命令:msiexec /i YourApp.msi FOO=BAR /qn(/qn是静默安装,不想静默就去掉),然后启动应用,调用getFooValue(),应该就能拿到BAR啦!
内容的提问来源于stack exchange,提问作者Pablo Fernandez

