Using Array in Invoke-Command on Remote Machine

I'm trying to run a script that will test if various network drives are mounted to several systems (i.e. \\path\to\share mounts as T:). These are all stored in a CSV file, and each drive letter is separated by a space. I can import each row into a variable and loop through them, but I can't seem to pass them into an Invoke-Command script block.

I've spent some time googling the issue and did find a few suggestions, but I still seem to be having issues getting everything to work. Code is as follows:

$credentials = Get-Credential
$sysdrives = Import-Csv .\systems.csv
$i = 0

while ($i -lt $sysdrives.length) {
    $drives = $sysdrives[$i].Drives.split(" ")
    $currsystem = $sysdrives[$i].System

    Write-Host "Testing $currsystem..."
    foreach($drive in $drives) {
        Invoke-Command -ComputerName $currsystem -Credential $credentials -ScriptBlock {
            $currdrive = $Using:drive
            Write-Host "Testing if $currdrive is present..."
            if (!(Test-Path $currdrive)) {
                Write-Host "$currdrive not present!"
            }
            else {
                Write-Host "$currdrive is mounted"
            }
        } -ArgumentList $drive
    }
    $i += 1
}

Example entry from my CSV file:

fqdn.server.name,X: Y: Z:

EDIT: In case someone else stumbles across this post, this is how I was able to solve it:

  1. I was missing a param() block underneath inside the Invoke-Command ScriptBlock
  2. I replaced Test-Path with Get-PSDrive. This allowed me to test the drives successfully, despite not being logged into the machine. Your mileage may vary in your own environment, but it worked just fine for me.

I made a few other modifications to clean up the output a bit, but here's the code I'm using:

$credentials = Get-Credential
$sysdrives = Import-Csv .\systems.csv
$i = 0

while ($i -lt $sysdrives.length) {
    $drives = $sysdrives[$i].Drives.split(" ")
    $currsystem = $sysdrives[$i].System

    Write-Host "Testing $currsystem..."
    foreach($drive in $drives) {
        Invoke-Command -ComputerName $currsystem -Credential $credentials -ScriptBlock {
            param($currdrive)
            Write-Verbose "Testing if $currdrive is present..."
            if (!(Get-PSDrive $currdrive -ErrorAction SilentlyContinue)) {
                Write-Host "ERROR: $currdrive is not mounted!!!" -BackgroundColor Black -ForegroundColor Red
            }
            else {
                Write-Verbose "$currdrive is mounted"
            }
        } -ArgumentList $drive
    }
    $i += 1
}

8 comments · 75% upvoted · other discussions

comments

sk82jack

Mapped drives are attached to a user profile rather than a system so are you using the same account that has the mapped drives on? If not, but the user who has the mapped drives is logged on then you can query the registry to find what drives are mapped and what letters are used to map them. I'm on mobile so I don't have examples or links but hopefully that will point you in the right direction.

Ta11ow

You're using values in the script block chat don't exist on the remote computer. You're halfway there with the -argumentlist parameter, but you're not passing in everything you need, and you haven't defined the parameters in the script block.

Define a param() block in the script block much like you would for a function, and then pass in the arguments. The other thing you can do is just pass everything in you need, and then reference the parameters using $args. However, that tends to lead to less readable code. :)

Idmorul [OP]

Thanks, it was the param() block that actually got the variables into the script block, and the script does run as expected for the most part. I'm now having issues detecting the drives remotely, but that becomes a separate topic.

Ta11ow

You may have some difficulty with that. When you invoke a command remotely, it doesn't run under the current user context. Mapped network drives are valid only for the individual user, so you'll probably end up having to dig through the user's registry or something.

Idmorul [OP]

I was actually able to use Get-PSDrive without issue. I've updated the OP with my working code.

Sheppard_Ra

The code seems legit. Are you getting back that the drives aren't present? I'd imagine it'd be because there's no session with a mounted drive. Physical drives would be present, but network drives wouldn't mount until a user logged in.

Idmorul [OP]

The drives are mapped on boot, using a script that runs as SYSTEM.

Ultimately, the issue is it doesn't recognize the vairable I'm passing into Invoke-Command, which leads me to run Test-Path on Null, which fails.

EDIT: Though I've just discovered that running the command using a different account doesn't work on mapped drives remotely (Invoke-Command X: will work if I'm logged in). I'll have to do some digging on that.

aXenoWhat

Thank you for posting back with the fix!