Uninstall: Can registry metadata be rewritten before exit?
I'd wish to get the .msi uninstall process add some values under this regkey that's being removed:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\D888EDC8E8...
to simulate uninstall didn't happened to avoid undesired effect on a dependent app that is not actually needing it. I'd wish to do it that way or similar one to be able to trigger uninstall from the entry in ARP, to avoid confusion among users.
And I don't know if this is possible. I'm trying with a previously tested .vbs from custom action type 38 (.vbs in one line ... : ... : ...) with no luck. I'm beginning to think I'm wasting my time.
Any ideas?
Thx in advance.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\D888EDC8E8...
to simulate uninstall didn't happened to avoid undesired effect on a dependent app that is not actually needing it. I'd wish to do it that way or similar one to be able to trigger uninstall from the entry in ARP, to avoid confusion among users.
And I don't know if this is possible. I'm trying with a previously tested .vbs from custom action type 38 (.vbs in one line ... : ... : ...) with no luck. I'm beginning to think I'm wasting my time.
Any ideas?
Thx in advance.
0 Comments
[ + ] Show comments
Answers (8)
Please log in to answer
Posted by:
AngelD
15 years ago
Posted by:
strel
15 years ago
I'd want to know at what moment of the uninstall process is this metadata removed from the registry, and if it can be rewritten to registry in some way from the same process before it exits, or scheduled the execution of a script to be run immediately after process finish, subverting this part of the uninstall process, to do everything in a single step from ARP.
I've tried to trigger the uninstall with a script to modify the registry after uninstall changing the UninstallString with no luck. And all my trials modifying the database with a transform injecting a custom action have failed. I'm exploring commit custom actions with an .vbs
Is it possible?
Thx for your help.
I've tried to trigger the uninstall with a script to modify the registry after uninstall changing the UninstallString with no luck. And all my trials modifying the database with a transform injecting a custom action have failed. I'm exploring commit custom actions with an .vbs
Is it possible?
Thx for your help.
Posted by:
AngelD
15 years ago
Posted by:
strel
15 years ago
It's because I want to have freedom to install and uninstall the unnecessary piece of software without affecting other applications.
The thing is that the values I want to add under this metadata regkeys are not included in the packet, because it corresponds to a non patcheable update I wanted to avoid too.
So I suppose I should search the removing standard action just before InstallFinalize action in InstallExecuteSequence table, and I'll need deferred custom action(s), all this because of the elevated privileges needed to write the registy. Is this correct?
About the .vbs I read in other post it's better not to embed it. Is this meaning not to use vbs code from custom action type 38?
Thx.
The thing is that the values I want to add under this metadata regkeys are not included in the packet, because it corresponds to a non patcheable update I wanted to avoid too.
So I suppose I should search the removing standard action just before InstallFinalize action in InstallExecuteSequence table, and I'll need deferred custom action(s), all this because of the elevated privileges needed to write the registy. Is this correct?
About the .vbs I read in other post it's better not to embed it. Is this meaning not to use vbs code from custom action type 38?
Thx.
Posted by:
strel
15 years ago
I've found the solution:
As I couldn't find the way to disable the install/uninstall process metadata writting onto the registry nor the way of writting my own metadata before install/uninstall process ends, what I did is to use the return processing options of the custom action to set it msidbCustomActionTypeContinue + msidbCustomActionTypeAsync (continue on return and asynchronous), so that the custom action can be executed after the install/uninstall process ends.
This way the custom action has to be EXE type so I choose type 2 (exe from bynary table stream) and insert an .exe obtained from an .vbs file with ExeScript (http://www.hide-folder.com/overview/hf_7.html) that checks if the install/uninstall process has ended, and then write my metadata to registry.
Then I inserted this custom action into InstallExecuteSequence table between InstallInitialize and InstallFinalize standard actions.
And voila!
Enjoy. =P
As I couldn't find the way to disable the install/uninstall process metadata writting onto the registry nor the way of writting my own metadata before install/uninstall process ends, what I did is to use the return processing options of the custom action to set it msidbCustomActionTypeContinue + msidbCustomActionTypeAsync (continue on return and asynchronous), so that the custom action can be executed after the install/uninstall process ends.
This way the custom action has to be EXE type so I choose type 2 (exe from bynary table stream) and insert an .exe obtained from an .vbs file with ExeScript (http://www.hide-folder.com/overview/hf_7.html) that checks if the install/uninstall process has ended, and then write my metadata to registry.
Dim blnRunning, colProcesses
blnRunning = True
Do Until Not blnRunning
Set colProcesses = GetObject( "winmgmts:{impersonationLevel=impersonate}" ).ExecQuery( "Select * From Win32_Process Where Name = '" & "msiexec.exe" & "'" )
WScript.Sleep 100
If colProcesses.Count = 0 Then
blnRunning = False
End If
Loop
Set WshShell = CreateObject( "WScript.Shell" )
WshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\15B3183CD7C6F2D8E8F0DCC03A48AD88\Value1", WshShell.ExpandEnvironmentStrings( "%SYSTEMROOT%\Installer\1234mxj.msi" ), "REG_SZ"
WshShell.RegWrite "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\15B3183CD7C6F2D8E8F0DCC03A48AD88\Patches\DAE54917E4E118470E9485F10410F3FB\Value2", "1", "REG_DWORD"
Set WshShell = Nothing
Then I inserted this custom action into InstallExecuteSequence table between InstallInitialize and InstallFinalize standard actions.
And voila!
Enjoy. =P
Posted by:
anonymous_9363
15 years ago
What you mean by 'This way the custom action has to be EXE type'?
If I were you I'd:
- add a LOT of error-trapping to your code. It assumes that everything is going to work first time, every time. ALWAYS program defensively and assume NOTHING is going to work.
- add another loop into your process-watching loop so that it only waits for time 'x' before assuming that the process isn't going to end. Otherwise, if your package gets run after any other, MSIExec.EXE will quite likely still be running (the engine sometimes keeps the server instance running, long after the install which started it has completed) meaning that you script will be stuck in an endless loop. That sort of behaviour isn't too popular with users...
If I were you I'd:
- add a LOT of error-trapping to your code. It assumes that everything is going to work first time, every time. ALWAYS program defensively and assume NOTHING is going to work.
- add another loop into your process-watching loop so that it only waits for time 'x' before assuming that the process isn't going to end. Otherwise, if your package gets run after any other, MSIExec.EXE will quite likely still be running (the engine sometimes keeps the server instance running, long after the install which started it has completed) meaning that you script will be stuck in an endless loop. That sort of behaviour isn't too popular with users...
Posted by:
strel
15 years ago
I mean that using this Return Processing options above there's limits described in Windows Installer SDK help file:
"An asynchronous execution that does not wait for completion.
Execution continues after Windows Installer terminates.
This option can only be used with the EXE type custom actions—that is, executable files.
All other types of custom actions can be asynchronous only within the install session, and must end for the installation to terminate.
This option cannot be used with Concurrent Installations."
I had observed yet msiexec.exe still running after my install/uninstall process ends, in fact I was using:
But you're right it could get in an endless loop, so it can be added code to stop or wait any msiexec.exe processes running before starting, and to avoid not run concurrently with another msiexec.exe process. But this is not my intention, I'm not beeing paid for this, so my users will have to follow my yellow brick path. But up to anyone who uses this idea.
Anyway luckyly I can make the script watch another singular process related to this install/uninstall to determine when to write the metadata registry keys, avoiding that problems easyly.
Thx for you advices.
"An asynchronous execution that does not wait for completion.
Execution continues after Windows Installer terminates.
This option can only be used with the EXE type custom actions—that is, executable files.
All other types of custom actions can be asynchronous only within the install session, and must end for the installation to terminate.
This option cannot be used with Concurrent Installations."
I had observed yet msiexec.exe still running after my install/uninstall process ends, in fact I was using:
...If colProcesses.Count = 1 Then...
But you're right it could get in an endless loop, so it can be added code to stop or wait any msiexec.exe processes running before starting, and to avoid not run concurrently with another msiexec.exe process. But this is not my intention, I'm not beeing paid for this, so my users will have to follow my yellow brick path. But up to anyone who uses this idea.
Anyway luckyly I can make the script watch another singular process related to this install/uninstall to determine when to write the metadata registry keys, avoiding that problems easyly.
Thx for you advices.
Posted by:
AngelD
15 years ago
If you're going that path which I wouldn't recommend ;) I would pass the msiexec processid and check when that process has ended.
ProcessId = Session.Property("CLIENTPROCESSID")
The select query would then look like:
"Select * From Win32_Process Where ProcessId = '" & ProcessId & "'"
I've used a similar wmi script at http://www.appdeploy.com/messageboards/fb.asp?m=44926
You need to tweak if for your purpose.
ProcessId = Session.Property("CLIENTPROCESSID")
The select query would then look like:
"Select * From Win32_Process Where ProcessId = '" & ProcessId & "'"
I've used a similar wmi script at http://www.appdeploy.com/messageboards/fb.asp?m=44926
You need to tweak if for your purpose.
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.