Reputation: 7919
The script mounts the drive correctly, but the drive is not persisted after rebooting the machine:
function RemapDrive {
param(
$DriveLetter,
$FullPath,
$Credential
)
Write-Host "Trying to remove $DriveLetter in case it already exists ..."
# $DriveLetter must be concatenated with ":" for the command to work
net use "${DriveLetter}:" /del
## $DriveLetter cannot contain ":"
$psDrive = New-PSDrive -Name "$DriveLetter" -PSProvider "FileSystem" -Root "$FullPath" -Credential $Credential -Scope "Global" -Persist
Write-Host "$DriveLetter was successfully added !"
}
function BuildCredential {
param (
$Username,
$Password
)
$pass = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $pass)
return $credential
}
$credential = (BuildCredential -Username "xxxxxx" -Password "yyyyyy")[-1]
RemapDrive -DriveLetter "X" -FullPath "\\my-server\x" -Credential $credential
What I have found:
“When you scope the command locally, that is, without dot-sourcing, the Persist parameter does not persist the creation of a PSDrive beyond the scope in which you run the command. If you run New-PSDrive inside a script, and you want the new drive to persist indefinitely, you must dot-source the script. For best results, to force a new drive to persist, specify Global as the value of the Scope parameter in addition to adding Persist to your command.”
I have tried executing the script with ". .\my-script.ps1" (to dot-source the script?), but the result is the same.
Playing around with "net use" and the registry to try to add the network drive has lead me to a cul-de-sac as well.
Specs:
Windows 10 Home
Powershell version:
Major Minor Build Revision
----- ----- ----- --------
5 1 18362 1171
Upvotes: 4
Views: 5103
Reputation: 7919
What finally work was user19702's option #2, with a bit of extra work regarding the registration of the username and the password.
WARNING: as he mentioned, the best option (option #1) would have been "fixing the file share permissions instead of using a separate username/password". This was not possible in my case, and this is why I had to go with option #2.
This is the script:
# ---
# Helper functions:
function RemapDrive {
param(
$DriveLetter,
$Server,
$FullPath,
$Credential
)
# For net.exe to work, DriveLetter must end with with ":"
Write-Host "Trying to remove $DriveLetter in case it already exists ..."
net use "$DriveLetter" /del
# "net use" requires username and password as plain text
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($credential.Password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$Username=$Credential.Username
Write-Host "Registring credentials for server '$Server' ..."
cmdkey /add:$Server /user:$Username /pass:$Password
Write-Host "Mapping the drive ..."
net use $DriveLetter $FullPath /persistent:yes i
Write-Host "$DriveLetter was successfully added !"
}
function BuildCredential {
param (
$Username,
$Password
)
$pass = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $pass)
return $credential
}
# ---
# Process to execute:
$credential = (BuildCredential -Username "xxxxxx" -Password "yyyyyy")[-1]
RemapDrive -DriveLetter "X:" -Server "my-server" -FullPath "\\my-server\x" -Credential $credential
If you do not want to use a hardcoded password in BuildCredential
, but you want to prompt the user instead:
function GetCredential {
param(
$Label
)
$credential = Get-Credential -Message "Write your credentials for '$Label':"
if(!$credential) {
throw "A credential was needed to continue. Process aborted."
}
return $credential
}
Also, if instead of using $Server
as a param, you want to extract it from $FullPath
using regex, you can do that.
It presumes the $FullPath
has the following format: \\server-name\dir1\dir2\etc
# Get server name using regex:
$FullPath -match '\\\\(.*?)\\.*?'
$Server = $Matches[1]
Upvotes: 1
Reputation: 5351
Basically, New-PSDrive
doesn't have the /SAVECRED
parameter from net use
, and will not persistently map drives as a user other than the one running the script.
There are three ways to handle this:
New-PSDrive -Name "$DriveLetter" -PSProvider "FileSystem" -Root "$FullPath" -Scope 'Global' -Persist
with no credential flag. This assumes your file share allows kerberos logins, so may not work in some edge cases.net use
, and include the username, password, /persistent:yes
and /savecred
. This can be done in powershell without any issues.HKCU\Network\[drive letter]\ConnectionType = 1
HKCU\Network\[drive letter]\DeferFlags= 4
Upvotes: 5