Cmdlets/New-SPCheckedOutFileSummary/New-SPCheckedOutFileSummary.psm1

Function New-SPCheckedOutFilesSummary
{
    [cmdletbinding()]
    param(
    [Parameter(mandatory=$True, position=0, HelpMessage="Site Collection URL for which the summary report should be prepared")]
    [URI]$SiteURL,
    [parameter(mandatory=$False, position=1, HelpMessage="The directory that the summary file should be placed in")]
    [URI]$OutputDirectory,
    [parameter(mandatory=$True, position=2, HelpMessage="The emails to generate from the summary")]
    [ValidateSet("None","UserOnly", "SiteOwnerOnly","UserAndSiteOwner")]
    [String]$EmailsToSend,
    [parameter(mandatory=$False, position=3, HelpMessage="Use this switch to indicate that you have multiple domains")]
    [Switch]$MultiDomain
    )
    DynamicParam
    {
        $paramDictionary = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
        if (-not ([String]::IsNullOrEmpty($EmailsToSend)) -and ($EmailsToSend -ne "None"))
        {
            $SMTPServerAttribute = New-Object System.Management.Automation.ParameterAttribute
            $SMTPServerAttribute.HelpMessage = "Please specify the SMTP Server:"
            $SMTPServerAttribute.Mandatory = $True
            $SMTPServerAttribute.Position = 4
            $smtpServerAttribute.ParameterSetName = "SendMail"
            $SMTPFromAddressAttribute = New-Object System.Management.Automation.ParameterAttribute
            $SMTPFromAddressAttribute.HelpMessage = "Please enter the SMTP From Address:"
            $SMTPFromAddressAttribute.Mandatory = $True
            $SMTPFromAddressAttribute.Position = 5
            $SMTPFromAddressAttribute.ParameterSetName = "SendMail"
            $SMTPReplyToAddressAttribute = New-Object System.Management.Automation.ParameterAttribute
            $SMTPReplyToAddressAttribute.HelpMessage = "Please enter the SMTP Reply Address:"
            $SMTPReplyToAddressAttribute.Mandatory = $True
            $SMTPReplyToAddressAttribute.Position = 6
            $SMTPReplyToAddressAttribute.ParameterSetName = "SendMail"
            $SMTPCCAddressAttribute = New-Object System.Management.Automation.ParameterAttribute
            $SMTPCCAddressAttribute.HelpMessage = "Please enter an address to CC on the e-mail:"
            $SMTPCCAddressAttribute.Mandatory = $False
            $SMTPCCAddressAttribute.position = 7
            $SMTPCCAddressAttribute.ParameterSetName = "SendMail"
            $SMTPBodyFileAttribute = New-Object System.Management.Automation.ParameterAttribute
            $SMTPBodyFileAttribute.HelpMessage = "Specify the file to use as a standard e-mail body"
            $SMTPBodyFileAttribute.Mandatory = $True
            $SMTPBodyFileAttribute.Position = 8
            $SMTPBodyFileAttribute.ParameterSetName = "SendMail"
            $FileFormatAttribute = New-Object System.Management.Automation.ParameterAttribute
            $FileFormatAttribute.HelpMessage = "Specify the type of file you would like to provide to end-users"
            $FileFormatAttribute.Mandatory = $True
            $FileFormatAttribute.Position = 9
            $FileFormatAttribute.ParameterSetName = "SendMail"
            $SMTPServerAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $SMTPServerAttributeCollection.Add($SMTPServerAttribute)
            $SMTPFromAddressAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $SMTPFromAddressAttributeCollection.Add($SMTPFromAddressAttribute)
            $SMTPReplyToAddressAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $SMTPReplyToAddressAttributeCollection.Add($SMTPReplyToAddressAttribute)
            $SMTPCCAddressAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $SMTPCCAddressAttributeCollection.Add($SMTPCCAddressAttribute)
            $SMTPBodyFileAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $SMTPBodyFileAttributeCollection.Add($SMTPBodyFileAttribute)
            $FileFormatAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $FileFormatAttributeCollection.Add($FileFormatAttribute)
            $FileFormatValidationOptions=@("CSV", "HTML")
            $FileFormatValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($FileFormatValidationOptions)
            $FileFormatAttributeCollection.Add($FileFormatValidateSetAttribute)
            $SMTPServerParam = New-Object System.Management.Automation.RuntimeDefinedParameter('SMTPServer', [String], $SMTPServerAttributeCollection)
            $SMTPFromAddressParam = New-Object System.Management.Automation.RuntimeDefinedParameter('SMTPFromAddress', [String], $SMTPFromAddressAttributeCollection)
            $SMTPReplyToAddressParam = New-Object System.Management.Automation.RuntimeDefinedParameter('SMTPReplyToAddress', [String], $SMTPReplyToAddressAttributeCollection)
            $SMTPCCAddressParam = New-Object System.Management.Automation.RuntimeDefinedParameter('SMTPCCAddress', [String], $SMTPCCAddressAttributeCollection)
            $SMTPBodyFileParam = New-Object System.Management.Automation.RuntimeDefinedParameter('SMTPBodyFile', [URI], $SMTPBodyFileAttributeCollection)
            $FormatParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Format', [String], $FileFormatAttributeCollection)
            $paramDictionary.Add('SMTPServer', $SMTPServerParam)
            $paramDictionary.Add('SMTPFromAddress', $SMTPFromAddressParam)
            $paramDictionary.Add('SMTPReplyToAddress', $SMTPReplyToAddressParam)
            $paramDictionary.Add('SMTPCCAddress', $SMTPCCAddressParam)
            $paramDictionary.Add('SMTPBodyFile', $SMTPBodyFileParam)
            $paramDictionary.Add('Format', $FormatParam)

        }
        if($MultiDomain)
        {
            $MultiDomainCSVAttribute = New-Object System.Management.Automation.ParameterAttribute
            $MultiDomainCSVAttribute.HelpMessage = "Specify the file that contains information about your domains"
            $MultiDomainCSVAttribute.Mandatory = $False
            $MultiDomainCSVAttribute.Position = 10
            $MultiDomainCSVAttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $MultiDomainCSVAttributeCollection.Add($MultiDomainCSVAttribute)
            $MultiDomainValidateScriptAttribute = New-Object -TypeName System.Management.Automation.ValidateScriptAttribute([System.Management.Automation.ScriptBlock]::Create("if(`$_.localpath.endswith(`".csv`")){`$True}else{Throw `"`$MultiDomainCSV must be a CSV file`"}"))
            $MultiDomainCSVAttributeCollection.Add($MultiDomainValidateScriptAttribute)
            $MultiDomainCSVParam = New-Object System.Management.Automation.RuntimeDefinedParameter('MultiDomainCSV', [URI], $MultiDomainCSVAttributeCollection)
            $paramDictionary.Add('MultiDomainCSV', $MultiDomainCSVParam)


        }
        return $paramDictionary
    }
    Begin
    {
            Write-Progress -Activity "Processing site $($SiteURL)" -Status "Retrieving Site Collection" -PercentComplete 0 -id 1
            $CheckedOutFileSummary = New-Object System.Collections.Arraylist
            if(-not $OutputDirectory)
            {
                $OutputDirectory = (Get-Location | Select-Object -ExpandProperty path)
            }
            if(-not (Test-Path $OutputDirectory.localpath))
            {
                New-Item -Path $OutputDirectory.localpath -ItemType Directory | Out-Null
            }
            $OutputDirectory = $OutputDirectory.LocalPath.replace("%20", " ")
            $OutputFile = (join-path $OutputDirectory.LocalPath "$(Get-Date -Format MM-dd-yyyy)_$($SiteURL.originalstring.Substring($SiteURL.originalstring.LastIndexOf("//")+2).replace(".","_").replace("/","_"))CheckedOutFiles_Master.csv")
            if($MultiDomain -and (-not ($PSBoundParameters.MultiDomainCSV)))
            {
                $AllDomainInfo = Get-DomainsFromADForest
            }
            elseif($MultiDomain -and (-not [String]::IsNullOrEmpty($PSBoundParameters.MultiDomainCSV.localpath)))
            {
                $AllDomainInfo = Import-Csv $PSBoundParameters.MultiDomainCSV.localpath
                write-host $PSBoundParameters.multidomaincsv.localpath
            }

    }
    Process
    {
        $CurrentSPSite = Get-SPSite $SiteURL.OriginalString
        if(-not ([String]::IsNullOrEmpty($currentSPSite.url)))
        {
            Write-Progress -Activity "Processing Site $($SiteURL)" -Status "Retrieved Site Collection" -PercentComplete 100 -id 1
            Write-Progress -Activity "Processing Site $($SiteURL)" -Status "Retrieving All Webs" -PercentComplete 0 -Id 1
            [Array]$AllWebs = $CurrentSPSite.allwebs
            Write-Progress -Activity "Processing Site $($SiteURL)" -Status "Retrieved $($AllWebs.count) webs" -PercentComplete 100 -id 1
            Write-Progress -Activity "Processing Site $($SiteURL)" -Status "Processing Webs" -PercentComplete 0 -id 1
            foreach($Web in $AllWebs)
            {
                Write-Progress -Activity "Processing Site $($SiteURL)" -Status "Processing Webs" -PercentComplete $(($AllWebs.Indexof($web)/$AllWebs.count)*100) -Id 1
                Write-Progress -Activity "Processing Web $($Web.url)" -Status "Retrieving Libraries" -PercentComplete 0 -ParentId 1
                [Array]$Libraries = $Web.Lists | Where-Object {$_ -is [Microsoft.SharePoint.SPDocumentLibrary]}
                Write-Progress -Activity "Processing Web $($Web.url)" -Status "Retrieved $($Libraries.count) Libraries" -PercentComplete 100 -ParentId 1
                foreach($Library in $Libraries)
                {
                    Write-Progress -Activity "Processing Web $($Web.url)" -Status "Retrieving checked out files in list `'$($Library.title)`'" -PercentComplete $(($Libraries.indexof($Library)/$Libraries.count)*100) -ParentId 1
                    [Array]$AllCheckedOutFiles = $Library.Items | Where-Object {-not ([String]::IsNullOrEmpty($_.file.CheckedOutByUser))}
                    [Array]$AllCheckedOutFilesWithNoVersion = $Library.CheckedOutFiles
                    if($AllCheckedOutFiles.count -gt 0)
                    {
                        $UserLookup=@{}
                        foreach($file in $AllCheckedOutFiles)
                        {
                            Write-Progress -Activity "Processing checked out files" -Status "Processing file $($Web.url+$File.url)" -PercentComplete 100 -ParentId 2
                            $CheckedOutFileInformation = New-Object System.Object
                            $CheckedoutFileInformation | Add-Member -MemberType NoteProperty -Name 'SiteURL' -Value $SiteURL
                            if($PSBoundParameters.Format -eq "HTML")
                            {
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -name 'WebURL' -value $Web.url
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'ListID' -value $Library.ID
                            }
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'SiteOwner' -value $CurrentSPSite.owner.UserLogin
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'SiteAdmins' -Value ($CurrentSPSite.RootWeb.SiteAdministrators -join ";")
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'File' -value "$($Web.url)/$($File.url)"
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'CheckedOutUser' -Value "$($File.File.CheckedOutByUser.DisplayName)[$($File.File.CheckedOutByUser)]"
                            $SharePointUserSID = $File.File.CheckedOutByUser.SystemUserKey.SubString($File.File.CheckedOutByUser.SystemUserKey.LastIndexOf("|")+1)
                            $ADExpression = "Get-ADUser -Filter 'SID -eq `$SharePointUserSID' -ErrorAction SilentlyContinue"
                            if($MultiDomain)
                            {
                                $DomainSID = $SharePointUserSID.Substring(0,$SharePointUserSID.LastIndexOf("-"))
                                $DomainName = $AllDomainInfo | where-object {$DomainSID -match $_.DomainSID} | Select-Object -ExpandProperty DomainFQDN
                                $ADExpression  = "$($ADExpression) -Server $($DomainName)"
                            }
                            Try
                            {
                                if(-not ($UserLookup["$($SharePointUserSID)"]))
                                {
                                    $ADUser = Invoke-Expression $ADExpression
                                    Remove-Variable -Name ADExpression
                                }
                                elseif($UserLookup["$($SharePointUserSID)"] -eq "True")
                                {
                                   $ADUser = $True
                                }

                            }
                            Catch
                            {
                                Write-Host "Could not find user with SID $($SharePointUserSID)" -ForegroundColor Yellow
                            }
                            if($ADUser)
                            {
                                if(-not ($UserLookup["$($SharePointUserSID)"]))
                                {
                                    $UserLookup.Add("$($SharePointUserSID)", "True")
                                }
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name "SharePointUserSIDFoundInAD" -value "Yes"
                                if($ADUser)
                                {
                                    Remove-Variable -Name ADUser
                                }
                            }
                            else
                            {
                                if(-not ($UserLookup["$($SharePointUserSID)"]))
                                {
                                    $UserLookup.Add("$($SharePointUserSID)", "False")
                                }
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name "SharePointUserSIDFoundInAD" -value "No"
                            }
                            $CheckedOutFileSummary.Add($CheckedOutFileInformation) | Out-Null
                            if($CheckedOutFileInformation)
                            {
                                Remove-Variable -Name CheckedOutFileInformation
                            }
                        }
                        foreach($File in $AllCheckedOutFilesWithNoVersion)
                        {
                            Write-Progress -Activity "Processing files with no checked in versions" -Status "Processing file $($Web.url+$File.url)" -PercentComplete 100 -ParentId 2
                            $CheckedOutFileInformation = New-Object System.Object
                            $CheckedoutFileInformation | Add-Member -MemberType NoteProperty -Name 'SiteURL' -Value $SiteURL
                            if($PSBoundParameters.Format -eq "HTML")
                            {
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -name 'WebURL' -value $Web.url
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'ListID' -value $Library.ID
                            }
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'SiteOwner' -value $CurrentSPSite.owner.UserLogin
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'SiteAdmins' -Value ($CurrentSPSite.RootWeb.SiteAdministrators -join ";")
                            if(($Web.URL -as [URI]).AbsolutePath -eq "/")
                            {
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'File' -value "$($Web.url)/$($File.url)"
                            }
                            else
                            {
                                $CheckedOutFileInformation | add-member -MemberType NoteProperty -Name 'File' -Value "$($Web.url)/$($file.Url.Substring($Web.url.Substring($Web.url.IndexOf(`"/`", $Web.url.IndexOf(`"//`")+2)).length))"
                            }
                            $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name 'CheckedOutUser' -Value "$($File.CheckedOutBy.DisplayName)[$($File.CheckedOutBy.UserLogin)]"
                            $SharePointUserSID = $File.CheckedOutBy.SystemUserKey.SubString($File.CheckedOutBy.SystemUserKey.LastIndexOf("|")+1)
                            $ADExpression = "Get-ADUser -Filter 'SID -eq `$SharePointUserSID' -ErrorAction SilentlyContinue"
                            if($MultiDomain)
                            {
                                $DomainSID = $SharePointUserSID.Substring(0,$SharePointUserSID.LastIndexOf("-"))
                                $DomainName = $AllDomainInfo | where-object {$DomainSID -match $_.DomainSID} | Select-Object -ExpandProperty DomainFQDN
                                $ADExpression  = "$($ADExpression) -Server $($DomainName)"
                            }
                            Try
                            {
                                if(-not ($UserLookup["$($SharePointUserSID)"]))
                                {
                                    $ADUser = Invoke-Expression $ADExpression
                                    Remove-Variable -Name ADExpression
                                }
                                elseif($UserLookup["$($SharePointUserSID)"] -eq "True")
                                {
                                   $ADUser = $True
                                }

                            }
                            Catch
                            {
                                Write-Host "Could not find user with SID $($SharePointUserSID)" -ForegroundColor Yellow
                            }
                            if($ADUser)
                            {
                                if(-not ($UserLookup["$($SharePointUserSID)"]))
                                {
                                    $UserLookup.Add("$($SharePointUserSID)", "True")
                                }
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name "SharePointUserSIDFoundInAD" -value "Yes"
                                if($ADUser)
                                {
                                    Remove-Variable -Name ADUser
                                }
                            }
                            else
                            {
                                if(-not ($UserLookup["$($SharePointUserSID)"]))
                                {
                                    $UserLookup.Add("$($SharePointUserSID)", "False")
                                }
                                $CheckedOutFileInformation | Add-Member -MemberType NoteProperty -Name "SharePointUserSIDFoundInAD" -value "No"
                            }
                            $CheckedOutFileSummary.Add($CheckedOutFileInformation) | Out-Null
                            if($CheckedOutFileInformation)
                            {
                                Remove-Variable -Name CheckedOutFileInformation
                            }
                        }
                        Remove-Variable -name UserLookup
                    }
                    else
                    {
                        Write-Progress -Activity "Processing web $($Web.url)" -Status "Did not retrieve any checked out files" -PercentComplete 100 -ParentId 2
                    }

                }
                Write-Progress -Activity "Processing web $($Web.url)" -Status "All Lists have been processed" -PercentComplete 100 -ParentId 1 -Completed
            }
            Write-Progress -Activity "Processing Site $($SiteURL)" -Status "Copmleted Processing" -PercentComplete 100
        }
    }
    End
    {
        Write-Progress -Activity "Processing Site $($SiteURL)" -Completed
        $CheckedOutFileSummary | ConvertTo-Csv -NoTypeInformation | Out-File $OutputFile -Force
        if(($EmailsToSend -match "User"))
        {
            $UniqueUsers = Get-SMATReportUniqueUsers -InputFile $OutputFile
            foreach($User in $UniqueUsers)
            {
                $Expression = "New-SMATReportIndividualUserPackage -InputFile `$OutputFile -User `$User -OutputDirectory `$OutputDirectory -SendMail -SMTPServer `$PSboundParameters.SMTPServer -SMTPFromAddress `$PSboundParameters.SMTPFromAddress -SMTPReplyToAddress `$PSboundParameters.SMTPReplyToAddress -SMTPBodyFile `$PSboundParameters.SMTPBodyFile -format `$PSBoundParameters.Format"
                if($PSBoundParameters.SMTPCCAddress)
                {
                    $Expression = "$($Expression) -SMTPCCAddress `$PSboundParameters.SMTPCCAddress"
                }
                Try
                {
                    Invoke-Expression $Expression
                }
                Catch
                {
                    Write-Warning "Encountered an error calling New-SMATReportIndividualUserPackage for user $($User)"
                }
            }

        }
        if($EmailsToSend -match "SiteOwner")
        {
            $Expression = "New-SMATReportSiteOwnerPackage -InputFile `$OutputFile -SiteOwner `$(`$CurrentSPSite.Owner.Userlogin) -OutputDirectory `$OutputDirectory -SendMail -SMTPServer `$PSboundParameters.SMTPServer -SMTPFromAddress `$PSboundParameters.SMTPFromAddress -SMTPReplyToAddress `$PSboundParameters.SMTPReplyToAddress -SMTPBodyFile `$PSboundParameters.SMTPBodyFile -format `$PSBoundParameters.Format"
            if($PSBoundParameters.SMTPCCAddress)
            {
                $Expression = "$($Expression) -SMTPCCAddress `$PSboundParameters.SMTPCCAddress"
            }
            Invoke-Expression $Expression
        }
    }
}