Проблема с отображением домашнего диска пользователя в Windows 10

#powershell #active-directory #wsh

#powershell #active-directory #wsh

Вопрос:

В среде, в которой я работаю, иногда домашний диск Active Directory (AD) пользователя не отображается при входе в систему, поскольку он не подключен к сети. Позже, когда они подключатся к сети через VPN, они должны иметь возможность сопоставить свой домашний диск AD. Я создал скрипт в PowerShell для этого, но в Windows 10 я получаю сообщение об ошибке: «Ссылка на объект не установлена для экземпляра объекта». И сценарию не удается сопоставить домашний диск пользователя. Если я запускаю тот же скрипт в Windows 7, он работает без проблем. Буду признателен за любую помощь в решении этой проблемы.

 Param (
    [switch] $verbose,
    [switch] $whatif
)

Function Write-Event{
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param (
        [Parameter(Mandatory=$true)]
        $Message,
        [parameter(Mandatory=$FALSE)]
        [String[]] $LogName = 'Application',
        [String[]] $Source = "WSH",
        [String[]] $EntryType = "Information",
        [Int] $EventId = 4  
    )
    $tab= [char]9
    Write-Verbose "$tab In the function to write the event to the log"
    TRY {
        Write-Verbose "$tab Using the Wscript.shell COM object to write the event"
        $WShell = New-Object -ComObject WScript.Shell
        IF ($WhatIf){
            Write-output "What if: Performing operation Writing message to the $LogName with Event ID $EventId and message, $Message"
        } Else {
            $WShell.LogEvent($EventId, $Message) > $null
            Write-Verbose "$tab Info: Successfully wrote, $Message, to $LogName log"    
        }

    }
    CATCH {
        Write-Warning "$tab Error writing, $Message, to $LogName log"
    }
    Write-Verbose "$tab End of function to write the event to the log"
}
Function Get-ADUserProperties {
    #Requires -Version 3.0
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param (
        [parameter(Mandatory=$FALSE)]
        [String] $Username = [Environment]::UserName    
    )

    $DateNow = Get-Date
    Write-verbose "$DateNow - Getting Active Directory User Account information"
    Write-Event -Message "$DateNow - Getting Active Directory User Account information"

    # Get the user accounts AD properties       
    Try 
    {
        Write-verbose "Checking to see if User, $Username, can be found within the domain ..."
        $strFilter = "(amp;(objectClass=user)(name=$Username))"
        # Connect to the domain and create search object
        $objDomain = New-Object System.DirectoryServices.DirectoryEntry
        $objSearcher = New-Object System.DirectoryServices.DirectorySearcher
        $objSearcher.SearchRoot = $objDomain
        $objSearcher.PageSize = 15000
        $objSearcher.Filter = $strFilter
        $objSearcher.SearchScope = "Subtree"
        # Search for System
        $AllObj = $objSearcher.FindAll() 
        $ADUser = $AllObj.Properties

        Return $ADUser
    }
    CATCH 
    {
        $DateNow = Get-Date
        Write-Warning -Message "$DateNow - Error: $Username could not be found in AD"
        Return $null
    }

}

