I have been looking at how to pass MSI properties to Windows Installer when performing repairs of installed MSI packages using the automation interface (COM object: WindowsWindowsInstaller.Installer) for VBScript. The two methods available for doing repairs are:
  • ReinstallProduct (repairs an MSI package based on product code)
  • ReinstallFeature (repairs the specified feature based on feature name and product code)
However, I have yet to figure out how to pass MSI properties at run-time to Windows Installer when using VBScript automation for doing repairs.

Example: When Office 2003 applications are run for the first time by a new user, they trigger a repair of the installation. In the log file for the repair you can see that Windows Installer is called using the following MSI properties:

REINSTALL=OfficeUserData REINSTALLMODE=ocmu MSICLIENTUSESEXTERNALUI=1

Both "REINSTALL" and "REINSTALLMODE" are handled as arguments to the ReinstallFeature method above but how do I pass the value for "MSICLIENTUSESEXTERNALUI" to Windows Installer when doing the repair?

I have looked at creating a Session object for the installation by using the OpenProduct method and setting properties that way using the property "Property" for the session object. Unfortunately, the repair cannot take place as long as the session object remains active and when it is closed any properties set using it are discarded.

Another alternative, which would be closer to how Msiexec.exe could be called from the command line, is to use the method "InstallProduct" of the Installer object. However, this method requires as an argument the path to an MSI file and can not use the product code of an installed package. I can not assume that I will always have access to the original source media where the MSI file is located. Although it might be possible in some cases to use the INSTALLPROPERTY_LOCALPACKAGE property of the installed package to get the locally cached MSI package this seems somewhat unreliable according to the MSI documentation:

http://msdn.microsoft.com/en-us/library/aa370130.aspx

MsiGetProductInfo(INSTALLPROPERTY_LOCALPACKAGE) does not necessarily return a path to the cached package. The cached package is for internal use only.


Any suggestions on a good, generic way of solving this? I am not looking for specific pointers for the Office 2003 repair but rather how this should be solved for any type of installation.

Note: Using msiexec.exe to perform the repairs is not an option.
0 Comments   [ + ] Show Comments

Comments

Please log in to comment

Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.

Answers

0
You need to write the properties to the registry during install and then read them back during a repair using AppSearch.
Have a look at http://etlengineering.com/installer/repair.txt
Answered 07/02/2008 by: AngelD
Red Belt

Please log in to comment
0
ORIGINAL: AngelD

You need to write the properties to the registry during install and then read them back during a repair using AppSearch.
Have a look at http://etlengineering.com/installer/repair.txt



I'm afraid that's not an option in this case since I can't make any changes to the installed package or reinstall it using a transform, patch, etc.
Answered 07/02/2008 by: Jonas Olsson
Senior Yellow Belt

Please log in to comment
0
My suggestion was regarding your "Any suggestions on a good, generic way of solving this?" statement.

In you case I would first modify the cached MSI or if you previous installed with a transform then update the tranform and replace the cached transform. Then trigger the repair in anyway you like.
Answered 07/02/2008 by: AngelD
Red Belt

Please log in to comment
0
[/align]
[blockquote]
ORIGINAL: Jonas Olsson

ORIGINAL: AngelD

You need to write the properties to the registry during install and then read them back during a repair using AppSearch.
Have a look at http://etlengineering.com/installer/repair.txt



I'm afraid that's not an option in this case since I can't make any changes to the installed package or reinstall it using a transform, patch, etc.




Sounds like you've dug yourself into a hole by only using VBScript automation to install.

Why are you using such an inflexible method?

What are you trying to accomplish?

[/blockquote]
Answered 07/05/2008 by: aogilmor
Ninth Degree Black Belt

Please log in to comment
0
ORIGINAL: aogilmor

Sounds like you've dug yourself into a hole by only using VBScript automation to install.
Why are you using such an inflexible method?
What are you trying to accomplish?


The reason I have been looking at VBScript automation to repair products and features is because it circumvents a domain group policy in use at the enterprise in question, forbidding ordinary users from running the msiexec.exe executable (security by obscurity, I know, but making changes to the group policy is difficult for political reasons). Using VBScript automation allows our users to repair installed MSI packages anyway as part of their login routine. We do this for users logging on to a workstation for the first time (only local, non-roaming profiles in use) in order to populate their profiles with some initial settings which we then make changes to.

