About Windows Installer, the .NET Framework, and Visual Studio.
If you have authored a custom action into your installer package and are
annoyed by the console window that always pops up when the custom action runs,
it's because the custom action executable is running under the console
When you link your object files with the VC++ linker you can
specify the subsystem using the
/SUBSYSTEM switch. If you're using the C# or VB.NET compilers the
/target switch allows you to specify which subsystem to use for the
executable. However you specify the subsystem or however it's determined depending on
which entry point you use, you shouldn't use the console subsystem for custom
actions if you don't want the console window to appear, unless you have a good
reason for it. For example, maybe you just want to reuse a console application
that you're installing such as for
custom action type 18
or any custom action using msidbCustomActionTypeExe (0x01).
In most cases you should consider running under the Windows subsystem. No
window is created unless you create a window yourself and you can still
allocate a console if necessary.
If you already have a console EXE you want to use, you can cause the window
not to be displayed by passing certain parameters to APIs like the CreateProcess
function. When calling CreateProcess pass CREATE_NO_WINDOW (0x08000000).
WiX defines the CAQuietExec custom
action function that does this and redirects standard handles as well.
<CustomAction id=startsvc.command Value="[SystemFolder]net.exe start myservice" Property="QtExecCmdLine" /><CustomAction id=startsvc Return="check" Execute="immediate" DllEntry="CAQuietExec" BinaryKey="wixca" />...<Custom After="InstallInitialize" Action="startsvc.command">NOT Installed</CUSTOM><Custom After="startsvc.command" Action="startsvc">NOT Installed</Custom>
Madnad, there's several things wrong with that snippet.
First, if you're installing a service you should use both the ServiceInstall and ServiceControl tables not a custom solution with a command-line like this. It presents serviceability problems where if you use the ServiceInstall and ServiceControl tables you can properly reinstall and patch your service.
Second, immediate CAs should never modify system state.
Third, you scheduled your immediate CA after InstallInitialize. The file hasn't even been installed yet. InstallFiles is a deferred standard action that only gets scheduled between InstallInitialize and InstallFinalize and doesn't get processed until after InstallFinalize or any occurance of InstallExecute or InstallExecuteAgain. Windows error 2 would happen if the service doesn't exist. Try this: go to a machine where your product or service isn't installed and type "net start myservice". Now type "echo %errorlevel%" and you'll see 2 returned - the same error as you got back from the MSI custom action server in your log (wrapped in an HRESULT using the FACILITY_WIN32 (7) facility).
I highly recommend that you read all of the topic "Custom Actions" at http://msdn.microsoft.com/library/en-us/msi/setup/custom_actions.asp and child topics. For WiX information see http://wix.sourceforge.net. Look up the <ServiceInstall> and <ServiceControl> elements. Using these will schedule everything correctly and will help produce a more serviceable MSI.
heaths, thanks for the continued replies. I tried what you suggest but still get the 0002 error. I think it has to do with net.exe because when I change it to something like "notepad" it works. I took out all the params to net.exe so my code now looks like this (still does not work):
<Property id="QtExecDeferred" Value="c:\windows\system32\net.exe"></Property><CustomAction id="QtExecDeferred" Return="check" Execute="deferred" DllEntry="CAQuietExec" BinaryKey="wixca" />...<Custom After="InstallInitialize" Action="QtExecDeferred">NOT Installed</Custom>
So now I am not even referencing any of the files I am installing and still I get the error. I'm going nuts :)