|
![]() |
This command can be used to check for per-machine or per-user installed products that should not be installed for your install to go ahead. This can be used to supplement or replace the "Upgrade" table logic".
The "Upgrade" table
is not able to remove previously installed per-user
products if you are installing the current MSI per-machine and visa versa.
This validation can pick up this problem in those circumstances...
This command takes these parameters:
function Allowed(ByVal ProductCode, ByVal ProductName, ByVal ProductVersion, ByVal PerUser)
The parameters above refer to an already installed product, you can also refer to "InstallingProductName" and "InstallingProductVersion".
These are the available options:
#define? PRODUCTVAL_PRODUCT_ENUM_USERSID WI_SID_EVERYONE ;;See 2nd parm of oInstaller.ProductsEx
#define? PRODUCTVAL_PRODUCT_ENUM_CONTEXTS WI_ALL_CONTEXTS ;;See 3nd parm of oInstaller.ProductsEx
#define? PRODUCTVAL_CA_DESCRIPTION Looking for install problematic products. ;;Don't make too long
#define? PRODUCTVAL_CONSTANTS ;;Any constants or global variables you'd like to define
#define? PRODUCTVAL_SUBROUTINES ;;Any functions etc your code needs, perhaps replacement for ProductsMatchCaseInsensitive()
#define? PRODUCTVAL_PROBLEMATIC_PRODUCTLIST_DELIMITER ; ;;Delimiter used in "other products list"
#define? PRODUCTVAL_PROBLEMATIC_PRODUCTLIST_TRIM_WHITESPACE Y ;;Remove leading and trailing whitespace (almost always doesn't matter and may become common error)
#define? PRODUCTVAL_PROBLEMATIC_PRODUCTLIST_COMPARE() ProductsMatchCaseInsensitive(Look4, ProductName, ProductVersion)
#( ';'
#define? PRODUCTVAL_PROBLEMATIC_PRODUCTLIST
;--- List of products (By default just the product we are installing) ---
<$ProdInfo.ProductName>
#)
#( '<?NewLine>'
;--- Becomes part of Allowed() ------------------------------------------
#define? PRODUCTVAL_VALIDATION_CODE_FUNCTION_Allowed_StandardValidation
<?NewLine><?NewLine>
dim ProductList : ProductList = "<$PRODUCTVAL_PROBLEMATIC_PRODUCTLIST>"
if ProductList <> "" then
;--- We have a list so break it up ----------------------------------
dim Delimiter, Products, i
Delimiter = "<$PRODUCTVAL_PROBLEMATIC_PRODUCTLIST_DELIMITER>"
Products = split(ProductList, Delimiter)
for i = 0 to ubound(Products)
;--- Get this product name --------------------------------------
#if ['<$PRODUCTVAL_PROBLEMATIC_PRODUCTLIST_TRIM_WHITESPACE $$UPPER>' = 'N']
dim Look4 : Look4 = Products(i)
#elseif
dim Look4 : Look4 = trim( Products(i) )
#endif
;--- Double delimiter is likely to be a common mistake, ignore ---
if trim(Look4) <> "" then
;--- Use defined compare function (allows easy user override) ---
if <$PRODUCTVAL_PROBLEMATIC_PRODUCTLIST_COMPARE()> then
Allowed = False
exit function
end if
end if
next
end if
#)
#define? PRODUCTVAL_SCHEDULE_LOCATION RemoveExistingProducts- ;;We will let "RemoveExistingProducts" (its scheduled before installation) do what it can first..
#define? PRODUCTVAL_SCHEDULE_TABLES InstallExecuteSequence
#define? PRODUCTVAL_SCHEDULE_CONDITION <$CONDITION_INSTALL_ONLY> and <$@@ProductValidationNotDisabled>
#define? PRODUCTVAL_SCHEDULE_TYPE immediate ;;Not deferred
#define? PRODUCTVAL_DEBUG N ;;Y = Always fail (test multiple times)
#define? @@ProductValidationNotDisabled (%MsiProductValidation = "" or %MsiProductValidation ~= "Y") ;;Allow disabling of CA by env var
#(
#define? PRODUCTVAL_VBSCA_BINARY_COMMENT
This custom action is used to search for products which should be uninstalled
before the install continues.
If such products are found then the install aborts.
#)
From the above you can see that this processing is normally sequenced after the "RemoveExistingProducts" action allowing it to have a go at removing previous versions first (therefore causing an abort only if the action doesn't remove it).
| NOTE: ProductsEx versus Products |
On Windows Installer v3.0+ the "Installer" object's "ProductsEx" property is used to enumerate products otherwise it falls back to using "Products" instead (which will not detect per-user installed products by other users).
| EXAMPLE |
Abort the installation if the installed product or "PerUserTestByDennis" is already installed:
#include "Dennis.MMH"
;--- Add validation to ensure we don't have any products that need uninstallation first ---
#( '<?NewLine>'
#define? SPECIFIC_PRODUCTS_WE_DISALLOW
;--- We don't want to install if this product found... ------------------
dim Look4 : Look4 = "PerUserTestByDennis"
CaDebug 0, "We are looking for a specific problem product (""" & Look4 & """)..."
VbsCaLogInc 1
if ProductName = Look4 then
CaDebug 0, "Version " & ProductVersion & " of the product """ & Look4 & """ is already installed!"
Allowed = False
end if
VbsCaLogInc -1
#)
<$ProductValidation MoreValidation="SPECIFIC_PRODUCTS_WE_DISALLOW">
![]() | ![]() |