wmmayms Posted February 24, 2011 Report post Posted February 24, 2011 Hi guys In this guide I will show you how you can dynamically upgrade applications no matter who installed it or from what source MSI package. I will start of by introducing you to MSI UpgradeCode which is similar to the ProductCode but not the same. Normally this code is used by the MSI package to determine if there is an earlier application of the same type installed and in that case upgrade. The ProductCode is the unique key for a specific MSI package. The upgradeCode is the unique key for the specific software (at least if its a serious company who created the MSI installer) Okay! So would it not be great to be able to run this command: msiexec /x <ProductCode> /qn And uninstall any version of the software that you no longer need? If that worked it would be great, but unfortunately you cannot do this. To uninstall a MSI package you need to specify the ProductCode after you /x switch. So what to do? Create a script of course! I created this script: MSIUninstallFromUpgradeCode.vbs 'Written by wmmayms @ WindowsNoob 2010-23/2 On Error Resume Next '==================================== ' Define Logpath '==================================== strLogPath = "c:\MSIUninstallFromUpgradeCode.log" '==================================== ' Check arguments '==================================== Set objArguments = Wscript.Arguments If WScript.Arguments.Count = 1 Then strUpgradeCode = objArguments.Named.Item("Upgradecode") Else Wscript.Echo "Usage: MSIUninstallFromUpgradeCode.vbs /Upgradecode:[upgradecode]" Wscript.Quit End If '==================================== ' Setup Logging '==================================== Set objFSO = CreateObject("Scripting.FileSystemObject") If not objFSO.FileExists(strLogPath) Then Set objOutputFile = objFSO.CreateTextFile(strLogPath) Else Set objOutputFile = objFSO.OpenTextFile(strLogPath, 8) End if objOutputFile.WriteLine "--Script triggerd with the following UpgradeCode: " & strUpgradeCode '==================================== ' Main Script '==================================== Set installer = CreateObject("WindowsInstaller.Installer") For Each prod In installer.ProductsEx("", "", 7) sLocalPkg = prod.InstallProperty("LocalPackage") set oDB = installer.OpenDataBase(sLocalPkg, 0) sQuery = "SELECT `Value` FROM `Property` WHERE `Property` = 'UpgradeCode'" Set oView = oDB.OpenView(sQuery) oView.Execute Set oRecord = oView.Fetch If Not (oRecord is Nothing) Then sUpgradeCode = oRecord.StringData(1) If strUpgradeCode = sUpgradeCode Then set WshShell = CreateObject("wscript.shell") objOutputFile.WriteLine "About to run: msiexec.exe /x" & prod.ProductCode & " /qn" Return = WshShell.Run("msiexec.exe /x" & prod.ProductCode & " /qn", 1, true) If Return <> 0 Then objOutputFile.WriteLine "Uninstall failed. Error Code " & Return objOutputFile.Close Wscript.Quit() Else objOutputFile.WriteLine "Uninstall succeeded" End If End If End If Next '==================================== ' Close Logging '==================================== objOutputFile.WriteLine "--Script has finished, if there is no information between Script Triggerd and Script finished then no package was found." objOutputFile.Close The script works like this: cscript.exe MSIUninstallFromUpgradeCode.vbs /UpgradeCode:<UpgradeCode> Example: cscript.exe MSIUninstallFromUpgradeCode.vbs /UpgradeCode:{529316F8-601C-48AB-BAF6-D9E09938D8D3} The script will log it´s activities to a logfile located here: c:\MSIUninstallFromUpgradeCode.log What it does is that it basically creates a query for the ProductCode based on what UpgradeCode you use as an argument when triggering the script. This makes it possible for us to create a uninstall command based on the UpgradeCode which in my opinion is great! So how do we use this in the best way possible? Upgrade scenarios of course! Here is how: 1. Start by creating a new SCCM package with nothing else but the script i supplied above. Don´t forget to add it to your distribution point. 2. Create another package containing the MSI installers of the software you want to upgrade to. Again, don´t forget the distribution point. 3. Okay, now lets create a new custom task sequence. Give it a good name and then right click on it and choose edit. 4. Let the fun begin! Create two default groups and name them "Uninstall" and "Install" 5. Under Uninstall create a "Run Command Line" Step. Input this command line: XCOPY ".\*.*" %temp% /D /E /C /I /Q /H /R /Y /S And make it run from the package containing your "MSIUninstallFromUpgradeCode.vbs" script 6. Create a new "Run Command Line" Step under uninstall group. Click on the option tab and click "Add Condition". Choose "installed software". Now browse for the MSI software that you want to uninstall. This can be either a new MSI Installer or the original (remember we are doing this based on the UpgradeCode NOT the ProductCode) Don´t forget to mark "Match any version of this product (UpgradeCode only)" 7. Before going back to the properties tab make sure you copy the UpgradeCode. 8. On the properties tab enter the following commandline: cscript.exe MSIUninstallFromUpgradeCode.vbs /UpgradeCode:<UpgradeCode> Replace <UpgradeCode> with the code you just copied from the options tab. Now make the command start running from %temp% by adding that value. Okay this means that the uninstall group is complete in our task sequence! If you followed my example above this will uninstall any version of iTunes on the computer where this task sequence is advertised. This is all good... But we want the newest version to get installed aswell! 1. Under the install groupl create a "Run Command Line" Step. Input this command line: XCOPY ".\*.*" %temp% /D /E /C /I /Q /H /R /Y /S And make it run from the package containing your new software MSI package/packages 2. Create a new "Run Command Line" Step under install group Add the following command: msiexec /i i <MSI Installer> REBOOT="ReallySuppress" /qn And make it run in this folder: %temp% Okay that is it! If you advertise this task sequence it will now uninstall any version and then install the newest version which is currently 10.1.2.17 Without the need of creating different collections based on what software they currently have and different programs for running different commands. This is all you need to do If your software requires many different parts you can do something like this: I hope you guys can find some good use of the info provided here. Feel free to get back to me with thoughts and improvements. Here is the task sequence if you want to import the finished thing example.xml Cheers 1 Quote Share this post Link to post Share on other sites More sharing options...
anyweb Posted February 24, 2011 Report post Posted February 24, 2011 excellent post Marcus thanks for sharing Quote Share this post Link to post Share on other sites More sharing options...
YiannosG Posted February 24, 2011 Report post Posted February 24, 2011 Thanks. was thinking of a way to have a general uninstall program for specific software like all versions of Firefox/Chrome. Could use the Uninstall part and keep the next part for future reference. Great post Quote Share this post Link to post Share on other sites More sharing options...
YiannosG Posted February 25, 2011 Report post Posted February 25, 2011 Hi again. Do you know a way to find any version of a program without the localization. As you can see from my screenshot i am able to uninstall all Firefox en-US but it is failing for GB. Only way is to edit my msi with an msi editor? What is the reason of having a condition if we want to uninstall all versions? If i remove the condition it can not find the software on the client to uninstall it. Quote Share this post Link to post Share on other sites More sharing options...
wmmayms Posted February 25, 2011 Report post Posted February 25, 2011 Hi again. Do you know a way to find any version of a program without the localization. As you can see from my screenshot i am able to uninstall all Firefox en-US but it is failing for GB. Only way is to edit my msi with an msi editor? What is the reason of having a condition if we want to uninstall all versions? If i remove the condition it can not find the software on the client to uninstall it. Hm good feedback! I have not had time to test it so much yet, and especially not in international enviroments But we must remember why we use the condition. This is to make it run only on computer which has the software targeted installed. To work around this problem you can simply remove the condition and let the script run on all computers targeted by the advertisement. If the script does not find a productcode for the given upgradecode it will do nothing. And the "c:\MSIUninstallFromUpgradeCode.log" (found locally on the client) will tell you that no productcode was found. I will look into the condition section to see if it is possible to use another condition under these circumstances. cheers! Quote Share this post Link to post Share on other sites More sharing options...
YiannosG Posted February 25, 2011 Report post Posted February 25, 2011 Hi thanks for replying. I actually made a collection based on Add/Remove Programs having %Firefox% installed so i know they have the program. but with the condition removed as well it does not work for a majority. Will have a look again on Monday and let you know if i found anything else. Quote Share this post Link to post Share on other sites More sharing options...
wmmayms Posted February 25, 2011 Report post Posted February 25, 2011 Hi thanks for replying. I actually made a collection based on Add/Remove Programs having %Firefox% installed so i know they have the program. but with the condition removed as well it does not work for a majority. Will have a look again on Monday and let you know if i found anything else. I would tick the "Continue on Error" box for the uninstall steps. Then i would also think about how the uninstall process works if the program or any of its dependencies are loaded when you trigger your command. This might make the uninstall process fail. The eventlog is a good place to find this information. If this is the case then maybe you need to run your upgrade while users are logged off. Or you might need to add a step for killing started processes before trying to uninstall. If you decide to do this I strongly recommend an optional advertisement or at least a long countdown time to not upset your customers to much PS: Chrome > Firefox Quote Share this post Link to post Share on other sites More sharing options...
YiannosG Posted February 25, 2011 Report post Posted February 25, 2011 I would tick the "Continue on Error" box for the uninstall steps. Then i would also think about how the uninstall process works if the program or any of its dependencies are loaded when you trigger your command. This might make the uninstall process fail. The eventlog is a good place to find this information. If this is the case then maybe you need to run your upgrade while users are logged off. Or you might need to add a step for killing started processes before trying to uninstall. If you decide to do this I strongly recommend an optional advertisement or at least a long countdown time to not upset your customers to much PS: Chrome > Firefox The script says that package not found so i don't think that continue on error will work. is as if its different upgradecode. Will check again. Well we use IE cause its manageable at work and ofcourse users can not use anything else since im blocking them from the proxy We are mean... Quote Share this post Link to post Share on other sites More sharing options...
YiannosG Posted February 28, 2011 Report post Posted February 28, 2011 Hi some more info: The upgrade ID is the same no matter the language, at least on Firefox Msi. But when i view the Resourse Explorer the product ID is Mozilla Firefox (Version) oh well Quote Share this post Link to post Share on other sites More sharing options...
Tracy Posted August 1, 2018 Report post Posted August 1, 2018 This is great - anyway to convert it to Powershell? Quote Share this post Link to post Share on other sites More sharing options...