net commands

Mapping Drives Revisited

In my old drive mapping post, I was forced to do some fairly ugly stuff because I had to call the old net use command. Yech. Eventually, we got New-PSDrive, and that helped, but in PowerShell v5 (Windows 10's version), we get New-SmbMapping and it actually works. (New-SmbMapping was added earlier, but there were issues. Those appear to be resolved in the final version of v5.)

 

When New-PSDrive finally had persistent drive mappings, I replaced my my old MapDrives.cmd file with a new MapDrives.ps1 that used the New-PSDrive syntax:

New-PSDrive -Name I -root \\srv2\Install -Scope Global -PSProv FileSystem -Persist

A bit awkward, but it works. However, it sometimes ran into problems with drives that were mapped with net use, so I was glad when we finally got a useful version of New-SmbMapping. Now the syntax for mapping my I: drive to \\srv1\install is:

New-SmbMapping -LocalPath I: -RemotePath \\srv2\Install -Persistent $True

Great. But it doesn't have a -Force parameter, so I can't tell it to override any maps that already exist. That requires cleaning up the old maps before I make new ones. For that, we have Remove-SmbMapping and Remove-PsDrive.

Function Remove-myMaps () {
   $DriveList = (Get-SmbMapping).LocalPath
   write-verbose "Removing drives in DriveList: $drivelist"
   Foreach ($drive in $DriveList) {
      $psDrive = $drive -replace ":" #remove unwanted colon from PSDrive name
      Write-Verbose "Running Remove-SmbMapping -LocalPath $Drive -Force -UpdateProfile"
      Remove-SmbMapping -LocalPath $Drive -Force -UpdateProfile 
      If ( (Get-PSDrive -Name $psDrive) 2>$Null ) {
      Write-Verbose "Running Remove-PsDrive -Name $psDrive -Force "
      Remove-PSDrive -Name $psDrive -Force
      }
   }
      write-host " "
      $DriveList = (Get-SMBMapping).LocalPath
      Write-Verbose "The drive list is now: $DriveList"
}

As you might have noticed, PsDrives don't have a colon, and SmbMapping drives do. But PowerShell gives us the useful -replace operator, allowing us to simply remove the stray colon from the drive letter that SmbMapping has.

So, here's the entire script. Feel free to use it as the basis for your own mappings, but please, respect the copyright and don't republish it but link to here instead. Thanks. :)

Charlie.

<#
.Synopsis
Maps network drives to drive letters
.Description
Map-myDrive is used to map network resources to local drive letters. It can use SmbMapping or PsDrive to 
do the mapping, but defaults to simple PsDrives for historical reasons. (SmbMapping was buggy when it 
was first introduced!)
.Example
Map-myDrive

Performs a standard drive mapping on the local machine using New-PsDrive syntax.
.Example
Map-MyDrive -SMB

Performs a standard drive mapping on the local machine using New-SmbMapping syntax.
.Example
Map-MyDrive -SMB -Force

Performs a standard drive mapping on the local machine using New-SmbMapping syntax, and
forces an unmapping of any existing drive maps before remapping.
.Example
Map-MyDrives -SMB -Force -AtHome $False

Performs a standard drive mapping on the local machine using New-SmbMapping syntax, and
forces an unmapping of any existing drive maps before remapping. The script assumes that 
it is NOT being run in my home domain, and therefore does only local mappings.
.Parameter SMB
When set, Map-myDrive uses SMB syntax to do the drive mappings
.Parameter Force
When set, Map-myDrive completely unmaps any existing drive mappings, and then remaps them. 
.Parameter AtHome
When True, Map-myDrive assumes that it has connectivity to the home domain resources. When
False, it assumes no home domain resources are available and maps to local shares. 
.Inputs
[switch]
[switch]
[switch]
[Boolean]
.Notes
    Author: Charlie Russel
 Copyright: 2016 by Charlie Russel
          : Permission to use is granted but attribution is appreciated
   Initial: 10 June, 2012
   ModHist: 26 June, 2012 A single, cleaner, call to GWMI
          : 26 April,2015 Cleaned up smb unmapping failures, and added Verbose
          : 27 June, 2015 New unmapping function
          : 04 Sept, 2016 Added AtHome Boolean to override environment, Force switch to force unmapping/remapping
          :
#>
[CmdletBinding(SupportsShouldProcess=$True)] 
Param ([Parameter(Mandatory=$false)][Switch]$SMB,
       [Parameter(Mandatory=$false)][Switch]$Force,
       [Parameter(Mandatory=$false)][Boolean]$AtHome=$True)

