1

I'm trying to write a PowerShell script to change drive letter of I: to something else. Here's the script.

$driveI = Get-WmiObject -Class win32_volume -Filter "DriveLetter='I:'"

if ($driveI.SerialNumber=""){

    write-host "I: is free..."

}   else  {

    write-host "I: is occupied"
    foreach ( $s in @("'Z:'", "'Y:'", "'X:'", "'W:'", "'V:'", "'U:'", "'T:'", "'R:'", "'Q:'", "'P:'", "'O:'", "'N:'", "'M:'", "'L:'", "'K:'", "'J:'", "'H:'", "'G:'", "'F:'", "'E:'", "'D:'", "'B:'", "'A:'"))
    {
        $testdrv = Get-WmiObject -Class win32_volume -Filter "DriveLetter=$s"

        if (!$testdrive.Exist)
        {
            $s = '"'+$s.Trim([char]0x0027)+'"'
            Set-WmiInstance -input $driveI -Arguments @{DriveLetter=$s}
            Write-Host I: has been moved to $s
            break
        }
    }
}

Allow me to walk you through the script. $driveI is used to retrieve all information regarding I:. Now, if I: has no serial number, it indicates that I: doesn't exist. If, on the other hand, I: exists, I'm trying to find a drive letter which is free. I'm implementing my search with the foreach loop. Now, when we call Get-WmiObject, we use drive letters with single quote. But when we use Set-WmiInstance, we use double quotes. However, even when I modify $s to be wrapped by double quote, it doesn't work. In short, if I use Write-Host $s, I get in output, say, "E:". When I use Set-WmiInstance -input $driveI -Arguments @{DriveLetter="E:"}, it works. But when I use Set-WmiInstance -input $driveI -Arguments @{DriveLetter=$s}, it doesn't work. Could anyone tell me what I'm doing wrong?

2
  • 1
    In your working example you are passing a string, which is quoted as that is how you define a literal string. In the non-working example you are passing a string where you are coding in quotes. I wonder if that is the issue as there is no drive called "E:" but actually just E:. What happens if you change the line to $s = $s.Trim([char]0x0027)? Commented May 11, 2015 at 16:32
  • 1
    Define you drive letters as simple strings... $s in @("Z:", "Y:",.... Then your filter will look like this: -Filter "DriveLetter='$s'" and you can get rid off the whole $s = '"'+$s.Trim([char]0x0027)+'"' mess. Commented May 12, 2015 at 6:24

2 Answers 2

3

Don't put quotes in strings when you're going to remove them later anyway. Instead add the quotes where you actually need them:

$driveLetters = 'Z:', 'Y:', 'X:', ..., 'D:', 'B:', 'A:'
foreach ( $s in $driveLetters ) {
    $testdrv = Get-WmiObject -Class Win32_Volume -Filter "DriveLetter='$s'"

    if (-not $testdrv) {
        Set-WmiInstance -input $driveI -Arguments @{DriveLetter=$s}
        Write-Host "I: has been moved to $s"
        break
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

It's a bit clumsy, but this code works. I'll take your suggestions, and get rid of the Trim mess.

$driveI = Get-WmiObject -Class win32_volume -Filter "DriveLetter='I:'"

if ($driveI -eq $null)  {

    write-host "I: is free..."

}  else    {    
    write-host "I: is occupied..."
    foreach ( $s in @("'Z:'", "'Y:'", "'X:'", "'W:'", "'V:'", "'U:'", "'T:'", "'R:'", "'Q:'", "'P:'", "'O:'", "'N:'", "'M:'", "'L:'", "'K:'", "'J:'", "'H:'", "'G:'", "'F:'", "'E:'", "'D:'", "'B:'", "'A:'"))
    {
        $testdrv = Get-WmiObject -Class win32_volume -Filter "DriveLetter=$s"

        if ($testdrv -eq $null)
        {
            $s = $s.Trim([char]0x0027)
            Set-WmiInstance -input $driveI -Arguments @{DriveLetter=$s}
            Write-Host I: has been moved to $s
            break
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.