在 Wix 安装期间,C# 自定义操作无法找到 appsettings.json 文件

C# Custom Action not able to locate appsettings.json file during Wix install

我为我的网络应用程序创建了一个 Wix 安装程序,但在尝试替换我的 appsettings.json 文件中的值时 运行 遇到了问题(使用我从用户那里获得的信息我创建的自定义对话框)。信息从我的对话框完美地传递到我的自定义操作。然后它失败并抛出错误。下面,我将 post 我得到的错误,安装程序项目的 .wixproj 文件,安装程序项目中的 Produxt.wxs 文件,最重要的是 CustomAction class 来自我的自定义动作项目。问题是我不知道如何在安装过程中以编程方式识别 appsettings.json 文件的正确文件路径。我很迷茫,真的需要一些帮助...谢谢。

错误(在 CustomActions.cs 中的 AddOrUpdateAppSetting 方法的第二行抛出)

ex = {"Could not find file 'C:\Users\DeanFriedland\AppData\Local\Temp\MSI8E19.tmp-\appSettings.json'.":"C:\Users\DeanFriedland\AppData\Local\Temp\MSI8E19.tmp-\appSettings.json"}

.wixproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
    <ProductVersion>3.10</ProductVersion>
    <ProjectGuid>79a05790-9945-41e3-888d-01b39ed87514</ProjectGuid>
    <SchemaVersion>2.0</SchemaVersion>
    <OutputName>OpenBotInstaller-$(Configuration)-$(Platform)</OutputName>
    <OutputType>Package</OutputType>
    <Cultures>;</Cultures>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <OutputPath>bin$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>Debug</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <OutputPath>bin$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj$(Configuration)\</IntermediateOutputPath>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
    <OutputPath>bin$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>Debug</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
    <OutputPath>bin$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj$(Configuration)\</IntermediateOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="Components.wxs" />
    <Compile Include="ComponentsGenerated.wxs" />
    <Compile Include="DatabaseConfigDialog.wxs" />
    <Compile Include="Directories.wxs" />
    <Compile Include="Product.wxs" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="Common.wxl" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\InstallerCustomAction\InstallerCustomAction.csproj">
      <Name>InstallerCustomAction</Name>
      <Project>{81128cc3-071e-4926-8a8c-1b9ac52272d6}</Project>
      <Private>True</Private>
      <DoNotHarvest>True</DoNotHarvest>
      <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
      <RefTargetDir>INSTALLFOLDER</RefTargetDir>
    </ProjectReference>
    <ProjectReference Include="..\OpenBots.Server.Web\OpenBots.Server.Web.csproj">
      <Name>OpenBots.Server.Web</Name>
      <Project>{9ca5640a-4894-497f-b89e-1c28bcee22cf}</Project>
      <Private>True</Private>
      <DoNotHarvest>True</DoNotHarvest>
      <RefProjectOutputGroups>Binaries;Content;Satellites</RefProjectOutputGroups>
      <RefTargetDir>INSTALLFOLDER</RefTargetDir>
    </ProjectReference>
  </ItemGroup>
  <ItemGroup>
    <WixExtension Include="WixUIExtension">
      <HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
      <Name>WixUIExtension</Name>
    </WixExtension>
  </ItemGroup>
  <Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
  <Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
    <Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
  </Target>
  <Target Name="BeforeBuild">
    <!-- Clean previous build folder -->
    <Exec Command="rd /s /q ..\OpenBots.Server.Web\bin$(Configuration)\netcoreapp3.1\win-$(Platform)" />
    <!-- Publish dotnet core app -->
    <Exec Command="dotnet publish ..\OpenBots.Server.Web\OpenBots.Server.Web.csproj -c $(Configuration) -r win-$(Platform)" />
    <!-- Get assembly version -->
    <GetAssemblyIdentity AssemblyFiles="..\OpenBots.Server.Web\bin$(Configuration)\netcoreapp3.1\win-$(Platform)\OpenBots.Server.Web.dll">
      <Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
    </GetAssemblyIdentity>
    <!-- Define some variables we need -->
    <PropertyGroup>
      <DefineConstants>BuildVersion=%(AssemblyVersion.Version);BasePath=..\OpenBots.Server.Web\bin$(Configuration)\netcoreapp3.1\win-$(Platform)\publish</DefineConstants>
    </PropertyGroup>
    <!-- Harvest file components from publish folder -->
    <HeatDirectory OutputFile="ComponentsGenerated.wxs" DirectoryRefId="INSTALLFOLDER" ComponentGroupName="PublishedComponents" SuppressCom="true" Directory="..\OpenBots.Server.Web\bin$(Configuration)\netcoreapp3.1\win-$(Platform)\publish" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" AutoGenerateGuids="false" GenerateGuidsNow="true" ToolPath="$(WixToolPath)" PreprocessorVariable="var.BasePath" />
  </Target>
  <Target Name="AfterBuild">
    <!-- Get assembly version -->
    <GetAssemblyIdentity AssemblyFiles="..\OpenBots.Server.Web\bin$(Configuration)\netcoreapp3.1\win-$(Platform)\OpenBots.Server.Web.dll">
      <Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
    </GetAssemblyIdentity>
    <!-- Rename and move final MSI -->
    <Exec Command="if not exist Installs mkdir Installs" />
    <Exec Command="move bin$(Configuration)$(OutputName).msi Installs\OpenBots-%(AssemblyVersion.Version)-$(Configuration)-$(Platform).msi" />
  </Target>
</Project>