#
Write-Verbose "Running mapdrives.ps1 with SMB set to $SMB"
Write-Verbose "Athome is set to $AtHome"
Write-Verbose "Force is $Force"

$Psh = Get-Process PowerShell

# Start by checking for mapped drives
$DriveList = $Null
$PSDriveList = $Null
#$DriveList = Get-WMIObject Win32_LogicalDisk | Where-Object { $_.DriveType -eq 4 }

$DriveList = (Get-SMBMapping).LocalPath
write-verbose "The DriveList is: $DriveList"

if ($DriveList) {
   $PSDriveList = $DriveList -replace ":"
   write-verbose "The PSDrivelist is: $PSDriveList"
}

# Unmap any lingering ones
Function Remove-myMaps () {
   write-verbose "Removing drives in DriveList: $drivelist"
   Foreach ($drive in $DriveList) {
      $psDrive = $drive -replace ":" #remove unwanted colon from PSDrive name
      Write-Verbose "Running Remove-SmbMapping -LocalPath $Drive -Force -UpdateProfile"
      Remove-SmbMapping -LocalPath $Drive -Force -UpdateProfile 
      If ( (Get-PSDrive -Name $psDrive) 2>$Null ) {
      Write-Verbose "Running Remove-PsDrive -Name $psDrive -Force "
      Remove-PSDrive -Name $psDrive -Force
      }
   }
      write-host " "
      $DriveList = (Get-SMBMapping).LocalPath
      Write-Verbose "The drive list is now: $DriveList"
} 

Function Map-myPSDrive () {
   New-PSDrive -Name I -root \\server\Install    -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name J -root \\server\Download   -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name S -root \\server\SharedDocs -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name W -root \\server\Working    -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name H -root \\server2\Download  -Scope Global -PSProv Filesystem -Persist
   New-PSDrive -Name K -root \\server2\Kindle    -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name M -root \\server2\Music     -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name N -root \\server2\Audible   -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name P -root \\server2\Pictures  -Scope Global -PSProv FileSystem -Persist
   New-PSDrive -Name T -root \\labserver\Captures\70-742 -Scope Global -PSProv FileSystem -Persist
}

# Map using SMBMapping. It's more robust
Function New-mySMBMaps () {
   New-SmbMapping -LocalPath I: -RemotePath \\server\Install    -Persistent $True
   New-SmbMapping -LocalPath J: -RemotePath \\server\Download   -Persistent $True
   New-SmbMapping -LocalPath S: -RemotePath \\server\SharedDocs -Persistent $True
   New-SmbMapping -LocalPath W: -RemotePath \\server\Working    -Persistent $True
   New-SmbMapping -LocalPath H: -RemotePath \\server2\Downloads -Persistent $True
   New-SmbMapping -LocalPath K: -RemotePath \\server2\Kindle    -Persistent $True
   New-SmbMapping -LocalPath M: -RemotePath \\server2\Music     -Persistent $True
   New-SmbMapping -LocalPath N: -RemotePath \\server2\Audible   -Persistent $True
   New-SmbMapping -LocalPath P: -RemotePath \\server2\Pictures  -Persistent $True
   New-SmbMapping -LocalPath T: -RemotePath \\labserver\Captures\70-742 -Persistent $True
}

Function Map-myLocal () {
   New-SmbMapping -LocalPath K: -RemotePath \\localhost\Kindle          -Persistent $False  
   New-SmbMapping -LocalPath T: -RemotePath \\localhost\Captures\70-742 -Persistent $False  
}

if(! $PSDriveList ) {
   if ($Force) { Remove-myMaps }
   Write-Verbose "SMB is set to $SMB"
   if ($SMB) { 
      If ($AtHome) { 
         New-mySMBMaps 
      } else {
         Map-myLocal
      }
   } else { 
      If ($AtHome) { 
         Map-myPSDrive 
      } else {
         Map-myLocal
      }
    }
} else { 
   # $Psh.count is the number of open PowerShell windows. I know that if it's less than or equal
   # to 2, then I haven't yet mapped the drives on both limited user and administrative windows. 
   # Therefore, we need to mapdrives here. Or, if I have run this with a -Force command, obviously.
   if (($Psh.count -le 2) -OR ($Force)) {
   Remove-myMaps
   Write-Verbose "SMB is set to $SMB"
   if ($SMB) { 
      If ($AtHome) { 
         New-mySMBMaps 
      } else {
         Map-myLocal
      }
   } else { 
      If ($AtHome) { 
         Map-myPSDrive 
      } else {
         Map-myLocal
      }
   }
  }
}