Contents |
The Problem
At first it seems simple: you've had an app you created a few years back, and now you'd like to give it a new name, so what's the problem? Just type in the new name in the edit form of App Central for the app right?
Unfortunately, it turns out there are a lot of issues to consider, which can likely turn into problems you'll need to overcome. Some of the issues are listed below :
- The name of the app will need to be changed internally to the app (usually as a string in an associated .xml file) in order to match the new name (also perhaps as associated dialog titles or messages), along with the names of all the files (.vbs, .xml, and the .wepm usually at a minimum).
- Most apps have been written using an algorithm for finding the web URL for their XML updates page based on use of their current name.
App Central does allow for the accessing of the XML update page for each app where the address of the page is based on the app name stored in App Central's database. Therefore, when the name changes on App Central, this XML web page for the app's update information will no longer be available at it's former URL. This is a definite problem for any existing copies of the app which utilized this method of locating their XML update page.
- When an update is applied by Window-Eyes, it does not first uninstall the previous version of the app. Instead,it simply installs the updated version, relying on this installation to overwrite existing files with newer versions of the same name. When the name is changed however, this will leave the previous version of the app in place, and will simply end-up adding a second copy of the app, running under it's newer name (resulting in two copies of the app running together).
- At this point, if the older app is uninstalled (to try and correct the situation), and if there were files in both versions of the app whose names did not change, then these files will be deleted as part of the uninstallation process; this will likely cause errors in the newer copy of the app, which will now be missing some of it's needed files.
A Solution
A possible solution involves releasing the update to rename the app as a 3-step process, with a sufficiently long time between the second and the third steps to assure that users will have applied the update (which is the second step) before completing the third step (when this is done, any users who have yet to apply the part 2 update will no longer be able to do so via the automatic updates feature).
Warning
This article contains a small app which relies on data and file formats not documented by GW Micro; furthermore, these file types aren't guaranteed to continue to exist in future versions of Window-Eyes. This was written using Window-Eyes 7.5.1, so if you are using a later version, you should test and verify the accuracy of the included app before distributing it widely.
Step 1
The first step is to modify your app with a change to the url web page being used for it's XML updates. This doesn't mean you'll need to release this change as an update (although you certainly could, it wouldn't interfear with this process, it's just not necessary to be done separately).
App Central also allows for the accessing of each app's web page, and it's XML update page, by using a unique ID number assigned to the app as part of it's creation on App Central. After your app has been created on App Central, choose it from any of the App Central listings. On it's web page, you'll find a link to it's XML update page labeled "XML Feed for <app name>". Select this link, and you'll be taken to the XML update page. When on the XML update page, you can move to the address bar of your browser, and copy the URL to be used in your app, in place of the one which currently involves adding the app name to a string starting with "http". This URL will resemble:
https://www.gwmicro.com/App_Central/scriptTools.php?scriptid=1238&showXML&showChanges
And most importantly, this URL will work regardless of the name entered in App Central for the associated app.
Step 2
In this step, you will actually carry out the tasks of renaming your app (the part which runs on the user's pc, but not the App Central entry yet), and distribute it as an update.
This means modifying the app's name where-ever it may exist (as a string in an XML file, or as a string in the code itself), along with renaming all files involved. It's very important to rename every file which is included in the .wepm file, and the .wepm file itself. Renaming the files allows for them to be considered separately from the files which make up the app as it exists under it's older name; this is important because the older version of the app will need to be uninstalled, after the newer version has been installed, and you wouldn't want there to be any files in common between the two versions.
When all files have been updated and renamed, the associated .wepm file should be edited. Here you will need to change the app's name to it's new name, remove all the old files, and add all the new files. Don't forget to make the proper association for the primary file (either global or application-specific).
Finally, you will need to add an additional file which is a global app; it only executes one time, then it removes itself from the list of apps, and deletes its own program file. It's purpose is to uninstall the old version of your app, which it does by locating and deleting each of the files which were part of the original .wepm file; finally, it deletes your app (under it's old name) from the list of apps which are run by Window-Eyes.
You can also use this utility app to display a message to the user, which will only be displayed one time. You could as an example, advise the user that this update has renamed the app from <old name> to <new name>.
When you add this utility app to your .wepm file (and it can be named anything at all, the user will never see it hopefully), don't forget that it also needs an association, which should be "global" for it. And finally, "create" your .wepm package file.
An example of the utility app to include is listed below; you will need to make slight modifications to it to suit your situation. These usually are in the global portion of the app. However, if there are special files you may not want deleted, which were included in the original .wepm file, then you'll need to add tests for their names in this code, so they won't be deleted.
This was named WAF_initializer.vbs, and I included in a .wepm package when I was changing the name of the app from "MS Word" to "Word Advanced Features".
Note that one obvious change is in one of the very first lines, which calls a subroutine with the name of the app to be removed, and the name of the associated .we file if it's an application-specific app being removed. The line which will need to be edited is:
RemoveApp "MS Word", "winword.we"
The second parameter should just be an empty string if you are removing a global app.
And the other couple of lines which need editing are a few lines down, where this utility app removes itself; they need to be changed to reflect the name of the file you give this app:
If Not removeGlobalAssociation("WAF_initializer") Then
MsgBox "Failed to unload temporary global app WAF_initializer", vbExclamation + vbMsgBoxSetForeground + vbOKOnly, "Update to
Option Explicit ' used as part of the installation of Word Advanced Features ' it uninstalls the previous version, known as MS Word.
Dim oFSO Dim oCurFile
If foundApp("ms word") Then
RemoveApp "MS Word", "winword.we"
' here you can display a one-time message which displays at the time the update/rename is applied
MsgBox "Please note that the name of this app has changed from MS Word to Word Advanced Features.", _ vbExclamation + vbMsgBoxSetForeground + vbOKOnly, "Update to MS Word app" End If
' the following message is needed because this is a program-specific app MsgBox "Please note that the Word Advanced Features app does not have an entry in the App menu, and is not listed in the App Manager, until Word has been started.", _ vbExclamation + vbMsgBoxSetForeground + vbOKOnly, "Update to Word Advanced Features app"
' now remove this .vbs file
If Not removeGlobalAssociation("WAF_initializer") Then
MsgBox "Failed to unload temporary global app WAF_initializer", vbExclamation + vbMsgBoxSetForeground + vbOKOnly, "Update to MS Word app"
End If
Set oFSO = CreateObject("scripting.filesystemobject")
On Error Resume Next
Set oCurFile = oFSO.GetFile(clientInformation.scriptPath & "\waf_initializer.vbs")
oCurFile.Delete
On Error GoTo 0
stopScript
Function RemoveApp(ByVal theScriptName, ByVal associatedWEFile) ' returns true if an app has been removed (it's entire package) successfully ' set parameter AssociatedWEFile to a blank string if it's a global app.
If InStr(theScriptName, ".") = 0 Then theScriptName = theScriptName & ".vbs" End If
If associatedWEFile = "" Then ' it's a global script If Not removeGlobalAssociation(theScriptName) Then RemoveApp = False End If
Else ' AssociatedWEFile = "" Then ' it's associated with a program If Not removeProgramAssociation(theScriptName, associatedWEFile) Then RemoveApp = False End If End If ' AssociatedWEFile = "" Then
' now uninstall it's files uninstallFiles theScriptName
End Function
Function removeGlobalAssociation(ByVal theScriptName)
Dim wineyesINIPath
wineyesINIPath = clientInformation.scriptPath & "\wineyes.ini" removeGlobalAssociation = removeScriptFromINI(wineyesINIPath, theScriptName)
End Function
Function removeScriptFromINI(ByVal theINIFileName, ByVal theScriptName)
Dim myRegExp Dim match Dim matchCount Dim scriptList Dim lastEntry, theEntry
removeScriptFromINI = False
If InStr(theScriptName, ".") = 0 Then theScriptName = theScriptName & ".vbs" End If
Set myRegExp = New RegExp
myRegExp.Pattern = "Script\d+"
myRegExp.Global = True
myRegExp.IgnoreCase = True
Set scriptList = myRegExp.Execute(INIFile(theINIFileName).GetSectionKeys ("Scripts"))
If scriptList.Count = 0 Then
MsgBox "Unexpectedly failed to find any scripts in wineyes.ini", vbExclamation + vbMsgBoxSetForeground + vbOKOnly, "Update to MS Word app"
Exit Function
End If
matchCount = 1
' find the last entry first (having highest number) lastEntry = "0" For Each match In scriptList If CInt(Mid(match, 7)) > CInt(lastEntry) Then lastEntry = Mid(match, 7) Next lastEntry = "Script" & lastEntry
' search for the entry to be deleted
For Each match In scriptList
theEntry = Trim(INIFile(theINIFileName).text("Scripts", match))
If Left(theEntry, 1) = "*" Then theEntry = Trim(Mid(theEntry, 2)) ' remove disabled indicator
If LCase(theEntry) = LCase(theScriptName) Then
If matchCount <> scriptList.Count Then
' not the very last entry
' Update the current key with the last one
INIFile(theINIFileName).text("Scripts", match) = _
INIFile(theINIFileName).text("Scripts", lastEntry)
End If
' Nuke the last key INIFile(theINIFileName).DeleteEntry "Scripts", lastEntry
removeScriptFromINI = True Exit Function End If
matchCount = matchCount + 1 Next
removeScriptFromINI = False
End Function
Function foundApp(ByVal appName) ' returns true if the related file for this app is found in the uninstall dir
Dim uninstallFilename Dim oFSO
If InStr(appName, ".") > 0 Then
' remove extension
appName = Left(appName, InStr(appName, ".") - 1)
End If
Set oFSO = CreateObject("scripting.filesystemobject")
uninstallFilename = clientInformation.scriptPath & "\uninstall\" & appName & "."
If oFSO.FileExists(uninstallFilename) Then
' there is a file in the uninstall dir
foundApp = True
Else ' oFSO.FileExists(uninstallFilename) foundApp = False End If ' oFSO.FileExists(uninstallFilename)
End Function
Function removeProgramAssociation(ByVal theScriptName, ByVal associatedWEFile) ' open .WEFile and find this script in [scripts] section and remove it
removeProgramAssociation = removeScriptFromINI(associatedWEFile, theScriptName)
End Function
Function uninstallFiles(ByVal appName) ' open the related file for this script in the uninstall dir (which is in .ini format), get the list of installed files (from the [files] section), ' and remove each file
Dim fileList Dim curKey, curFileName Dim uninstallFilename Dim oFSO Dim oCurFile Dim retval
Speak "removing app " & appName
retval = True
If InStr(appName, ".") > 0 Then
' remove extension
appName = Left(appName, InStr(appName, ".") - 1)
End If
Set oFSO = CreateObject("scripting.filesystemobject")
uninstallFilename = clientInformation.scriptPath & "\uninstall\" & appName & "."
If oFSO.FileExists(uninstallFilename) Then
' there is a file in the uninstall dir, so process it's files and then delete it
fileList = Split(INIFile(uninstallFilename).GetSectionKeys("files"), vbNullChar)
If UBound(fileList) < 0 Then
retval = False
Exit Function
End If
For Each curKey In fileList
curFileName = clientInformation.scriptPath & "\" & Trim(INIFile(uninstallFilename).text("files", curKey, ""))
If oFSO.FileExists(curFileName) Then
Set oCurFile = oFSO.GetFile(curFileName)
On Error Resume Next
oCurFile.Delete
If Err.Number <> 0 Then retval = False
On Error GoTo 0
Else ' oFSO.FileExists(curFilename) MsgBox "Could not find file to be uninstalled: " & curFileName, vbOKOnly + vbExclamation, "Script Uninstall Message" retval = False End If ' oFSO.FileExists(curFilename) Next
Set oCurFile = oFSO.GetFile(uninstallFilename) On Error Resume Next oCurFile.Delete If Err.Number <> 0 Then retval = False On Error GoTo 0
Else ' oFSO.FileExists(uninstallFilename) retval = False MsgBox "Could not find uninstall file: " & uninstallFilename, vbOKOnly + vbExclamation, "Script Uninstall Message" End If ' oFSO.FileExists(uninstallFilename)
End Function
Step 3
Once you release the update described above, you will need to allow some time to pass. During this time, users will be running the app under it's new name (as the update is applied), but it will continue to exist on App Central under it's old name. This is absolutely necessary, in order that the older copies are able to find the needed XML update page, which allows them to apply this update, and so get the new name. I'd recommend a minimum of two weeks.
Once you feel enough time has passed so that everyone has updated, you can then complete this project by editing the App Central entry, and change the name of the app! Just remember, once done, anyone with an old copy of the app won't be able to use the automatic update feature to get this new update; you can however email it to them, or instruct them to visit the web page and download the app and install it manually. It will rename everything to use the new name, even if installed manually.


