So I wanted to install RealmCrafter, but I found it it would mess up trying to read drives over about E:. I'd installed it to I:, so this was a problem.
So I decided to sort my drives out...
See I had 3 hard drives, and drive letters like:
C:\ 5G "Boot" part'n on Drive 1
D:\ 20G "OS" part'n on Drive 1
(& a ton of wasted space on drive 1...)
E:\ 180G "Backup" drive, all of a removable drive.
F:\ 180G "Media" drive, all of drive 2.
G:\ DVD Drive
H:\ 64M Thumbdrive
I:\ 180G "Apps" drive, all of drive 3.
J:\ Encrypted TrueCrypt drive for password file on thumbdrive
K:\ and onwards are virtual drives for things like Daemon tools, other truecrypt drives, etc.
How had it got like this?
Back in the 90s, I started out like everyone else, with everything on C:, a CD drive on D:. So there was C:\windows, c:\program files, C:\autoexec.bat, and so on...
I upgraded my drives over the years, going from 120M to about 5G.
As time wore on, my 5G drive filled up, as they do. So I bought another 20G drive, D:, and installed all future programs to "program files" on that.
And then I upgraded to Win2k. Well, that got installed to D:\win2k\ of course, because that's where there was space, and I didn't want to trash 95, I wanted to dual boot!
So D: became the OS drive, apart from the programs already on it, and I got another drive, 180G, I:, on which I installed all future apps. (I'm simplifying, I've gone through lots more drives than this really).
Now, years later, those original two partitions have been copied over to a new disk, but were left as they were because... well partly because this layout is really handy for testing installers (I've also set most of my shell paths to abnormal places for this reason). Back in the '95 days tstuff would try to write to C:\windows or c:\program files, and I could notice that. But the biggest reason I kept it like that was that changing drive letters would be a nightmare.
But today I decided the time had come, after 8 years, to face this nightmare.
First step was of course to plan it all out.
My tool of choice for this is PartitionMagic (PM) - it has almost never let me down, and has bailed me out so many times. Great utility, I couldn't imagine doing stuff like this, or even basic disk stuff, without it.
* Have a general clear-out. Empty caches, delete unused programs, etc.
* Scan C: and D: with Windows' scandisk for any problems and fix them.
* Delete that \r\n file that's been bugging me. I had a file with the filename "0x0D0A": two invalid bytes long. I was unsure if partition manipulation would barf on this, so I Even the normally wonderful freeware UnLocker (the best file unlocking/deleting app I've yet found) could not delete it. In the end I used the for-pay program WinHex, which has got to be the best disk editor I've every played with. I'm sticking it right next to Partition Magic in my recovery tools. This was the only utility I found which even noticed there was anything odd about this file. Using this program, I was able to hex edit the directory entries - basically just overwriting the bad directory entry with the entry for an adjacent deleted file.
* Reboot to scan the disk surface for problems. None found, but still wise. I suspect windows' scandisk only scans allocated space, so for this I used PM to create a partition in the free space, and scanned that as well as the two existing drives. I'm sure there are better apps for scanning disks than this. I also ran Power Defragmenter (a windows Gui around SysInternals' defrag engine) to make sure everything was tidy.
* Back everything up.
* Convert C: and D: to NTFS. Could have done this at a much later stage, but it seemed sensible to do it early on, so everything would be using the same format.
* Use PM to copy both partitions into the ton of unused space on that drive. At first I tried merging the copied partitions using PM, but it barfed on that, so instead I enlarged the "copy of C:" so it could hold all the files from the "copy of D:".
* Back in Windows, manually copy everything from "copy of D:" into the "copy of C:". I would have had to do this even using PM's "merge" option, since the merge places all files on the hard drive into a subdirectory, like "D:\CopyOfE\", so I woulda had to move everything out. There was some faff merging the program files dirs, since some apps had folders from both C and D, but I just went with the newest version in each case. Knowing the "shift-click 'no' means 'no to all'" trick really helped here - meant I could drag-move a folder's contents like "Program Files"'s, and click shift-no to leave any folders that already existed, so I could deal with them manually in turn.
* Use PM to delete the "copy of D:" and move the original D: to the end of the disk.
* Check it'll still boot (I did this after prettymuch every PM change. Slower, but MUCH better than setting a whole queue of PM actions to go, then have the queue barf halfway through and find you can't boot).
* Edit boot.ini so that I have a menu option for partition numbers 1-5 on that disk, just in case. I mean, the new C: *should* be partition 1, just like the old one, but I'm paranoid...
* Delete the original C: and move the merged copy to replace it at the start of the disk.
* Pray it still boots... it did, using the menu option for partition 2. So I have a partition 2 and no partition 1. OK.
* Run the PM drive letter changer.
* Do a registry search-replace to move everything from D: to C: that PM missed. For this I used Funduc's Registry Toolkit since it lets you search/replace regular expression bulk search-replaces - I woulda liked proper Perl-style regexes though, I wanted "\bD:".
* Reboot, repeat last two steps to be sure you caught everything.
* I had to fix a few apps that had broken in the move. Editpad Pro needed re-registering. The freeware apps VLC and AVG needed reinstalling. All the connection titles in SecureCRT became uppercase, I suspect that's from the change from Fat32 to NTFS.
* Finally, the PM letter changer only works for valid shortcuts. I had a few shortcuts that were not valid but which I wanted to redirect anyway: shortcuts to folders I'd archived off but might restore at some point, that kinda thing.
For that, I stole some code by Rob Dunn which searches through a folder tree and replaces the servername in all shortcut paths, and modified it so that it could also change drives and paths as well as servernames.
Sorry, I'm too lazy to update the generated HTML to be "proper", at least unless someone shows an interest in it.
My first experience of vBscript - what a very basic language! Goto and subroutines but no return or continue... <> instead of !=, And instead of &&, = instead of ==. Now that, more than plots of games, takes me back to my childhood, and Spectrum BASIC.
So I decided to sort my drives out...
See I had 3 hard drives, and drive letters like:
C:\ 5G "Boot" part'n on Drive 1
D:\ 20G "OS" part'n on Drive 1
(& a ton of wasted space on drive 1...)
E:\ 180G "Backup" drive, all of a removable drive.
F:\ 180G "Media" drive, all of drive 2.
G:\ DVD Drive
H:\ 64M Thumbdrive
I:\ 180G "Apps" drive, all of drive 3.
J:\ Encrypted TrueCrypt drive for password file on thumbdrive
K:\ and onwards are virtual drives for things like Daemon tools, other truecrypt drives, etc.
How had it got like this?
Back in the 90s, I started out like everyone else, with everything on C:, a CD drive on D:. So there was C:\windows, c:\program files, C:\autoexec.bat, and so on...
I upgraded my drives over the years, going from 120M to about 5G.
As time wore on, my 5G drive filled up, as they do. So I bought another 20G drive, D:, and installed all future programs to "program files" on that.
And then I upgraded to Win2k. Well, that got installed to D:\win2k\ of course, because that's where there was space, and I didn't want to trash 95, I wanted to dual boot!
So D: became the OS drive, apart from the programs already on it, and I got another drive, 180G, I:, on which I installed all future apps. (I'm simplifying, I've gone through lots more drives than this really).
Now, years later, those original two partitions have been copied over to a new disk, but were left as they were because... well partly because this layout is really handy for testing installers (I've also set most of my shell paths to abnormal places for this reason). Back in the '95 days tstuff would try to write to C:\windows or c:\program files, and I could notice that. But the biggest reason I kept it like that was that changing drive letters would be a nightmare.
But today I decided the time had come, after 8 years, to face this nightmare.
First step was of course to plan it all out.
My tool of choice for this is PartitionMagic (PM) - it has almost never let me down, and has bailed me out so many times. Great utility, I couldn't imagine doing stuff like this, or even basic disk stuff, without it.
* Have a general clear-out. Empty caches, delete unused programs, etc.
* Scan C: and D: with Windows' scandisk for any problems and fix them.
* Delete that \r\n file that's been bugging me. I had a file with the filename "0x0D0A": two invalid bytes long. I was unsure if partition manipulation would barf on this, so I Even the normally wonderful freeware UnLocker (the best file unlocking/deleting app I've yet found) could not delete it. In the end I used the for-pay program WinHex, which has got to be the best disk editor I've every played with. I'm sticking it right next to Partition Magic in my recovery tools. This was the only utility I found which even noticed there was anything odd about this file. Using this program, I was able to hex edit the directory entries - basically just overwriting the bad directory entry with the entry for an adjacent deleted file.
* Reboot to scan the disk surface for problems. None found, but still wise. I suspect windows' scandisk only scans allocated space, so for this I used PM to create a partition in the free space, and scanned that as well as the two existing drives. I'm sure there are better apps for scanning disks than this. I also ran Power Defragmenter (a windows Gui around SysInternals' defrag engine) to make sure everything was tidy.
* Back everything up.
* Convert C: and D: to NTFS. Could have done this at a much later stage, but it seemed sensible to do it early on, so everything would be using the same format.
* Use PM to copy both partitions into the ton of unused space on that drive. At first I tried merging the copied partitions using PM, but it barfed on that, so instead I enlarged the "copy of C:" so it could hold all the files from the "copy of D:".
* Back in Windows, manually copy everything from "copy of D:" into the "copy of C:". I would have had to do this even using PM's "merge" option, since the merge places all files on the hard drive into a subdirectory, like "D:\CopyOfE\", so I woulda had to move everything out. There was some faff merging the program files dirs, since some apps had folders from both C and D, but I just went with the newest version in each case. Knowing the "shift-click 'no' means 'no to all'" trick really helped here - meant I could drag-move a folder's contents like "Program Files"'s, and click shift-no to leave any folders that already existed, so I could deal with them manually in turn.
* Use PM to delete the "copy of D:" and move the original D: to the end of the disk.
* Check it'll still boot (I did this after prettymuch every PM change. Slower, but MUCH better than setting a whole queue of PM actions to go, then have the queue barf halfway through and find you can't boot).
* Edit boot.ini so that I have a menu option for partition numbers 1-5 on that disk, just in case. I mean, the new C: *should* be partition 1, just like the old one, but I'm paranoid...
* Delete the original C: and move the merged copy to replace it at the start of the disk.
* Pray it still boots... it did, using the menu option for partition 2. So I have a partition 2 and no partition 1. OK.
* Run the PM drive letter changer.
* Do a registry search-replace to move everything from D: to C: that PM missed. For this I used Funduc's Registry Toolkit since it lets you search/replace regular expression bulk search-replaces - I woulda liked proper Perl-style regexes though, I wanted "\bD:".
* Reboot, repeat last two steps to be sure you caught everything.
* I had to fix a few apps that had broken in the move. Editpad Pro needed re-registering. The freeware apps VLC and AVG needed reinstalling. All the connection titles in SecureCRT became uppercase, I suspect that's from the change from Fat32 to NTFS.
* Finally, the PM letter changer only works for valid shortcuts. I had a few shortcuts that were not valid but which I wanted to redirect anyway: shortcuts to folders I'd archived off but might restore at some point, that kinda thing.
For that, I stole some code by Rob Dunn which searches through a folder tree and replaces the servername in all shortcut paths, and modified it so that it could also change drives and paths as well as servernames.
Sorry, I'm too lazy to update the generated HTML to be "proper", at least unless someone shows an interest in it.
My first experience of vBscript - what a very basic language! Goto and subroutines but no return or continue... <> instead of !=, And instead of &&, = instead of ==. Now that, more than plots of games, takes me back to my childhood, and Spectrum BASIC.
'~~Author~~. Rob Dunn
'~~Updated slightly by~~. Dewi Morgan, Jan 2008
'~~Blatently borrowed a little bit of code from~~. Jim de Graff
'~~Email_Address~~. qc_metal@hotmail.com
'~~Script_Type~~. vbscript
'~~Sub_Type~~. SystemAdministration
'~~Keywords~~. Update Shortcuts Migrate New Server Desktop lnk
'~~Script~~.
Dim Silent, CurTime
Dim newlink, oldfull, fullname, oldfile, targetpath
Dim w, ws
const ForReading = 1
const ForWriting = 2
const ForAppending = 8
On Error Resume Next
'Find current time that the script runs
set wso = CreateObject("Wscript.Shell")
set fso = CreateObject("Scripting.FileSystemObject")
' pull the system's process variables (we'll be using TEMP
' for the output file and WINDIR for default location of
' user's desktop folder - whether 9x or NT/2k/XP)
Set WshSysEnv = wso.Environment("PROCESS")
'pull the system's profile environment variable
userprofile = wso.ExpandEnvironmentStrings("%userprofile%")
'set your variables here
'silent = 0/1/2
' 0 - verbose
' 1 - turns off verification prompts
' 2 - turns off verification and initial config prompts
'curserver = server string you wish to replace
'newserver = server string you wish to change curserver to above server vars
' are needed only for when silent = 2
'ouputfile = location of output filename, you can use a string in place of
' all the code after the equal sign (i.e. outputfile = "x:\temp," etc.)
'curtime = finds time of execution of script
Silent = 0
OSType = WshSysEnv("OS")
CurServer = "//oldsrvrname/oldpath"
NewServer = "//newsrvrname/newpath"
OutputFile = WshSysEnv("TEMP") & "\" & "migrate_shortcuts_log.htm"
CurTime = Now
WinDirectory = WshSysEnv("WINDIR")
If OSType <> "Windows_NT" Then
CheckFolder = Windirectory & "\desktop"
Else
CheckFolder = userprofile & "\desktop"
End If
'check to see if ouputfile exists or not, deletes it if it does
If CheckFileExists(OutputFile) Then
Set oldfile = fso.GetFile(OutputFile)
oldfile.Delete
Else
'wscript.echo oldfile & " does not yet exist."
End If
If Silent <= 1 Then
Call CServer
End If
Dim msg, title
msg = "Enter a '//Servername' or 'drive:' to search for in your shortcuts."
title = "Enter old target."
CurServer = getShortcutPath(msg, title, CurServer)
msg = "Enter a '//Servername' or 'drive:' to replace " & CurServer & " with."
title = "Enter replacement."
NewServer = getShortcutPath(msg, title, NewServer)
call CFolder
'set fso = Nothing
'set wso = Nothing
'Start writing the HTM Log file...
Set w = fso.OpenTextFile (OutputFile, ForAppending, True)
w.Writeline ("<html>")
w.Writeline ("<title>Changing Shortcuts in root folder " & CheckFolder & "</title>")
w.Writeline ("<table BORDER=0 width=100% cellspacing=0 cellpadding=3>")
w.Writeline ("<tr>")
w.Writeline ("<th bgcolor=#000080 colspan=3 width=100>")
w.Writeline ("<p align=left>")
w.Writeline ("</th>")
w.Writeline ("</tr>")
w.Writeline ("<h0><B><font face=Arial color=#000033 size=2>Shortcuts located in: <font color=#CC0000> "_
& CheckFolder & " <font face=Arial color=#000033 size=2>, searching recursively at " & CurTime & "</B></font></h0>")
w.WriteLine ("<TR bgcolor=gray colspan=3 width=100>")
w.WriteLine ("<TD><font face=Arial size=1 color=white> Shortcut Path</font></TD>")
w.WriteLine ("<TD><font face=Arial size=1 color=white> Target Path</font></TD>")
w.WriteLine ("<TD><font face=Arial size=1 color=white> Updated to</font></TD>")
w.WriteLine ("</TR>")
'process the shortcuts
ModifyLinks CheckFolder
w.Writeline ("</html>")
'if silent = 2, then it will not open the log file
If Silent <= 1 Then
'set command variable with path in quotes (for long filenames)
Command = Chr(34) & OutputFile & Chr(34)
'run htm file in your default browser
wso.Run Command
End If
' The End.
wscript.quit
'--------------------
' Subs and functions follow.
'--------------------
Function getShortcutPath(msg, title,defaultpath)
Path = InputBox (msg,title,defaultpath)
Do While (Path = "") Or ((InStr(Path, "//") <> 1) And (InStr(Path, ":") <> 2))
If Path = "" Then
MsgBox "Input cancelled, quitting."
wscript.quit
End If
MsgBox "Drives must be a single driveletter and a ':' colon;" & VBCrlf & "servers must be a '//' doubleslash and a servername." & VBCrlf & "You may include a path, eg '//newserver/stuff', 'C:\stuff\'."
Path = InputBox (msg,title,Path)
Loop
getShortcutPath = Path
End Function
'Bring up inputbox for root folder to search (recursive)
Sub CFolder
CheckFolder = InputBox ("Type the root folder path that you wish to"_
& "start your scan from (recursive).","Begin shortcut (lnk) scan"_
& "from:",CheckFolder)
If CheckFolder = "" Then
MsgBox "Input cancelled, quitting."
wscript.quit
End If
End Sub
Sub ModifyLinks (foldername)
CurServer = LCase(CurServer)
dim file 'for stepping through the files collection '
dim folder 'for stepping through the subfolders collection '
dim fullname 'fully qualified link file name '
dim link 'object connected to the link file '
'process all the files in the folder
For each file in fso.GetFolder(foldername).Files
'check only link files
If strcomp(right(file.name,4),".lnk",vbTexctCompare) = 0 then
'Find full path of shortcut
fullname = fso.GetAbsolutePathName(file)
oldfull = fullname
'Find full path of target within shortcut
set link = wso.CreateShortcut(fullname)
targetpath = link.targetpath
newlink = "Skipped (link not relevant)"
'Displays current shortcut that is being checked (good for
' troubleshooting the script).
'If Silent = 0 Then
'MsgBox "Checking shortcut: " & fullname & "." & VBCrlf_
'& "Shortcut target: " & targetpath
'End If
'Figures the starting position of the server name
'MyPos should = 1 for both //server/path/ and D:/path/
MyPos = InStr(LCase(targetpath), CurServer)
'If the current server (one you want to change) is found at the start of
' the target path, then run the following code
If 1=MyPos Then
If link.workingdirectory = "" Then
link.workingdirectory = "not set"
End If
'if you are running in verbose mode, you will be prompted with
'each shortcut and working folder.
'If Silent = 0 Then
' MsgBox "Path contains " & CurServer & ". Full Path is: " & targetpath & "." & " Working path is " & link.workingdirectory & "."
'End If
'Set numerical length of server name you want to replace
VarLengthSrv = Len(CurServer)
'Set numerical length of full target path
VarLengthPath = Len(targetpath)
'Subtract length of \\servername from full path to parse rest
' of path to PathwoServer
PathwoServer = VarLengthPath - VarLengthSrv
'Sometimes shortcuts don't have working dirs (not sure why)
'If there is a working dir, then run following code
If link.workingdirectory <> "not set" Then
'Set numerical length of working directory
VarLengthWorking = Len(link.workingdirectory)
'Subtract server length from total working dir length to
'parse rest of path to WorkingPathwoServer
WorkingDir = VarLengthWorking - VarLengthSrv
Else
link.workingdirectory = ""
End If
'Parse the actual text of PathwoServer by using the numerical
' length of the path without the \\servername; do the same
' for WorkingPathwoServer
PathwoServer = Right(targetpath,PathwoServer)
WorkingPathwoServer = Right(link.workingdirectory,WorkingDir)
'wscript.echo "Path of shortcut is " & PathwoServer_
'& ". Working folder is " & WorkingPathwoServer & "."
'Display input box to modify each shortcut as the script finds them
If Silent = 0 Then
ModifyPath = InputBox ("Modify path for " & targetpath & "and replace with " & NewServer & PathwoServer & "?","Type 'yes' to modify.","yes")
ElseIf Silent >= 1 Then
ModifyPath = "yes"
End If
If ModifyPath = "yes" Then
'Set link target path attribute to
' \\newservername\targetpath
link.targetpath = NewServer & PathwoServer
newlink = link.targetpath
oldfull = link
If VarLengthWorking <> "" Then
'Set link working dir attribute to
' \\newservername\workingpath
link.workingdirectory = NewServer & ""_
& WorkingPathwoServer
End If
'Save the shortcut with the new information
link.save
'If answer above is anything but yes, the script will proceed
' to the next shortcut
Else
oldfull = "Skipped (user cancelled)"
End if
'Clear link variable
End if
'write output to logfile
Call WriteEntry
End If
Next
'process all the subfolders in the folder
For each folder in fso.GetFolder(foldername).Subfolders
call ModifyLinks(folder.path)
Next
End Sub
'--------------------
' Function WriteEntry to write change history to logfile in outputfile path
'--------------------
Function WriteEntry
If newlink <> "0" Then
w.WriteLine ("<TR>")
w.WriteLine ("<TD><font face=Arial color=#000033 size=1>" & "" & oldfull & "</font></TD>")
w.WriteLine ("<TD><font face=Arial color=#000033 size=1>" & "" & targetpath & "</font></TD>")
w.WriteLine ("<TD><font face=Arial color=#000033 size=1>" & "" & newlink & "</font></TD>")
w.WriteLine ("</TR>")
oldfull = "0"
newlink = "0"
targetpath = "0"
End If
End Function
'-------------------
'Function to see if outputfile already exists
'-------------------
Function CheckFileExists(sFileName)
Dim FileSystemObject
Set FileSystemObject = CreateObject("Scripting.FileSystemObject")
If (FileSystemObject.FileExists(sFileName)) Then
CheckFileExists = True
Else
CheckFileExists = False
End If
Set FileSystemObject = Nothing
End Function

But you knew that :)
I do agree with the lack of "RETURN" function, though. Does seem weird to have subroutines and no obvious way to return back out of them.
Means that, rather than just having some ifs at the top of your function checking the parameters and returning false for errors, you have to stick the whole darn function into an else - which nests deeply.
Difference between:
if param1 is bad
return false
If param2 is bad
return false
Do some initialisation
if the init is bad
return false
Do some more initialisation
if the init is bad
return false
Rest of the function goes here
And
if param1 is bad
set false return value
elseif param2 is bad
set false return value
else
do some init
if the init is bad
set false return value
else
do some more init
if the init is bad
set false return value
else
Rest of the function goes here
You can get really rather deeply nested, with the topmost, "most important looking" tests being just trivial param checking. It sorta turns the programming inside out to have the "most important bits" be the innermost nested details.
Apparently "while .. wend" is also deprecated and you have to use "do while .. loop" instead.
Still it's these fun differences that makes using multiple languages keep my brain stretchy.