Hi,

I am creating an msi file to install a program but if the old version is already installed on the pc it needs to have the old version uninstalled first. I will be running the msi with a transform file but have edited the msi to include a custom script to check if the old version is installed first and if so uninstall it before installing the new version.

However when I run the cmd line for the msi and mst it errors saying that there is an old version on the pc already so it is obviously ignoring my line in the script to uinstall.

This is the script I have got:-

Option Explicit
Dim objShell, objFSO, WScript, strcomputer, strPath
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strPath = "C:\Program Files\Bentley\MX"
' ####### Search PC for Bentley MX V8 #######
' ###########################################
If objFSO.FileExists("C:\Program Files\Bentley\MX\mfw\inst\uninst\setup.exe") Then
'#### Uninstall old Bentley MX V8 ####
'#####################################
CopyFile "\\ntserv01\sms\Bentley XM\Bentley MX\Bentley MX V8 XM\setup.iss", "C:\Program Files\Bentley\MX\mfw\inst\uninst\"
objShell.Run "cmd /c CD c:.. & cd Program Files\Bentley\MX\mfw\inst\uninst\ & setup.exe -s -f1setup.iss"
'WScript.Sleep(150000)
End If
' ######## CopyFile Function ########
Sub CopyFile(strSource, strDest)
Dim lfsObject
Dim Source
On Error Resume Next
Set lfsObject = CreateObject("Scripting.FileSystemObject")
Set Source = lfsObject.GetFile(strSource)
Source.Copy strDest
Set lfsObject = nothing
If Err.Number <> 0 Then WriteErr( strUserID & ": Copy " & strSource & " to " & strDest & " " & Err.Description & " " & Now() )
End Sub
'WScript.quit

The copy file part works so I know it is running the script and detects the old version on there but it seems to not even attempt to uninstall it.

Can anyone offer me some advice to how to get this to work? I am new to scripting and have never done custom actions in msi before!

Thanks
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
objShell.Run "cmd /c CD c:.. & cd Program Files\Bentley\MX\mfw\inst\uninst\ & setup.exe -s -f1setup.iss" Hi, Sarah. I can't see how this part of the script would ever run. Apart from anything else, you'd need quote marks around the paths. I wouldn't bother with launching CMD, either, as you're launching a console which then runs a windowing app! How about (untested, just OTTOMH):

Dim strCmdLine

strPath = strPath & "\mfw\inst\uninst"
strCmdLine = Chr(34) & strPath & "\setup.exe & Chr(34) & " -s -f1" & Chr(34) & strPath & Chr(34) & "\setup.iss" & Chr(34)
objShell.Run strCmdLine
Answered 05/16/2008 by: VBScab
Red Belt

Please log in to comment
0
Thanks, I have now modified my script and when run on its own it works fine but when I add this script into the custom actions in my msi it still seems to ignore the script and just try to install the new software.

Am I missing something obvious??
Answered 05/16/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
Where do you have the script sequenced, User Interface, Execute Immediate or Execute Deferred? If ED, what context did you select for its execution?
Answered 05/16/2008 by: VBScab
Red Belt

Please log in to comment
0
It is in the Installation Sequence under Execute. The In-Script Execution is set to Immediate Execution and I have set it to be the FirstAction to be run.
Answered 05/16/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
Why don't you use the uninstall registry key?? located in

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

and do a simple script which will get the uninstall string.


it's more simple!
Answered 05/16/2008 by: jmpouliot
Second Degree Blue Belt

Please log in to comment
0
ORIGINAL: jmpouliot
Why don't you use the uninstall registry key?? located in

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

and do a simple script which will get the uninstall string.
Jean, you have assumed that the old install was MSI-based. The giveaway that it isn't is the reference to an ISS file. These are files containing recorded installation steps and get passed to an InstallShield set-up stub executeable.
Answered 05/16/2008 by: VBScab
Red Belt

Please log in to comment
0
ORIGINAL: VBScab

ORIGINAL: jmpouliot
Why don't you use the uninstall registry key?? located in

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

and do a simple script which will get the uninstall string.
Jean, you have assumed that the old install was MSI-based. The giveaway that it isn't is the reference to an ISS file. These are files containing recorded installation steps and get passed to an InstallShield set-up stub executeable.



yeah I forgot, you got a point !!
Answered 05/16/2008 by: jmpouliot
Second Degree Blue Belt