Mind you, we do not currently use VBScript automation to install MSI packages. That is done using msiexec.exe. However, I am not sure I agree that VBScript automation in general is an inflexible method for working with Windows Installer. Although it seems Microsoft hasn't included the ability to send along MSI properties when performing repairs using the reinstall methods above and has not enabled the "InstallProduct" method to use product codes instead of MSI package paths, there are many other methods and properties in the interface which allows you to dig pretty deep into the Windows Installer environment using API calls.
Answered 07/06/2008 by: Jonas Olsson
Senior Yellow Belt

Please log in to comment
0
Jonas, at the risk of possibly violating forum rules, I have a script-friendly interface to MSI.DLL via a VB-authored ActiveX DLL. I presently use it ONLY to access the CreateAdvertiseScript which enables my current client to add MSIs to Group Policy Objects entirely in script. As you know, adding MSIs to GPOs involves so much clicking and browsing that it drives most people nuts when performed enough times. Well, for me, I figured there had to be a way to automate it and set about that task. Many times, I wish I hadn't, thanks to missing/poor documentation but with the judicious use of ProcMon (sigh...), AD Explorer and other similar tools, I worked it out. The major fly in the ointment was access to the CerateAdvertsieScript function. This has been added (apparently) to MSI v4 but we're not using that yet (and no propsect likely for a long while, bearing in mind the client only migrated to XP LAST December!) so I had to persist.

Anyway, to my point! If you'd like a copy of my DLL, PM me and I'll pop it on to SendUIt.com for you. The DLL will be provided to you - and only you - on a strictly for-experimentation-only basis. I do not expect to see copies of it floating around the web, thanks. The major caveat is that I have not tested ANY OTHER FUNCTION that it interfaces with other than CreateAdvertiseScript so you're on your own in using it. I can advise you of parameter data types (although they'll be the same as on MSDN) and so on but, other than that....
Answered 07/07/2008 by: VBScab
Red Belt

Please log in to comment
0
ORIGINAL: VBScab

Anyway, to my point! If you'd like a copy of my DLL, PM me and I'll pop it on to SendUIt.com for you. The DLL will be provided to you - and only you - on a strictly for-experimentation-only basis. I do not expect to see copies of it floating around the web, thanks. The major caveat is that I have not tested ANY OTHER FUNCTION that it interfaces with other than CreateAdvertiseScript so you're on your own in using it. I can advise you of parameter data types (although they'll be the same as on MSDN) and so on but, other than that....



VBScab, thanks for the offer but unfortunately it does not seem that being able to call functions directly from MSI.DLL will help with the challenge introduced by Microsoft's limited API. The scriptable automation interface seems to correspond well to the functions available in MSI.DLL for performing the tasks that I am interested in:

MsiInstallProduct
MsiReinstallProduct
MsiReinstallFeature

These functions use the same parameters as their automation interface counterparts so you would still be unable to combine using product codes for repairs with sending along MSI properties at run-time.

Thanks anyway though.
Answered 07/07/2008 by: Jonas Olsson
Senior Yellow Belt

Please log in to comment
0
REINSTALL=OfficeUserData REINSTALLMODE=ocmu MSICLIENTUSESEXTERNALUI=1ORIGINAL: Jonas Olsson

ORIGINAL: VBScab

Anyway, to my point! If you'd like a copy of my DLL, PM me and I'll pop it on to SendUIt.com for you. The DLL will be provided to you - and only you - on a strictly for-experimentation-only basis. I do not expect to see copies of it floating around the web, thanks. The major caveat is that I have not tested ANY OTHER FUNCTION that it interfaces with other than CreateAdvertiseScript so you're on your own in using it. I can advise you of parameter data types (although they'll be the same as on MSDN) and so on but, other than that....



VBScab, thanks for the offer but unfortunately it does not seem that being able to call functions directly from MSI.DLL will help with the challenge introduced by Microsoft's limited API. The scriptable automation interface seems to correspond well to the functions available in MSI.DLL for performing the tasks that I am interested in:

MsiInstallProduct
MsiReinstallProduct
MsiReinstallFeature

These functions use the same parameters as their automation interface counterparts so you would still be unable to combine using product codes for repairs with sending along MSI properties at run-time.

Thanks anyway though.



Maybe I'm just being dense, but I still don't get it....

If vbscript doesn't support this, use a simple command line, use another tool to run the command (wisesscript?) or shell out the command with vbscript, bat, powershell, WMI or however fits best for you.

