HideWindowsExplorerDrives.psm1

Function Get-DriveStatus
{
    Param(
        [Parameter(
            ValueFromPipeline
        )]
        [ValidatePattern('^[A-z]$')]
        [String[]]
        $DriveLetter
    )
    Begin
    {
        $hiddenDrives = Get-HiddenDriveValue
        $letterMap = Get-LetterMap
    }
    
    Process
    {
        $lettersToCheck = $letterMap.Keys | 
            Sort-Object
        if ($DriveLetter)
        {
            $lettersToCheck = $lettersToCheck | 
                Where-Object {$PSItem -in $DriveLetter}
        }        
        foreach ($letter in $lettersToCheck)
        {
            $driveHidden = ($hiddenDrives -band $letterMap[$letter]) -eq $letterMap[$letter]
            [pscustomobject]@{
                DriveLetter = $letter
                IsHidden    = $driveHidden
            }
        }
    }
}
Function Hide-DriveLetter
{
    Param(
        [Parameter(
            ValueFromPipeline
        )]
        [ValidatePattern('[a-z]')]
        [ValidateLength(1, 1)]
        [String[]]
        $DriveLetter
    )
    Begin
    {
        $isAdmin = Test-IsAdmin
        if ($isAdmin)
        {
            $letterMap = Get-LetterMap
        }
        else
        {
            Write-Warning "Must be an administrator to hide drives"           
        }
    }
    Process
    {
        if ($isAdmin)
        {
            ForEach ($drive in $DriveLetter)
            {
                $driveStatus = Get-DriveStatus -DriveLetter $drive
                if ($driveStatus.IsHidden)
                {
                    Write-Verbose -Message "Drive Letter [$drive] already hidden"
                }
                else
                {
                    $hiddenDrives = Get-HiddenDriveValue
                    $driveValue = $hiddenDrives -bor $letterMap[$drive]
                    Write-Verbose -Message "Hidding Drive Letter [$drive]"
                    Set-HiddenDriveValue -NewValue $driveValue
                }
            
            }
        }
    }
    End
    {
        Write-Verbose -Message "Please restart explorer for changes to take effect"
    }
}
Function Show-DriveLetter
{
    [CmdletBinding()]
    Param(
        [Parameter(
            ValueFromPipeline
        )]
        [ValidatePattern('[a-z]')]
        [ValidateLength(1, 1)]
        [String[]]
        $DriveLetter
    )
    Begin
    {
        $isAdmin = Test-IsAdmin
        if ($isAdmin)
        {
            $letterMap = Get-LetterMap
        }
        else
        {
            Write-Warning "Must be an administrator to show drives"           
        }
    }
    Process
    {
        if ($isAdmin)
        {
            ForEach ($drive in $DriveLetter)
            {
                $driveStatus = Get-DriveStatus -DriveLetter $drive
                if ($driveStatus.IsHidden)
                {
                    $hiddenDrives = Get-HiddenDriveValue
                    $driveValue = $hiddenDrives - $letterMap[$drive]
                    Write-Verbose -Message "Showing Drive Letter [$drive]"
                    Set-HiddenDriveValue -NewValue $driveValue
                } 
                else
                {
                    Write-Verbose -Message "Drive [$drive] already shown"   
                }
            }
        }
        
    }
    End
    {
        Write-Verbose -Message "Please restart explorer for changes to take effect"
    }
}
Function Get-HiddenDriveValue
{
    $HIDDEN_DRIVES_KEY = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\'
    (Get-Item -Path $HIDDEN_DRIVES_KEY).GetValue("NoDrives")
}
Function Get-LetterMap
{
    @{
        A = 1
        B = 2
        C = 4
        D = 8
        E = 16
        F = 32
        G = 64
        H = 128
        I = 256
        J = 512
        K = 1024
        L = 2048
        M = 4096
        N = 8192
        O = 16384
        P = 32768
        Q = 65536
        R = 131072
        S = 262144
        T = 524288
        U = 1048576
        V = 2097152
        W = 4194304
        X = 8388608
        Y = 16777216
        Z = 33554432
    }
}
Function New-LetterMap
{
    $letterMap = @{}
    1..26 | ForEach-Object {
        $currentNumber = $_
        [string]$letter = [char]($currentNumber + 64)
        $driveValue = [math]::Pow(2, ($currentNumber - 1))
        $letterMap[$letter] = $driveValue
    }
    $letterMap
}
Function Set-HiddenDriveValue
{
    Param([int]$NewValue)
    $HIDDEN_DRIVES_KEY = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\'
    $PROPERTY_NAME = "NoDrives"
    Set-ItemProperty -Path $HIDDEN_DRIVES_KEY -Name $PROPERTY_NAME -Value $NewValue -Force
}
Function Test-IsAdmin
{
    ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
}
if (Get-Command -Name Get-Partition)
{
    $type = 'Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/Storage/MSFT_Partition'
    
    $TypeData = @{
        TypeName   = $type
        MemberType = 'ScriptProperty'
        MemberName = 'IsHidden'
        Value      = {
            (Get-DriveStatus -DriveLetter $this.DriveLetter).IsHidden
        }
    }
    Update-TypeData @TypeData -Force
    
    $TypeData = @{
        TypeName   = $type
        MemberType = 'ScriptMethod'
        MemberName = 'HidePartition'
        Value      = {
            Hide-DriveLetter -DriveLetter $this.DriveLetter
        }
    }
    Update-TypeData @TypeData -Force
    
    $TypeData = @{
        TypeName   = $type
        MemberType = 'ScriptMethod'
        MemberName = 'ShowPartition'
        Value      = {
            Show-DriveLetter -DriveLetter $this.DriveLetter
        }
    }
    Update-TypeData @TypeData -Force
    
}