Disallowing uninstallation of component: xxx ....
Hello all!
I've been messing about with the windows cleanup util (MSIZAP.exe) and trying to break my MSI as much as possible, to help simulate the actions of an extremely stupid user.. however i have got the point where Windows Installer still thinks many of my components exist despite there being no physical files and none of my registry entries exist... Giving a tonne of the following types of messages:
I'm no expert on the ins and outs of windows installer so could someone advise the best course of action to remove the entries out of Windows installer so there are no associated records in there. Basically i am developing a cleanup utility to remove all the files/registry i put down including windows installer entries if an install became corrupt.
Regards
Paul
I've been messing about with the windows cleanup util (MSIZAP.exe) and trying to break my MSI as much as possible, to help simulate the actions of an extremely stupid user.. however i have got the point where Windows Installer still thinks many of my components exist despite there being no physical files and none of my registry entries exist... Giving a tonne of the following types of messages:
Disallowing uninstallation of component: {5C517030-1AA5-4018-82F2-A2D6F784EC04} since another client exists
I'm no expert on the ins and outs of windows installer so could someone advise the best course of action to remove the entries out of Windows installer so there are no associated records in there. Basically i am developing a cleanup utility to remove all the files/registry i put down including windows installer entries if an install became corrupt.
Regards
Paul
0 Comments
[ + ] Show comments
Answers (8)
Please log in to answer
Posted by:
jmcfadyen
17 years ago
The keys will be written to here
HKLM\Software\microsoft\windows\currentversion\Installer\userdata\<xxxxxxx>\components
<xxxxxxx> depends on wether you deploy per user and or per machine.
per machine will be <S-1-5-18>
Inside there you will find a very messed up version of you component code.
{xxxxxxx-xxxx-xxxx-xxxx-xxxx) <---- i didnt count these
I dont know what the names are of the groups are but for the sake of this lets call them octets (like in subnets even though they are not really octets)
for the first three octets the entire octet is reversed
for the last 2 octets only every two are reversed
for example
{abcdefghijkl- is =
{lkjihgfedcba
and so on and so on.
then the last 2 octets only each 2 characters are reversed so
-ABCD- would become BADC
confusing i know but the powers at be say this saves space ? go figure ... my wisdom does not extend far enough to know exactly how this saves space cos in my eyes its exactly the same but jumbled up.
inside this key you will find another messed up GUID or maybe lots of them
When you mark a component DO NOT uninstall you are actually telling the install to write all {00000000000-0000000-00000-0000000} again i didnt count those.
so if you see all Zero's then you will know the component will not be uninstalled.
where you see more mixed up GUIDS you will find these guids are the product codes of the associated applications that have installed those components.
As such this is in effect how reference counting actually works.
It does not count the number of times components are installed it actually associated the products that have installed the component. As such when you uninstall an APP you remove the apps product from the component list.
that about covers your question i reckon.
HKLM\Software\microsoft\windows\currentversion\Installer\userdata\<xxxxxxx>\components
<xxxxxxx> depends on wether you deploy per user and or per machine.
per machine will be <S-1-5-18>
Inside there you will find a very messed up version of you component code.
{xxxxxxx-xxxx-xxxx-xxxx-xxxx) <---- i didnt count these
I dont know what the names are of the groups are but for the sake of this lets call them octets (like in subnets even though they are not really octets)
for the first three octets the entire octet is reversed
for the last 2 octets only every two are reversed
for example
{abcdefghijkl- is =
{lkjihgfedcba
and so on and so on.
then the last 2 octets only each 2 characters are reversed so
-ABCD- would become BADC
confusing i know but the powers at be say this saves space ? go figure ... my wisdom does not extend far enough to know exactly how this saves space cos in my eyes its exactly the same but jumbled up.
inside this key you will find another messed up GUID or maybe lots of them
When you mark a component DO NOT uninstall you are actually telling the install to write all {00000000000-0000000-00000-0000000} again i didnt count those.
so if you see all Zero's then you will know the component will not be uninstalled.
where you see more mixed up GUIDS you will find these guids are the product codes of the associated applications that have installed those components.
As such this is in effect how reference counting actually works.
It does not count the number of times components are installed it actually associated the products that have installed the component. As such when you uninstall an APP you remove the apps product from the component list.
that about covers your question i reckon.
Posted by:
anonymous_9363
17 years ago
ORIGINAL: HotSpotKind of...
VBScab i guess your using the split command and reversing it, would you mind letting take a peek at the code to do this?
Option Explicit
Call ListCodes(path_containing_MSI_or_MSIs)
'=========================================================================================================
' Name: ListCodes
' Purpose: Passed a path, this routine tests for the presence of an MSI,
' interrogates it for its UpgradeCode and ProductCode, then returns those
' and their MS-munged versions
' Input: strRootPath - the folder to start listing from
'=========================================================================================================
Sub ListCodes(ByVal strRootPath)
Dim strDummy
Dim objInstaller_ROC
Dim objView
Dim objRecord
Dim objDatabase
Dim objFSO_ROC
Dim objFolder
Dim objFileCollection
Dim objFile
Dim strFiles
Dim strFileName
Dim strProperty
Dim intPropertyIndex
Dim strPropertyValue
'// Set which property you want to test for here
strProperty = "ProductCode"
intPropertyIndex = 2
Set objInstaller_ROC = CreateObject("WindowsInstaller.Installer")
Set objFSO_ROC = CreateObject("Scripting.FileSystemObject")
'// There should only be one, but this code iterates through all of them anyway
Set objFolder = objFSO_ROC.GetFolder(strRootPath)
Set objFileCollection = objFolder.Files
For Each objFile In objFileCollection
'// Files do not have an 'Extension' property in VBS, we have to do this nonsense...
If UCase(objFSO_ROC.GetExtensionName(objFile.Name)) = "MSI" Then
strFileName = strRootPath & "\" & objFile.Name
'// Open database
Set objDatabase = objInstaller_ROC.OpenDatabase(strFileName, 0)
'// Get property
Set objView = objDatabase.OpenView("SELECT * FROM Property WHERE Property = '" & strProperty & "'")
objView.Execute
Set objRecord = objView.Fetch
strPropertyValue = Empty
strPropertyValue = objRecord.StringData(intPropertyIndex)
If Len(strPropertyValue) = 0 Then
'// Display the error that occurred
strDummy = "Unable to retrieve value for MSI property '" & strProperty & "'."
MsgBox strDummy, vbExclamation, WSCript.ScriptName & ".ListCodes"
Exit Sub
End If
WScript.Echo "Getting " & strProperty & " for " & objFile.ParentFolder & "\" & objFile.Name
strDummy = GetMungedCode(strPropertyValue)
strDummy = vbTAB & strPropertyValue & vbTAB & strDummy & vbCRLF
WScript.Echo strDummy
'// Now do UpgradeCode
strProperty = "UpgradeCode"
'// Get property
Set objView = objDatabase.OpenView("SELECT * FROM Property WHERE Property = '" & strProperty & "'")
objView.Execute
Set objRecord = objView.Fetch
strPropertyValue = Empty
strPropertyValue = objRecord.StringData(intPropertyIndex)
If Len(strPropertyValue) = 0 Then
'// Display the error that occurred
strDummy = "Unable to retrieve value for MSI property '" & strProperty & "'."
MsgBox strDummy, vbExclamation, WSCript.ScriptName & ".ListCodes"
Exit Sub
End If
WScript.Echo "Getting " & strProperty & " for " & objFile.ParentFolder & "\" & objFile.Name
strDummy = GetMungedCode(strPropertyValue)
strDummy = vbTAB & strPropertyValue & vbTAB & strDummy & vbCRLF
WScript.Echo strDummy
objView.Close
Set objDatabase = Nothing
Set objView = Nothing
Set objRecord = Nothing
End If
Next
Set objFileCollection = Nothing
Set objFolder = Nothing
Set objFSO_ROC = Nothing
Set objInstaller_ROC = Nothing
End Sub
Function GetMungedCode(ByVal strCode)
Dim arrCharacterOrder
Dim intIndex
Dim strMungedCode
Const intArraySize = 32
arrCharacterOrder = Array(9,8,7,6,5,4,3,2,14,13,12,11,19,18,17,16,22,21,24,23,27,26,29,28,31,30,33,32,35,34,37,36)
'// Generate the munged version of the code
For intIndex = 0 to intArraySize - 1
strMungedCode = strMungedCode & Mid(strCode,arrCharacterOrder(intIndex),1)
Next
GetMungedCode = strMungedCode
End Function
Posted by:
AngelD
17 years ago
Hi Paul,
Thanks for that piece of information.
I was wondering how if shared components would get zipped or not and you just confirm that.
As other applications installed from an MSI also have installed that component (component GUID) you are not allowed to zap that component for the specific product you're choosing from msizap.
I guess you would have to change the counter for the shared component in the registry to 1 before using the msizip for the product having that component.
Thanks for that piece of information.
I was wondering how if shared components would get zipped or not and you just confirm that.
As other applications installed from an MSI also have installed that component (component GUID) you are not allowed to zap that component for the specific product you're choosing from msizap.
I guess you would have to change the counter for the shared component in the registry to 1 before using the msizip for the product having that component.
Posted by:
anonymous_9363
17 years ago
I've discovered that MSIZAP doesn't zap all the detrius of per-user managed installs (used at my current client) so I'm building a script to handle those, using the output from MSIZAP as a guide to what I need to ditch (I know most of the locations but guarantee I'd miss one or more without that output...getting too old to rely on memory)
Posted by:
anonymous_9363
17 years ago
ORIGINAL: jmcfadyenThis is documented as 'Darwinian transforms' on, IIRC, InstallSite but it's too much like hard work to translate every time so I have a VB Script function to do the work for you. Feed it a GUID and it squirts out the (what I call) munged string.
{xxxxxxx-xxxx-xxxx-xxxx-xxxx) <---- i didnt count these
I dont know what the names are of the groups are but for the sake of this lets call them octets (like in subnets even though they are not really octets)
for the first three octets the entire octet is reversed
for the last 2 octets only every two are reversed
for example
{abcdefghijkl- is =
{lkjihgfedcba
and so on and so on.
then the last 2 octets only each 2 characters are reversed so
-ABCD- would become BADC
confusing i know but the powers at be say this saves space ? go figure ... my wisdom does not extend far enough to know exactly how this saves space cos in my eyes its exactly the same but jumbled up.
Posted by:
HotSpot
17 years ago
Posted by:
AngelD
17 years ago
Ian,
I don't recall if I have posted this vbscript before so here goes.
It will convert GUID to InstallerCode or as you said it "munged string" [:D] and vice versa
I don't recall if I have posted this vbscript before so here goes.
It will convert GUID to InstallerCode or as you said it "munged string" [:D] and vice versa
'// Convert ProductCode to InstallerCode and vice versa
Option Explicit
Const CodeIndex = 0
WScript.Echo ConvertGuid(CodeIndex, "{70F784E9-59C8-4EDD-BAEE-A0AF409CFF33}")
WScript.Echo ConvertGuid(CodeIndex, "726A9C95A4F54c7449DFA988F6A59C17")
Function ConvertGuid(iCodeIndex, sGuidCode)
Dim aCode, iIndex, sSectionCode, sSectionDigits, sGuid, bAddHyphen
bAddHyphen = True
sGuid = sGuidCode
iIndex = iCodeIndex
If iIndex = 0 Then
If InStr(sGuid, "-") Then bAddHyphen = False
End If
sGuid = ConvertCode(sGuid)
sGuid = ConvertSection(iIndex, sGuid)
ConvertGuid = sGuid
aCode = Split(sGuid, "-")
If iIndex = Ubound(aCode) Then Exit Function
sGuid = ConvertGuid(iIndex + 1, sGuid)
If Not bAddHyphen Then sGuid = Join(Split(sGuid, "-"),"")
If iIndex = 0 AND bAddHyphen Then sGuid = "{" & sGuid & "}"
ConvertGuid = sGuid
End Function
Function ConvertCode(sGuidCode)
Dim aGuidSection
If Left(sGuidCode, 1) = "{" Then sGuidCode = Replace(Replace(sGuidCode,"{",""),"}","")
If InStr(sGuidCode, "-") Then
aGuidSection = Split(sGuidCode, "-")
Else
Redim aGuidSection(4)
aGuidSection(0) = Left(sGuidCode, 8)
aGuidSection(1) = Mid(sGuidCode, 9, 4)
aGuidSection(2) = Mid(sGuidCode, 13, 4)
aGuidSection(3) = Mid(sGuidCode, 17, 4)
aGuidSection(4) = Right(sGuidCode, 12)
End If
ConvertCode = Join(aGuidSection, "-")
End Function
Function ConvertSection(iSectionIndex, sGuidCode)
Dim aGuidSection, iIndex, sSectionDigits
aGuidSection = Split(sGuidCode, "-")
If iSectionIndex <= 2 Then aGuidSection(iSectionIndex) = StrReverse(aGuidSection(iSectionIndex))
If iSectionIndex >= 3 Then
For iIndex = 0 To len(aGuidSection(iSectionIndex)) Step 2
sSectionDigits = sSectionDigits & StrReverse(Right(Left(aGuidSection(iSectionIndex), iIndex), 2))
Next
aGuidSection(iSectionIndex) = sSectionDigits
End If
sGuidCode = Join(aGuidSection, "-")
ConvertSection = sGuidCode
End Function
Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.
so that the conversation will remain readable.