ChangeDriveLetter script for XYplorer

Discuss and share scripts and script files...
Post Reply
highend
Posts: 13274
Joined: 06 Feb 2011 00:33

ChangeDriveLetter script for XYplorer

Post by highend »

Take a look at the "Remarks:" section on top of the code on how to use it.

Paypal donations are always accepted :D

Code: Select all

/* 04.08.2011, change drive letters
   ::load "<xyscripts>\ChangeDriveLetter.xys";

   Remarks: XYplorer must have been started with admin rights. As an alternative you could create a task with highest privileges that
   executes the VBScript file and can be called with a temporary batch file (like schtasks /run /tn "ChangeDriveLetter"). A third way
   would be the use of psexec but it requires a small bit of configuration on your pc (enable Administrator account, give it a password,
   etc.). See http://technet.microsoft.com/de-de/sysinternals/bb897553 for further details.

*/

"_Initialize"
	global $SelectedDriveLetter, $DestinationDriveLetter, $ExcludedDriveLetters, $AvailableDriveLetters, $UsedDriveLetters, $VBSTempScriptFile;

	// Please change only the $ExcludedDriveLetters variable to fit your needs.
	// Don't forget to add the colon and the | character after each drive letter
	$ExcludedDriveLetters = "A:|B:|";

	// Don't change anything in the script below this point
	$SelectedDriveLetter = "";
	$DestinationDriveLetter = "";
	$UsedDriveLetters = "";
	$AvailableDriveLetters = "A:|B:|C:|D:|E:|F:|G:|H:|I:|J:|K:|L:|M:|N:|O:|P:|Q:|R:|S:|T:|U:|V:|W:|X:|Y:|Z:|";
	$VBSTempScriptFile = "%temp%\~ChangeDriveLetter.vbs";


"Change drive letter for...|<xypath>\.Icons\RSync_Upload.ico|1"
	;

"... &current drive"
	global $CurrentSelectedMenuItem;

	sub "_Initialize";

	$CurrentSelectedMenuItem = "current_drive";

	sub "_Main";

	status "Changed drive letter successfully";


"... &select drive"
	global $CurrentSelectedMenuItem;

	sub "_Initialize";

	$CurrentSelectedMenuItem = "selected_drive";

	sub "_Main";

	status "Changed drive letter successfully";


"- : Separator"

"Cancel"

"- : Separator"

"Edit this &script : edit"
	self $ScriptFile, file;
	openwith "<xydrive>\Tools\EditPlus\editplus.exe", ,$ScriptFile;


/*
Functions
*/

"_Main"
	global $SelectedDriveLetter, $DestinationDriveLetter, $ExcludedDriveLetters, $AvailableDriveLetters, $UsedDriveLetters, $VBSTempScriptFile;
	global $CurrentSelectedMenuItem;

	// Remove the $ExcludedDriveLetters from $AvailableDriveLetters
	foreach($Drive, $ExcludedDriveLetters, "|") {
		if($Drive == "") { break; }
		$Drive = $Drive . "|";
		$AvailableDriveLetters = replace($AvailableDriveLetters, "$Drive", "");
	}

	// Find all used drive letters
	// Create new tab and go to the "Computer" node
	tab("new", "Computer");
	// Report the names for all drives
	$UsedDriveLettersNames = report("{name}|");
	// Make a new "|" separated $UsedDriveLetters list
	foreach($Item, $UsedDriveLettersNames, "|") {
		if($Item == "") { break; }
		$DriveLetter = regexreplace($Item, "(.*\()([A-Za-z]:)(.*)", "$2");

		// Get single used drive letters to remove them from the $AvailableDriveLetters list
		$DriveLetterWithSeparator = $DriveLetter . "|";
		
		// Build $UsedDriveLetters list for later use
		$UsedDriveLetters = $UsedDriveLetters . $DriveLetter . "|";

		// Remove the $UsedDriveLetters from $AvailableDriveLetters
		$AvailableDriveLetters = replace($AvailableDriveLetters, "$DriveLetterWithSeparator", "");
	}
	// Close current tab
	#351;


	// Change drive letter for... current drive
	if($CurrentSelectedMenuItem == "current_drive") {
		$CurrentPath = "<curpath>";
		$SelectedDriveLetter = regexreplace($CurrentPath, ".*([A-Za-z]:)\\(.*)", "$1");

		$DestinationDriveLetter = inputselect("Please select the destination drive letter:", "$AvailableDriveLetters", "|", 1);
	}

	// Change drive letter for... selected drive
	if($CurrentSelectedMenuItem == "selected_drive") {
		$SelectedDriveLetter = inputselect("Please select the source drive letter:", "$UsedDriveLetters", "|", 1);

		$DestinationDriveLetter = inputselect("Please select the destination drive letter:", "$AvailableDriveLetters", "|", 1);
	}

	$SelectedDriveLetterForScript = "(" . chr(34) . "Select * from Win32_Volume Where Name = '" . $SelectedDriveLetter . "\\'" . chr(34) . ")";
	$DestinationDriveLetterForScript = "objVolume.DriveLetter = " . chr(34) . $DestinationDriveLetter . chr(34);

	writefile($VBSTempScriptFile, 'strComputer = "."'.<crlf>, o, ta);
	writefile($VBSTempScriptFile, 'Set objWMIService = GetObject("winmgmts:" _'.<crlf>, a, ta);
	writefile($VBSTempScriptFile, '& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")'.<crlf>, a, ta);
	writefile($VBSTempScriptFile, <crlf>, a, ta);
	writefile($VBSTempScriptFile, 'Set colVolumes = objWMIService.ExecQuery _'.<crlf>, a, ta);
	writefile($VBSTempScriptFile, $SelectedDriveLetterForScript.<crlf>, a, ta);
	writefile($VBSTempScriptFile, <crlf>, a, ta);
	writefile($VBSTempScriptFile, 'For Each objVolume in colVolumes'.<crlf>, a, ta);
	writefile($VBSTempScriptFile, $DestinationDriveLetterForScript.<crlf>, a, ta);
	writefile($VBSTempScriptFile, 'objVolume.Put_'.<crlf>, a, ta);
	writefile($VBSTempScriptFile, 'Next'.<crlf>, a, ta);

	open "$VBSTempScriptFile";