Produxt.wxs

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

  <!-- Give product a unique ID per platform -->
  <?if $(var.Platform)=x64 ?>
  <?define ProductCode = "{51741540-BF67-4925-8624-6EF3859DD7E4}" ?>
  <?else?>
  <?define ProductCode = "{097B9DA2-EA62-4990-9012-B58AFB785634}" ?>
  <?endif?>

  <!-- Fixed upgrade Id -->
  <?define UpgradeCode = "{A0BCAB0C-23E8-414F-B9AA-D7B7304CE503}" ?>

  <?define BuildVersion = 1.0.0.0 ?>

  <Product Id="$(var.ProductCode)"
           Name="!(loc.ProductName_$(var.Platform))"
           Language="!(loc.Language)"
           Version="$(var.BuildVersion)"
           Manufacturer="!(loc.Company)"
           UpgradeCode="$(var.UpgradeCode)">

    <Package InstallerVersion="200"
             Compressed="yes"
             InstallScope="perMachine"
             Platform="$(var.Platform)"
             Manufacturer="!(loc.Company)"
             Languages="!(loc.Language)"
             />

    
    <!-- Option 1 -->
    <CustomAction Id="ConfigureDatabaseValues" BinaryKey="CustomActionBinary" DllEntry="ConfigureDatabaseValues"/>

    <Binary Id="CustomActionBinary" SourceFile="$(var.InstallerCustomAction.TargetDir)$(var.InstallerCustomAction.TargetName).CA.dll" />

    <InstallExecuteSequence>
      <Custom Action="ConfigureDatabaseValues" Before="InstallFinalize"/>
    </InstallExecuteSequence>

    
    <!-- Option 2 -->
    <!--<CustomAction Id="ConfigureDatabaseValues" BinaryKey="CustomActionBinary" DllEntry="ConfigureDatabaseValues" Execute="immediate" />
    
    <Binary Id="CustomActionBinary" SourceFile="$(var.InstallerCustomAction.TargetDir)$(var.InstallerCustomAction.TargetName).CA.dll" />
    
    <InstallExecuteSequence>
      <Custom Action='ConfigureDatabaseValues' Before='InstallFinalize'>NOT Installed</Custom>
    </InstallExecuteSequence>-->
    

    <!-- Downgrade error message -->
    <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeErrorMessage)" />

    <!-- Include .cab file into .msi file -->
    <MediaTemplate
      EmbedCab="yes"
      />

    <!-- Define main app icon -->
    <Icon Id="icon.ico" SourceFile="$(var.OpenBots.Server.Web.ProjectDir)\ClientApp\src\openBotsfavicon.ico" />

    <!-- Use the icon.ico icon for this installer (shows up in Add/Remove programs) -->
    <Property Id="ARPPRODUCTICON">icon.ico</Property>
    <!-- Help/Support website (shows in the Add/Remove programs) -->
    <Property Id="ARPURLINFOABOUT">http://www.accelirate.com</Property>

    <!-- Create a basic UI for the installer -->
    <UI Id="MyWixUI_Mondo">
      <UIRef Id="WixUI_Mondo" />
      <UIRef Id="WixUI_ErrorProgressText" />

      <DialogRef Id="DatabaseConfigDialog" />

      <Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="DatabaseConfigDialog" Order="3">LicenseAccepted = "1"</Publish>
      <Publish Dialog="SetupTypeDlg" Control="Back" Event="NewDialog" Value="DatabaseConfigDialog">1</Publish>
    </UI>
    

    <!-- Change the installer UI background images -->
    <WixVariable Id="WixUILicenseRtf" Value="$(var.ProjectDir)\Assets\License.rtf" />
    <WixVariable Id="WixUIDialogBmp" Value="$(var.ProjectDir)\Assets\Background.bmp" />
    <WixVariable Id="WixUIBannerBmp" Value="$(var.ProjectDir)\Assets\Banner.bmp" />

    <!-- Define components, shortcuts, files etc... for installer -->
    <Feature Id="ProductFeature" Title="OpenBotInstaller" Level="1">
      <ComponentGroupRef Id="ProductComponents" />
      <ComponentGroupRef Id="PublishedComponents" />
    </Feature>

  </Product>




</Wix>

CustomActions.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
using System.Diagnostics;


namespace InstallerCustomAction
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult ConfigureDatabaseValues(Session session)
        {
            try
            {
                Debugger.Launch();

                session.Log("Begin Configuring database values in appsettings.json");

                string connectionString = session["CONNECTIONSTRING"];
                string databaseEngine = session["CHOICE_WIN_SQL"];


                //replace the values in appsettings.json for DB Engine and connection string based on user input
                string dbEngineKey = "DbOption:UseSqlServer";
                var dbEngineValue = databaseEngine == "1" ? false : true;
                AddOrUpdateAppSetting(dbEngineKey, dbEngineValue);

                session.Log("End appsettings.json configuration");

                return ActionResult.Success;
            }
            catch (Exception)
            {
                return ActionResult.Failure;
            }            
        }

        private static void AddOrUpdateAppSetting<T>(string key, T value)
        {
            try
            {

                var filePath = Path.Combine(AppContext.BaseDirectory, "appSettings.json");
                string json = File.ReadAllText(filePath);
                dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

                var sectionPath = key.Split(':')[0];
                if (!string.IsNullOrEmpty(sectionPath))
                {
                    var keyPath = key.Split(':')[1];
                    jsonObj[sectionPath][keyPath] = value;
                }
                else
                {
                    jsonObj[sectionPath] = value; // if no sectionpath just set the value
                }
                string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
                File.WriteAllText(filePath, output);

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}

答案是让我从这样的安装文件夹中找到路径:

var filePaths = Directory.GetFiles(@"c:\Program Files (x86)\OpenBotServer\", "*.json");