I have some problems with managed code custom actions. I have 3 custom actions but only one of them is working. They are called at different times in InstallExecuteSequence but moving them makes no difference. I know there not getting very far because if I place a message box at the beginning of the routine(for debugging) it never get called . Where am I going wrong ? The actions are created like so.
<Binary Id="CA" SourceFile="$(var.ca.Custom.Actions.TargetDir)$(var.ca.Custom.Actions.TargetName).CA.dll" />
<CustomAction Id="WriteRemoveArpEntry" Property="CustomActionData" Value="PNAME=$(var.ProductName)" HideTarget="yes" />
<CustomAction Id="RemoveArpEntry" BinaryKey="CA" DllEntry="RemoveProductFromARP" Return="ignore" />
<CustomAction Id="SetValueforProductFolder" Property="CustomActionData" Value="SDIR=[INSTALLDIR];TDIR=[MANUDIR]\backup\$(var.ProductName)\$(var.VersionNumber)" HideTarget="yes" />
<CustomAction Id="Backup_Product_DIR" BinaryKey="CA" DllEntry="BackupDIR" Return="ignore" />
<CustomAction Id="WriteInstallAttemptData" Property="CustomActionData" Value="PRODUCTNAME=$(var.ProductName);APPVERSION=$(var.VersionNumber)" HideTarget="yes" />
<CustomAction Id="WriteInstallAttempt" BinaryKey="CA" DllEntry="WriteXMLServer" Return="ignore" />
I then call them here
<Custom Action="SetValueforProductFolder" Before="Backup_Product_DIR">NOT Installed AND NOT REMOVE</Custom>
<Custom Action="Backup_Product_DIR" Before="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
<Custom Action="WriteRemoveArpEntry" Before="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
<Custom Action="RemoveArpEntry" After="WriteRemoveArpEntry">NOT Installed AND NOT REMOVE</Custom>
<Custom Action="WriteInstallAttemptData" After="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
<Custom Action="WriteInstallAttempt" After="WriteInstallAttemptData">NOT Installed AND NOT REMOVE</Custom>
</InstallExecuteSequence>
The headers for the routines look like this
public static ActionResult BackupDIR(Session session)
{
public static ActionResult RemoveProductFromARP(Session session)
{
Public static ActionResult WriteXMLServer(Session session)
{
However only WriteXMLServer works. In the log file I get the following .
MSI (s) (BC:9C) [07:23:45:562]: Invoking remote custom action. DLL:
C:\Windows\Installer\MSI2E2A.tmp, Entrypoint: BackupDIR CustomAction
Backup_Product_DIR returned actual error code 1154 but will be
translated to success due to continue marking
In the one that works I get
MSI (s) (BC:A0) [07:24:25:994]: Invoking remote custom action. DLL:
C:\Windows\Installer\MSICC20.tmp, Entrypoint: WriteXMLServer SFXCA:
Extracting custom action to temporary directory:
C:\Windows\Installer\MSICC20.tmp-\ SFXCA: Binding to CLR version
v4.0.30319
The answer was very simple I forgot the
[CustomAction]
For the other two routines.
Related
So I created this customAction that gets me the path of another app using Registries
string value = Registry.GetValue(userRoot, key, -1).ToString();
session["INSTALLLOCATION"] = value;
And it works. The problem is how I send it back to the .wxs file and set the installation path of something to be that string value. I have this thing in the Wix file:
<CustomAction Id="CustomAction" Property="CustomAction2" Value="path=[INSTALLLOCATION]" />
<Binary Id="CustomActionBinary" SourceFile="$(var.ProAdmin_TargetDir)ExtractRegistryPath\bin\Debug\ExtractRegistryPath.CA.dll"/>
<CustomAction Id="CustomAction2" Impersonate="no" BinaryKey="CustomActionBinary" DllEntry="CustomAction1" Return="check" Execute="deferred"/>
<InstallUISequence>
<Custom Action="CustomAction" Before="CustomAction2" />
<Custom Action='CustomAction2' Before="ExecuteAction" />
</InstallUISequence>
This thing throws an 2762 error code.
You're getting error 2762 because you can't have deferred actions in the InstallUISequence. The custom action that populates the INSTALLLOCATION property should be called at the beginning of both the InstallUISequence and InstallExecuteSequence as an 'immediate' action - and - INSTALLLOCATION should be a folder in the Directory table.
Passing the PATH to custom action
<Property Id="ModifyConfig" Value="PATH=[PATH]"/>
<CustomAction Id='ModifyConfig'
BinaryKey="WebAppCA"
DllEntry="ModifyConfig"
Execute="deferred"
Return="check"
HideTarget="no"
Impersonate="no"/>
<InstallExecuteSequence>
<Custom Action="ModifyConfig" After="InstallFiles"></Custom>
</InstallExecuteSequence>
My custom action
[CustomAction]
public static ActionResult ModifyConfig(Session session)
{
string PATH = session.CustomActionData["PATH"];
FileInfo file = new FileInfo(PATH + "appsettings.json");
session.Log("PATH: " + PATH);
session.Log("Search for configuration file " + file.FullName);
}
When custom action executes I get following in log:
PATH: C:\MyPath\
Search for configuration file C:\WINDOWS\Installer\MSIE38D.tmp-\C:\MyPath\appsettings.json
How it can be and how I can get the file?
EDIT: This works good - Execute="immediate" and After="InstallFinalize"
<CustomAction Id='ModifyConfig'
BinaryKey="WebAppCA"
DllEntry="ModifConfig"
Execute="immediate"
Return="check"/>
<InstallExecuteSequence>
<Custom Action="ModifyConfig" After="InstallFinalize"></Custom>
</InstallExecuteSequence>
I have a CustomAction written in C#. I want to call the DllEntry twice in my wix installer code. How can I achieve this?
I am doing this in the following manner. But this is working for me. Is there any other fair way to do this?
C# Code:
[CumtomAction]
public static ActionResult SymbolicLink(Session session)
{
string s1=session.CustomActionData["value1"];
string s2=session.CustomActionData["value2"];
//mycode;
}
WixCode:
<CustomAction Id="ca" Property="dllCA" Value="value1='one';value2='two'" />
<CustomAction Id="dllCA" BinaryKey="InstallerLibrary" DllEntry="SymbolicLink" Execute="deferred"/>
<CustomAction Id="ca1" Property="dllCA1" Value="value1='three';value2='four'" />
<CustomAction Id="dllCA1" BinaryKey="InstallerLibrary" DllEntry="SymbolicLink" Execute="deferred"/>
<InstallExecuteSequence>
<Custom Action="ca" Before="InstallFinalize"></Custom>
<Custom Action="dllCA" After="ca"></Custom>
<Custom Action="ca1" Before="InstallFinalize"></Custom>
<Custom Action="dllCA1" After="ca1"></Custom>
</InstallExecuteSequence>
Defining it once should be suffice, ensuring you are setting the property correctly before you make the call to the SymbolicLink custom action:
<CustomAction Id="ca" Property="SymbolicLink" Value="value1='one';value2='two'" />
<CustomAction Id="ca1" Property="SymbolicLink" Value="value1='three';value2='four'" />
<CustomAction Id="dllCA" BinaryKey="InstallerLibrary" DllEntry="SymbolicLink" Execute="deferred"/>
<InstallExecuteSequence>
<Custom Action="ca" Before="InstallFinalize"></Custom>
<Custom Action="dllCA" After="ca"></Custom>
<Custom Action="ca1" Before="InstallFinalize"></Custom>
<Custom Action="dllCA" After="ca1"></Custom>
</InstallExecuteSequence>
I've read How do I pass msiexec properties to a WiX C# custom action? , but that didn't answer my question, or maybe I just don't see what I am doing wrong.
My install package fails to install, and the logs say that my property wasn't found in the custom actions collection. My code is:
<CustomAction Id="SetCustomActionDataValue" Return="check" Property="Itp.Configurator.WixCustomAction" Value="G=G2" />
<CustomAction Id="CreateDatabase" BinaryKey="Binary1" DllEntry="CreateDatabase" Execute="deferred" Return="check" />
<InstallExecuteSequence>
<Custom Action='SetCustomActionDataValue' After="InstallFiles"/>
<Custom Action='CreateDatabase' After="SetCustomActionDataValue">
NOT Installed AND NOT PATCH
</Custom>
</InstallExecuteSequence>
And code inside the custom action is:
string Property1 = session.CustomActionData["G"];
The name of the property in your first element must be exactly the same as the name of the deferred custom action you'd like to pass the value to. So, if the deferred action is CreateDatabase, then the first element should look like this:
<CustomAction Id="SetCustomActionDataValue" Return="check" Property="CreateDatabase" Value="G=G2" />
i got a problem regarding wix and managed custom actions: I already managed it to create an managed custom action and got it called from my installer (verified it in the installation log files). My Problem is now that i did't manage it to pass data to the custom action. Afaik if i choose to run the custom action in such a late stage i must mark the action as "deferred". With this limitation it's only possible to access the CustomActionData Property right? Why does this not work in my case? (As far as i can see i adoptet everything correctly from the samples?)
Here is what i already tried:
Custom Action:
public class CustomActions
{
[CustomAction]
public static ActionResult RegisterDflHelp(Session session)
{
session.Log("Begin CustomAction1");
session.Log("Before Access to customactiondata");
//string helpdir = session["HELP_DIR"];
string cad = session["CustomActionData"];
Debugger.Break();
session.Log("Help dir is: " + helpdir);
session.Log("Custom Action Data is: " + cad);
return ActionResult.Success;
}
}
Merge Module which calls custom action:
<CustomAction Id='RegisterDflHelp' BinaryKey='RegisterDflHelpDll' DllEntry='RegisterDflHelp' Execute='deferred' />
<CustomAction Id="HELP_DIR.SetProperty" Return="check" Property="HELP_DIR" Value="Teeest" />
<Property Id='HELP_DIR' Secure='yes'/>
<InstallExecuteSequence>
<Custom Action='HELP_DIR.SetProperty' After='InstallFiles' />
<Custom Action='RegisterDflHelp' After='HELP_DIR.SetProperty' />
</InstallExecuteSequence>
<Directory Id="TARGETDIR" Name="SourceDir">
</Directory>
<ComponentGroupRef Id="HelpGroup"/>
Product which includes Help-Merge Module:
<Product....>
<Package....>
...
<Directory>
<!--Directory which gets the help folder--!>
<Merge Id ="DflHelpInstaller" SourceFile="DflHelpInstaller.msm" Language="1033" DiskId="1" />
Anyone an idea? Thanks in advance!!
Daniel
Btw: What would also be interesting to know: At which stage in the installationprocess must an action marked as deferred? And if i managed it to call my custom action before this stage. Whats the advantage?
You are still setting the HELP_DIR property instead of the custom action data. If you are trying to set the CustomActionData for the RegisterDfHelp action to "Teeest", then I think you should do this:
<CustomAction Id="SetRegisterDflHelpCustomActionData" Return="check"
Property="RegisterDflHelp" Value="Teeest" />
<InstallExecuteSequence>
<Custom Action='SetRegisterDflHelpCustomActionData' After='InstallFiles' />
<Custom Action='RegisterDflHelp' After='SetRegisterDflHelpCustomActionData' />
</InstallExecuteSequence>
somethimes using your head really helps;-)
the reason why the sample above does not work is quite simple:
Instead of:
CustomAction Id="HELP_DIR.SetProperty" Return="check" Property="HELP_DIR" Value="Teeest" />
I head to set the Property Attribute to the Action which should get the custom data!! here:
<CustomAction Id="HELP_DIR.SetProperty" Return="check" Property="RegisterDflHelp" Value="$(var.HelpSourceDir)" />
Hope that helps others to save the time i spend to solve this silly problem;-)