WiX:将安装路径传递给托管自定义操作

发布于 2024-08-12 12:15:54 字数 2960 浏览 3 评论 0原文

新的一天,新的问题;-) 仍然需要与托管的自定义操作作斗争。我已经设法让它调用自定义操作并向其传递一些测试数据。现在我想用我需要的真实数据替换测试数据。问题就开始了:我想调用一个安装在我的安装子目录中的批处理文件。因此我需要将安装路径传递给自定义操作。据我所知,这可以使用 customactiondata 机制来完成。但这是行不通的。当我记录安装时,我可以看到在 customaction INSTALLLOCATION 之外指向正确的路径,但是当我查看 customaction 时,customactiondata 属性为空...

我做错了什么?

调用自定义操作的合并模块:

<Module Id="DflHelpInstaller" Language="1033" Version="1.0.0.0">
    <Package Id="f952de58-1dc6-46b3-872a-7a49e2d9ea0a" Manufacturer="DflHelpInstaller" InstallerVersion="200" />

<Binary Id='RegisterDflHelpDll' SourceFile="$(var.REGISTERHELP.TargetDir)RegisterDflHelp.CA.dll" />

    <CustomAction Id='RegisterDflHelp' BinaryKey='RegisterDflHelpDll'  DllEntry='RegisterDflHelp' Execute='deferred' />

    <CustomAction Id="RegisterDflHelp.SetProperty" Return="check" Property="RegisterDflHelp" Value='[INSTALLLOCATION]' Execute='immediate' />

   
    <InstallExecuteSequence>
      <Custom Action='RegisterDflHelp.SetProperty' After='CostFinalize' />
      <Custom Action='RegisterDflHelp' After='InstallFiles' />
    </InstallExecuteSequence>

    <Directory Id="TARGETDIR" Name="SourceDir">
        </Directory>
    <ComponentGroupRef Id="HelpGroup"/>

    </Module>
</Wix>

使用 MergeModule 的安装程序项目概述:

....

<Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="ProgramFilesFolder" SourceName="PFFiles">
<Directory Id="Company" Name='$(var.COMPANY)'>
  <Directory Id="INSTALLLOCATION" SourceName='$var.v[SDK_VERSION]'>
    <Component Id="MyBanner" Guid="C8C28B92-9326-4991-BFB1-BBDFDF3653AB">
      <File Id ="Banner.bmp" Source="Banner.bmp" KeyPath="yes" DiskId="1"/>
    </Component>
    <Merge Id ="DflHelpInstaller" SourceFile="DflHelpInstaller.msm" Language="1033" DiskId="1" />
      </Directory>
</Directory>

....

    <Feature Id="Complete" Title="Setup" Description="Installs the SDK on your local machine." Display="expand" Level="1" ConfigurableDirectory="INSTALLLOCATION">
      <ComponentRef Id="Banner" />
      <ComponentRef Id ="UNINSTALLER"/>
      <ComponentGroupRef Id="ReferenceGroup"/>
      <MergeRef Id="DflHelpInstaller"/>
</Feature>

CustomAction:

   public class CustomActions
   { 
        [CustomAction]
        public static ActionResult RegisterDflHelp(Session session)
        {
            session.Log("Begin CustomAction1");
            session.Log("Before Access to customactiondata");
 
            //should contain the installation path - unfortunately it is empty! why?
            string cad = session["CustomActionData"];
            Debugger.Break();


            RegisterHelp(cad);

            session.Log("End of custom action..");
            return ActionResult.Success;
        }

new Day, new Problem;-) Still got to struggle with managed custom action. I already managed it to call an custom action and passing some test data to it. Now I want to replace the testdata with the real data i need. And here the problems starts: I want to call a batch file which was installed in a subdirectory of my installation. Therefore i need to pass the installation path to the custom action. Afaik this can be done using the customactiondata mechanism. But this does not work. When I log the installation I can see that outside of the customaction INSTALLLOCATION is pointing to the correct path, but as soon as i look in the customaction the customactiondata property is empty...

What am I doing wrong?

Merge Module which calls the custom action:

<Module Id="DflHelpInstaller" Language="1033" Version="1.0.0.0">
    <Package Id="f952de58-1dc6-46b3-872a-7a49e2d9ea0a" Manufacturer="DflHelpInstaller" InstallerVersion="200" />

<Binary Id='RegisterDflHelpDll' SourceFile="$(var.REGISTERHELP.TargetDir)RegisterDflHelp.CA.dll" />

    <CustomAction Id='RegisterDflHelp' BinaryKey='RegisterDflHelpDll'  DllEntry='RegisterDflHelp' Execute='deferred' />

    <CustomAction Id="RegisterDflHelp.SetProperty" Return="check" Property="RegisterDflHelp" Value='[INSTALLLOCATION]' Execute='immediate' />

   
    <InstallExecuteSequence>
      <Custom Action='RegisterDflHelp.SetProperty' After='CostFinalize' />
      <Custom Action='RegisterDflHelp' After='InstallFiles' />
    </InstallExecuteSequence>

    <Directory Id="TARGETDIR" Name="SourceDir">
        </Directory>
    <ComponentGroupRef Id="HelpGroup"/>

    </Module>
