【问题标题】:WIX Custom Action modify file in INSTALLFOLDER after InstallFinalizeWIX 自定义操作在 InstallFinalize 之后修改 INSTALLFOLDER 中的文件
【发布时间】:2021-03-29 04:23:19
【问题描述】:

我为我的 WIX V3 安装程序编写了一个 C# 自定义操作,它应该在 INSTALLFOLDER 中修改我的 appsettings.json。该操作的 Execute-attribute 设置为 immediate 和 Impersonate="no",它在 InstallFinalize 之后调用,但在此操作中遇到问题,即缺少管理员权限。 该操作会修改 INSTALLFOLDER 中的 appsettings.json,即 Program File (x86)。

自定义操作正常无错误地读取、反序列化、修改和序列化数据。 错误发生在写入 InstallFolder 中的 appsettings.json 期间。 虽然出现了错误,但应用程序的其余部分已安装并且工作正常。

我尝试在 ALL 可能的组合中组合执行和自定义操作,如果我在安装完成之前将自定义操作更改为运行,我将获得写入 InstallFolder 的权限,但我找不到appsettings.json 文件,因为此时的所有文件都是临时文件 (.tmp),并且名称不相关。

出现的错误: Error message

我的 Product.wsx 代码的一部分:

      <Property Id="Password" Value="Error password" />
      <Property Id="FilePath" Value="C:\Program Files (x86)\Company\Product\" />
      
      <CustomAction Id="SetUserName" Property="Username" Value="[ACCOUNT]"/>
      <CustomAction Id="SetPassword" Property="Password" Value="[PASSWORD]"/>
      <CustomAction Id="SetFilePath" Property="FilePath" Value="[INSTALLFOLDER]"/>
      
      <Binary Id="GetData" SourceFile="$(var.SetupExtensions.TargetDir)\$(var.SetupExtensions.TargetName).CA.dll" />  
      <CustomAction Id="ChangeJSON" BinaryKey="GetData" DllEntry="CustomAction1" Execute="immediate" Impersonate="no"  Return="check"/>
      
      <InstallExecuteSequence>
          <Custom Action="SetUserName" After="CostFinalize" />
          <Custom Action="SetPassword" After="CostFinalize" />
          <Custom Action="SetFilePath" After="CostFinalize"/>
          <Custom Action='ChangeJSON'  After='InstallFinalize'></Custom>
      </InstallExecuteSequence> 

我的自定义操作代码:

      public static ActionResult CustomAction1(Session session)
      {
          try
          {
              session.Log( "Begin CustomAction1" );
              string user = session["Username"];
              string password = session["Password"];
              string loc = session["FilePath"];

              var json = System.IO.File.ReadAllText( loc +"appsettings.json" );
              var root = JsonConvert.DeserializeObject<Root>(json);

              root.Default.UserName = user;
              root.Default.Password = password;
          
              json = JsonConvert.SerializeObject( root, Formatting.Indented );
              System.IO.File.WriteAllText( loc + "appsettings.json", json );
              //The MessageBox bellow shows(and is with correct info) when I remove System.IO.File.WriteAllText above ^^
              MessageBox.Show("Username: "+ user +"\nPassword: "+password +"\nFilePath: " + loc);
              return ActionResult.Success;
          }
          catch(Exception ex )
          {
              session.Log( "Error: " + ex.Message );
              MessageBox.Show(ex.Message);
              return ActionResult.Failure;
          }

如何通过自定义操作修改 appsettings.json?

【问题讨论】:

标签: c# wix wix3.5 wix3 wix3.6


【解决方案1】:

应用程序启动:如果可以的话,我会考虑通过应用程序启动序列更新 JSON。 1) 单源解决方案2) 开发人员熟悉的领域3) 更简单更好的调试功能4) 没有 impersonation-sequencing-conditioning-complexities 喜欢你获取自定义操作Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?


延迟 CA 示例:您可以在此处找到延迟模式自定义操作 WiX 解决方案的示例: https://github.com/glytzhkof/WiXDeferredModeSample

内联示例:这个较旧的答案显示了答案中内联的关键结构: Wix Custom Action - session empty and error on deferred action.

CustomActionData:延迟模式自定义操作无法像即时模式自定义操作那样访问会话对象属性值。正如 Painter 所写,您需要通过将数据写入执行脚本来将文本或设置“发送”到延迟模式。然后通过读取特殊属性 CustomActionData,可以在延迟模式下使用数据。上面的示例应该具有所需的构造,以了解其工作原理。 See the MSI documentation as wellRobert Dickau's MSI Properties and Deferred Execution

事务:延迟模式自定义操作只能存在于 InstallInitialize 和 InstallFinalize 之间。这些操作之间的操作以提升的权限运行,并且可以写入每台机器的位置(普通用户不可写入)。您可以在 InstallFinalize 之前安排自己,让初学者测试您当前的删除机制(我会尝试其他方法)。

回滚 CA:回滚自定义操作旨在撤消对 JSON 自定义操作所做的操作,然后将所有内容恢复到之前的状态(安装失败后的清理)。编写这些内容非常复杂,需要进行大量测试 - 许多人只是跳过它们。最好尝试找到可以为您完成这项工作的库或框架。我不知道除了下面链接的那个,我不知道它的状态。回滚自定义操作必须在 InstallExecuteSequence 中的实际 CA 之前(当 MSI 回滚时,它会反向执行序列)。

由于所有这些复杂性,自定义操作成为部署错误的主要来源:https://robmensching.com/blog/posts/2007/8/17/zataoca-custom-actions-are-generally-an-admission-of-failure/


链接:

【讨论】:

  • 您好,感谢您回答我的问题。我尝试了 Json 扩展,但不幸的是它不起作用。回滚 CA 是个好主意,我一定会实现它。是否可以在 InstallFinalize 之前获取 appsettings.json,将其发送到我的自定义操作以进行更改,然后将更改后的 appsettings.json 发送回 .msi 安装程序?基本上我需要一个更改用户名和密码的对话框,并将其保存到 appsettings.json(我已经有一个工作对话框,它将数据传递给 CA)
【解决方案2】:

更改系统状态的自定义操作应在 InstallIntialize 和 InstallFinalize 之间运行。这意味着您应该在 InstallFinalize 之前而不是之后安排它。

它还应该在没有模拟的情况下以延迟执行的方式运行。您将需要在此之前安排另一个自定义操作,以创建自定义操作数据并将数据传递给延迟的自定义操作。

理想情况下,您还应该有回滚和提交操作以支持回滚并使用 WIXFAILWHENDEFERRED 自定义操作进行测试。

阅读: http://www.installsite.org/pages/en/isnews/200108/index.htm http://blog.iswix.com/2011/10/beam-me-up-using-json-to-serialize.html

【讨论】:

  • WIXFAILWHENDEFERRED 自定义操作功能很好 - 我一直忘记它。测试回滚时的关键要素。不必为每个项目都自己写这个很好。你知道我在回答中提到的 JSON WiX 项目吗?还有其他项目吗?
  • 嗨,谢谢你的回答。我尝试在 InstallFinalize 之前延迟运行它,但我收到一条错误消息,提示“找不到 appsettings.json”,因为尚未安装文件。是否有可能以某种方式从 .msi 安装程序中提取 appsettings.json 并将其发送到我的自定义操作?这样我只需在安装前更改文件(我有一个更改用户名和密码的对话框,我会从对话框中获取数据,并用它们更改 appsetings.json)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多