Custom action of Wix failed to call vb script

2019-01-29 01:20发布

问题:

I have one VB script in the package itself. I need to call it using CMD, the default way of calling the script taking too much time, so I am trying to call it with CMD and CSCRIPT but the installer raises the error while installation.

I am using the following code which is not working as expected. I searched a lot but didn't find the solution.

<Binary Id="ServiceInstall"  SourceFile="..\..\..\AddVirDir.vbs" />

 <CustomAction Id="InstallService" BinaryKey ="ServiceInstall" 
               ExeCommand="CMD /C &quot;[#ServiceInstall]&quot;" 
               Execute="immediate" Return="check"  HideTarget="no" Impersonate="no"/>

回答1:

WiX IIS Elements: If this is all IIS, I would avoid scripting and custom actions whenever possible and use WiX's built-in IIS elements. Here is a Web-installer sample from Rainer Stropek available on github.com.

Look for <iis:WebVirtualDir ... /> et al. Find the WiX Documentation here. I believe you should be able to accomplish what you need without too many custom actions.

DISM.exe: Stropek himself uses custom actions in another sample source to set up IIS using DISM.exe. Not sure I would do it like this (no other suggestions though), but it is a sample of custom actions and IIS.


Need-For-Speed: As to your installation performance issues. Maybe you need to suppress the creation of a restore point and limit file costing? The Windows Installer engine allows this - see link below. I doubt it will be very effective though. I think there must be something else wrong in your installer. Some timeout issue? It could relate to other custom actions, slow network, or some other issue. Can you elaborate on your deployment scenario?

In any case, here is some documentation on speeding up MSI installations in general. Essentially the MSIFASTINSTALL property is the only one I would recommend. DISABLEROLLBACK can cause genuine problems.


Logging: I normally recommend that setup developers enable default verbose MSI logging - as described in the "Globally for all setups on a machine" section, to always have a log file ready when you need one. It is created with a random name for every MSI operation in the TEMP folder and you sort by modify to get the latest one. The log file might give clues as to why the installation is slow - just determine what is really going on. Apologies if this is just obvious trifles and you have this set up already.

Manual log file creation:

msiexec.exe /i C:\Path\Your.msi /L*v C:\Your.log

Interpreting an MSI log: interpreting a log file can be challenging sometimes. Here is an answer with some links to help with this.



回答2:

Service Installation & Control: You should not install services with scripts. There are built-in mechanisms in MSI that are vastly superior. You simply use the ServiceInstall and ServiceControl WiX XML Elements and "declare" how the service should be registered and when and how the service should be started and stopped:

<Component>
   <File Source="$(var.SourceDir)\WindowsService.exe" />
   <ServiceInstall Name="MyService" ErrorControl="normal" Start="auto" Type="ownProcess" />
   <ServiceControl Id="MyService" Name="MyService" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
</Component>

Look! No custom actions! :-) - Just MSI auto-magic. There is no need to use any custom actions for this. MSI is full-featured and reliable provided your service executable behaves as it is supposed to.

Let me link to a similar sample on github in case the above is not clear. It is more complete and elaborate.


VBScript: I wrote this before I saw you dealt with services. I'll just throw it in: to call a script that doesn't have a function you can try something like this:

<!-- The VBScript file -->
<Binary Id='Sample.vbs' SourceFile='Sample.vbs' />

<!-- The Custom Action -->
<CustomAction Id='Sample.vbs' VBScriptCall='' BinaryKey='Sample.vbs' 
              Execute='immediate' Return='ignore'/>

<!-- And Insert Into Installation Sequence -->
<InstallExecuteSequence>
    <Custom Action='Sample.vbs' After='AppSearch'/>
</InstallExecuteSequence>

That should work for a script like this (Sample.vbs - no funtions, just an implicit main function):

MsgBox(Session.Property("ProductName"))

There is an answer on the topic of VBScript custom actions here: WIX installer execute vbscript from CustomAction.