Dev
Dev

Reputation: 1020

Custom Action After InstallInitialize to check the Drive Existence

I have written a custom action in C# to check for the drive existence like below, I got stuck in between.

 [CustomAction]
    public static ActionResult MySimpleAction(Session session)
    {        
        if (Directory.Exists("F:\\"))
        {
            return ActionResult.Success;
        }
        else
        {
            return ActionResult.Failure;
        }
    }

And in wxs file, I am running the custom action as like below.

 <Binary Id="myAction" SourceFile="MyCustomAction.CA.dll" />
 <CustomAction Id="myActionId"
                  BinaryKey="myAction"
                  DllEntry="MySimpleAction"
                  Execute="immediate"
                  Return="check" />

<InstallExecuteSequence>
  <Custom Action="myActionId" After="InstallInitialize"  >  </Custom> 
</InstallExecuteSequence>

If I run the msi in the target machine where I have F:\ drive then installation succeeds, if the target machine doesn't have F:\ drive then Setup failed, I am getting error as "Setup wizard ended prematurely because of an error. Your system has not been modified."

What I am trying to do here is, if F:\ drive is available in the target computer (My Custom action succeeds), I want to set my root drive as F:\, and I want to install the application in F:\MyApp\Bin

     <Property Id="ROOTDRIVE"><![CDATA[F:\]]></Property>
     <Directory Id="TARGETDIR" Name="SourceDir">
       <Directory Id="INSTALLFOLDERLOCATION" Name="MyApp">
        <Directory Id="INSTALLLOCATION" Name="Bin">

if F:\ drive is not available in the target computer (My Custom action fails), I want to set my root drive as C:\, and I want to install in C:\MyApp\Bin

     <Property Id="ROOTDRIVE"><![CDATA[C:\]]></Property>
      <Directory Id="TARGETDIR" Name="SourceDir">
       <Directory Id="INSTALLFOLDERLOCATION" Name="MyApp">
        <Directory Id="INSTALLLOCATION" Name="Bin">

How can I set the root drive property by using this custom action? Thanks for the help!

Upvotes: 1

Views: 1524

Answers (3)

Dev
Dev

Reputation: 1020

I thank Christopher Painter and ChrisPatrick for helping me!!! the below code made the trick to work.

 [CustomAction]
    public static ActionResult MySimpleAction(Session session)
    {
        session.Log("DriveInfo Starts");
        DriveInfo[] drives = DriveInfo.GetDrives();
        foreach (DriveInfo d in drives)
        {
            if (d.Name.Contains("F") & d.IsReady == true & d.DriveType.ToString() == "Fixed")
            {                   
              session["TARGETDIR"] = "F:\\";                   
            }
            else
            {
                session["TARGETDIR"] = "C:\\";
                session.Log("No F:\\ Drive Found!!!!");                    
            }
        }
        session.Log("DriveInfo Ends");
        return ActionResult.Success;

And in the .wxs file,

  <Binary Id="myAction" SourceFile="MyCustomAction.CA.dll" />

   <Directory Id="TARGETDIR" Name="SourceDir">
   <Directory Id="INSTALLFOLDERLOCATION" Name="MyApp">
    <Directory Id="INSTALLLOCATION" Name="Bin">

     <CustomAction Id="myActionId" BinaryKey="myAction" DllEntry="MySimpleAction" Execute="immediate" Return="check" />

      <InstallUISequence>
      <Custom Action="myActionId" Before="CostFinalize" > NOT Installed </Custom>      
      </InstallUISequence>

Upvotes: 0

Christopher Painter
Christopher Painter

Reputation: 55581

You are on the right track. Here's what I do differently.

1) I use the DriveInfo class to see if the drive exists and it's of DriveType Fixed. (Not CDROM, USB Drive, Network....)

2) The custom action is scheduled in both the UI and Execute sequence after AppSearch and sets a property called something like InstallDirOverride. The custom action always returns ActionResult.Success.

3) I use a Set Property custom action (wxs element) to assign InstallDirOverride to INSTALLLOCATION (or INSTALLDIR... whatever you have called your main directory ) with the condition that INSTALLLOCATION doesn't yet have a value and InstallDirOverride does have a value and Not Installed. This custom action gets scheduled in both the UI Sequence and ExecuteSequence prior to CostInitialize.

The result of all this is an installer that defaults to C:\Program Files\My Company\My Product but changes it's behavior to default to something else based on the business rules in your C# custom action. This gives you the flexibility to default the way you want for a specific platform environment and yet still be complaint to Windows Standards when your platform is missing that resource.

Upvotes: 0

ChrisPatrick
ChrisPatrick

Reputation: 984

When using an immediate Custom Action, you can set property values by using session["PROPERTYNAME"] so in your case you could use session["ROOTDRIVE"] = "F:\\"; in your Custom Action.

The reason it's failing at the moment is that you are returning a Failure message from your custom action, and since you have specified Return="check", the installer checks the return value, and fails the install if the Custom Action has failed.

Upvotes: 2

Related Questions