Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MSI Installer cannot find InstallState when using custom action with parameters

First off, yes, I know that the VS Setup Projects are evil. It's what I have to work with. I've also seen several related questions, but they either go unanswered or they don't match my situation close enough for the answer to work (or they harp on about the evils of VS Setup Projects and the marvels of WiX).

I have an install project for my application. It worked just fine to copy files, but I needed to perform two custom actions after copying the files. I created an installer class and set it up as a custom action in the setup project, and the skeleton of it (which did no work, just showed a dialog so I could attach a debugger and look around) worked just fine. Then, I found I needed to pass parameters from the MSI to my custom action so I could access them via the Context property of the installer class.

Here's the current code of the installer class (some names have been changed to protect the innocent). It basically does nothing but show a dialog at the right time (after files are copied but before the installation is committed):

namespace MyApp.Install.CustomSetup
{
    [RunInstaller(true)]
    public partial class MyAppCustomInstallActions : System.Configuration.Install.Installer
    {
        public MyAppCustomInstallActions()
        {
            InitializeComponent();
        }

        protected override void OnAfterInstall(IDictionary savedState)
        {
            try
            {
                base.OnAfterInstall(savedState);
                if (MessageBox.Show(
                    "Custom Action OnAfterInstall successfully integrated. You can attach a debugger if desired. Do you wish to perform the custom actions?",
                    "DEBUG", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) return;

                SetEditablePermissionOnFolder(savedState);
                SetApplicationSettingsFromWizard(savedState);
            }
            catch (Exception ex)
            {
                Context.LogMessage(ex.ToString());
                throw;
            }
        }

        private void SetApplicationSettingsFromWizard(IDictionary savedState)
        { 
            //TODO: Implement
        }

        private void SetEditablePermissionOnViewerFolder(IDictionary savedState)
        {
            //TODO: Implement
        }
    }
}

The plan is to get the custom actions working, then take out the dialog and just do it.

Here is the string for CustomActionData for the Install action of the setup project's custom actions:

/phonenumber=[phonenumber] /thirdpartyinstallpath1="[thirdpartyinstallpath1]\" /thirdpartyinstallpath2="[thirdpartyinstallpath2]\" /thirdpartyinstallpath3="[thirdpartyinstallpath3]\"

If I do not use this parameter string, it's fine but I have no parameters. If I do specify this string, the installer fails before my own dialog box shows up, with two errors: "Exception occurred while initializing the installation: Could not load file or assembly 'file:///C:\Windows\SysWOW64\Files' or one of its dependencies. The system cannot find the file specified", and "Error 1001. Could not find file C:\Program Files (x86)\MyCompany\MyApp\MyApp.Install.CustomSetup.InstallState".

What am I doing wrong? Am I doing anything wrong? Is there a solution that doesn't require me to re-create an installer using some different framework?

EDIT: I found that removing everything but the phone number parameter, and putting [PHONENUMBER] in quotes, allows that parameter to be passed. However, I cannot pass any of the directory paths; I tried with [INSTALLDIR] exactly how several blogs and walkthroughs say to do it, no dice.

like image 347
KeithS Avatar asked Feb 15 '11 19:02

KeithS


4 Answers

I had a similar problem and solved it by:

On the properties of your custom action set InstallerClass to false.

like image 137
bplus Avatar answered Oct 18 '22 00:10

bplus


I found that the problem was in the format of the parameter string. Because the various parameters, though they were file paths, included the file name instead of ending in a backslash, I didn't need the trailing backslash to end those value strings. Because I did anyway, the ending quotes were treated as part of the string, which made the parser use the next opening quote as the end of the previous value, corrupting the whole parameter string. Because of this, InstallState couldn't be written correctly, and failed when the custom install logic tried to use it.

like image 30
KeithS Avatar answered Oct 18 '22 00:10

KeithS


If anyone gets this error after upgrading from VS2008 to VS2010 then check out this thread: http://social.msdn.microsoft.com/Forums/en-US/winformssetup/thread/829d5c90-9a0d-4258-9d4d-1341cc50f95b/

This solved the issue for me:

Change "BackwardCompatibleIDGeneration" to true on setup project properties.

like image 2
surfen Avatar answered Oct 18 '22 00:10

surfen


One thing I would make sure of is that my paths were escaped properly; either do it with

@"My Documents\Blah"

or

"My\ Documents\\Blah"
like image 1
Coder2000 Avatar answered Oct 18 '22 00:10

Coder2000