Please log in to comment
0
VBScab is right, the uninstall string is for an exe and not msi based :(

Does anyone know about the custom actions and why it doesn't seem to be looking at it?
Answered 05/19/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
Sarah, have you logged the installation with a verbose log file? Other than running the MSI through a debugger, that's the only way you're going to know if the CA is being run.
Answered 05/19/2008 by: VBScab
Red Belt

Please log in to comment
0
Have you installed the msi + mst with logging, you may spot something obvious?

It sounds like you haven't but are there any conditions on the CA?
Answered 05/19/2008 by: timmsie
Fourth Degree Brown Belt

Please log in to comment
0
I have set logging on it and everything comes back with a return value of 1 but the lines for my script are:-

Action start 10:19:32: CheckOldVersionInstalled.
Action ended 10:19:33: CheckOldVersionInstalled. Return value 0.

So it is trying to run it but seems to fail but I'm not sure why!
Answered 05/19/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
In my script it copies the iss file to the pc and then is supposed to run the uninstall using the iss file. I have run the msi + mst and logged it and it comes back with the Return value of 0 but I have checked and it has copied the iss file, it just never seems to of run the uninstall.

Below is a copy of my script incase you can spot anything obvious?!?! Also, it didn't like wscript.sleep command, what command can I use to make it wait a couple of mins for the uninstall to happen before it moves onto the next action?

Dim strCmdLine, objShell, strpath
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strPath = "C:\Program Files\Bentley\MX\mfw\inst\uninst"
'If objFSO.FileExists(Chr(34) & strPath & "\setup.exe" & Chr(34)) Then
'#### Uninstall old Bentley MX V8 ####
'#####################################
CopyFile "\\ntserv01\sms\Bentley XM\Bentley MX\Bentley MX V8 XM\setup.iss", strpath & "\"
strCmdLine = Chr(34) & strPath & "\setup.exe" & Chr(34) & " -s -f1" & Chr(34) & strPath & "\setup.iss" & Chr(34)
objShell.Run strCmdLine
' WScript.Sleep(150000)
'End If
' ######## CopyFile Function ########
Sub CopyFile(strSource, strDest)
Dim lfsObject
Dim Source
On Error Resume Next
Set lfsObject = CreateObject("Scripting.FileSystemObject")
Set Source = lfsObject.GetFile(strSource)
Source.Copy strDest
Set lfsObject = nothing
If Err.Number <> 0 Then WriteErr( strUserID & ": Copy " & strSource & " to " & strDest & " " & Err.Description & " " & Now() )
End Sub
Answered 05/19/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
ORIGINAL: SarahG
Also, it didn't like wscript.sleep command, what command can I use to make it wait a couple of mins for the uninstall to happen before it moves onto the next action?
You can't use any 'WScript[dot]' directive bcause that is explicitly for Windows Scripting Host. The VB Script engine in Windows Installer is self-contained and knows nothing of WSH.

Here's a delay Sub:

Sub Sleep(ByVal intDelayInSecs)
Dim datStart
Dim blnCompleted

datStart = Now()
blnCompleted = False

While Not blnCompleted
If DateDiff("s", datStart, Now()) >= CInt(intDelayInSecs) Then
blnCompleted = True
End If
Wend
End Sub
However, because your script has no control over how long the uninstall will take, it would be much neater to wait in a loop until the folder has been deleted, then wait another couple of seconds, THEN continue.

On that point, I wonder if the uninstall is failing because it's trying to remove the folder but cannot because it contains the ISS file? Try copying the ISS file to %TEMP% instead.
Answered 05/19/2008 by: VBScab
Red Belt

Please log in to comment
0
Ahh so is that why my uninstall isn't working as I have the line Set objShell = CreateObject("WScript.Shell") in there? How do I go about running the uninstall then without using that wscript.shell??

Thanks for the delay sub, do I run it by having sleep 120 in there?

Sorry for my apparent ignorance at this scripting malarky, as I said, I am new to it especially now I can't use wscript!
Answered 05/19/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
No, not at all. If you had this:

. Set objShell = WScript.CreateObject("WScript.Shell")

then THAT would fail.

As for the delay, I would use it for now, passing in the number of seconds that you want the delay to wait, yes. Long term, I'd highly recommend using the folder existence loop I mentioned.
Answered 05/19/2008 by: VBScab
Red Belt

Please log in to comment
0
Ahh, after leaving my pc alone for a while after I thought it had failed I noticed that the uninstall part carried on and finally did uninstall the product. I added in your sleep sub and now it has time to uninstall before the new install starts! :) HURRAH! So it looks like it was the wscript.sleep line that was the problem all along!

If I have the old version of the software installed and I comment out the IF statement lines it runs fine, uninstalls and installs new version. However, I do need it to check if the old product exists on the pc so it only runs the script if the software exists and ignores the script if it isn't installed. Should I be able to use IF statements in MSI VB Scripting or is it a different type of code for this?

