切换到宽版
  • 47837阅读
  • 0回复

[求助]使用脚本列出Exchange 2007客户端访问许可 [复制链接]

上一主题 下一主题
 
只看楼主 倒序阅读 0楼  发表于: 2011-03-20
— 本帖被 YOYO 从 Exchange 脚本中心 移动到本区(2015-06-25) —
  • 脚本环境:PowerShell
  • 适合版本:Exchange 2007
  • 适用平台:
估计的Exchange Server 2007客户端访问许可证(CAL)的数量和类型的CAL要求给予您的组织的Exchange环境中作业特性(例如,对某些高级功能的用户启用)。这可能有助于理解您的组织的Exchange Server 2007功能的使用,也可以协助您的内部审计和验证中,您许可证。本报告不计算设备CAL,和您的组织的实际牌照责任可能因不同的授权计划提供单品,它已经授权的基础。无论本报告的结果,它是你的组织的责任,以确保它完全为这个产品的授权。

# Trap block
trap {
    write-host "An error has occurred running the script:"
    write-host $_
    $Global:AdminSessionADSettings.DefaultScope = $OriginalDefaultScope
    exit
}
# Function that returns true if the incoming argument is a help request
function IsHelpRequest
{
    param($argument)
    return ($argument -eq "-?" -or $argument -eq "-help");
}
# Function that displays the help related to this script following
# the same format provided by get-help or <cmdletcall> -?
function Usage
{
@"
NAME:
`tReportExchangeCALs.ps1
SYNOPSIS:
`tReports Exchange client access licenses (CALs) of this organization in Enterprise or Standard categories.
SYNTAX:
`tReportExchangeCALs.ps1
PARAMETERS:
USAGE:
`t.\ReportExchangeCALs.ps1
"@
}
# Function that resets AdminSessionADSettings.DefaultScope to original value and exits the script
function Exit-Script
{
    $Global:AdminSessionADSettings.DefaultScope = $OriginalDefaultScope
    exit
}
########################
## Script starts here ##
########################
# Check for Usage Statement Request
$args | foreach { if (IsHelpRequest $_) { Usage; Exit-Script; } }
# Introduction message
write-host "Report Exchange client access licenses (CALs) in use in the organization"
write-host "It will take some time if there are a large amount of users......"
write-host ""
# Report all recipients in the org.
$OriginalDefaultScope = $Global:AdminSessionADSettings.DefaultScope
$Global:AdminSessionADSettings.DefaultScope = $Null
$TotalMailboxes = 0
$TotalEnterpriseCALs = 0
$UMUserCount = 0
$ManagedCustomFolderUserCount = 0
$AdvancedActiveSyncUserCount = 0
$AdvancedAntispamUserCount = 0
$AdvancedAntispamEnabled = $False
$OrgWideJournalingEnabled = $False
$AllMailboxIDs = @{}
$EnterpriseCALMailboxIDs = @{}
$JournalingUserCount = 0
$JournalingMailboxIDs = @{}
$JournalingDGMailboxMemberIDs = @{}
$TotalStandardCALs = 0
$VisitedGroups = @{}
$DGStack = new-object System.Collections.Stack
# Bool variable for outputing progress information running this script.
$EnableProgressOutput = $True
if ($EnableProgressOutput -eq $True) {
    write-host "Progress:"
}
################
## Debug code ##
################
# Bool variable for output hash table information for debugging purpose.
$EnableOutputCounts = $False
function Output-Counts
{
    if ($EnableOutputCounts -eq $False) {
        return
    }
    write-host "Hash Table Name                                 Count"
    write-host "---------------                                 -----"
    write-host "AllMailboxIDs:                                 " $AllMailboxIDs.Count
    write-host "EnterpriseCALMailboxIDs:                       " $EnterpriseCALMailboxIDs.Count
    write-host "JournalingMailboxIDs:                          " $JournalingMailboxIDs.Count
    write-host "JournalingDGMailboxMemberIDs:                  " $JournalingDGMailboxMemberIDs.Count
    write-host "VisitedGroups:                                 " $VisitedGroups.Count
    write-host ""
    write-host ""
}
function Merge-Hashtables
{
    $Table1 = $args[0]
    $Table2 = $args[1]
    $Result = @{}
    
    if ($null -ne $Table1)
    {
        $Result += $Table1
    }
    if ($null -ne $Table2)
    {
        foreach ($entry in $Table2.GetEnumerator())
        {
            $Result[$entry.Key] = $entry.Value
        }
    }
    $Result
}
# Function that outputs Exchange CALs in the organization
function Output-Report {
    write-host "========================="
    write-host "Exchange CAL Usage Report"
    write-host "========================="
    write-host ""
    write-host "Total Users:                                    $TotalMailboxes"
    write-host "Total Standard CALs:                            $TotalStandardCALs"
    write-host "Total Enterprise CALs:                          $TotalEnterpriseCALs"
}
#################
## Total Users ##
#################
# Note!!!
# Only user, shared and linked mailboxes are counted.
# Resource mailboxes and legacy mailboxes are NOT counted.
Get-Mailbox -ResultSize 'Unlimited' -Filter { (RecipientTypeDetails -eq 'UserMailbox') -or
                                              (RecipientTypeDetails -eq 'SharedMailbox') -or
                                              (RecipientTypeDetails -eq 'LinkedMailbox') } | foreach {
    $Mailbox = $_
    
    $AllMailboxIDs[$Mailbox.Identity] = $null
    $Script:TotalMailboxes++
}
if ($TotalMailboxes -eq 0) {
    # No mailboxes in the org. Just output the report and exit
    Output-Report
    
    Exit-Script
}
#########################
## Total Standard CALs ##
#########################
# All users are counted as Standard CALs
$TotalStandardCALs = $TotalMailboxes
## Progress output ......
if ($EnableProgressOutput -eq $True) {
    write-host "Total Standard CALs calculated:                 $TotalStandardCALs"
}
#############################
## Per-org Enterprise CALs ##
#############################
# If advanced anti-spam is turned on, all mailboxes are counted as Enterprise CALs
Get-TransportServer | foreach {
    # If advanced anti-spam is turned on any Hub/Edge server, all mailboxes in the org are counted as Exchange CALs
    
    $AntispamUpdates = Get-AntispamUpdates $_
    if (($AntispamUpdates.SpamSignatureUpdatesEnabled -eq $True) -or
        ($AntispamUpdates.IPReputationUpdatesEnabled -eq $True) -or
        ($AntispamUpdates.UpdateMode -eq "Automatic")) {
        $Script:AdvancedAntispamEnabled = $True
        $Script:AdvancedAntispamUserCount = $Script:TotalMailboxes    
        $Script:TotalEnterpriseCALs = $Script:TotalMailboxes
        ## Progress output ......
        if ($EnableProgressOutput -eq $True) {
            write-host "Advanced Anti-spam Enabled:                     True"
            write-host "Total Enterprise CALs calculated:               $TotalEnterpriseCALs"
            write-host ""
        }
        # All mailboxes are counted as Enterprise CALs, report and exit.
        Output-Counts
        Output-Report
        Exit-Script
    }
}
## Progress output ......
if ($EnableProgressOutput -eq $True) {
    write-host "Advanced Anti-spam Enabled:                     False"
}

##############################
## Per-user Enterprise CALs ##
##############################
#
# Calculate Enterprise CAL users using UM, MRM Managed Custom Folder, and advanced ActiveSync policy settings
#
$AllMailboxIDs.Keys | foreach {  
    $Mailbox = Get-Mailbox $_
    
     # UM usage classifies the user as an Enterprise CAL  
    if ($Mailbox.UMEnabled)
    {
        $Script:UMUserCount++
        $Script:EnterpriseCALMailboxIDs[$Mailbox.Identity] = $null
    }
    # MRM Managed Custom Folder usage classifies the user as an Enterprise CAL
    if ($Mailbox.ManagedFolderMailboxPolicy -ne $null)
    {    
        $ManagedFolderLinks = (Get-ManagedFolderMailboxPolicy $Mailbox.ManagedFolderMailboxPolicy).ManagedFolderLinks
        foreach ($FolderLink in $ManagedFolderLinks) {
            $ManagedFolder = Get-ManagedFolder $FolderLink
            # Managed Custom Folders require an Enterprise CAL
            If ($ManagedFolder.FolderType -eq "ManagedCustomFolder")
            {
                $Script:ManagedCustomFolderUserCount++
                $Script:EnterpriseCALMailboxIDs[$Mailbox.Identity] = $null
                break
            }
        }
    }

    # Advanced ActiveSync policies classify the user as an Enterprise CAL
    $Mailbox = Get-CASMailbox $_
    if ($Mailbox.ActiveSyncEnabled -and ($Mailbox.ActiveSyncMailboxPolicy -ne $null))
    {
        $ASPolicy = Get-ActiveSyncMailboxPolicy $CASMailbox.ActiveSyncMailboxPolicy
        if (($ASPolicy.AllowDesktopSync -eq $False) -or
            ($ASPolicy.AllowStorageCard -eq $False) -or
            ($ASPolicy.AllowCamera -eq $False) -or
            ($ASPolicy.AllowTextMessaging -eq $False) -or
            ($ASPolicy.AllowWiFi -eq $False) -or
            ($ASPolicy.AllowBluetooth -eq "Disable") -or
            ($ASPolicy.AllowIrDA -eq $False) -or
            ($ASPolicy.AllowInternetSharing -eq $True) -or
            ($ASPolicy.AllowRemoteDesktop -eq $True) -or
            ($ASPolicy.AllowPOPIMAPEmail -eq $False) -or
            ($ASPolicy.AllowConsumerEmail -eq $True) -or
            ($ASPolicy.AllowBrowser -eq $True) -or
            ($ASPolicy.AllowUnsignedApplications -eq $True) -or
            ($ASPolicy.AllowUnsignedInstallationPackages -eq $True) -or
            ($ASPolicy.ApprovedApplicationList -ne $null) -or
            ($ASPolicy.UnapprovedInROMApplicationList -ne $null)) {
            $Script:AdvancedActiveSyncUserCount++
            $Script:EnterpriseCALMailboxIDs[$Mailbox.Identity] = $null
        }
    }
}
## Progress output ......
if ($EnableProgressOutput -eq $True) {
    write-host "Unified Messaging Users calculated:             $UMUserCount"
    write-host "Managed Custom Folder Users calculated:         $ManagedCustomFolderUserCount"
    write-host "Advanced ActiveSync Policy Users calculated:    $AdvancedActiveSyncUserCount"
}
#
# Calculate Enterprise CAL users using Journaling
#
# Help function for function Get-JournalingGroupMailboxMember to traverse members of a DG/DDG/group
function Traverse-GroupMember
{
    $GroupMember = $args[0]
    
    if( $GroupMember -eq $null )
    {
        return
    }
    # Note!!!
    # Only user, shared and linked mailboxes are counted.
    # Resource mailboxes and legacy mailboxes are NOT counted.
    if ( ($GroupMember.RecipientTypeDetails -eq 'UserMailbox') -or
         ($GroupMember.RecipientTypeDetails -eq 'SharedMailbox') -or
         ($GroupMember.RecipientTypeDetails -eq 'LinkedMailbox') ) {
        # Journal one mailbox
        $Script:JournalingMailboxIDs[$GroupMember.Identity] = $null
    } elseif ( ($GroupMember.RecipientType -eq "Group") -or ($GroupMember.RecipientType -like "Dynamic*Group") -or ($GroupMember.RecipientType -like "Mail*Group") ) {
        # Push this DG/DDG/group into the stack.
        $DGStack.Push(@($GroupMember.Identity, $GroupMember.RecipientType))
    }
}
# Function that returns all mailbox members including duplicates recursively from a DG/DDG
function Get-JournalingGroupMailboxMember
{
    # Skip this DG/DDG if it was already enumerated.
    if ( $Script:VisitedGroups.ContainsKey($args[0]) ) {
        return
    }
    
    $DGStack.Push(@($args[0],$args[1]))
    while ( $DGStack.Count -ne 0 ) {
        $StackElement = $DGStack.Pop()
        
        $GroupIdentity = $StackElement[0]
        $GroupRecipientType = $StackElement[1]
        if ( $Script:VisitedGroups.ContainsKey($GroupIdentity) ) {
            # Skip this this DG/DDG if it was already enumerated.
            continue
        }
        
        # Check the members of the current DG/DDG/group in the stack.
        if ( ($GroupRecipientType -like "Mail*Group") -or ($GroupRecipientType -eq "Group" ) ) {
            $varGroup = Get-Group $GroupIdentity -ErrorAction SilentlyContinue
            if ( $varGroup -eq $Null )
            {
                $errorMessage = "Invalid group/distribution group/dynamic distribution group: " + $GroupIdentity
                write-error $errorMessage
                return
            }
            
            $varGroup.members | foreach {    
                # Count users and groups which could be mailboxes.
                $varGroupMember = Get-User $_ -ErrorAction SilentlyContinue
                if ( $varGroupMember -eq $Null ) {
                    $varGroupMember = Get-Group $_ -ErrorAction SilentlyContinue                  
                }

                if ( $varGroupMember -ne $Null ) {
                    Traverse-GroupMember $varGroupMember
                }
            }
        } else {
            # The current stack element is a DDG.
            $varGroup = Get-DynamicDistributionGroup $GroupIdentity -ErrorAction SilentlyContinue
            if ( $varGroup -eq $Null )
            {
                $errorMessage = "Invalid group/distribution group/dynamic distribution group: " + $GroupIdentity
                write-error $errorMessage
                return
            }
            Get-Recipient -RecipientPreviewFilter $varGroup.LdapRecipientFilter -OrganizationalUnit $varGroup.RecipientContainer -ResultSize 'Unlimited' | foreach {
                Traverse-GroupMember $_
            }
        }
        # Mark this DG/DDG as visited as it's enumerated.
        $Script:VisitedGroups[$GroupIdentity] = $null
    }    
}

