Because I spend my day working from a PowerShell prompt, I rely heavily on PSDrives to quickly access files and folders. And because I am mobile, I might be working at my desk in my home office, or I might be on the road with my trusty Thinkpad. Of course, this means, I want an easy way to provide a seamless experience in either situation. I thought I'd share my solution as well as some other fun I've been having with PSDrives.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Using Drive Data
As you might imagine I'm going to use a PowerShell script to handle my drive mapping. Using OneDrive, I synchronize my scripts folder between all machines I might be using. This means I only have to manage the file in one location. I start with data. You can use whatever format you'd like. I'm using CSV because it is simple and my drive mapping data is flat.
#add some psdrives from this CSV data
$drivedata = @"
"Name","Root","Description"
"S", "c:\scripts"
"T",$(Join-Path "C:\" 'training')
"P",$(Join-Path "C:\" 'presentations'),
"Downloads", $(Join-Path -path $env:userprofile -childpath downloads)
"Docs",$([environment]::GetFolderPath("MyDocuments")),"my Documents folder"
"Drop",$(Join-Path -path $env:userprofile -childpath dropbox)
"One", $env:OneDriveConsumer,"my OneDrive folder"
"GDrive", $(Join-Path -path $env:userprofile -childpath "Google Drive")
"Scores", $(Join-Path -path $env:userprofile -childpath documents\musescore3\scores)
"@
I could have created an external CSV file to import, but by putting my data in the script file using a here-string, I can use PowerShell variables. $Drivedata is an in-memory CSV file. I can use ConvertFrom-CSV to "import" it.
This means I can use this data to create a New-PSDrive with code like this:
#create the PSDrive if it doesn't already exist and the root path exists
(ConvertFrom-Csv $drivedata).where({
-Not (Test-Path "$($_.name):\") -AND (Test-Path $_.root) }).foreach({
$splat = @{
Name = $_.Name
Root =$_.root
PSProvider = 'FileSystem'
}
if ($_.Description) { $splat.Add("Description",$_.Description)}
[void](New-PSDrive @splat) })
This code is using the Where() and ForeEach() methods instead of Where-Object and Foreach-Object because the methods run a little faster. This is code that is called from my PowerShell profile script so I want it to run quickly. Technically, this is a one-line command but you could easily break it into separate steps. The expression is testing if the drive doesn't already exist and that the specified root does. For each matching result, I'm building a hashtable, $splat, with parameters that will be splatted to New-PSDrive. I have to test if there is a description value and add it when found. Finally, New-PSDrive is run. The [void]() syntax prevents the New-PSDrive from displaying the results. You could also pipe New-PSDrive to Out-Null, but technically, using [void] is a few milliseconds faster. This should map all local PSDrives.
Where Am I
However, I also have a few PSDrives that I map to my NAS device when I am home. I guess I could add them to the code above since I'm testing if the root exists, but to improve performance a bit, I went a different route. I decided to use the Get-NetNeighbor command to verify I can reach the NAS device. I found this faster than pinging, or the PowerShell equivalent. If the MAC address matches the expected MAC, I can map drives.
#test for NAS MAC and only process NAS drives if at home
Try {
$gw = Get-NetNeighbor -IPAddress 172.16.10.100 -ErrorAction Stop
if ($gw.LinkLayerAddress -eq '00-11-32-58-7B-10') {
#map local drives for admin mode
$mapped = @{
M = "\\ds416\media"
N = "\\ds416\files"
V = "\\ds416\video"
Backup = "\\ds416\backup"
}
($mapped.GetEnumerator()).ForEach({
if (! (Test-Path "$($_.name):")) {
[void](New-PSDrive -Name $_.name -PSProvider FileSystem -Root $_.value)
} #if not test-path
})
} #if MAC matches NAS
}
Catch {
Write-Warning "You are not at home or DS416 is offline."
}
I suppose I don't need to test the MAC address because if Get-NetNeigbor fails, I'm most likely on a travel computer. But, just in case I'm home and something is messed up with IP Addressing, the extra check doesn't hurt anything. In this code, I'm mapping drives a little bit differently. Here, $mapped is a hashtable of drive letters and roots. Using the GetEnumerator() method and create the new PSDrive if it doesn't already exist.
All of the code I've shown you is in a script file that replicates between systems. In my PowerShell profile script, I dot source the file. I do the same thing in my Windows PowerShell and PowerShell 7 CurrentUserAllHosts profile scripts. Regardless of version or host, I should always have access to all of my PSDrives.
Doing More
Because I can't help myself, I needed to have fun working with PSDrives, especially those that belong to the file system. But I'll save that for another day.
1 thought on “Fun with Mapping PowerShell Drives”
Comments are closed.