Search code examples
c#wixwindows-installercustom-action

WiX Toolset: How to store a file from Binary Table in a Custom Action


I want to store a file from Binary table to temp location in Custom Action. I have two Custom actions, first is 'immediate', another one is 'deferred'.

When during run of the 'immediate' custom action I invoke Microsoft.Deployment.WindowsInstaller.Record.GetStream method, it does not save the file.

[CustomAction]
public static ActionResult ImmediateAction(Session session)
{
    try
    {
        View view = db.OpenView("SELECT Name, Data FROM Binary");
        view.Execute();

        foreach (Record row in view)
        {
            row.GetStream("Data", Path.Combine(Environment.GetEnvironmentVariable("temp"), row.GetString("Name"));
        }

        return ActionResult.Success;
    }
    catch (Exception ex)
    {
        session.Log(ex.Message);
        return ActionResult.Failure;
    }
    finally
    {
        db.Close();
    }
}

The Custom Action works without errors, but the file does not get being created.

Update:

In the InstallExecuteSequence the Custom Action described like:

    <InstallExecuteSequence>
       <Custom Action="ImmediateAction"
             Before="DeferredAction">
          NOT Installed
        </Custom>

        <Custom Action="DeferredAction"
             After="InstallInitialize">
          NOT Installed
        </Custom>
   </InstallExecuteSequence>

From the 'deferred' custom action I am not able to get the db view, which is expected. And, I am not able to pass the File's binary data from 'immediate' to 'deferred' Custom Action since System.IO.Stream class does not support serialization.


Solution

  • Excellent Alex. Thanks for the feedback. The solution to the original question was to call the Fetch() method of the View() object: https://msdn.microsoft.com/en-us/library/windows/desktop/aa372509(v=vs.85).aspx

    tempFile = Path.GetTempFileName(); 
    using (View binaryView = session.Database.OpenView("SELECT Name, Data FROM Binary")) 
    { 
        binaryView.Execute(); 
        using (Record binaryRec = binaryView.Fetch()) 
        { 
            binaryRec.GetStream(2, tempFile); 
        } 
    }