/build/static/layout/Breadcrumb_cap_w.png

Suppress Custom Action EXE

Hi all,

finally starting to somewhat get a hang of Windows Installer.I have a custom action that runs an executable in the system32 directory (ServerManagercmd.exe) to install IIS. My conditions are fine as it is running however I'd this executable brings up a cmd-prompt progress window. I'm wondering if there's a way to suppress it?

1 Comment   [ + ] Show comment

Answers (20)

Posted by: spartacus 15 years ago
Black Belt
1
Seems like a good time to post and article I wrote on this subject some time ago. It is geared towards InstallShield users, but can easily be adapted for WISE &c.

Background

From time to time it is convenient to create a custom action that calls (say) an executable that is already part of the Operating System but which runs in the COMMAND subsystem. One example might be to call the NET.EXE executable to stop a service (OK, I know it's not a great example as you should be using the ServiceControl table here [;)])

The custom action might, for example, call NET.EXE as follows :

C:\Windows\System32\NET.EXE STOP SPOOLER

The problem with commands like these is that when the Custom Action executes, a command window usually appears on the screen and, besides generally looking untidy, may cause confusion to the end user during installation.

This article outlines a method that can be used to invoke the executable to run under the Windows subsystem and not the Command subsystem and thereby avoids the appearance of the command window.

Method

The method devised makes use of wixca.dll, a DLL supplied in the WiX toolset. If you don't already have it you can download the full WiX tookit from this link

http://sourceforge.net/project/downloading.php?group_id=105970&use_mirror=garr&filename=wix-2.0.5805.0-binaries.zip&85039060

We only need the one DLL from the toolkit, so use WinZip or similar to extract the wixca.dll file from the download.

1) Now establish what the exact command is you wish to run. The command must contain a quoted path to the executable, followed (optionally) by any parameters.

For example, if we wish to stop the Print Spooler service, the command would be :

"C:\Windows\System32\NET.EXE" STOP SPOOLER

2) In your package, create a property named QtExecCmdLine and set the value of this property to the command line in exactly the format shown above.

3) In InstallShield editor, launch the custom action wizard, Click Next then assign the custom action a name plus (optionally) any comments. In my example I will name the custom action StopSpooler and leave the comments blank

4) Click Next, then in the Type field select "Call a function in a Windows Installer dynamic-link library" and click Next

5) In the source field browse to the wixca.dll file you extracted earlier. In the target field enter CAQuietExec then click Next

6) Leave the Return Processing field as Synchronous(Check Exit Code) and click Next

7) Leave the In-Script Execution as Immediate Execution and Execution Scheduling as "Always Execute" and click Next

8) Leave the Install UI Sequence as <Absent from Sequence> and set the Install Execute Sequence field to the desired position in the sequence (e.g. just before InstallFinalize). Apply any Install Execute conditions you need to (e.g. NOT REMOVE~="ALL") then click Next.

9) Click Finish.

Thats all there is to it. When the CA runs, you will no longer see a command box, but with verbose logging enabled you will be able to see any output the command created in the MSI log file - very useful for troubleshooting !

Deferred Mode

If you wish to run your command in deferred mode, then at step 2, enter a property name of your own choice to hold the command string and make sure (at Step 3) that your custom action is named the same as the property name you chose. This will then instruct the DLL to use the CustomActionData method to determine the command line it needs to execute.

(Dont forget to place the custom action between InstallInitialize and InstallFinalize)

Further information can be found at the following link :
http://wix.sourceforge.net/manual-wix2/qtexec.htm

Regards,
Spartacus
Posted by: shweta_kar 15 years ago
Blue Belt
0
Hi,
Use intWindowStyle while using Run Method.
e.g. Wshshell.Run(path of the setup,0,True)






intWindowStyle Description



0 Hides the window
and activates
another window.
Posted by: anonymous_9363 15 years ago
Red Belt
0
You assume that the OP is running a VBScript-based CA which may not necessarily be the case.
Posted by: jayteeo 15 years ago
Purple Belt
0
Thanks for responding guys.. VBScab was correct in saying that the custom action is running an EXE from its destination. I did as suggested write a VBScript to run the install, however the install fails. Strangely even when I tell it to ignore the exit code and to run asynchronously.

Here is my script:

'Create Shell Object
Dim WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
'Set Style Property
Dim WindowStyle
WindowStyle = 4 '0 for hidden, 4 to show it
Dim intExitCode
Dim Executable, Parameters
Executable = "ServerManagerCmd.exe"
Parameters = "-install Web-Server"
intExitCode = WshShell.Run(Executable & " " & Parameters, _
WindowStyle, True)

When I run it from cscript, it actually runs fine. The verbose logging doesn't tell me anything besides that the script did not run successfully. Do you guys see something in my script that WISE would complain about? I will read the article linked above. TIA.
Posted by: jayteeo 15 years ago
Purple Belt
0
Sparticus - Appreciate your response. Would rather avoid having to include additional files (i.e. the WiX DLL you mentioned).
Posted by: anonymous_9363 15 years ago
Red Belt
0
Why on earth you are making this more complicated escapes me but anyway...

Change this:Set WshShell = WScript.CreateObject("WScript.Shell") to this:Set WshShell = CreateObject("WScript.Shell")You cannot use the WScript directive, as it is unique to Window Scripting Host, whereas the Windows Installer engine has its own host for VBScript.
Posted by: jayteeo 15 years ago
Purple Belt
0
VBScab - What should I do to make it less complicated? If there is a way to do this with a Custom Action using an EXE from its location, please let me know.
Posted by: spartacus 15 years ago
Black Belt
0
ORIGINAL: jayteeo

