Saturday, April 30, 2005

Cleaning up the Recent Workspaces list

You know that option in PowerBuilder under Tools -> Options -> Workspaces, the command button marked "Clean Up"? It scans the registry and automatically removes references to workspaces and targets that are no longer available.

What drives me nuts is that is that the one thing that option doesn't to is clean up the File -> Recent Workspaces list. That's something I use quite frequenty, and I wish the Clean Up option would address it too.





Well, until it does, I wrote a little add in for PowerBuilder to do it for me. The Workspace MRU list is also kept in the registry. Under the HKEY_CURRENT_USERSoftwareSybasePowerBuilderXX.0 key (where XX is the major version of PowerBuilder) there is a Workspace subkey that has an entry for each item on the MRUList. There is also an MRUList entry which shows the order the entries should appear in.

What the utility does is loop through the items in the Workspace subkey, pulling out the reference to the location of the workspace file. If then determines if that file still exists:

GetEnvironment(lenv)
ls_key = "HKEY_CURRENT_USERSoftwareSybasePowerBuilder"
ls_key += String ( lenv.PBMajorRevision ) + ".0WorkspaceMRUList"

RegistryValues ( ls_key, ls_mru[] )
RegistryGet ( ls_key, "MRUList", RegString!, ls_mrulist )

li_count = UpperBound ( ls_mru )

FOR li_index = 1 TO li_count
IF ls_mru[li_index] = "MRUList" THEN CONTINUE
//Get the workspace reference
RegistryGet ( ls_key, ls_mru[li_index], RegString!, ls_mruitem )

The entries contain some extraneous data, and some encoded data, so we have to process the entry before we can use it.

//Strip off "workspace:///" from the beginning and "?action=open&entry" from the end
ls_mruitem = Mid ( ls_mruitem, 14, Len ( ls_mruitem ) - 31 )
//Replace | with :
li_pos = Pos ( ls_mruitem, '|' )
DO WHILE li_pos > 0
ls_mruitem = Replace ( ls_mruitem, li_pos, 1, ':' )
li_pos = Pos ( ls_mruitem, '|' )
LOOP
//Replace %20 with space
li_pos = Pos ( ls_mruitem, '%20' )
DO WHILE li_pos > 0
ls_mruitem = Replace ( ls_mruitem, li_pos, 3, ' ' )
li_pos = Pos ( ls_mruitem, '%20' )
LOOP
//Replace / with
li_pos = Pos ( ls_mruitem, '/' )
DO WHILE li_pos > 0
ls_mruitem = Replace ( ls_mruitem, li_pos, 1, '' )
li_pos = Pos ( ls_mruitem, '/' )
LOOP

Then we check to see if the file exists. If not, we delete that entry from the registry and remove the number that represents that item from the MRUList entry.

//See if the workspace is still there
IF NOT FileExists ( ls_mruitem ) THEN
//If not, delete the registry key
RegistryDelete ( ls_key, ls_mru[li_index] )
//And delete the item from the MRUList order
li_pos = Pos ( ls_mrulist, ls_mru[li_index] )
IF li_pos > 0 THEN
ls_mrulist = Replace ( ls_mrulist, li_pos, 1, '' )
END IF
//Replace the MRUlist order entry
RegistrySet ( ls_key, 'MRUList', RegString!, ls_mrulist )
END IF
NEXT

Once we're done, we notify the user that they will need to restart PowerBuilder for the change to become effective. Apparently PowerBuilder only reads those entries on the initial load of the IDE.

The utility is designed to be compiled into a PBD and then added to the Tools pane on the New dialog within PowerBuilder using the registry entry method of customizing the PowerBuilder IDE that I've discussed previously. The entire utility, including the compiled PBDs and the registry entries needed to add it to that dialog are available on CodeXchange.

No comments: