Need Help to make this Script create the drives from powershell in Azure

William Kirby 1 Reputation point
2021-07-28T10:21:02.763+00:00

So I found a script online that works a charm when I am connected on a VPN - I am in the process of creating an Always on VPN connection at the moment so when that happens this should be redundant to a degree, but that is a few months away and I need something now - urgently.

So I need to edit this script so that mapped network drives will be created regardless of whether the end user is connected or not to the VPN and our .local domain on Premise.

I have checked through forums and seen the following "Net Use"

"net use [{devicename | *}] [\computername\sharename[\volume] [{password | *}]] [/user:[domainname]username] [/user:[dotteddomainname]username] [/user:[username@dotteddomainname] [/home {devicename | *} [{password | *}]] [/persistent:{yes | no}] [/smartcard] [/savecred] [/delete] [/help] [/?]

But I am not sure how this would fit in with the script I have for PowerShell in azure when configuring devices (Using Autopilot and Heavily Edited out to conceal domain information and generalized for posting!)

Set-ExecutionPolicy -Scope CurrentUser -executionpolicy Bypass

[CmdletBinding()]
Param()

###########################################################################################
# Start transcript for logging
###########################################################################################

Start-Transcript -Path $(Join-Path $env:temp "DriveMapping.log")

###########################################################################################
# Input values from generator
###########################################################################################

$driveMappingJson = '[{"Path":"\\\\DN-EXAMPLE\\Production","DriveLetter":"P","Label":"Production","Id":1,"GroupFilter":"Azure_P_Drive"}]'

$driveMappingConfig = $driveMappingJson | ConvertFrom-Json -ErrorAction Stop

# Override with your Active Directory Domain Name e.g. 'DN-EXAMPLE' if you haven't configured the domain name as DHCP option
$searchRoot = "DN-EXAMPLE"

# If enabled all mounted PSdrives from filesystem except os drives get disconnected if not specified in drivemapping config
$removeStaleDrives = $true

###########################################################################################
# Helper function to determine a users group membership
###########################################################################################

# Kudos for Tobias Renström who showed me this!
function Get-ADGroupMembership {
    param(
        [parameter(Mandatory = $true)]
        [string]$UserPrincipalName
    )

    process {

        try {

            if ([string]::IsNullOrEmpty($env:USERDNSDOMAIN) -and [string]::IsNullOrEmpty($searchRoot)) {
                Write-Error "Security group filtering won't work because `$env:USERDNSDOMAIN is not available!"
                Write-Warning "You can override your AD Domain in the `$overrideUserDnsDomain variable"
            }
            else {

                # if no domain specified fallback to PowerShell environment variable
                if ([string]::IsNullOrEmpty($searchRoot)) {
                    $searchRoot = $env:USERDNSDOMAIN
                }

                $searcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher
                $searcher.Filter = "(&(userprincipalname=$UserPrincipalName))"
                $searcher.SearchRoot = "LDAP://$searchRoot"
                $distinguishedName = $searcher.FindOne().Properties.distinguishedname
                $searcher.Filter = "(member:1.2.840.113556.1.4.1941:=$distinguishedName)"

                [void]$searcher.PropertiesToLoad.Add("name")

                $list = [System.Collections.Generic.List[String]]@()

                $results = $searcher.FindAll()

                foreach ($result in $results) {
                    $resultItem = $result.Properties
                    [void]$List.add($resultItem.name)
                }

                $list
            }
        }
        catch {
            #Nothing we can do
            Write-Warning $_.Exception.Message
        }
    }
}

#check if running as system
function Test-RunningAsSystem {
    [CmdletBinding()]
    param()
    process {
        return [bool]($(whoami -user) -match "S-1-5-18")
    }
}

###########################################################################################
# Get current group membership for the group filter capabilities
###########################################################################################

Write-Output "Running as SYSTEM: $(Test-RunningAsSystem)"

if ($driveMappingConfig.GroupFilter) {
    try {
        #check if running as user and not system
        if (-not (Test-RunningAsSystem)) {

            $groupMemberships = Get-ADGroupMembership -UserPrincipalName $(whoami -upn)
        }
    }
    catch {
        #nothing we can do
    }
}
###########################################################################################
# Mapping network drives
###########################################################################################
#Get PowerShell drives and rename properties

if (-not (Test-RunningAsSystem)) {

    $psDrives = Get-PSDrive | Where-Object { $_.Provider.Name -eq "FileSystem" -and $_.Root -notin @("$env:SystemDrive\", "D:\") } `
    | Select-Object @{N = "DriveLetter"; E = { $_.Name } }, @{N = "Path"; E = { $_.DisplayRoot } }

    # only map drives where group membership applicable
    $driveMappingConfig = $driveMappingConfig | Where-Object { $groupMemberships -contains $_.GroupFilter -or $_.GroupFilter -eq $null }

    #iterate through all network drive configuration entries
    foreach ($drive in $driveMappingConfig) {

        try {
            #check if variable in unc path exists, e.g. for $env:USERNAME -> resolving
            if ($drive.Path -match '\$env:') {
                $drive.Path = $ExecutionContext.InvokeCommand.ExpandString($drive.Path)
            }

            #if label is null we need to set it to empty in order to avoid error
            if ($null -eq $drive.Label) {
                $drive.Label = ""
            }

            $exists = $psDrives | Where-Object { $_.Path -eq $drive.Path -or $_.DriveLetter -eq $drive.DriveLetter }
            $process = $true

            if ($null -ne $exists -and $($exists.Path -eq $drive.Path -and $exists.DriveLetter -eq $drive.DriveLetter )) {
                Write-Output "Drive '$($drive.DriveLetter):\' '$($drive.Path)' already exists with correct Drive Letter and Path"
                $process = $false

            }
            else {
                # Mapped with wrong config -> Delete it
                Get-PSDrive | Where-Object { $_.DisplayRoot -eq $drive.Path -or $_.Name -eq $drive.DriveLetter } | Remove-PSDrive -EA SilentlyContinue
            }

            if ($process) {
                Write-Output "Mapping network drive $($drive.Path)"
                $null = New-PSDrive -PSProvider FileSystem -Name $drive.DriveLetter -Root $drive.Path -Description $drive.Label -Persist -Scope global -EA Stop
                (New-Object -ComObject Shell.Application).NameSpace("$($drive.DriveLetter):").Self.Name = $drive.Label
            }
        }
        catch {
            $available = Test-Path $($drive.Path)
            if (-not $available) {
                Write-Error "Unable to access path '$($drive.Path)' verify permissions and authentication!"
            }
            else {
                Write-Error $_.Exception.Message
            }
        }
    }

    # Remove unassigned drives
    if ($removeStaleDrives -and $null -ne $psDrives) {
        $diff = Compare-Object -ReferenceObject $driveMappingConfig -DifferenceObject $psDrives -Property "DriveLetter" -PassThru | Where-Object { $_.SideIndicator -eq "=>" }
        foreach ($unassignedDrive in $diff) {
            Write-Warning "Drive '$($unassignedDrive.DriveLetter)' has not been assigned - removing it..."
            Remove-SmbMapping -LocalPath "$($unassignedDrive.DriveLetter):" -Force -UpdateProfile
        }
    }

    # Fix to ensure drives are mapped as persistent!
    $null = Get-ChildItem -Path HKCU:\Network -ErrorAction SilentlyContinue | ForEach-Object { New-ItemProperty -Name ConnectionType -Value 1 -Path $_.PSPath -Force -ErrorAction SilentlyContinue }
}

###########################################################################################
# End & finish transcript
###########################################################################################

Stop-transcript

###########################################################################################
# Done
###########################################################################################

#!SCHTASKCOMESHERE!#

###########################################################################################
# If this script is running under system (IME) scheduled task is created  (recurring)
###########################################################################################

if (Test-RunningAsSystem) {

    Start-Transcript -Path $(Join-Path -Path $env:temp -ChildPath "IntuneDriveMappingScheduledTask.log")
    Write-Output "Running as System --> creating scheduled task which will run on user logon"

    ###########################################################################################
    # Get the current script path and content and save it to the client
    ###########################################################################################

    $currentScript = Get-Content -Path $($PSCommandPath)

    $schtaskScript = $currentScript[(0) .. ($currentScript.IndexOf("#!SCHTASKCOMESHERE!#") - 1)]

    $scriptSavePath = $(Join-Path -Path $env:ProgramData -ChildPath "intune-drive-mapping-generator")

    if (-not (Test-Path $scriptSavePath)) {

        New-Item -ItemType Directory -Path $scriptSavePath -Force
    }

    $scriptSavePathName = "DriveMappping.ps1"

    $scriptPath = $(Join-Path -Path $scriptSavePath -ChildPath $scriptSavePathName)

    $schtaskScript | Out-File -FilePath $scriptPath -Force

    ###########################################################################################
    # Create dummy vbscript to hide PowerShell Window popping up at logon
    ###########################################################################################

    $vbsDummyScript = "
    Dim shell,fso,file

    Set shell=CreateObject(`"WScript.Shell`")
    Set fso=CreateObject(`"Scripting.FileSystemObject`")

    strPath=WScript.Arguments.Item(0)

    If fso.FileExists(strPath) Then
        set file=fso.GetFile(strPath)
        strCMD=`"powershell -nologo -executionpolicy ByPass -command `" & Chr(34) & `"&{`" &_
        file.ShortPath & `"}`" & Chr(34)
        shell.Run strCMD,0
    End If
    "

    $scriptSavePathName = "IntuneDriveMapping-VBSHelper.vbs"

    $dummyScriptPath = $(Join-Path -Path $scriptSavePath -ChildPath $scriptSavePathName)

    $vbsDummyScript | Out-File -FilePath $dummyScriptPath -Force

    $wscriptPath = Join-Path $env:SystemRoot -ChildPath "System32\wscript.exe"

    ###########################################################################################
    # Register a scheduled task to run for all users and execute the script on logon
    ###########################################################################################

    $schtaskName = "IntuneDriveMapping"
    $schtaskDescription = "Map network drives from intune-drive-mapping-generator."

    $trigger = New-ScheduledTaskTrigger -AtLogOn
    #Execute task in users context
    $principal = New-ScheduledTaskPrincipal -GroupId "S-1-5-32-545" -Id "Author"
    #call the vbscript helper and pass the PosH script as argument
    $action = New-ScheduledTaskAction -Execute $wscriptPath -Argument "`"$dummyScriptPath`" `"$scriptPath`""
    $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries

    $null = Register-ScheduledTask -TaskName $schtaskName -Trigger $trigger -Action $action  -Principal $principal -Settings $settings -Description $schtaskDescription -Force

    Start-ScheduledTask -TaskName $schtaskName

    Stop-Transcript
}

###########################################################################################
# Done
###########################################################################################
Windows 10 Network
Windows 10 Network
Windows 10: A Microsoft operating system that runs on personal computers and tablets.Network: A group of devices that communicate either wirelessly or via a physical connection.
2,346 questions
Windows 10 Setup
Windows 10 Setup
Windows 10: A Microsoft operating system that runs on personal computers and tablets.Setup: The procedures involved in preparing a software program or application to operate within a computer or mobile device.
1,942 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Candy Luo 12,701 Reputation points Microsoft Vendor
    2021-07-29T07:43:12.16+00:00

    Hi ,

    Based on my understanding, you want to use net use command to create mapped network drives regardless of whether the end user is connected or not connect to the VPN. Is that right? Please feel free to let me know if I have any misunderstanding.

    If we want to map network drive, we need first ensure network connection is fine:

    119011-1.png

    If you disconnect and there is no network connection between your VPN client and file server, then net use command will not work:

    119012-2.png

    So we must confirm network connection is fine and then we can map network drive.

    Best Regards,
    Candy

    --------------------------------------------------------------

    If the Answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. William Kirby 1 Reputation point
    2021-08-05T13:35:44.88+00:00

    That doesn't really help too much, as the user won't be connected to the VPN when the drive mapping script (in powershell scripting via intune) runs.

    I might have to approach this differently

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.