Sparticus - Appreciate your response. Would rather avoid having to include additional files (i.e. the WiX DLL you mentioned).


Just to clarify, the WiX DLL will not be deployed to the target system *permanently* if used in the method I described. It is just a resource that sits in the Binary table of the package. During installation, it will be extracted to a temporary folder when needed by the custom action and then discarded.

Also, last time I looked, it was about 110 KBytes, so the impact on the overall size of the MSI would also be minimal should you decide to use it.

Regards,

Spartacus
Posted by: jayteeo 15 years ago
Purple Belt
0
Thanks sir. Will keep it in mind if I ever need it. VBScript method is working just fine now.
Posted by: anonymous_9363 15 years ago
Red Belt
0
What should I do to make it less complicated? You could always prefix your command with opening a CMD window but with the '/C' switch. Thus, the command window would open, kick off the EXE, then exit immediately. You'd see a DOS window briefly but not for the duration of the EXE's execution.

Also, you can install IIS using the same command string that 'Control Panel\Add/Remove Programs\Add/Remove Windows Components' does (using sysocmgr.exe) but silently. http://technet.microsoft.com/en-us/library/cc758047.aspx
Posted by: jayteeo 15 years ago
Purple Belt
0
Hi VBScab,

One of the first things I tried was calling cmd.exe with the /c switch. This would only work if the executable being called does not open its own cmd-style window (which ServerManagerCmd.exe does).

Additionally, sysocmgr is not a good option for our intentions. This MSI package not only will install IIS but also install the FTP component, which is dependent on IIS being installed. Sysocmgr exits immediately after execution while IIS installs in the background thus the FTP install will not be blocked and execute immediately which results in an error.
Posted by: jayteeo 15 years ago
Purple Belt
0
K.. I made the assumption that my vbscript would work but am getting an unexpected error.

Error 1720. There is a problem with this Windows Installer package. A script required for this install to complete could not be run. Contact your support personnel or package vendor. Custom action Instasll_IIS_7 script error -2147024894, : Line 14, Column 1,

I've been pulling my hair out on this one..what does it not like about the script?

'Create Shell Object
'Set Style Property
Dim WindowStyle
WindowStyle = 4 '0 for hidden, 4 to show it
Dim intExitCode
Dim Executable, Parameters

Executable = "ServerManagerCmd.exe"
Parameters = "-install Web-Server"
Set WshShell = CreateObject("WScript.Shell")
intExitCode = WshShell.Run("C:\Windows\System32\ServerManagerCmd.exe -install Web-Server", 4, True)

Also, I was getting a different error before. Something to the effect of WshShell was not an object instance ("object needed for WshShell"). I got around this error by removing my variable declartion in the beginning of the script. Why does Wise complain when I explicitly declare WshShell?

PS - I do realized there are some unused variables there, this was due to me trying to fix the problem I'm encountering
Posted by: anonymous_9363 15 years ago
Red Belt
0
-2147024894 converts to 'FFFFFFFF80070002' in hex. Throw away the junk and we get down to '2'. DOS error 2 equates to 'File not found', probably because it's looking for a file called "C:\Windows\System32\ServerManagerCmd.exe -install Web-Server". You need to alter the command line you're running.

Once again, my assertion that QAD scripts will always catch out the unsuspecting is vindicated. If you had built in proper error-trapping from the beginning, your script would check for the existence of 'C:\Windows\System32' then for 'ServerManagerCmd.exe' before attempting to run the EXE. In that process you would end up with variables which you could re-use in your command line.
Posted by: jayteeo 15 years ago
Purple Belt
0
You are correct- I was able to figure out the error and the root cause of the problem. Once I had gotten the script working, I had intended on catching the exit code and the standard/error output of running the script. If the script fails, display the oerror output in a dialog box.

ServerManagerCmd actually does reside in System32. However, I am running this on a 2k8 box. The problem is MSIExec runs under the 32-bit subsystem whose System32 folder does not contain the executable. I need to some how direct MSIExec to access the Sysnative folder. Have you heard of people running into this problem?
Posted by: jayteeo 15 years ago
Purple Belt
0
Got it.. changed the path to %Windir%\SysNative
Posted by: AngelD 15 years ago
Red Belt
0
spartacus,

Could you specity the Custom Action type that corresponds to "Call a function in a Windows Installer dynamic-link library"?

/Kim
Posted by: ahcash 15 years ago
Orange Belt
0
spartacus, your guide is excellent. Thanks.
Posted by: spartacus 15 years ago
Black Belt
0
Call a function in a Windows Installer dynamic-link libraryORIGINAL: AngelD

spartacus,

Could you specity the Custom Action type that corresponds to "Call a function in a Windows Installer dynamic-link library"?

/Kim


Yes Kim, it is a type 1 custom action.

Regards,

Spartacus
Posted by: AngelD 15 years ago
Red Belt
0
Thanks Graham for providing this nice article!
Worked beautiful, a golden star to you :)

/Kim
Posted by: turbokitty 15 years ago
6th Degree Black Belt
0
Nice one Graham.

I wish regular folks would understand how hard it is to do something so seemingly simple.
Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.
 
This website uses cookies. By continuing to use this site and/or clicking the "Accept" button you are providing consent Quest Software and its affiliates do NOT sell the Personal Data you provide to us either when you register on our websites or when you do business with us. For more information about our Privacy Policy and our data protection efforts, please visit GDPR-HQ