One of my scripts helped you out? Please donate via Paypal

rhoelzl
Posts: 200
Joined: 28 Dec 2009 11:20

Re: ChangeDriveLetter script for XYplorer

Post by rhoelzl »

Not bad! :)

Thanks for this. I have hacked the code a bit to make it always change the current drive, see below. This way you can make it into a nice user button. I recommend ":rename" as icon.
Last edited by rhoelzl on 09 Aug 2011 22:19, edited 1 time in total.

rhoelzl
Posts: 200
Joined: 28 Dec 2009 11:20

Re: ChangeDriveLetter script for XYplorer

Post by rhoelzl »

Hello again,

I have attached the following code at the end of the script:

Code: Select all

   $NewPath = replace("<curpath>",$SelectedDriveLetter,$DestinationDriveLetter);
   tab("relocate", $NewPath);
The idea is to stay in the current folder after drive letter change to make it more practical.

But I get some very strange behavior with this code: Apparently, changing drive letters takes a a short while, so as soon as "relocate" is called I only see the "path does not exist" error message. Which would be fine because with a little delay the folder should become available, so everything should be fine.

But what really happens is that I see that error message only for a very short period (less than a second) and then I get "forwarded" to %computer%. Am I doing something wrong? Or is this a bug?

highend
Posts: 13274
Joined: 06 Feb 2011 00:33

Re: ChangeDriveLetter script for XYplorer

Post by highend »

Am I doing something wrong? Or is this a bug?
Don't know.

Have you tried to use a while loop with exists() to only change the folder when it gets available?
One of my scripts helped you out? Please donate via Paypal

rhoelzl
Posts: 200
Joined: 28 Dec 2009 11:20

Re: ChangeDriveLetter script for XYplorer

Post by rhoelzl »

I had tried that but it did not work.

But now I have figured out that for some reason you need to add an additional wait. I don't really know why, but here you go, this works well.

Of course another nice upgrade would be to cycle through all open tabs, looking for all paths using the old letter and replacing it with the new one. But currently I am too lazy for that. :P

Code: Select all

/* 04.08.2011, change drive letters
   ::load "<xyscripts>\ChangeDriveLetter.xys";

   Remarks: XYplorer must have been started with admin rights. As an alternative you could create a task with highest privileges that
   executes the VBScript file and can be called with a temporary batch file (like schtasks /run /tn "ChangeDriveLetter"). A third way
   would be the use of psexec but it requires a small bit of configuration on your pc (enable Administrator account, give it a password,
   etc.). See http://technet.microsoft.com/de-de/sysinternals/bb897553 for further details.

*/

   global $CurrentSelectedMenuItem;
   sub "_Initialize";
   $CurrentSelectedMenuItem = "current_drive";
   sub "_Main";
   status "Changed drive letter successfully";
   
   

