Starting Managed Custom Actions (starting Installer Class and its C# Code located in an Assembly during installation)

by Markus 2. November 2009 21:37

  

Starting Managed Custom Actions

(starting Installer Class and its C# Code located in an Assembly during installation)

 

Starting Managed Code during an installations is considered BAD STUFF by the MSI Team!!!!

  

So use it only if you really need to… Lots of articles can be found if you use google on this… The Main point is, that if the Framework is deinstalled before your product and you call a Managed Custom Action during the removal – it will fail… So your product can NOT be uninstalled any more…

  

But still it is possible:

Usefull Links:

 

Step 1

  • Create a C# ClassLibrary Project in Visual Studio.
  • Add a Installer Class to the Project
  • Override the Functions you need like:

public override void Install(IDictionary savedState) {
    string isUpgrade = Context.Parameters["IsUpgrade"];

    var f = new InstallerForm("Install", savedState, isUpgrade);
    f.ShowDialog();
    base.Install(savedState);
}

public override void Uninstall(IDictionary savedState) {
    string isUpgrade = Context.Parameters["IsUpgrade"];

    var f = new InstallerForm("Uninstall", savedState, isUpgrade);
    f.ShowDialog();
    base.Uninstall(savedState);
}

public override void Commit(IDictionary savedState) {
    string isUpgrade = Context.Parameters["IsUpgrade"];

    var f = new InstallerForm("Commit", savedState, isUpgrade);
    f.ShowDialog();
    base.Commit(savedState);
}

public override void Rollback(IDictionary savedState) {
    string isUpgrade = Context.Parameters["IsUpgrade"];

    var f = new InstallerForm("Rollback", savedState, isUpgrade);
    f.ShowDialog();
    base.Rollback(savedState);
}

 

Step 2

 

Add an App.config File to Your Project and place the Following Tags there:

<configuration>
  <startup>
    <supportedRuntime version="v2.0.50727" />
  </startup>
</configuration>

 

Step 3

Define the following Custom Actions in your product.wxs

  

<!--Define Custom Actions for calling the Project Installer in AP1ServiceDienst.exe with installUtilLib-->
<Binary Id='InstallUtil' SourceFile='C:\windows\Microsoft.NET\Framework\v2.0.50727\InstallUtilLib.dll' />

<CustomAction Id='Uninstall' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='deferred'  Impersonate='no'/>
<CustomAction Id='UninstallSetProp' Property='Uninstall' Value=' /PreviousFound="[PREVIOUSFOUND]" /DP_TargetDir="[APPLICATIONROOTDIRECTORY]\" /installtype=notransaction /action=uninstall /LogFile= "[#TheTesterSetupManagerDLL.dll]" "[#TheTesterSetupManagerDLL.dll.config]"' />

<CustomAction Id='Install' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='deferred' Impersonate='no' />
<CustomAction Id='InstallSetProp' Property='Install' Value=' /PreviousFound="[PREVIOUSFOUND]" /DP_TargetDir="[APPLICATIONROOTDIRECTORY]\" /installtype=notransaction /action=install /LogFile= /BinDir="[TARGETDIR]\" /Package="[ProductName]" "[#TheTesterSetupManagerDLL.dll]" "[#TheTesterSetupManagerDLL.dll.config]"' />

<CustomAction Id='Rollback' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='rollback'  Impersonate='no'/>
<CustomAction Id='RollbackSetProp' Property='Rollback' Value=' /installtype=notransaction /action=rollback /LogFile= "[#TheTesterSetupManagerDLL.dll]" "[#TheTesterSetupManagerDLL.dll.config]"' />

<CustomAction Id='Commit' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='commit' Impersonate='no' />
<CustomAction Id='CommitSetProp' Property='Commit' Value=' /installtype=notransaction /action=commit /LogFile= "[#TheTesterSetupManagerDLL.dll]" "[#TheTesterSetupManagerDLL.dll.config]"' />

Note: If the complete string for value is getting to long for the MSI Table the custom Action is NOT started any more. During compile of your project you will see a warning, that a string is to long. You have to reduce the amount of parameters to fix this problem, otherwise the setup will NOT work at all!

Step 4

Schedule the Actions

  

<InstallExecuteSequence>

……..


  <!--Schedule calling InstalDBDll-->
  <Custom Action="InstallSetProp" After="StartServices">(NOT Installed)</Custom>
  <Custom Action="Install" After="InstallSetProp">(NOT Installed)</Custom>

  <Custom Action="UninstallSetProp" After="MsiUnpublishAssemblies">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
  <Custom Action="Uninstall" After="UninstallSetProp">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>

  <Custom Action="CommitSetProp" After="Rollback">(NOT Installed)</Custom>
  <Custom Action="Commit" After="CommitSetProp">(NOT Installed)</Custom>

  <Custom Action="RollbackSetProp" After="Install">(NOT Installed)</Custom>
  <Custom Action="Rollback" After="RollbackSetProp">(NOT Installed)</Custom>

</InstallExecuteSequence>

  

Step 5 (optional)

If you want to avoid problems during uninstall, for example, if the user deleted the program files by hand before uninstalling the product than you need to look if the assemblies containing the custom actions are still there before calling them.

 

First you need to do a file search

<!--****************************************************************************************-->
<!--Check if the Files are still there -->
<!--****************************************************************************************-->
<Property Id="CUSTOMACTIONDLLFILEEXISTS">
  <DirectorySearch Id="CheckFileDir" Path="C:\program files\" Depth="2" AssignToProperty="yes">
    <FileSearch Id="CheckFile" LongName="TheTesterSetupManagerDLL.dll" />
  </DirectorySearch>
</Property>

Note: I tryed using the TARGETDIR or APPLICATIONROOTDIRECTORY Property instead of c:\programm files but they are all set after AppSearch und uninstall. If anybody has a solution for this please comment it!!!

 

Second you need to launch the Custom Action only if the file is present

Add the following Condition to your Uninstall Custom Action: (in Red)

<Custom Action="UninstallSetProp" After="MsiUnpublishAssemblies">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") AND (NOT CUSTOMACTIONDLLFILEEXISTS="")</Custom>
<Custom Action="Uninstall" After="UninstallSetProp">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") AND (NOT CUSTOMACTIONDLLFILEEXISTS="")</Custom>

Note: If the File is Found the CUSTOMACTIONDLLFILEEXISTS contains the FolderPath

 

Third: Ignore the Return Code on the Unistall Action

This is optional but it will uninstall the product also if an error occurs in your custom action…

Add the following Attribute to the Uninstall Custom Action: (In Red)

<CustomAction Id='Uninstall' Return='ignore' BinaryKey='InstallUtil' DllEntry='ManagedInstall' Execute='deferred'  Impersonate='no'/>

 

<= Back to Content

Tags:

About MaHop.Net

Just look on our Webpage http://www.mahop.net

Tag cloud