# Check all journaling mailboxes for all journaling rules.
foreach ($JournalRule in Get-JournalRule){
    # There are journal rules in the org.
    if ( $JournalRule.Recipient -eq $Null ) {
        # One journaling rule journals the whole org (all mailboxes)
        $OrgWideJournalingEnabled = $True
        $Script:JournalingUserCount = $Script:TotalMailboxes
        $Script:TotalEnterpriseCALs = $Script:TotalMailboxes
        break
    } else {
        $JournalRecipient = Get-Recipient $JournalRule.Recipient.Local -ErrorAction SilentlyContinue
        if ( $JournalRecipient -ne $Null ) {
            # Note!!!
            # Only user, shared and linked mailboxes are counted.
            # Resource mailboxes and legacy mailboxes are NOT counted.
            if ( ($JournalRecipient.RecipientTypeDetails -eq 'UserMailbox') -or
                 ($JournalRecipient.RecipientTypeDetails -eq 'SharedMailbox') -or
                 ($JournalRecipient.RecipientTypeDetails -eq 'LinkedMailbox') ) {
                # Journal a mailbox
                $Script:JournalingMailboxIDs[$JournalRecipient.Identity] = $null
            } elseif ( ($JournalRecipient.RecipientType -like "Mail*Group") -or ($JournalRecipient.RecipientType -like "Dynamic*Group") ) {
                # Journal a DG or DDG.
                # Get all mailbox members for the current journal DG/DDG and add to $JournalingDGMailboxMemberIDs
                Get-JournalingGroupMailboxMember $JournalRecipient.Identity $JournalRecipient.RecipientType
                Output-Counts
            }
        }
    }
}
if ( !$OrgWideJournalingEnabled ) {
    # No journaling rules journaling the entire org.
    # Get all journaling mailboxes
    $Script:JournalingMailboxIDs = Merge-Hashtables $Script:JournalingDGMailboxMemberIDs $Script:JournalingMailboxIDs
    $Script:JournalingUserCount = $Script:JournalingMailboxIDs.Count
}
## Progress output ......
if ($EnableProgressOutput -eq $True) {
    write-host "Journaling Users calculated:                    $JournalingUserCount"
}
#
# Calculate Enterprise CALs
#
if ( !$OrgWideJournalingEnabled ) {
    # Calculate Enterprise CALs as not all mailboxes are Enterprise CALs
    $Script:EnterpriseCALMailboxIDs = Merge-Hashtables $Script:JournalingMailboxIDs $Script:EnterpriseCALMailboxIDs
    $Script:TotalEnterpriseCALs = $Script:EnterpriseCALMailboxIDs.Count
}
## Progress output ......
if ($EnableProgressOutput -eq $True) {
    write-host "Total Enterprise CALs calculated:               $TotalEnterpriseCALs"
    write-host ""
}

###################
## Output Report ##
###################
Output-Counts
Output-Report
$Global:AdminSessionADSettings.DefaultScope = $OriginalDefaultScope

################################
## Sample Exchange CAL Report ##
################################
#[PS] D:\>.\ReportExchangeCALs.ps1
#Report Exchange client access licenses (CALs) in use in the organization
#It will take some time if there are a large amount of users......
#
#Progress:
#Total Standard CALs calculated:                 10000
#Advanced Anti-spam Enabled:                     False
#Unified Messaging Users calculated:             2000
#Managed Custom Folder Users calculated:         1000
#Advanced ActiveSync Policy Users calculated:    200
#Journaling Users calculated:                    500
#Total Enterprise CALs calculated:               2200
#
#=========================
#Exchange CAL Usage Report
#=========================
#
#Total Users:                                    10000
#Total Standard CALs:                            10000
#Total Enterprise CALs:                          2200

分享到
快速回复
限60 字节
 
上一个 下一个