</Wix>

Outline of the installer Project which use the MergeModule:

....

<Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="ProgramFilesFolder" SourceName="PFFiles">
<Directory Id="Company" Name='$(var.COMPANY)'>
  <Directory Id="INSTALLLOCATION" SourceName='$var.v[SDK_VERSION]'>
    <Component Id="MyBanner" Guid="C8C28B92-9326-4991-BFB1-BBDFDF3653AB">
      <File Id ="Banner.bmp" Source="Banner.bmp" KeyPath="yes" DiskId="1"/>
    </Component>
    <Merge Id ="DflHelpInstaller" SourceFile="DflHelpInstaller.msm" Language="1033" DiskId="1" />
      </Directory>
</Directory>

....

    <Feature Id="Complete" Title="Setup" Description="Installs the SDK on your local machine." Display="expand" Level="1" ConfigurableDirectory="INSTALLLOCATION">
      <ComponentRef Id="Banner" />
      <ComponentRef Id ="UNINSTALLER"/>
      <ComponentGroupRef Id="ReferenceGroup"/>
      <MergeRef Id="DflHelpInstaller"/>
</Feature>

CustomAction:

   public class CustomActions
   { 
        [CustomAction]
        public static ActionResult RegisterDflHelp(Session session)
        {
            session.Log("Begin CustomAction1");
            session.Log("Before Access to customactiondata");
 
            //should contain the installation path - unfortunately it is empty! why?
            string cad = session["CustomActionData"];
            Debugger.Break();


            RegisterHelp(cad);

            session.Log("End of custom action..");
            return ActionResult.Success;
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

逆光下的微笑 2024-08-19 12:15:54

如果您将数据描述为...

<CustomAction Id="MyCustomActionData" Return="check" Property="MyCustomAction" Value='PROPERTY0=[PROPERTY0];PROPERTY1=[PROPERTY1];PROPERTY2=[PROPERTY2]' Execute='immediate' />

您可以像这样访问数据:

string property0 = session.CustomActionData["Property0"];
string property1 = session.CustomActionData["Property1"];
string property2 = session.CustomActionData["Property2"];

在前面的示例中,您将使用:

<CustomAction Id="RegisterDflHelp.SetProperty" Return="check" Property="RegisterDflHelp" Value='INSTALLLOCATION=[INSTALLLOCATION]' Execute='immediate' />

然后

string cad = session.CustomActionData["INSTALLLOCATION"];

If you delineate your data like ...

<CustomAction Id="MyCustomActionData" Return="check" Property="MyCustomAction" Value='PROPERTY0=[PROPERTY0];PROPERTY1=[PROPERTY1];PROPERTY2=[PROPERTY2]' Execute='immediate' />

You can access the data like:

string property0 = session.CustomActionData["Property0"];
string property1 = session.CustomActionData["Property1"];
string property2 = session.CustomActionData["Property2"];

In the previous example you would use:

<CustomAction Id="RegisterDflHelp.SetProperty" Return="check" Property="RegisterDflHelp" Value='INSTALLLOCATION=[INSTALLLOCATION]' Execute='immediate' />

then

string cad = session.CustomActionData["INSTALLLOCATION"];
兲鉂ぱ嘚淚 2024-08-19 12:15:54

我在 .WXS 文件中使用以下内容完成了此操作:

<Directory Id="TARGETDIR" Name="SourceDir">
 <Directory Id="ProgramFilesFolder" Name="PFiles">
  <Directory Id="ManufacturerDir" Name="Company" ShortName="Company">
   <Directory Id="INSTALLDIR" Name="TheApp">
    <Directory Id="BatchFileLocation" Name="BatchFiles">
     <Component Id="BatchFilesComp" ... >
      <File Id="SomeFile_BAT" Source="BatchFiles\SomeFile.bat" Name="SomeFile.bat" ... />
     </Component>
    </Directory>
   </Directory>
  </Directory>
 </Directory>
</Directory>

在自定义操作中:

var batchDirectory = session.GetTargetPath("BatchFileLocation");
var batchFile = batchDirectory + "SomeFile.bat"

现在,我还没有弄清楚如何避免文件名重复,但这确实成功返回了批处理文件的安装位置。

I accomplished this using the following in the .WXS file:

<Directory Id="TARGETDIR" Name="SourceDir">
 <Directory Id="ProgramFilesFolder" Name="PFiles">
  <Directory Id="ManufacturerDir" Name="Company" ShortName="Company">
   <Directory Id="INSTALLDIR" Name="TheApp">
    <Directory Id="BatchFileLocation" Name="BatchFiles">
     <Component Id="BatchFilesComp" ... >
      <File Id="SomeFile_BAT" Source="BatchFiles\SomeFile.bat" Name="SomeFile.bat" ... />
     </Component>
    </Directory>
   </Directory>
  </Directory>
 </Directory>
</Directory>

And in the custom Action:

var batchDirectory = session.GetTargetPath("BatchFileLocation");
var batchFile = batchDirectory + "SomeFile.bat"

Now, I haven't yet figured out how to avoid the duplication of the filename, but this does successfully return where the batch file was installed.

南风起 2024-08-19 12:15:54

经过几个小时的努力,以下内容对我有用:

string UserDefinedInstallDir = session["INSTALLDIR"];

希望它对其他人有帮助!

After several hours of struglling, the following worked for me:

string UserDefinedInstallDir = session["INSTALLDIR"];

Hope it helps somenone else!

甜嗑 2024-08-19 12:15:54

您正确传递了值,但尝试用这种方式引用它。

        string[] keys = new string[session.CustomActionData.Keys.Count];
        session.CustomActionData.Keys.CopyTo(keys, 0);
        string cad = keys[0];

这应该将 cad 设置为您想要的安装路径。

Your passing the value correctly but try this way to reference it.

        string[] keys = new string[session.CustomActionData.Keys.Count];
        session.CustomActionData.Keys.CopyTo(keys, 0);
        string cad = keys[0];

This should set cad to the installation path like you want it.

稀香 2024-08-19 12:15:54

您是否尝试过直接从托管 CA 中查询 INSTALLLOCATION 属性?

string cad = session["INSTALLLOCATION"];

使用 DTF 的优点之一是您可以读/写访问所有 MSI 属性,而无需使用命令行等。因此,即使无法像普通属性一样查询 INSTALLLOCATION,您也可以定义自己的 MSI 属性,将其设置为INSTALLOCATION 的值并在您的 CA 内查询该值。

Have you tried querying the INSTALLLOCATION property directly from within the managed CA?

string cad = session["INSTALLLOCATION"];

One of the beauties of using DTF is that you have read/write access to all the MSI properties without having to use command-lines etc. So even if INSTALLLOCATION cannot be queried like a normal property you could define your own MSI property set it to the value of INSTALLOCATION and query that one inside your CA instead.

时光与爱终年不遇 2024-08-19 12:15:54

为了向 Session 对象添加新属性:

public static ActionResult CustomAction1(Session session)

以安装目录路径为例:

<Directory Id="ProgramFiles64Folder" Name="name">
            <Directory Id="INSTALLDIR" Name="name1">

只需添加一个新的 CustomAction 类型属性:

<CustomAction Id="CustomAction1.SetProperty" Return="check" Property="INSTALLDIR_PROP" Value='[INSTALLDIR]' Execute='immediate' />

并添加一个新的 InstallExecuteSequence

<Custom Action='CustomAction1.SetProperty' After='CostFinalize' />

然后在代码中您可以像这样访问这个新属性:

public static ActionResult CustomAction1(Session session)
{
        session.Log("MY NEW ADDED PROPERTY " + session["INSTALLDIR_PROP"]);

        return ActionResult.Success;
}

In order to add a new property to the Session object :

public static ActionResult CustomAction1(Session session)

with the installation directory path for example :

<Directory Id="ProgramFiles64Folder" Name="name">
            <Directory Id="INSTALLDIR" Name="name1">

Just add a new CustomAction of type property :

<CustomAction Id="CustomAction1.SetProperty" Return="check" Property="INSTALLDIR_PROP" Value='[INSTALLDIR]' Execute='immediate' />

And add a new InstallExecuteSequence

<Custom Action='CustomAction1.SetProperty' After='CostFinalize' />

Then in the code you access this new property like this :

public static ActionResult CustomAction1(Session session)
{
        session.Log("MY NEW ADDED PROPERTY " + session["INSTALLDIR_PROP"]);

        return ActionResult.Success;
}
与君绝 2024-08-19 12:15:54

WixSharp 的示例:

[CustomAction]
public static ActionResult RunAfterInstall(Session session)
{
    System.Diagnostics.Process process = new();
    process.StartInfo.FileName = string.Format("{0}\\{1}", session["INSTALLDIR"], $"\\{Definitions.AppName}.exe");
    //process.StartInfo.FileName = @$"%ProgramFiles%\{Definitions.AppName}";
    process.StartInfo.Arguments = "--start-notification";
    //process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
    process.Start();

    return ActionResult.Success;
}

Example for WixSharp:

[CustomAction]
public static ActionResult RunAfterInstall(Session session)
{
    System.Diagnostics.Process process = new();
    process.StartInfo.FileName = string.Format("{0}\\{1}", session["INSTALLDIR"], 
quot;\\{Definitions.AppName}.exe");
    //process.StartInfo.FileName = @
quot;%ProgramFiles%\{Definitions.AppName}";
    process.StartInfo.Arguments = "--start-notification";
    //process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
    process.Start();

    return ActionResult.Success;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文