Just for giggles I ran an office reinstall of 2003 on my own machine. msiexec /i {90110409-6000-11D3-8CFE-0150048383C9} REINSTALL=OfficeUserData REINSTALLMODE=ocmu MSICLIENTUSESEXTERNALUI=1, and it worked fine.

I guess my point is that lack of support from one msft tool shouldn't prevent you from accomplishing your desired user config.
Answered 07/07/2008 by: aogilmor
Ninth Degree Black Belt

Please log in to comment
0
ORIGINAL: aogilmor

Maybe I'm just being dense, but I still don't get it....

If vbscript doesn't support this, use a simple command line, use another tool to run the command (wisesscript?) or shell out the command with vbscript, bat, powershell, WMI or however fits best for you.


Well, as I wrote in an earlier post, a domain group policy is in effect at the enterprise in question preventing ordinary users from running the msiexec.exe executable. For this reason a per-user repair can not be initiated for these users using msiexec.exe directly. It doesn't matter if the command is called from a script or from another compiled executable.

To access the Windows Installer functionality and perform the repair, the Windows Installer automation interface or its API (from MSI.DLL) must be used to initiate the operation. Although I am sure there are several more or less ugly hacks around the domain group policy, for example making a copy of the msiexec.exe file and renaming and/or editing its contents and then running it, these types of solutions are not what I am looking for.

Actually there is a solution to the problem, which I mentioned in my original post. You can get the locally cached MSI package file path for the installed MSI package using the property INSTALLPROPERTY_LOCALPACKAGE or, failing that and using other methods, the path to the actual installation source for the package. The MSI package source path could then be used with the automation interface method "InstallProduct" to send along the appropriate MSI properties to perform the repair, including any extra properties required.

The reason I discarded this method in my original post was due to the uncertainty of whether or not the INSTALLPROPERTY_LOCALPACKAGE would be populated for all installed MSI packages. The real installation source path was also not available on some of the client platforms where this solution was supposed to work.

This may however be a method I will use if the need arises again but for now it seems that Office 2003 can be repaired sufficiently well using only the ReinstallFeature method, the product code and the feature name. The additional MSI property MSICLIENTUSESEXTERNALUI=1 used by Office applications when they initiate the repair does not seem to be necessary for successfully completing the per-user repair.
Answered 07/07/2008 by: Jonas Olsson
Senior Yellow Belt

Please log in to comment
0
ORIGINAL: Jonas Olsson

ORIGINAL: aogilmor

Maybe I'm just being dense, but I still don't get it....

If vbscript doesn't support this, use a simple command line, use another tool to run the command (wisesscript?) or shell out the command with vbscript, bat, powershell, WMI or however fits best for you.


Well, as I wrote in an earlier post, a domain group policy is in effect at the enterprise in question preventing ordinary users from running the msiexec.exe executable. For this reason a per-user repair can not be initiated for these users using msiexec.exe directly. It doesn't matter if the command is called from a script or from another compiled executable.

To access the Windows Installer functionality and perform the repair, the Windows Installer automation interface or its API (from MSI.DLL) must be used to initiate the operation. Although I am sure there are several more or less ugly hacks around the domain group policy, for example making a copy of the msiexec.exe file and renaming and/or editing its contents and then running it, these types of solutions are not what I am looking for.



I'd favor fixing the policy rather than chasing down ugly hacks, but maybe that's just me....
Never heard of a policy that wouldn't even let a user execute msiexec.exe...why? With proper user lockdown they can't install programs anyway.
Answered 07/07/2008 by: aogilmor
Ninth Degree Black Belt

Please log in to comment
0
ORIGINAL: aogilmor
I'd favor fixing the policy rather than chasing down ugly hacks, but maybe that's just me....
It does seem bizarre to block MSIExec when it can be bypassed by another route but then I gave up questioning management decrees years ago. They're generally sourced from a bigoted POV in the first place and no amount of engaging head with wall will change that.
Answered 07/08/2008 by: VBScab
Red Belt

Please log in to comment
0
I guess by blocking the msiexec process from running will only prevent a repair from triggering automatically if required.
Maybe it's on a TS environment?
Answered 07/08/2008 by: AngelD
Red Belt

Please log in to comment
0
Believe me, i've been stuck with my share of bad implementations, like having to do runas and use sanur to do office patches with a vbscript. Even that would do no good here; he needs to apply user settings and it would apply under the wrong user context. Is there anything you could run under an admin context that'll kick off a reinstall of all users' settings? Not to my knowledge.....
Answered 07/08/2008 by: aogilmor
Ninth Degree Black Belt

