mapping network drives

Hi,

Basically I am trying to disconnect shares from old DC1 server and map shares on a new DC2 server (having the same permissions and same share names)

BAT script runs a PS script (to disconnect drives) and then executes map commands.

BAT script
@echo off
#runs a PS script
PowerShell.exe -ExecutionPolicy Bypass -Command “& ‘%~dpn0.ps1’”
#maps drives
net use * \dc2\production /P:Yes
net use * \dc2\finance /P:Yes

PS script
#Delete drives
Import-Module activedirectory
$mapped = Get-WmiObject Win32_MappedLogicalDisk | Select DeviceId, ProviderName
foreach ($item in $mapped) {
if ($item.ProviderName -eq ‘\DC1\production’) {net use $item.DeviceId /del}
}
$mapped = Get-WmiObject Win32_MappedLogicalDisk | Select DeviceId, ProviderName
foreach ($item in $mapped) {
if ($item.ProviderName -eq ‘\DC1\finance’) {net use $item.DeviceId /del}
}

Everything works well. But I am facing an issue that all of the shared drives are still mapped on everyone’s PC regardless if they have access to the share or not(they remain mapped but you are unable to access the share obviously). So I was wondering is there a way that PS or BAT script could check if the share exists on laptop and if it does it would map a share and if it does not it would just skip mapping that particular share?

You’d need to have your script run in the user’s logon session - that’s the only place where the mappings would be visible.

hi, sorry I am not quite sure what do you mean ? The script is run over “Logon script” field under AD Profile. which is configured for each user in ADUC

Ah. OK - you didn’t mention the logon script part :).

So - after you run the script, which runs without errors, the mapped drives are still visible. There’s a couple of possibilities here, but we need some more data from which to troubleshoot.

foreach ($item in $mapped) { 
 Write-Host "Attempting $($item.deviceid)"
 if ($item.ProviderName -eq '\\DC1\production') {net use $item.DeviceId /del}
}

$mapped = Get-WmiObject Win32_MappedLogicalDisk | Select DeviceId, ProviderName

foreach ($item in $mapped) {
 Write-Host "Attempting $($item.Deviceid)"
 if ($item.ProviderName -eq '\\DC1\finance') {net use $item.DeviceId /del}
}

What does that output when you try it? It’s also possible that the NET USE command isn’t receiving the data correctly - PowerShell’s parser isn’t 100% spot-on when mixing external commands with variables. I might try:

foreach ($item in $mapped) {
 Write-Host "Attempting $($item.Deviceid)"
 $dev = $item.deviceid
 if ($item.ProviderName -eq '\\DC1\finance') {net use $dev /del}
}

And see if the parser maybe picked it up a bit better. If you’ve got any other output from this running, though, it’d be helpful to see it - it’s hard to troubleshoot essentially blind.

this looks exactly what I would need probably. Can it be mixed up so it maps a new drive from dc2 along with deleting and old from dc1 if found. Then I guess I can get rid of all using BAT commands completely and use just PS. I will test it out

Sure. I would definitely go with a pure Powershell solution. I’ve found that when you start to try and mix bat or python or anything like that into a powershell script the interpreter can sometimes not handle the returned output very well.

Powershell is object-oriented. If you use strictly Powershell cmdlets to remove your network drives, and map your new ones, you are going to be working with Powershell objects, which is exactly what it wants to do in the first place. Does the network drive have the same drive letter across everything you need to change it on, or is it mixed up? If it is mixed up, it might be easier to go after the root. Check this out:

Get-PSDrive | Where-Object { $_.DisplayRoot -eq "\\dc1\finance" } | Remove-PSDrive
Get-PSDrive | Where-Object { $_.DisplayRoot -eq "\\dc1\production" } | Remove-PSDrive

You’ll notice I used DisplayRoot instead of Root.

If you do this:

Get-PSDrive | Get-Member

You will notice a DisplayRoot and a Root property, but on the output of just Get-PSDrive the path the network shares have is just displayed as root. Looks like they are using a named property to change the name of that column in the output. Makes things a little confusing. If you target DisplayRoot though, you’ll get the values you are after.

You can then create your new network drives using this bit of code:

New-PSDrive -Name "P" -Root "\\dc2\production" -Persist -PSProvider "FileSystem"
New-PSDrive -Name "F" -Root "\\dc2\finance" -Persist -PSProvider "FileSystem"

Take note of this however with regard to using New-PSDrive. Copy/Pasted from the MSDN docs here: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.management/new-psdrive

The following features are added to New-PSDrive in Windows PowerShell 3.0:
Mapped network drives. You can use the Persist parameter of New-PSDrive to create Windows mapped network drives. Unlike temporary Windows PowerShell drives, Windows mapped network drives are not session-specific. They are saved in Windows and they can be managed by using standard Windows tools, such as File Explorer and Net Use. Mapped network drives must have a drive-letter name and be connected to a remote file system location. When your command is scoped locally (no dot-sourcing), the Persist parameter does not persist the creation of a PSDrive beyond the scope in which the command is running. If you are running New-PSDrive inside a script, and you want the drive to persist indefinitely, you must dot-source the script. For best results, to force a new drive to persist indefinitely, add the Scope parameter to your command, and set its value to Global.

I was able to get this working. However there is an issue if another share exists on same letter. It then returns and error and goes to the next command, etc…:

Import-Module activedirectory
$mapped = Get-WmiObject Win32_MappedLogicalDisk | Select DeviceId, ProviderName
foreach ($item in $mapped) {
if ($item.ProviderName -eq ‘\dc1\finance’) {net use $item.DeviceId /del
New-PSDrive -Name “A” -Root “\dc2\finance” -Persist -PSProvider “FileSystem”}
}
$mapped = Get-WmiObject Win32_MappedLogicalDisk | Select DeviceId, ProviderName
foreach ($item in $mapped) {
if ($item.ProviderName -eq ‘\dc1\production’) {net use $item.DeviceId /del
New-PSDrive -Name “Y” -Root “\dc2\production” -Persist -PSProvider “FileSystem”}
}