Many thanks for all your help so far VBScab, Very Much Appreciated!! :)
Answered 05/19/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
There's no reason why you couldn't add it to your script but the "best practise" way to do this would be to create a property and give it a nonsense value, e.g. 0 or "NotPresent". Then you'd use AppSearch to populate that property if a file or registry entry relating to the old product was present. Then, you'd add a condition to the one which your CA hopefully already has (If NOT Installed) which tests for that property NOT being the nonsense value. Thus, if your property was 'ISV5PRESENT' with a default value of 0, your CA's condition would change from

. If NOT Installed

to

. If NOT Installed AND ISV5PRESENT<>0

Do remember to ditch the delay functionality in your release version. I appreciate you're new to scripting but lessons learned now will serve you well in the future. Too many scripts make assumptions about software environments and, whilst they work in a perfect environment, when was the last time YOU worked in such an environment? The sort of thing I'm talking about would be, for example, if your script has code to create a directory, it should check immediately aftertrwards whether that directory got created and not simply rely on an error being generated by the scripting runtime.

Good luck!
Answered 05/19/2008 by: VBScab
Red Belt

Please log in to comment
0
Hi,

I have finally figured out what AppSearch is and think I have done it right. I have my Install Condition to be MXV8INSTALLED <> V8Installed but it doesn't seem to be running my script. When I run the msi I have looked at the log file it creates and I still get:-

Action start 10:45:40: AppSearch.
Action ended 10:45:40: AppSearch. Return value 1.
Action start 10:45:40: CheckOldVersionInstalled.
Action ended 10:48:40: CheckOldVersionInstalled. Return value 0.

Shouldn't my CheckOldVersionInstalled have a return value of 1 if it has run?
Answered 05/23/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
ORIGINAL: SarahG
Shouldn't my CheckOldVersionInstalled have a return value of 1 if it has run?
The value '1' doesn't mean that it's run: it means that it returned a value "ERROR_SUCCESS". Yet another perversity of WI is that the engine translates success values (normally 0 in Wndows) to '1'. So, your log entry 'Return value 0.' means that no success value was returned.

That doesn't necessarily mean that the script failed, only that it didn't reurn a success value.You need to force it to do that.

- Move your code into a function
- Change the script type to 'Executefrom installation' and add the function call name.
- Have your script exit with whatever the return value from the function was. For example:


Dim intReturn

intReturn = Main()
WScript.Quit(intReturn) '// Note that we can use WScript directive here because the script is external to the WI engine

Function Main()
Dim blnReturn

'// Always assume the worst
Main = 3 '// 3 is interpreted as 'Fatal error'

'// Do something which could succeed or fail
blnReturn = CallSomeOtherFunctionOrSub
If blnReturn = False Then
Exit Function
End If

Main = 0
End Function
Now, if the call CallSomeOtherFunctionOrSub is successful, Main returns 0 which WI will translate to 1 and you'll get the desired result.

Lastly, I don't think the value being returned in your current script is being acted on, as the install continues even though the CA didn't succeed. Make sure you have the processing option for the CA to NOT ignore errors, if you want the install to stop if removal of th eold version fails.
Answered 05/23/2008 by: VBScab
Red Belt

Please log in to comment
0
I have figured out why my script didnt appear to be working, it was a rookie error, it was set to copy a file from a location; only I forgot I changed the directory name the other day so it's issue was that it couldn't find it!! Grrrr!

I read your post from the other day where you told me to ditch the sleep function in my final msi but how else can I make it wait while the uninstall happens via my script before the main msi carries on and installs the new version?

Sorry to keep asking questions about all this!
Answered 05/23/2008 by: SarahG
Senior Yellow Belt

Please log in to comment
0
Well, if it makes you feel any better, I see scripts like that all the time and is why I keep banging on about robust code. For example, if you're going to use 'On Error Resume Next', you *MUST* check for errors after *EACH* operation. Thus, in your example, the line 'Set Source = lfsObject.GetFile(strSource)' would have produced an error, since (as you now know) the source file doesn't exist.

In my Production code, I typically use a routine which parses a file's path and checks that each part of it exists. Thus, for any error, I can tell the user EXACTLY which folder is missing.

OK, coming the Sleep part, did I say you should ditch it? I think I said you should not rely on a simple delay but should check for the folder's removal. You can do that but you need to retain the delay. Once you've added the robustness noted above, you will know how to test for a folder's existence. Thus, your code might look something like this:

While objFSO.FolderExists(strPath)
Call Delay(1) '// Just twiddle your thumbs for 1 second
Wend
'// Carry on with next part of the script


or

Do
Call Delay(1)
Loop Until Not objFSO.FolderExists(strPath)
'// Carry on with next part of the script


NB!
If this were me, I'd build in ANOTHER loop so that, if for some reason the folder didn't get deleted, the script would continue in some capacity. As the code above is now, it would loop forever! I'm sure by now, though, you get the idea.
Answered 05/23/2008 by: VBScab
Red Belt

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