"_Initialize"
   global $SelectedDriveLetter, $DestinationDriveLetter, $ExcludedDriveLetters, $AvailableDriveLetters, $UsedDriveLetters, $VBSTempScriptFile;

   // Please change only the $ExcludedDriveLetters variable to fit your needs.
   // Don't forget to add the colon and the | character after each drive letter
   $ExcludedDriveLetters = "A:|B:|C:|D:|";

   // Don't change anything in the script below this point
   $SelectedDriveLetter = "";
   $DestinationDriveLetter = "";
   $UsedDriveLetters = "";
   $AvailableDriveLetters = "A:|B:|C:|D:|E:|F:|G:|H:|I:|J:|K:|L:|M:|N:|O:|P:|Q:|R:|S:|T:|U:|V:|W:|X:|Y:|Z:|";
   $VBSTempScriptFile = "%temp%\~ChangeDriveLetter.vbs";








/*
Functions
*/

"_Main"
   global $SelectedDriveLetter, $DestinationDriveLetter, $ExcludedDriveLetters, $AvailableDriveLetters, $UsedDriveLetters, $VBSTempScriptFile;
   global $CurrentSelectedMenuItem;

   // Remove the $ExcludedDriveLetters from $AvailableDriveLetters
   foreach($Drive, $ExcludedDriveLetters, "|") {
      if($Drive == "") { break; }
      $Drive = $Drive . "|";
      $AvailableDriveLetters = replace($AvailableDriveLetters, "$Drive", "");
   }

   // Find all used drive letters
   // Create new tab and go to the "Computer" node
   tab("new", "Computer");
   // Report the names for all drives
   $UsedDriveLettersNames = report("{name}|");
   // Make a new "|" separated $UsedDriveLetters list
   foreach($Item, $UsedDriveLettersNames, "|") {
      if($Item == "") { break; }
      $DriveLetter = regexreplace($Item, "(.*\()([A-Za-z]:)(.*)", "$2");

      // Get single used drive letters to remove them from the $AvailableDriveLetters list
      $DriveLetterWithSeparator = $DriveLetter . "|";
      
      // Build $UsedDriveLetters list for later use
      $UsedDriveLetters = $UsedDriveLetters . $DriveLetter . "|";

      // Remove the $UsedDriveLetters from $AvailableDriveLetters
      $AvailableDriveLetters = replace($AvailableDriveLetters, "$DriveLetterWithSeparator", "");
   }
   // Close current tab
   #351;


   // Change drive letter for... current drive
   if($CurrentSelectedMenuItem == "current_drive") {
      $CurrentPath = "<curpath>";
      $SelectedDriveLetter = regexreplace($CurrentPath, ".*([A-Za-z]:)\\(.*)", "$1");

      $DestinationDriveLetter = inputselect("Please select the new drive letter for drive " . $SelectedDriveLetter, "$AvailableDriveLetters", "|", 1);
   }

   // Change drive letter for... selected drive
   if($CurrentSelectedMenuItem == "selected_drive") {
      $SelectedDriveLetter = inputselect("Please select the source drive letter:", "$UsedDriveLetters", "|", 1);

      $DestinationDriveLetter = inputselect("Please select the destination drive letter:", "$AvailableDriveLetters", "|", 1);
   }

   $SelectedDriveLetterForScript = "(" . chr(34) . "Select * from Win32_Volume Where Name = '" . $SelectedDriveLetter . "\\'" . chr(34) . ")";
   $DestinationDriveLetterForScript = "objVolume.DriveLetter = " . chr(34) . $DestinationDriveLetter . chr(34);

   writefile($VBSTempScriptFile, 'strComputer = "."'.<crlf>, o, ta);
   writefile($VBSTempScriptFile, 'Set objWMIService = GetObject("winmgmts:" _'.<crlf>, a, ta);
   writefile($VBSTempScriptFile, '& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")'.<crlf>, a, ta);
   writefile($VBSTempScriptFile, <crlf>, a, ta);
   writefile($VBSTempScriptFile, 'Set colVolumes = objWMIService.ExecQuery _'.<crlf>, a, ta);
   writefile($VBSTempScriptFile, $SelectedDriveLetterForScript.<crlf>, a, ta);
   writefile($VBSTempScriptFile, <crlf>, a, ta);
   writefile($VBSTempScriptFile, 'For Each objVolume in colVolumes'.<crlf>, a, ta);
   writefile($VBSTempScriptFile, $DestinationDriveLetterForScript.<crlf>, a, ta);
   writefile($VBSTempScriptFile, 'objVolume.Put_'.<crlf>, a, ta);
   writefile($VBSTempScriptFile, 'Next'.<crlf>, a, ta);

   open "$VBSTempScriptFile";
   
   $NewPath = replace("<curpath>",$SelectedDriveLetter,$DestinationDriveLetter);
   while ( exists($NewPath) == 0) {wait 100;};
   wait 100;
   tab("relocate", $NewPath);
   

Post Reply