Please log in to comment
0
Hello, I have written a script to run a MSi along with multiple instances of transforms and it throws an error called script time exceeded....

'==========================================================================
'
' APPLICATION NAME: Adobe Acrobat 9 Standard
' AUTHOR: DDS
' DATE : 7/092008
' COMMENT: Script to install Adobe Acrobat 9 Standard Version 9
'
'==========================================================================
On Error Resume Next
'--------------------------------------------------------------------------
'Set Variables
'--------------------------------------------------------------------------
Set WshShell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
Set WshNetwork = WScript.CreateObject("WScript.Network")
DATE = WshShell.ExpandEnvironmentStrings("%DATE%")
TIME = WshShell.ExpandEnvironmentStrings("%TIME%")
DATE_TIME = DATE & ":" & TIME &"-"
'---------------------------------------------------------------------------
'Script Path
'---------------------------------------------------------------------------
ScriptPath = Left(WScript.ScriptFullName, Len(WScript.ScriptFullName) - Len(WScript.ScriptName))
AppName = "AcroStan.msi"
AppName1 = "1031.mst"
AppName2 = "1033.mst"
AppName3 = "1036.mst"
'---------------------------------------------------------------------------
'LogFile
'---------------------------------------------------------------------------
'Check for temp folder and create if not present
if Not fso.FolderExists ("C:\Program Files\\Logs\Adobe\Acrobat 9.0") Then
fso.CreateFolder "C:\Program Files\"
fso.CreateFolder "C:\Program Files\DDS"
fso.CreateFolder "C:\Program Files\Logs"
fso.CreateFolder "C:\Program Files\\DDS\Logs\Adobe\Acrobat 9.0"
end If
Set LogFile = fso.CreateTextFile("C:\Program Files\BNYMELLON\DDS\Logs\Adobe\Acrobat 9.0\install.log")
LogFile.WriteLine(DATE_TIME & WshNetwork.UserDomain & "\" & WshNetwork.UserName & " executing on " & WshNetwork.ComputerName)
LogFile.WriteLine(DATE_TIME & "Executing " & WScript.ScriptFullName)
LogFile.WriteLine(DATE_TIME & "Beginning...")
LogFile.WriteLine(DATE_TIME & "Installing Adobe Acrobat 9.0")
'---------------------------------------------------------------------------
' Begins the Install process
'---------------------------------------------------------------------------
Return = WshShell.Run("msiexec/i" chr(34) & ScriptPath &AppName &chr(34) &"TRANSFORMS=" & chr(34) &"AppName1" &chr(34) &"/qb!", 1, True)
If Return = 0 Or Return = 3010 Then
WshShell.Popup AppName & " installation complete!", 10, "Install Status", 64
LogFile.WriteLine( DATE_TIME & "success" )
LogFile.WriteLine( DATE_TIME & "Setup.exe returned " & Return )
Else
WshShell.Popup AppName & " installation failed! Setup returned: " & Return & ".", 10, "Install Status", 16
LogFile.WriteLine( DATE_TIME & "Error...success" )
LogFile.WriteLine( DATE_TIME & "Setup.exe returned " & Return )
End If

'-----------------------------------------------------------------------------
LogFile.Close
'Final Return check
WScript.Quit Return

Please Help Me soughting out this error.
Answered 07/09/2008 by: yshariff
Orange Senior Belt

Please log in to comment
0
yshariff,

Do not hijack others thread as it's not relevant to the OP question.
Create a new thread with your question.

In the new thread please post the exact error and on which line it stops on.
Answered 07/09/2008 by: AngelD
Red Belt

Please log in to comment
0
Do you have a Timeout entry under HKCU\Software\Microsoft\Windows Script Host\Settings" or under HKLM?
Answered 07/09/2008 by: AngelD
Red Belt

Please log in to comment
0
You will never get the timeout value right. Too low and the same will happen, too high and scripts could potentially lock up the machine.

Use WMI to create the process and get its Process ID then build a loop (with its own timeout) to check for when that Process ID no longer exists. Alternatively, given your basic scripting capability (no slight intended, BTW), build a loop which checks for the existence of the products 'Uninstall' registry entry, since creating that entry is one of the last things which the WI engine does.
Answered 07/10/2008 by: VBScab
Red Belt

Please log in to comment
Answer this question or Comment on this question for clarity