Function Set-HomeDrive {
    #Requires -Version 3.0  
    <#
        .SYNOPSIS
        Script to map a users home folder
        .DESCRIPTION
        The script will check to see if the user running it is found within  Active directory. If the user does exist it will get the AD properties for the user.
        Once the AD properties are known it will check to see if the home folder and path exist and are mapped.
        If they are already mapped it will open explorer.exe to that location.
        If they are not mapped, it will map the folder and open explorer.exe to that location.

        .PARAMETER CRQ
        Takes the CRQ number as input.  Should be a string or integer.
        .PARAMETER Name
        Takes a string as input, this should not contain any spaces or special characters.  Will be part of the log file name.

        .EXAMPLE
        C:PS> .MapHomeDrive.ps1
        This will map the users Active Directory Home drive letter to their home share 

        .INPUTS
        None
        .OUTPUTS
        None    

    #>      
    [CmdletBinding(SupportsShouldProcess=$true)]
    Param (
        [parameter(Mandatory=$false)]
            [String[]] $CRQ = '19175-10468',
            [String[]] $Name = 'MapHomeDrive'   
    )
    Begin {
        $ErrorActionPreference = "Stop"
        Write-Output -InputObject "`n"
        $DateNow = Get-Date
        Write-Output "$DateNow - Preparing Environment to Map Home Drive"
        $strCompName = $env:computername ; $strWinDir = $env:windir
        $quote = [char]34 ; $tab= [char]9 ; $plus=[char]43 ; $LOGFILE=$null  ; $text = $null ; $Color = $null
        Write-Verbose -Message "Outputting all initial parameters: `n $tab $tab CRQ: $CRQ `n $tab $tab Name: $Name `n"      

    }
    Process {

        $DateNow = Get-Date
        Write-verbose "$DateNow - $Name script started running"
        Write-Event -Message "$DateNow - $Name script started running"
        # Get the user accounts AD properties
        $ADUserProps = Get-ADUserProperties
        IF ($ADUserProps -ne $null) 
        {
            # Set variables for the user's home folder and drive
            $HomeFolder = $ADUserProps.homedirectory
            $HomeDrive = $ADUserProps.homedrive             

            IF (($HomeFolder -eq $null) -or ($HomeDrive -eq $null)) 
            {
                Write-Warning -Message "Error: $Username does not have a home directory or home drive in AD, exiting script" 
                Write-Event -Message "Error: $Username does not have a home directory or home drive in AD, exiting script" -EventID 1               
            }
            ELSE 
            {
                IF ($HomeDrive -Match ":"){$HomeDrive1 = $HomeDrive -replace ".$"} else {$HomeDrive1 = $HomeDrive}          
                # Get the logical disk for the home drive
                $TestHomeDrive = Get-WMIObject Win32_LogicalDisk -Property *|Where-Object {($_.DeviceID -eq $HomeDrive)}
                # Check to see if the drive is already mapped
                IF ($TestHomeDrive -eq $null) 
                {
                    Write-Verbose "Info: The drive, $HomeDrive1, is NOT already mapped, mapping home drive"
                    Write-Event -Message "Info: The drive, $HomeDrive1, is NOT already mapped, mapping home drive" -EventID 2
                    $net = New-Object -ComObject WScript.Network
                   Write-Verbose "$net"
                    TRY 
                    {                       
                        IF ($WhatIf){
                            Write-output "What if: Performing operation mapping, $HomeFolder to $HomeDrive"
                        } Else {
                            $net.MapNetworkDrive($HomeDrive, $HomeFolder, $true)
                        }                       
                    }
                    CATCH {
                        Write-Error -Message "Unable to map $HomeFolder to $HomeDrive  - $_"
                    }
                }
                ELSEIF ($TestHomeDrive.ProviderName -eq $HomeFolder) 
                {
                    Write-Verbose "Info: The drive, $HomeDrive1, is already mapped to $HomeFolder."
                    Write-Event -Message "Info: The drive, $HomeDrive1, is already mapped to $HomeFolder." -EventID 2
                } 
                ELSE 
                {
                    Write-Verbose "$$$$You should not be here"
                }

            }               

        }
    ELSE 
    {
        Write-Warning -Message "Error: $Username could not be found in AD, the home drive will not be mapped, exiting script" 
        Write-Event -Message "Error: $Username could not be found in AD, the home drive will not be mapped, exiting script" -EventID 1          
    }

    # Ensure that the script can get to the Home drive and launch explorer to that location
    IF ($HomeDrive -ne $null)   
    {
        IF (test-path $HomeDrive)
        {
            $DateNow = Get-Date
            $MessageText = "$DateNow - Successfully mapped drive $HomeDrive1 to $HomeFolder"
            Write-Event -Message $MessageText -EventID 0
            Write-Output $MessageText
            # Launch Explorer.exe to the Home drive folder
            $EXSwitches = "/e,"   $quote   $HomeDrive1   ":"   $quote
            amp; "explorer.exe" $EXSwitches
        } 
    }
    ELSE 
    {
        $DateNow = Get-Date
        $MessageText = "$DateNow - Error mapping drive Home Drive to Home Folder"
        Write-Event -Message $MessageText -EventID 1    
        Write-Verbose $MessageText              
    }


    }
    End {
        $DateNow = Get-Date
        Write-Event -Message "$DateNow - $Name script finished running"
        Write-Output "$DateNow - End of script to map home drive"
        Write-Output -InputObject "`n"
    }

 }
IF ($Verbose) {Set-HomeDrive -verbose} ELSEIF ($Whatif) {Set-HomeDrive -whatif} ELSE {Set-HomeDrive }
  

Вывод ошибки показывает, что ошибка возникает из строки кода «IF ($Verbose) {Set-HomeDrive -verbose} ELSEIF ($ Whatif) {Set-HomeDrive -whatif} ELSE {Set-HomeDrive }». Когда я запускаю скрипт с подробным параметром, я получаю следующий вывод.

 VERBOSE: Outputting all initial parameters:
     CRQ: 19175-10468
     Name: MapHomeDrive
VERBOSE: 10/12/2016 12:08:30 - MapHomeDrive script started running
VERBOSE:   In the function to write the event to the log
VERBOSE:   Using the Wscript.shell COM object to write the event
VERBOSE:   Info: Successfully wrote, 10/12/2016 12:08:30 - MapHomeDrive script started running, to Application log
VERBOSE:   End of function to write the event to the log
VERBOSE: 10/12/2016 12:08:30 - Getting Active Directory User Account information
VERBOSE:   In the function to write the event to the log
VERBOSE:   Using the Wscript.shell COM object to write the event
VERBOSE:   Info: Successfully wrote, 10/12/2016 12:08:30 - Getting Active Directory User Account information, to
Application log
VERBOSE:   End of function to write the event to the log
VERBOSE: Checking to see if User, keith.richardson, can be found within the domain ...
VERBOSE: Info: The drive, H, is NOT already mapped, mapping home drive
VERBOSE:   In the function to write the event to the log
VERBOSE:   Using the Wscript.shell COM object to write the event
VERBOSE:   Info: Successfully wrote, Info: The drive, H, is NOT already mapped, mapping home drive, to Application log
VERBOSE:   End of function to write the event to the log
VERBOSE: System.__ComObject
  

Комментарии:

1. В какой строке Object reference not set to an instance of an object. возникает ошибка? В этом сценарии многое происходит, но может ли это быть связано со ссылкой на WScript COM?

2. Ошибка находится в строке «IF ($Verbose) {Set-HomeDrive -verbose} ELSEIF ($Whatif) {Set-HomeDrive -whatif} ELSE {Set-HomeDrive }». Но это происходит только после начала обработки скрипта.

3.Согласно подробному выводу, на котором сценарий фактически заканчивается Write-Verbose "$net" , это последняя строка, которая выводится, поэтому, скорее всего, происходит сбой внутри Try catch инструкции, так что, вероятно, это строка — $net.MapNetworkDrive($HomeDrive, $HomeFolder, $true) .