Mycroft Holmes
Mycroft Holmes

Reputation: 77

Passing string variable as Argument in Powershell

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?

Upvotes: 1

Views: 4511

Answers (2)

Mycroft Holmes
Mycroft Holmes

Reputation: 77

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
        }
    }
}

Upvotes: 0

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200293

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
    }
}

Upvotes: 3

Related Questions