Diag-V.psm1

<#
.Synopsis
    Evaluates if local device is a member of a cluster or a standalone server
.DESCRIPTION
    Evaluates several factors to determine if device is a member of a cluster or acting as a standalone server.
    The cluster service is evaluated, and if present the cluster nodes will be tested to determine if the local
    device is a member. If the cluster service is not running the cluster registry location is evaluated to
    determine if the server's cluster membership status.
.EXAMPLE
    Test-IsACluster
 
    Returns boolean if local device is part of a cluster
.OUTPUTS
    System.Boolean
.NOTES
    Author: Jake Morrison - @jakemorrison - https://techthoughts.info/
    The design of this function intends the function to be run on the device that is being evaluated
.COMPONENT
    Diag-V - https://github.com/techthoughts2/Diag-V
#>

function Test-IsACluster {
    [CmdletBinding()]
    param ()
    #-------------------------------
    #assume device is not a cluster
    [bool]$clusterEval = $false
    $nodes = $null
    $clusterCheck = $null
    $clusterNodeNames = $null
    #-------------------------------
    $hostName = $env:COMPUTERNAME
    Write-Verbose -Message "HostName is: $hostName"
    Write-Verbose -Message 'Verifying presence of cluster service...'
    $clusterCheck = Get-Service -Name ClusSvc -ErrorAction SilentlyContinue
    if ($null -ne $clusterCheck) {
        Write-Verbose -Message 'Cluster Service found.'
        Write-Verbose -Message 'Checking cluster service status...'
        if ($clusterCheck.Status -eq "Running") {
            Write-Verbose -Message 'Cluster serivce running.'
            Write-Verbose -Message 'Evaluating cluster nodes...'
            $nodes = Get-ClusterNode -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Verbose -Message 'Cluster nodes detected. Evaluating if this device is among them...'
                foreach ($node in $nodes) {
                    if ($hostName -eq $node) {
                        $clusterEval = $true
                        Write-Verbose -Message 'Hostname was found among cluster nodes.'
                        Write-Verbose -Message "Cluster evaluation: $clusterEval"
                    }#if_hostname
                    else {
                        Write-Verbose -Message 'Hostname was not found among cluster nodes.'
                    }#else_hostname
                }#foreach_node
                Write-Verbose -Message 'Cluster node evaulation complete.'
            }#if_nodes_null
            else {
                Write-Verbose -Message 'No cluster nodes were found. This is not a cluster.'
                Write-Verbose -Message "Cluster evaluation: $clusterEval"
            }#else_nodes_null
        }#if_clusterServiceRunning
        else {
            Write-Verbose -Message 'Cluster service is not running. Cluster cmdlets not possible. Switching to registry evaluation...'
            $clusterRegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\ClusSvc\Parameters'
            $clusterNodeNames = Get-ItemProperty -Path $clusterRegistryPath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty NodeNames -ErrorAction Stop
            if ($null -ne $clusterNodeNames) {
                foreach ($node in $clusterNodeNames) {
                    if ($clusterNodeNames -eq $hostName) {
                        $clusterEval = $true
                        Write-Verbose -Message 'Hostname was found in cluster registy settings'
                        Write-Verbose -Message "Cluster evaluation: $clusterEval"
                    }#if_hostname
                    else {
                        Write-Verbose -Message 'Hostname was not found in cluster registry settings.'
                    }#else_hostname
                }#foreach_node
            }#if_nodeNames
            else {
                Write-Verbose -Message 'No cluster names were returned from the registy. This is not a cluster.'
                Write-Verbose -Message "Cluster evaluation: $clusterEval"
            }#else_nodeNames
        }#else_clusterServiceRunning
    }#clusterServiceCheck
    else {
        Write-Verbose -Message 'No cluster service was found.'
        Write-Verbose -Message "Cluster evaluation: $clusterEval"
    }#clusterServiceCheck
    return $clusterEval
}#Test-IsACluster

<#
.Synopsis
    Tests if PowerShell Session is running as Admin
.DESCRIPTION
    Evaluates if current PowerShell session is running under the context of an Administrator
.EXAMPLE
    Test-RunningAsAdmin
 
    This will verify if the current PowerShell session is running under the context of an Administrator
.OUTPUTS
    System.Boolean
.NOTES
    Author: Jake Morrison - @jakemorrison - https://techthoughts.info/
.COMPONENT
    Diag-V - https://github.com/techthoughts2/Diag-V
#>

function Test-RunningAsAdmin {
    [CmdletBinding()]
    Param()
    $result = $false #assume the worst
    try {
        Write-Verbose -Message "Testing if current PS session is running as admin..."
        $eval = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
        if ($eval -eq $true) {
            Write-Verbose -Message "PS Session is running as Administrator."
            $result = $true
        }#if_eval
        else {
            Write-Verbose -Message "PS Session is NOT running as Administrator"
        }#else_eval
    }#try_security_principal
    catch {
        Write-Verbose -Message "Error encountering evaluating runas status of PS session"
        Write-Error $_
    }#catch_security_principal
    return $result
}

<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-AllVHD {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'No formatting of return object')]
        [switch]$NoFormat,
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message 'Getting VM Information. This can take a few moments...'
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            Write-Verbose -Message 'Processing VM return data...'
                            #####################################
                            foreach ($vm in $rawVM) {
                                #_____________________________________________________________
                                $vmname = ""
                                $vmname = $vm.VMName
                                $rawVHD = $null
                                #resets
                                Write-Verbose -Message "Retrieving VHD information for VM: $vmname"
                                try {
                                    if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                        $rawVHD = Get-VHD -ComputerName $node -VMId $VM.VMId -Credential $Credential -ErrorAction Stop
                                    }#if_Credential
                                    else {
                                        $rawVHD = Get-VHD -ComputerName $node -VMId $VM.VMId -ErrorAction Stop
                                    }#else_Credential
                                }#try_Get-VHD
                                catch {
                                    Write-Warning -Message "An error was encountered getting VHD information for: $vmname"
                                }#catch_Get-VHD
                                foreach ($vhd in $rawVHD) {
                                    Write-Verbose -Message 'Processing VHD.'
                                    #________________
                                    $vhdType = ''
                                    $size = 0
                                    $maxSize = 0
                                    $path = ''
                                    $object = New-Object -TypeName PSObject
                                    #________________
                                    #####################################################
                                    $vhdType = $vhd.VhdType
                                    [int]$size = $vhd.filesize / 1gb
                                    [int]$maxSize = $vhd.size / 1gb
                                    $path = $vhd.Path
                                    $object | Add-Member -MemberType NoteProperty -name Host -Value $node -Force
                                    $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                                    $object | Add-Member -MemberType NoteProperty -name VhdType -Value $vhdType -Force
                                    $object | Add-Member -MemberType NoteProperty -name 'Size(GB)' -Value $size -Force
                                    $object | Add-Member -MemberType NoteProperty -name 'MaxSize(GB)' -Value $maxSize -Force
                                    $object | Add-Member -MemberType NoteProperty -name Path -Value $path -Force
                                    $vmCollection += $object
                                    #####################################################
                                    $currentS += $size
                                    $potentialS += $maxSize
                                    #####################################################
                                }#foreachVHD
                                #_____________________________________________________________
                                Write-Verbose -Message 'VM Information processed.'
                                #_____________________________________________________________
                                if ($null -eq $rawVHD ) {
                                    $object = New-Object -TypeName PSObject
                                    $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                                    $vmCollection += $object
                                }#if_noVHDs
                                #_____________________________________________________________
                            }#foreachVM
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
                if ($vmCollection -ne '') {
                    #####################################
                    $object = New-Object -TypeName PSObject
                    $object | Add-Member -MemberType NoteProperty -name 'TotalVHD(GB)' -Value $currentS -Force
                    $object | Add-Member -MemberType NoteProperty -name 'TotalPotentialVHD(GB)' -Value $potentialS -Force
                    $vmCollection += $object
                    #####################################
                }#if_nullCheck
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                Write-Verbose -Message 'Processing VM return data...'
                #####################################
                $currentS = 0
                $potentialS = 0
                foreach ($vm in $rawVM) {
                    #_____________________________________________________________
                    $vmname = ""
                    $vmname = $vm.VMName
                    $rawVHD = $null
                    #resets

                    Write-Verbose -Message "Retrieving VHD information for VM: $vmname"
                    try {
                        $rawVHD = Get-VHD -VMId $VM.VMId -ErrorAction Stop
                    }#try_Get-VHD
                    catch {
                        Write-Warning -Message "An error was encountered getting VHD information for: $vmname"
                    }#catch_Get-VHD

                    foreach ($vhd in $rawVHD) {
                        Write-Verbose -Message 'Processing VHD.'
                        #________________
                        $vhdType = ''
                        $size = 0
                        $maxSize = 0
                        $path = ''
                        $object = New-Object -TypeName PSObject
                        #________________
                        #####################################################
                        $vhdType = $vhd.VhdType
                        [int]$size = $vhd.filesize / 1gb
                        [int]$maxSize = $vhd.size / 1gb
                        $path = $vhd.Path
                        $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                        $object | Add-Member -MemberType NoteProperty -name VhdType -Value $vhdType -Force
                        $object | Add-Member -MemberType NoteProperty -name 'Size(GB)' -Value $size -Force
                        $object | Add-Member -MemberType NoteProperty -name 'MaxSize(GB)' -Value $maxSize -Force
                        $object | Add-Member -MemberType NoteProperty -name Path -Value $path -Force
                        $vmCollection += $object
                        #####################################################
                        $currentS += $size
                        $potentialS += $maxSize
                        #####################################################
                    }#foreachVHD
                    #_____________________________________________________________
                    Write-Verbose -Message 'VM Information processed.'
                    #_____________________________________________________________
                    if ($null -eq $rawVHD ) {
                        $object = New-Object -TypeName PSObject
                        $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                        $vmCollection += $object
                    }#if_noVHDs
                    #_____________________________________________________________
                }#foreachVM
                #####################################
                $object = New-Object -TypeName PSObject
                $object | Add-Member -MemberType NoteProperty -name 'TotalVHD(GB)' -Value $currentS -Force
                $object | Add-Member -MemberType NoteProperty -name 'TotalPotentialVHD(GB)' -Value $potentialS -Force
                $vmCollection += $object
                #####################################
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    if ($NoFormat) {
        $final = $vmCollection
    }#if_NoFormat
    else {
        $final = $vmCollection | Format-Table
    }#else_NoFormat
    return $final
}#Get-AllVHD


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-BINSpaceInfo {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true,
            HelpMessage = 'StorageSavings for calculating space savings, VMInfo for VM BIN configuration information')]
        [ValidateSet('StorageSavings', 'VMInfo')]
        [string]$InfoType,
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $objCollection = @()
        $vmMemory = 0
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message 'Getting VM Information. This can take a few moments...'
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            $object = New-Object -TypeName PSObject
                            Write-Verbose -Message 'Processing VM return data...'
                            #####################################
                            foreach ($vm in $rawVM) {
                                #_____________________________________________________________
                                $vmname = ""
                                $vmname = $vm.name
                                Write-Verbose -Message "Retrieving information for VM: $vmname"
                                if ($vm.AutomaticStopAction -eq "Save") {
                                    $vmMemory += [math]::round($vm.MemoryAssigned / 1GB, 0)
                                }
                                #_____________________________________________________________
                                Write-Verbose -Message 'VM Information processed.'
                                #_____________________________________________________________
                            }#foreachVM
                            $vmCollection += $rawVM
                            $computerName = $vm | Select-Object -ExpandProperty ComputerName
                            $object | Add-Member -MemberType NoteProperty -name ComputerName -Value $node -Force
                            $object | Add-Member -MemberType NoteProperty -name StorageSavings -Value "$vmMemory GB" -Force
                            $objCollection += $object
                            #####################################
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            $object = New-Object -TypeName PSObject
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                Write-Verbose -Message 'Processing VM return data...'
                #####################################
                foreach ($vm in $rawVM) {
                    #_____________________________________________________________
                    $vmname = ""
                    $vmname = $vm.name
                    Write-Verbose -Message "Retrieving information for VM: $vmname"
                    if ($vm.AutomaticStopAction -eq "Save") {
                        $vmMemory += [math]::round($vm.MemoryAssigned / 1GB, 0)
                    }
                    #_____________________________________________________________
                    Write-Verbose -Message 'VM Information processed.'
                    #_____________________________________________________________
                }#foreachVM
                $vmCollection += $rawVM
                $computerName = $vm | Select-Object -ExpandProperty ComputerName
                $object | Add-Member -MemberType NoteProperty -name ComputerName -Value $env:COMPUTERNAME -Force
                $object | Add-Member -MemberType NoteProperty -name StorageSavings -Value "$vmMemory GB" -Force
                $objCollection = $object
                #####################################
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    switch ($InfoType) {
        'StorageSavings' {
            $final = $objCollection
        }#StorageSavings
        'VMInfo' {
            $final = $vmCollection | Select-Object ComputerName, VMName, AutomaticStopAction, @{ Label = "Memory Assigned"; Expression = { '{0:N0}' -F ($_.MemoryAssigned / 1GB) } }
        }#VMInfo
    }#switch_InfoType
    return $final
}#Get-BINSpaceInfo


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-CSVInfo {
    [cmdletbinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message "Cluster detected. Performing CSV discovery..."
            try {
                $clusterSharedVolume = Get-ClusterSharedVolume -ErrorAction Stop
            }#try_Get-ClusterSharedVolume
            catch {
                Write-Warning -Message 'An error was encountered retrieving CSV information:'
                Write-Error $_
                return
            }#catch_Get-ClusterSharedVolume
            if ($null -ne $clusterSharedVolume) {
                $results = @()
                foreach ($csv in $clusterSharedVolume) {
                    #___________________________________________________
                    $volumeowner = $null
                    $csvVolume = $null
                    $cimSession = $null
                    $volumeInfo = $null
                    $csvdisknumber = $null
                    $csvtophysicaldisk = $null
                    #___________________________________________________
                    $volumeowner = $csv.OwnerNode.Name
                    #___________________________________________________
                    $csvVolume = $csv.SharedVolumeInfo.Partition.Name
                    #___________________________________________________
                    try {
                        if ($Credential) {
                            $cimSession = New-CimSession -Credential $Credential -ComputerName $volumeowner -ErrorAction Stop
                        }#if_Credential
                        else {
                            $cimSession = New-CimSession -ComputerName $volumeowner -ErrorAction Stop
                        }#else_Credential
                        $volumeInfo = Get-Disk -CimSession $cimSession -ErrorAction Stop `
                            | Get-Partition -ErrorAction Stop `
                            | Select-Object DiskNumber, @{Name = "Volume"; Expression = {Get-Volume -Partition $_ -ErrorAction Stop}}
                        $csvdisknumber = ($volumeinfo | Where-Object { $_.volume.path -eq $csvVolume -or $_.volume.ObjectID -eq $csvVolume }).Disknumber
                        $fileSystemType = ($volumeinfo | Where-Object { $_.volume.path -eq $csvVolume -or $_.volume.ObjectID -eq $csvVolume }).Volume.FileSystemType
                        #___________________________________________________
                        $csvtophysicaldisk = New-Object -TypeName PSObject -Property @{
                            "CSVName"               = $csv.Name
                            "CSVOwnerNode"          = $volumeowner
                            "CSVVolumePath"         = $csv.SharedVolumeInfo.FriendlyVolumeName
                            "FileSystemType"        = $fileSystemType
                            "CSVPhysicalDiskNumber" = $csvdisknumber
                            "CSVPartitionNumber"    = $csv.SharedVolumeInfo.PartitionNumber
                            "Size (GB)"             = [int]($csv.SharedVolumeInfo.Partition.Size / 1GB)
                            "FreeSpace (GB)"        = [int]($csv.SharedVolumeInfo.Partition.Freespace / 1GB)
                            "Percent Free"          = $csv.SharedVolumeInfo.Partition.PercentFree
                        }
                        #___________________________________________________
                    }#try_All
                    catch {
                        Write-Warning -Message 'An error was encountered:'
                        Write-Error $_
                        return
                    }#catch_All
                    $results += $csvtophysicaldisk
                }#foreach_CSV
            }#if_nullCheck
            else {
                Write-Warning -Message 'No CSVs discovered.'
                return
            }#else_nullCheck
        }#if_cluster
        else {
            Write-Warning "No cluster detected. This function is only applicable to clusters with CSVs."
            return
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    return $results
}#Get-CSVInfo


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-FileSizeInfo {
    [cmdletbinding()]
    Param (
        #directory path that you wish to scan
        [Parameter(Mandatory = $true,
            HelpMessage = "Please enter a path (Ex: C:\ClusterStorage\Volume1)",
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true, Position = 0)
        ]
        [string]$Path
    )
    Write-Verbose -Message 'Verifying that path specified exists...'
    if (Test-Path $path) {
        Write-Verbose -Message "Path verified."
        Write-Warning -Message 'This can take some time depending on how many files are in the path you specified.'
        Write-Verbose -Message "Getting files..."
        $files = Get-ChildItem -Path $path -Recurse -Force -ErrorAction SilentlyContinue
        if ($null -ne $files) {
            Write-Verbose -Message "Processing files..."
            #___________________
            [double]$intSize = 0
            $results = @()
            #___________________
            foreach ($objFile in $files) {
                $intSize = $intSize + $objFile.Length
            }#foreach_File
            #___________________
            $intSize = [math]::round($intSize / 1GB, 0)
            #___________________
            $results += $files `
                | Select-Object Directory, Name, @{Label = 'Size(MB)'; Expression = {[math]::round($_.Length / 1MB, 2)}} `
                | Sort-Object 'Size(MB)' -Descending | Select-Object -First 10
            $results += "Total size of all files: $intSize GB"
            #___________________
        }#if_Null
        else {
            Write-Warning "No files were found at the specified location."
            return
        }#else_Null
    }#if_Test-Path
    else {
        Write-Warning "The path specified is not valid."
        return
    }#else_Test-Path
    return $results
}#Get-FileSizeInfo


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-HyperVLogInfo {
    [cmdletbinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'Hostname of destination machine')]
        [string]$HostName = $env:COMPUTERNAME,
        [Parameter(Mandatory = $false,
            HelpMessage = 'Admin credentials for destination machine')]
        [pscredential]$Credential,
        [Parameter(Mandatory = $false,
            HelpMessage = 'Name of logs you wish to pull results from')]
        [string[]]$LogName = "*Hyper-v*",
        [Parameter(Mandatory = $false,
            HelpMessage = 'Log level you wish to query')]
        [ValidateRange(1, 5)]
        [int[]]$Level = (1, 2, 3),
        [Parameter(Mandatory = $false,
            HelpMessage = 'Starting DateTime')]
        [datetime]$StartDate = (Get-Date).AddDays(-1),
        [Parameter(Mandatory = $false,
            HelpMessage = 'Ending DateTime')]
        [datetime]$EndDate = (Get-Date)
    )
    Write-Verbose -Message "Building filter..."
    $finalLogString = @()
    foreach ($log in $LogName) {
        $finalLogString += $log
    }#foreach_LogName
    $finalLevel = @()
    foreach ($number in $Level) {
        $finalLevel += $number
    }#foreach_Level
    Write-Verbose -Message "Log Name: $finalLogString"
    Write-Verbose -Message "Level: $finalLevel"
    Write-Verbose -Message "StartTime: $StartDate"
    Write-Verbose -Message "EndTime: $EndDate"
    #create filter hashtable
    $filter = @{
        LogName   = $finalLogString
        Level     = $finalLevel
        StartTime = $StartDate
        EndTime   = $EndDate
    }
    Write-Verbose -Message "Attempting to gather logs from $HostName ..."
    try {
        if ($Credential) {
            $creds = $Credential
            Write-Verbose -Message "Credentials set."
            $a = Get-WinEvent -FilterHashTable $filter -ComputerName $HostName -Credential $creds -ErrorAction Stop
        }
        else {
            $a = Get-WinEvent -FilterHashTable $filter -ComputerName $HostName -ErrorAction Stop
        }
        Write-Verbose -Message "Log capture complete."
    }#try_Get-WinEvent
    catch {
        Write-Verbose $_
        if ($_.Exception -like "*that match*") {
            $a = $null
        }#if_error_no_match
        else {
            Write-Warning "An error was encountered capturing logs from $HostName"
            Write-Error $_
            return
        }#else_error_no_match
    }#catch_Get-WinEvent
    if ($a) {
        Write-Verbose -Message "Processing logs results..."
        $results = $a | Select-Object TimeCreated, LogName, ProviderName, LevelDisplayName, Message
    }#if_logsNull
    else {
        Write-Verbose -Message "No logs were found that matched this search criteria."
        $results = [PSCustomObject]@{
            HostName  = $HostName
            LogName   = $finalLogString
            Level     = $finalLevel
            StartTime = $StartDate
            EndTime   = $EndDate
            Status    = "No logs were found that matched this search criteria."
        }
    }#else_logsNull
    return $results
}#Get-HyperVLogInfo


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-IntegrationServicesCheck {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'No formatting of return object')]
        [switch]$NoFormat,
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message "Getting VM Information. This can take a few moments..."
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            Write-Verbose -Message 'Processing VM return data...'
                            #####################################
                            foreach ($vm in $rawVM) {
                                #_____________________________________________________________
                                $vmname = ""
                                $vmname = $vm.VMName
                                $rawIntegration = $null
                                Write-Verbose -Message "Retrieving information for VM: $vmname"
                                #_____________________________________________________________
                                try {
                                    if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                        $rawIntegration = Get-VMIntegrationService -ComputerName $node -VMName $vmname -Credential $Credential -ErrorAction Stop
                                    }#if_Credential
                                    else {
                                        $rawIntegration = Get-VMIntegrationService -ComputerName $node -VMName $vmname -ErrorAction Stop
                                    }#else_Credential
                                }#try_Get-VMIntegrationService
                                catch {
                                    Write-Warning 'An issue was encountered getting VM information:'
                                    Write-Error $_
                                    return
                                }#catch_Get-VMIntegrationService
                                $rawCombine = $rawIntegration + $vm
                                $cObj = $rawCombine | Select-Object ComputerName, VMName, Name, Enabled, PrimaryStatusDescription, IntegrationServicesVersion
                                #_____________________________________________________________
                                Write-Verbose -Message 'VM Information processed.'
                                #_____________________________________________________________
                                $vmCollection += $cObj
                                #_____________________________________________________________
                            }#foreachVM
                            #####################################
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                Write-Verbose -Message 'Processing VM return data...'
                #####################################
                foreach ($vm in $rawVM) {
                    #_____________________________________________________________
                    $vmname = ""
                    $vmname = $vm.VMName
                    $rawIntegration = $null
                    Write-Verbose -Message "Retrieving information for VM: $vmname"
                    #_____________________________________________________________
                    try {
                        $rawIntegration = Get-VMIntegrationService -VMName $vmname -ErrorAction Stop
                    }#try_Get-VMIntegrationService
                    catch {
                        Write-Warning 'An issue was encountered getting VM information:'
                        Write-Error $_
                        return
                    }#catch_Get-VMIntegrationService
                    $rawCombine = $rawIntegration + $vm
                    $cObj = $rawCombine | Select-Object ComputerName, VMName, Name, Enabled, PrimaryStatusDescription, IntegrationServicesVersion
                    #_____________________________________________________________
                    Write-Verbose -Message 'VM Information processed.'
                    #_____________________________________________________________
                    $vmCollection += $cObj
                    #_____________________________________________________________
                }#foreachVM
                #####################################
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    Write-Verbose -Message 'Processing results for return'
    if ($NoFormat) {
        $final = $vmCollection
    }#if_NoFormat
    else {
        $final = $vmCollection | Format-Table
    }#else_NoFormat
    return $final
}#Get-IntegrationServicesCheck


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-SharedVHD {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message 'Getting VM Information. This can take a few moments...'
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            Write-Verbose -Message 'Processing VM return data...'
                            #####################################
                            foreach ($vm in $rawVM) {
                                #_____________________________________________________________
                                $vmname = ""
                                $vmname = $vm.VMName
                                #resets
                                $object = New-Object -TypeName PSObject
                                Write-Verbose -Message "Retrieving VHD information for VM: $vmname"
                                try {
                                    if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                        $rawVMDisk = Get-VMHardDiskDrive -ComputerName $node -VMName $vmname -Credential $Credential -ErrorAction Stop
                                    }#if_Credential
                                    else {
                                        $rawVMDisk = Get-VMHardDiskDrive -ComputerName $node -VMName $vmname -ErrorAction Stop
                                    }#else_Credential
                                }#try_Get-VMHardDiskDrive
                                catch {
                                    Write-Warning -Message "An error was encountered getting VHD disk information for: $vmname"
                                }#catch_Get-VMHardDiskDrive
                                $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                                foreach ($vhd in $rawVMDisk) {
                                    Write-Verbose -Message 'Processing VHD.'
                                    #________________
                                    $pReservation = $null
                                    $path = ''
                                    $object = New-Object -TypeName PSObject
                                    #________________
                                    #####################################################
                                    #$vhdType = $vhd.VhdType
                                    $pReservation = $vhd.SupportPersistentReservations
                                    $path = $vhd.Path
                                    $object | Add-Member -MemberType NoteProperty -name Host -Value $node -Force
                                    $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                                    $object | Add-Member -MemberType NoteProperty -name SupportPersistentReservations -Value $pReservation -Force
                                    $object | Add-Member -MemberType NoteProperty -name Path -Value $path -Force
                                    $vmCollection += $object
                                    #####################################################
                                    $currentS += $size
                                    $potentialS += $maxSize
                                    #####################################################
                                }#foreachVHD
                                #_____________________________________________________________
                                Write-Verbose -Message 'VM Information processed.'
                                #_____________________________________________________________
                                $vmCollection += $object
                                #_____________________________________________________________
                            }#foreachVM
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                Write-Verbose -Message 'Processing VM return data...'
                #####################################
                $currentS = 0
                $potentialS = 0
                foreach ($vm in $rawVM) {
                    #_____________________________________________________________
                    $vmname = ""
                    $vmname = $vm.VMName
                    #resets
                    $object = New-Object -TypeName PSObject
                    Write-Verbose -Message "Retrieving VHD disk information for VM: $vmname"
                    try {
                        $rawVMDisk = Get-VMHardDiskDrive -VMName $vmname -ErrorAction Stop
                    }#try_Get-VMHardDiskDrive
                    catch {
                        Write-Warning -Message "An error was encountered getting VHD information for: $vmname"
                    }#catch_Get-VMHardDiskDrive
                    $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                    foreach ($vhd in $rawVMDisk) {
                        Write-Verbose -Message 'Processing VHD.'
                        #________________
                        $pReservation = $null
                        $path = ''
                        $object = New-Object -TypeName PSObject
                        #________________
                        #####################################################
                        #$vhdType = $vhd.VhdType
                        $pReservation = $vhd.SupportPersistentReservations
                        $path = $vhd.Path
                        $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force
                        $object | Add-Member -MemberType NoteProperty -name SupportPersistentReservations -Value $pReservation -Force
                        $object | Add-Member -MemberType NoteProperty -name Path -Value $path -Force
                        $vmCollection += $object
                        #####################################################
                        $currentS += $size
                        $potentialS += $maxSize
                        #####################################################
                    }#foreachVHD
                    #_____________________________________________________________
                    Write-Verbose -Message 'VM Information processed.'
                    #_____________________________________________________________
                    $vmCollection += $object
                    #_____________________________________________________________
                }#foreachVM
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    <#
    if ($NoFormat) {
        $final = $vmCollection
    }#if_NoFormat
    else {
        $final = $vmCollection | Format-Table
    }#else_NoFormat
    #>

    $final = $vmCollection
    return $final
}#Get-SharedVHD


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-VMInfo {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    filter Import-CimXml {
        # Filter for parsing XML data

        # Create new XML object from input
        $CimXml = [Xml]$_
        $CimObj = New-Object System.Management.Automation.PSObject

        # Iterate over the data and pull out just the value name and data for each entry
        foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Name']")) {
            $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
        }

        foreach ($CimProperty in $CimXml.SelectNodes("/INSTANCE/PROPERTY[@NAME='Data']")) {
            $CimObj | Add-Member -MemberType NoteProperty -Name $CimProperty.NAME -Value $CimProperty.VALUE
            #return $CimProperty.VALUE
        }

        return $CimObj
    }#Import-CimXml

    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message 'Getting VM Information. This can take a few moments...'
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            Write-Verbose -Message 'Processing VM return data...'
                            #####################################
                            foreach ($vm in $rawVM) {
                                #_____________________________________________________________
                                $vmname = ""
                                $vmname = $vm.name
                                Write-Verbose -Message "Retrieving information for VM: $vmname on node: $node"
                                #_____________________________________________________________
                                #resets
                                $object = New-Object -TypeName PSObject
                                $cimS = $null
                                $VmCIM = $null
                                $msvmName = $null
                                $kvp = $null
                                $obj = $null
                                $opsName = $null
                                $fqdn = $null
                                $computerName = $null
                                $name = $null
                                $cpu = $null
                                $dyanamic = $null
                                $memMin = $null
                                $memMax = $null
                                $clustered = $null
                                $vmVersion = $null
                                $repHealth = $null
                                $repHealth = $null
                                $vhds = $null
                                #resets
                                $query = "Select * From Msvm_ComputerSystem Where ElementName='" + $vmname + "'"
                                if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                    try {
                                        $cimS = New-CimSession -ComputerName $node -Credential $Credential -ErrorAction Stop
                                        $VmCIM = Get-CimInstance -Namespace root\virtualization\v2 -query $query -CimSession $cimS -ErrorAction SilentlyContinue
                                        $msvmName = $VmCIM.Name
                                        $kvp = Get-CimInstance -Namespace root\virtualization\v2 -Filter "SystemName like ""$msvmName""" -CimSession $cimS -ClassName Msvm_KvpExchangeComponent
                                    }
                                    catch {
                                        Write-Warning -Message "Unable to establish CIM session to $node"
                                    }
                                }
                                else {
                                    $VmCIM = Get-CimInstance -Namespace root\virtualization\v2 -query $query -computername $node -ErrorAction SilentlyContinue
                                    $msvmName = $VmCIM.Name
                                    $kvp = Get-CimInstance -Namespace root\virtualization\v2 -Filter "SystemName like ""$msvmName""" -ComputerName $node -ClassName Msvm_KvpExchangeComponent
                                }
                                if ($null -ne $kvp -and $kvp -ne '') {
                                    $obj = $Kvp.GuestIntrinsicExchangeItems | Import-CimXml
                                    $opsName = $obj | Where-Object Name -eq OSName | Select-Object -ExpandProperty Data
                                    $fqdn = $obj | Where-Object Name -eq FullyQualifiedDomainName | Select-Object -ExpandProperty Data
                                }
                                if ($null -eq $opsName -or $opsName -eq '') {
                                    $opsName = "Unknown"
                                }
                                if ($null -eq $fqdn -or $fqdn -eq '') {
                                    $fqdn = "Unknown"
                                }
                                #_____________________________________________________________
                                $computerName = $vm | Select-Object -ExpandProperty ComputerName
                                $object | Add-Member -MemberType NoteProperty -name ComputerName -Value $computerName -Force

                                $name = $vm | Select-Object -ExpandProperty Name
                                $object | Add-Member -MemberType NoteProperty -name Name -Value $name -Force

                                $cpu = $vm | Select-Object -ExpandProperty ProcessorCount
                                $object | Add-Member -MemberType NoteProperty -name CPU -Value $cpu -Force

                                $dyanamic = $vm | Select-Object -ExpandProperty DynamicMemoryEnabled
                                $object | Add-Member -MemberType NoteProperty -name DynamicMemoryEnabled -Value $dyanamic -Force

                                $memMin = [math]::round($vm.MemoryMinimum / 1MB, 0)
                                $object | Add-Member -MemberType NoteProperty -name 'MemoryMinimum(MB)' -Value $memMin -Force

                                $memMax = [math]::round($vm.MemoryMaximum / 1GB, 0)
                                $object | Add-Member -MemberType NoteProperty -name 'MemoryMaximum(GB)' -Value $memMax -Force

                                $clustered = $vm | Select-Object -ExpandProperty IsClustered
                                $object | Add-Member -MemberType NoteProperty -name 'IsClustered' -Value $clustered -Force

                                $vmVersion = $vm | Select-Object -ExpandProperty Version
                                $object | Add-Member -MemberType NoteProperty -name 'Version' -Value $vmVersion -Force

                                $repHealth = $vm | Select-Object -ExpandProperty ReplicationHealth
                                $object | Add-Member -MemberType NoteProperty -name 'ReplicationHealth' -Value $repHealth -Force

                                $object | Add-Member -MemberType NoteProperty -name 'OSName' -Value $opsName -Force

                                $object | Add-Member -MemberType NoteProperty -name 'FQDN' -Value $fqdn -Force
                                #_____________________________________________________________
                                Write-Verbose -Message 'VM Information processed.'
                                Write-Verbose -Message 'Retrieving VHD information...'
                                $i = 0
                                try {
                                    if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                        $vhds = Get-VHD -ComputerName $node -VMId $VM.VMId -Credential $Credential -ErrorAction Stop
                                    }#if_Credential
                                    else {
                                        $vhds = Get-VHD -ComputerName $node -VMId $VM.VMId -ErrorAction Stop
                                    }#else_Credential
                                }#try_Get-VHD
                                catch {
                                    Write-Warning -Message "An error was encountered getting VHD information from $node :"
                                    Write-Error $_
                                }#catch_Get-VHD
                                foreach ($vhd in $vhds) {
                                    $vhdType = $vhd.vhdtype
                                    $object | Add-Member -MemberType NoteProperty -name "VHDType-$i" -Value $vhdType -Force
                                    #$vhdSize = $vhd.filesize / 1gb -as [int]
                                    [int]$vhdSize = $vhd.filesize / 1GB
                                    $object | Add-Member -MemberType NoteProperty -name "VHDSize(GB)-$i" -Value $vhdSize -Force
                                    #$vhdMaxSize = $vhd.size / 1gb -as [int]
                                    [int]$vhdMaxSize = $vhd.size / 1GB
                                    $object | Add-Member -MemberType NoteProperty -name "MaxSize(GB)-$i" -Value $vhdMaxSize -Force
                                    $i++
                                }#foreach_VHD
                                Write-Verbose -Message 'VHD info proccessed.'
                                #_____________________________________________________________
                                $vmCollection += $object
                                #_____________________________________________________________
                            }#foreachVM
                            #####################################
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                Write-Verbose -Message 'Processing VM return data...'
                #####################################
                foreach ($vm in $rawVM) {
                    #_____________________________________________________________
                    $vmname = ""
                    $vmname = $vm.name
                    Write-Verbose -Message "Retrieving information for VM: $vmname"
                    #_____________________________________________________________
                    #resets
                    $object = New-Object -TypeName PSObject
                    $VmCIM = $null
                    $msvmName = $null
                    $kvp = $null
                    $obj = $null
                    $opsName = $null
                    $fqdn = $null
                    $computerName = $null
                    $name = $null
                    $cpu = $null
                    $dyanamic = $null
                    $memMin = $null
                    $memMax = $null
                    $clustered = $null
                    $vmVersion = $null
                    $repHealth = $null
                    $repHealth = $null
                    $vhds = $null
                    #resets
                    $query = "Select * From Msvm_ComputerSystem Where ElementName='" + $vmname + "'"
                    $VmCIM = Get-CimInstance -Namespace root\virtualization\v2 -query $query -computername $node.name -ErrorAction SilentlyContinue
                    $msvmName = $VmCIM.Name
                    $kvp = $null
                    $kvp = Get-CimInstance -Namespace root\virtualization\v2 -Filter "SystemName like ""$msvmName""" -ClassName Msvm_KvpExchangeComponent
                    #$Kvp = Get-CimInstance -Namespace root\virtualization\v2 -query $query2 -computername $node.name -ErrorAction SilentlyContinue
                    if ($null -ne $kvp -and $kvp -ne '') {
                        $obj = $Kvp.GuestIntrinsicExchangeItems | Import-CimXml
                        $opsName = $obj | Where-Object Name -eq OSName | Select-Object -ExpandProperty Data
                        $fqdn = $obj | Where-Object Name -eq FullyQualifiedDomainName | Select-Object -ExpandProperty Data
                    }
                    if ($null -eq $opsName -or $opsName -eq '') {
                        $opsName = "Unknown"
                    }
                    if ($null -eq $fqdn -or $fqdn -eq '') {
                        $fqdn = "Unknown"
                    }
                    #_____________________________________________________________
                    $object | Add-Member -MemberType NoteProperty -name Name -Value $vmname -Force

                    $cpu = $vm | Select-Object -ExpandProperty ProcessorCount
                    $object | Add-Member -MemberType NoteProperty -name CPU -Value $cpu -Force

                    $dyanamic = $vm | Select-Object -ExpandProperty DynamicMemoryEnabled
                    $object | Add-Member -MemberType NoteProperty -name DynamicMemoryEnabled -Value $dyanamic -Force

                    $memMin = [math]::round($vm.MemoryMinimum / 1MB, 0)
                    $object | Add-Member -MemberType NoteProperty -name 'MemoryMinimum(MB)' -Value $memMin -Force

                    $memMax = [math]::round($vm.MemoryMaximum / 1GB, 0)
                    $object | Add-Member -MemberType NoteProperty -name 'MemoryMaximum(GB)' -Value $memMax -Force

                    $clustered = $vm | Select-Object -ExpandProperty IsClustered
                    $object | Add-Member -MemberType NoteProperty -name 'IsClustered' -Value $clustered -Force

                    $vmVersion = $vm | Select-Object -ExpandProperty Version
                    $object | Add-Member -MemberType NoteProperty -name 'Version' -Value $vmVersion -Force

                    $repHealth = $vm | Select-Object -ExpandProperty ReplicationHealth
                    $object | Add-Member -MemberType NoteProperty -name 'ReplicationHealth' -Value $repHealth -Force

                    $object | Add-Member -MemberType NoteProperty -name 'OSName' -Value $opsName -Force

                    $object | Add-Member -MemberType NoteProperty -name 'FQDN' -Value $fqdn -Force
                    #_____________________________________________________________
                    Write-Verbose -Message 'VM Information processed.'
                    Write-Verbose -Message 'Retrieving VHD information...'
                    $i = 0
                    try {
                        $vhds = Get-VHD -VMId $VM.VMId -ErrorAction Stop
                    }#try_Get-VHD
                    catch {
                        Write-Warning -Message "An error was encountered getting VHD information:"
                        Write-Error $_
                    }#catch_Get-VHD
                    foreach ($vhd in $vhds) {
                        $vhdType = $vhd.vhdtype
                        $object | Add-Member -MemberType NoteProperty -name "VHDType-$i" -Value $vhdType -Force
                        #$vhdSize = $vhd.filesize / 1gb -as [int]
                        [int]$vhdSize = $vhd.filesize / 1gb
                        $object | Add-Member -MemberType NoteProperty -name "VHDSize(GB)-$i" -Value $vhdSize -Force
                        #$vhdMaxSize = $vhd.size / 1gb -as [int]
                        [int]$vhdMaxSize = $vhd.size / 1gb
                        $object | Add-Member -MemberType NoteProperty -name "MaxSize(GB)-$i" -Value $vhdMaxSize -Force
                        $i++
                    }#foreach_VHD
                    Write-Verbose -Message 'VHD info proccessed.'
                    #_____________________________________________________________
                    $vmCollection += $object
                    #_____________________________________________________________
                }#foreachVM
                #####################################
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    Write-Verbose -Message 'Processing results for return'
    $final = $vmCollection
    return $final
}#Get-VMInfo


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-VMLocationPathInfo {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message 'Getting VM Information. This can take a few moments...'
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            $vmCollection += $rawVM
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                $vmCollection += $rawVM
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    $final = $vmCollection | Select-Object ComputerName, VMName, State, Path, ConfigurationLocation, SnapshotFileLocation, SmartPagingFilePath
    return $final
}#Get-VMLocationPathInfo


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-VMReplicationStatus {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message "Cluster detected. Executing cluster appropriate diagnostic..."
            Write-Verbose -Message "Getting all cluster nodes in the cluster..."
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message "Getting VM Information. This can take a few moments..."
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        if ($rawVM) {
                            $vmCollection += $rawVM
                        }#if_rawVM
                        else {
                            Write-Verbose "No VMs were returned from $node"
                        }#else_rawVM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            if ($rawVM) {
                $vmCollection += $rawVM
            }#if_rawVM
            else {
                Write-Verbose -Message 'No VMs were found on this device.'
            }#else_rawVM
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message "Not running as administrator. No further action can be taken."
    }#administrator check
    $repEval = $vmCollection | Where-Object { $_.ReplicationState -ne "Disabled" } | Select-Object ComputerName, VMName, Status, ReplicationState, ReplicationHealth, ReplicationMode
    if (-not ($repEval)) {
        Write-Warning -Message 'No VMs were found that have replication enabled.'
    }#if_repEval
    $final = $repEval
    return $final
}#Get-VMReplicationStatus


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Get-VMStatus {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'No formatting of return object')]
        [switch]$NoFormat,
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $vmCollection = @()
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Foreach ($node in $nodes) {
                    $rawVM = $null
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential) {
                                $rawVM = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                                $vmCollection += $rawVM
                            }#if_Credential
                            else {
                                $rawVM = Get-VM -ComputerName $node -ErrorAction Stop
                                $vmCollection += $rawVM
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                    }#else_connection
                }#foreach_Node
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            Write-Verbose -Message 'Getting VM Information...'
            try {
                $rawVM = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning 'An issue was encountered getting VM information:'
                Write-Error $_
                return
            }#catch_Get-VM
            $vmCollection += $rawVM
        }#else_standalone
    }#if_adminEval
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#else_adminEval
    Write-Verbose -Message 'Processing results for return'
    if ($NoFormat) {
        $final = $vmCollection
    }#if_NoFormat
    else {
        $final = $vmCollection | Sort-Object ComputerName, State | Select-Object ComputerName, Name, State, CPUUsage, @{N = "MemoryMB"; E = {$_.MemoryAssigned / 1MB}}, Uptime, Status | Format-Table -AutoSize
    }#else_NoFormat
    return $final
}#Get-VMStatus


<#
.EXTERNALHELP Diag-V-help.xml
#>

function Test-HyperVAllocation {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false,
            HelpMessage = 'PSCredential object for storing provided creds')]
        [pscredential]$Credential
    )
    Write-Verbose -Message 'Processing pre-checks. This may take a few seconds...'
    $adminEval = Test-RunningAsAdmin
    if ($adminEval -eq $true) {
        $clusterEval = Test-IsACluster
        if ($clusterEval -eq $true) {
            Write-Verbose -Message 'Cluster detected. Executing cluster appropriate diagnostic...'
            Write-Verbose -Message 'Getting all cluster nodes in the cluster...'
            $nodes = Get-ClusterNode  -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name
            if ($null -ne $nodes) {
                Write-Warning -Message 'Getting VM Information. This can take a few moments...'
                #__________________
                $results = @()
                $totalClusterRAM = 0
                $totalVMClusterRAM = 0
                $nodeCount = 0
                #__________________
                Foreach ($node in $nodes) {
                    $connTest = $false
                    if ($env:COMPUTERNAME -ne $node) {
                        Write-Verbose -Message "Performing connection test to node $node ..."
                        $connTest = Test-NetConnection -ComputerName $node -InformationLevel Quiet
                    }#if_local
                    else {
                        Write-Verbose -Message 'Local device.'
                        $connTest = $true
                    }#else_local
                    if ($connTest -ne $false) {
                        Write-Verbose -Message 'Connection succesful.'
                        #######################################################################################
                        #######################################################################################
                        #######################################################################################
                        #--------------------------------------------------------------------
                        #null all counts to permit multiple script runs
                        #--------------------------------------------------------------------
                        $nodeCount += 1
                        #__________________
                        $name = $null
                        $numCores = 0
                        $totalNumCores = 0
                        $numLogicProcs = 0
                        $totalNumLogicProcs = 0
                        $totalMemory = 0
                        $availVMMemory = 0
                        $freeMemory = 0
                        #__________________
                        $vmCount = 0
                        $vmProcCount = 0
                        $procRatio = 0
                        $cpuRatio = 0
                        $totalVMProcCount = 0
                        $finalRatio = ''
                        #__________________
                        $memorystartup = 0
                        $MemoryMaximum = 0
                        $totalstartupmem = 0
                        $totalDynamicMaxMem = 0
                        $static = 0
                        $staticmemory = 0
                        #__________________
                        $ramHealth = ''
                        $maxDynamicRamPotential = ''
                        ##########################################################################################
                        #Get ALL the Raw data up front and fail fast
                        #---------------------------------------------------------------------
                        #get Cim data loaded up
                        #---------------------------------------------------------------------
                        Write-Verbose -Message "Getting Cmi Information from node $node..."
                        if ($Credential -and $env:COMPUTERNAME -ne $node) {
                            try {
                                $cimS = New-CimSession -ComputerName $node -Credential $Credential -ErrorAction Stop
                                $w32ProcInfo = Get-CimInstance -class win32_processor -CimSession $cimS -ErrorAction Stop
                                $w32OSInfo = Get-CimInstance -class Win32_OperatingSystem -CimSession $cimS -ErrorAction Stop
                            }#try_Get-CimInstance
                            catch {
                                Write-Warning -Message "Unable to establish CIM session to $node"
                                Write-Error $_
                                return
                            }#catch_Get-CimInstance
                        }#if_Credential
                        else {
                            try {
                                $w32ProcInfo = Get-CimInstance -class win32_processor -ComputerName $node -ErrorAction Stop
                                $w32OSInfo = Get-CimInstance -class Win32_OperatingSystem -ComputerName $node -ErrorAction Stop
                            }#try_Get-CimInstance
                            catch {
                                Write-Warning -Message "An error was encountered getting Cim info from $node"
                                Write-Error $_
                                return
                            }#catch_Get-CimInstance
                        }#else_Credential
                        if ($null -eq $w32ProcInfo -or $null -eq $w32OSInfo) {
                            Write-Warning -Message "Data was not sucessfully from the Host OS on $node."
                            return
                        }#if_CimNullCheck
                        #---------------------------------------------------------------------
                        #get VM data loaded up
                        #---------------------------------------------------------------------
                        Write-Verbose -Message "Getting VM Information from node $node..."
                        try {
                            if ($Credential -and $env:COMPUTERNAME -ne $node) {
                                $vms = Get-VM -ComputerName $node -Credential $Credential -ErrorAction Stop
                            }#if_Credential
                            else {
                                $vms = Get-VM -ComputerName $node -ErrorAction Stop
                            }#else_Credential
                        }#try_Get-VM
                        catch {
                            Write-Warning "An issue was encountered getting VM information from $node :"
                            Write-Error $_
                            return
                        }#catch_Get-VM
                        ##########################################################################################
                        Write-Verbose -Message 'We are now beginning to process data we have previously retrieved...'
                        $object = New-Object -TypeName PSObject
                        ##########################################################################################
                        $name = $w32OSInfo.CSName
                        Write-Verbose -Message "name: $name"
                        $object | Add-Member -MemberType NoteProperty -name SystemName -Value $name -Force
                        #________________________________________________________________________
                        $numCores = $w32ProcInfo.numberOfCores
                        Write-Verbose -Message "numCores: $numCores"
                        foreach ($core in $numCores) {
                            $totalNumCores += $core
                        }#foreach_numCores
                        Write-Verbose -Message "totalNumCores: $totalNumCores"
                        $object | Add-Member -MemberType NoteProperty -name Cores -Value $totalNumCores -Force
                        #________________________________________________________________________
                        $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors
                        Write-Verbose -Message "numLogicProcs: $numLogicProcs"
                        foreach ($proc in $numLogicProcs) {
                            $totalNumLogicProcs += $proc
                        }#foreach_numLogicProcs
                        Write-Verbose -Message "totalNumLogicProcs: $totalNumLogicProcs"
                        $object | Add-Member -MemberType NoteProperty -name 'LogicalProcessors' -Value $totalNumLogicProcs -Force
                        ##########################################################################################
                        $totalMemory = [math]::round($w32OSInfo.TotalVisibleMemorySize / 1MB, 0)
                        Write-Verbose -Message "totalMemory: $totalMemory"
                        $object | Add-Member -MemberType NoteProperty -name 'TotalMemory(GB)' -Value $totalMemory -Force
                        ##########################################################################################
                        foreach ($vm in $vms) {
                            $vmProcCount += $vm.ProcessorCount
                            Write-Verbose "Getting memory information from VM $vm"
                            if ($vm.DynamicMemoryEnabled -eq $true) {
                                Write-Verbose "Dynamic Deteced..."
                                $memorystartup = [math]::Round(($VM | Select-Object MemoryStartup).MemoryStartup / 1GB, 0)
                                $memoryMaximum = [math]::Round(($VM | Select-Object MemoryMaximum).MemoryMaximum / 1GB, 0)

                                $totalstartupmem += $memoryStartup
                                $totalDynamicMaxMem += $memoryMaximum
                            }#if_Dynamic
                            else {
                                Write-Verbose "Static Deteced..."
                                $static = [math]::Round(($VM | Select-Object MemoryStartup).MemoryStartup / 1GB, 0)
                                Write-Verbose "Adding static memory of $static"
                                $staticmemory += $static
                            }#else_Static
                        }#foreach_VM
                        Write-Verbose -Message "vmProcCount: $vmProcCount"
                        #________________________________________________________________________
                        #8GB of memory is RESERVED for the host
                        $availVMMemory = $totalMemory - 8
                        $totalClusterRAM += $availVMMemory
                        Write-Verbose -Message "availVMMemory: $availVMMemory"
                        $object | Add-Member -MemberType NoteProperty -name 'AvailMemory(-8GBSystem)' -Value $availVMMemory -Force
                        #________________________________________________________________________
                        $freeMemory = [math]::round($w32OSInfo.FreePhysicalMemory / 1MB, 0)
                        Write-Verbose -Message "freeMemory: $freeMemory"
                        $object | Add-Member -MemberType NoteProperty -name 'FreeRAM(GB)' -Value $freeMemory -Force
                        #________________________________________________________________________
                        $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100
                        Write-Verbose -Message "memPercent: $memPercent"
                        $object | Add-Member -MemberType NoteProperty -name 'FreeRAM(%)' -Value $memPercent -Force
                        ##########################################################################################
                        $vmCount = $vms | Measure-Object | Select-Object -ExpandProperty count
                        Write-Verbose -Message "vmCount: $vmCount"
                        $object | Add-Member -MemberType NoteProperty -name 'TotalVMCount' -Value $vmCount -Force
                        #might adjust nomenclature here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        $totalVMProcCount = $vmProcCount
                        Write-Verbose -Message "totalVMProcCount: $totalVMProcCount"
                        $object | Add-Member -MemberType NoteProperty -name 'TotalvCPUs' -Value $totalVMProcCount -Force
                        #________________________________________________________________________
                        if ($totalVMProcCount -eq 0) {
                            $finalRatio = 'NA'
                        }#if_vCPU_0
                        elseif ($totalVMProcCount -gt $totalNumLogicProcs) {
                            $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount)
                            $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs)
                            $finalRatio = "$procRatio : 1"
                        }#elseif_vCPU-gt
                        else {
                            $finalRatio = '1 : 1'
                        }#else_vCPU
                        Write-Verbose -Message "cpuRatio: $cpuRatio"
                        Write-Verbose -Message "procRatio: $procRatio"
                        Write-Verbose -Message "finalRatio: $finalRatio"
                        $object | Add-Member -MemberType NoteProperty -name 'vCPURatio' -Value $finalRatio -Force
                        ##########################################################################################
                        #account for no static and no dynamic situations
                        if ($null -eq $totalstartupmem) {
                            $totalstartupmem = 0
                        }#nullCheck
                        if ($null -eq $staticmemory) {
                            $staticmemory = 0
                        }#nullCheck
                        Write-Verbose -Message "totalstartupmem: $totalstartupmem"
                        $object | Add-Member -MemberType NoteProperty -name 'DynamicStartupRequired' -Value $totalstartupmem -Force
                        Write-Verbose -Message "staticmemory: $staticmemory"
                        $object | Add-Member -MemberType NoteProperty -name 'StaticRAMRequired' -Value $staticmemory -Force
                        #________________________________________________________________________
                        $totalramrequired = $totalstartupmem + $staticmemory
                        $totalVMClusterRAM += $totalramrequired
                        Write-Verbose -Message "totalramrequired: $totalramrequired"
                        $object | Add-Member -MemberType NoteProperty -name 'TotalRAMRequired' -Value $totalramrequired -Force
                        #________________________________________________________________________
                        if ($totalramrequired -lt $availVMMemory) {
                            Write-Verbose -Message "Minimum RAM: $totalramrequired GB does not exceed available RAM: $availVMMemory GB"
                            $ramHealth = 'Healthy'
                        }#if_Healthy
                        elseif ($totalramrequired -eq $availVMMemory) {
                            Write-Verbose -Message "Minimum RAM: $totalramrequired GB is exactly at available RAM: $availVMMemory GB"
                            $ramHealth = 'Warning'
                        }#elseif_Warning
                        else {
                            Write-Verbose -Message "Minimum RAM: $totalramrequired GB exceeds available RAM: $availVMMemory GB"
                            $ramHealth = 'UNHEALTHY'
                        }#else_Unhealthy
                        Write-Verbose -Message "ramHealth: $ramHealth"
                        $object | Add-Member -MemberType NoteProperty -name 'RAMAllocation' -Value $ramHealth -Force
                        #________________________________________________________________________
                        Write-Verbose -Message "totalDynamicMaxMem: $totalDynamicMaxMem"
                        $object | Add-Member -MemberType NoteProperty -name 'DynamicMaxPotential' -Value $totalDynamicMaxMem -Force
                        #________________________________________________________________________
                        if ($totalDynamicMaxMem -ne 0) {
                            if ($totalDynamicMaxMem -lt $availVMMemory) {
                                Write-Verbose -Message "Maximum potential RAM: $totalDynamicMaxMem GB does not exceed available RAM: $availVMMemory GB"
                                $maxDynamicRamPotential = 'Good'
                            }#if_Good
                            else {
                                Write-Verbose -Message "Maximum potential RAM: $totalDynamicMaxMem GB exceeds available RAM: $availVMMemory GB"
                                $maxDynamicRamPotential = 'Warning'
                            }#else_Warning
                        }#if_Totalmax-ne-0
                        else {
                            Write-Verbose -Message 'No Dynamic VMs detected.'
                            $maxDynamicRamPotential = 'NA'
                        }#else_noDynamic
                        Write-Verbose -Message "maxDynamicRamPotential: $maxDynamicRamPotential"
                        $object | Add-Member -MemberType NoteProperty -name 'DynamicMaxAllocation' -Value $maxDynamicRamPotential -Force
                        ##########################################################################################
                        $results += $object
                        #######################################################################################
                        #######################################################################################
                        #######################################################################################
                    }#if_connection
                    else {
                        Write-Warning -Message "Connection test to $node unsuccesful."
                        return
                    }#else_connection
                }#foreach_Node
                #######################################################################################
                #######################################################################################
                #######################################################################################
                #CSV Storage Space checks - we will check CSV locations only for clustered Hyps
                #--------------------------------------------------------------------
                try {
                    $clusterName = "."
                    $clusterSharedVolume = Get-ClusterSharedVolume -Cluster $clusterName -ErrorAction Stop
                    if ($null -ne $clusterSharedVolume) {
                        foreach ($volume in $clusterSharedVolume) {
                            #____________________________________________________
                            $diskName = ''
                            $spaceFree = 0
                            $percentFree = 0
                            $size = 0
                            $expectations = 20
                            $object = New-Object -TypeName PSObject
                            $driveHealth = ''
                            #____________________________________________________
                            $diskName = $volume.SharedVolumeInfo.FriendlyVolumeName
                            $percentFree = $volume.SharedVolumeInfo.Partition.PercentFree
                            $spaceFree = [int]($volume.SharedVolumeInfo.Partition.Freespace / 1GB)
                            #expectations:
                            #15% For less than 1TB
                            #10 % For greater than 1TB
                            $size = [math]::Round($volume.SharedVolumeInfo.partition.Size / 1GB, 0)
                            $expectations = 20
                            if ($size -le 1000) {
                                $expectations = 15
                            }
                            elseif ($size -gt 1000) {
                                $expectations = 10
                            }

                            Write-Verbose -Message "diskName: $diskName"
                            Write-Verbose -Message "size: $size"
                            Write-Verbose -Message "spaceFree: $spaceFree"
                            Write-Verbose -Message "percentFree: $percentFree"
                            Write-Verbose -Message "expectations: $expectations"

                            $object | Add-Member -MemberType NoteProperty -name CSV -Value $diskName -Force
                            $object | Add-Member -MemberType NoteProperty -name 'Size(GB)' -Value $size -Force
                            $object | Add-Member -MemberType NoteProperty -name 'FreeSpace(GB)' -Value $spaceFree -Force
                            $object | Add-Member -MemberType NoteProperty -name 'FreeSpace(%)' -Value $percentFree -Force

                            if ($percentFree -lt $expectations) {
                                $driveHealth = 'UNHEALTHY'
                            }
                            else {
                                $driveHealth = 'HEALTHY'
                            }
                            Write-Verbose -Message "driveHealth: $driveHealth"
                            $object | Add-Member -MemberType NoteProperty -name 'DriveHealth' -Value $driveHealth -Force
                            $results += $object
                        }#foreach_CSV
                    }#if_null_csvs
                    else {
                        Write-Verbose -Message "No CSVs discovered - no storage information pulled"
                    }#else_null_csvs
                }#try_Get-ClusterSharedVolume
                catch {
                    Write-Warning -Message "An error was encountered getting CSVs spacing information from $node"
                    Write-Error $_
                }#catch_Get-ClusterSharedVolume
                #######################################################################################
                #######################################################################################
                #######################################################################################
                Write-Verbose -Message 'Calculating a node loss and its impact...'
                $object = New-Object -TypeName PSObject
                $n1Eval = $false #assume the worst
                $x = $totalClusterRAM / $nodeCount
                $clusterNodeDownUseable = $totalClusterRAM - $x
                Write-Verbose -Message "totalClusterRAM: $totalClusterRAM"
                Write-Verbose -Message "totalVMClusterRAM: $totalVMClusterRAM"
                Write-Verbose -Message "nodeCount: $nodeCount"
                if ($totalVMClusterRAM -gt $clusterNodeDownUseable) {
                    Write-Verbose -Message 'VMs would NOT survive a one node failure'
                }
                else {
                    $n1Eval = $true
                    Write-Verbose -Message 'VMs would survive a one node failure'
                }
                $object | Add-Member -MemberType NoteProperty -name 'N+1RAMEvaluation' -Value $n1Eval -Force
                $results += $object
                #######################################################################################
                #######################################################################################
                #######################################################################################
            }#if_nodeNULLCheck
            else {
                Write-Warning -Message 'Device appears to be configured as a cluster but no cluster nodes were returned by Get-ClusterNode'
                return
            }#else_nodeNULLCheck
        }#if_cluster
        else {
            Write-Verbose -Message 'Standalone server detected. Executing standalone diagnostic...'
            #######################################################################################
            #######################################################################################
            #######################################################################################
            #######################################################################################
            #######################################################################################
            #--------------------------------------------------------------------
            #null all counts to permit multiple script runs
            #--------------------------------------------------------------------
            $results = @()
            #__________________
            $name = $null
            $numCores = 0
            $totalNumCores = 0
            $numLogicProcs = 0
            $totalNumLogicProcs = 0
            $totalMemory = 0
            $availVMMemory = 0
            $freeMemory = 0
            #__________________
            $vmCount = 0
            $vmProcCount = 0
            $procRatio = 0
            $cpuRatio = 0
            $totalVMProcCount = 0
            $finalRatio = ''
            #__________________
            $memorystartup = 0
            $MemoryMaximum = 0
            $totalstartupmem = 0
            $totalDynamicMaxMem = 0
            $static = 0
            $staticmemory = 0
            #__________________
            $ramHealth = ''
            $maxDynamicRamPotential = ''
            ##########################################################################################
            #Get ALL the Raw data up front and fail fast
            $node = $env:COMPUTERNAME
            #---------------------------------------------------------------------
            #get Cim data loaded up
            #---------------------------------------------------------------------
            try {
                $w32ProcInfo = Get-CimInstance -class win32_processor -ErrorAction Stop
                $w32OSInfo = Get-CimInstance -class Win32_OperatingSystem -ErrorAction Stop
                $drives = Get-CimInstance win32_logicaldisk -ErrorAction Stop | Where-Object {$_.DeviceID -ne "C:"}
            }#try_Get-CimInstance
            catch {
                Write-Warning -Message "An error was encountered getting Cim info from $node"
                Write-Error $_
                return
            }#catch_Get-CimInstance
            if ($null -eq $w32ProcInfo -or $null -eq $w32OSInfo) {
                Write-Warning -Message "Data was not sucessfully from the Host OS."
                return
            }#if_CimNullCheck
            #---------------------------------------------------------------------
            #get VM data loaded up
            #---------------------------------------------------------------------
            try {
                $vms = Get-VM -ErrorAction Stop
            }#try_Get-VM
            catch {
                Write-Warning -Message "An error was encountered getting VM info from $node"
                Write-Error $_
                return
            }#catch_Get-VM
            ##########################################################################################
            Write-Verbose -Message 'We are now beginning to process data we have previously retrieved...'
            $object = New-Object -TypeName PSObject
            ##########################################################################################
            $name = $w32OSInfo.CSName
            Write-Verbose -Message "name: $name"
            $object | Add-Member -MemberType NoteProperty -name SystemName -Value $name -Force
            #________________________________________________________________________
            $numCores = $w32ProcInfo.numberOfCores
            Write-Verbose -Message "numCores: $numCores"
            foreach ($core in $numCores) {
                $totalNumCores += $core
            }#foreach_numCores
            Write-Verbose -Message "totalNumCores: $totalNumCores"
            $object | Add-Member -MemberType NoteProperty -name Cores -Value $totalNumCores -Force
            #________________________________________________________________________
            $numLogicProcs = $w32ProcInfo.NumberOfLogicalProcessors
            Write-Verbose -Message "numLogicProcs: $numLogicProcs"
            foreach ($proc in $numLogicProcs) {
                $totalNumLogicProcs += $proc
            }#foreach_numLogicProcs
            Write-Verbose -Message "totalNumLogicProcs: $totalNumLogicProcs"
            $object | Add-Member -MemberType NoteProperty -name 'LogicalProcessors' -Value $totalNumLogicProcs -Force
            ##########################################################################################
            $totalMemory = [math]::round($w32OSInfo.TotalVisibleMemorySize / 1MB, 0)
            Write-Verbose -Message "totalMemory: $totalMemory"
            $object | Add-Member -MemberType NoteProperty -name 'TotalMemory(GB)' -Value $totalMemory -Force
            ##########################################################################################
            foreach ($vm in $vms) {
                $vmProcCount += $vm.ProcessorCount
                Write-Verbose "Getting memory information from VM $vm"
                if ($vm.DynamicMemoryEnabled -eq $true) {
                    Write-Verbose "Dynamic Deteced..."
                    $memorystartup = [math]::Round(($VM | Select-Object MemoryStartup).MemoryStartup / 1GB, 0)
                    $memoryMaximum = [math]::Round(($VM | Select-Object MemoryMaximum).MemoryMaximum / 1GB, 0)

                    $totalstartupmem += $memoryStartup
                    $totalDynamicMaxMem += $memoryMaximum
                }#if_Dynamic
                else {
                    Write-Verbose "Static Deteced..."
                    $static = [math]::Round(($VM | Select-Object MemoryStartup).MemoryStartup / 1GB, 0)
                    Write-Verbose "Adding static memory of $static"
                    $staticmemory += $static
                }#else_Static
            }#foreach_VM
            Write-Verbose -Message "vmProcCount: $vmProcCount"
            #________________________________________________________________________
            #8GB of memory is RESERVED for the host
            $availVMMemory = $totalMemory - 8
            Write-Verbose -Message "availVMMemory: $availVMMemory"
            $object | Add-Member -MemberType NoteProperty -name 'AvailMemory(-8GBSystem)' -Value $availVMMemory -Force
            #________________________________________________________________________
            $freeMemory = [math]::round($w32OSInfo.FreePhysicalMemory / 1MB, 0)
            Write-Verbose -Message "freeMemory: $freeMemory"
            $object | Add-Member -MemberType NoteProperty -name 'FreeRAM(GB)' -Value $freeMemory -Force
            #________________________________________________________________________
            $memPercent = [math]::round($freeMemory / $totalMemory, 2) * 100
            Write-Verbose -Message "memPercent: $memPercent"
            $object | Add-Member -MemberType NoteProperty -name 'FreeRAM(%)' -Value $memPercent -Force
            ##########################################################################################
            $vmCount = $vms | Measure-Object | Select-Object -ExpandProperty count
            Write-Verbose -Message "vmCount: $vmCount"
            $object | Add-Member -MemberType NoteProperty -name 'TotalVMCount' -Value $vmCount -Force
            #might adjust nomenclature here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            $totalVMProcCount = $vmProcCount
            Write-Verbose -Message "totalVMProcCount: $totalVMProcCount"
            $object | Add-Member -MemberType NoteProperty -name 'TotalvCPUs' -Value $totalVMProcCount -Force
            #________________________________________________________________________
            if ($totalVMProcCount -eq 0) {
                $finalRatio = 'NA'
            }#if_vCPU_0
            elseif ($totalVMProcCount -gt $totalNumLogicProcs) {
                $cpuRatio = ($totalNumLogicProcs / $totalVMProcCount)
                $procRatio = [math]::round($totalVMProcCount / $totalNumLogicProcs)
                $finalRatio = "$procRatio : 1"
            }#elseif_vCPU-gt
            else {
                $finalRatio = '1 : 1'
            }#else_vCPU
            Write-Verbose -Message "cpuRatio: $cpuRatio"
            Write-Verbose -Message "procRatio: $procRatio"
            Write-Verbose -Message "finalRatio: $finalRatio"
            $object | Add-Member -MemberType NoteProperty -name 'vCPURatio' -Value $finalRatio -Force
            ##########################################################################################
            #account for no static and no dynamic situations
            if ($null -eq $totalstartupmem) {
                $totalstartupmem = 0
            }#nullCheck
            if ($null -eq $staticmemory) {
                $staticmemory = 0
            }#nullCheck
            Write-Verbose -Message "totalstartupmem: $totalstartupmem"
            $object | Add-Member -MemberType NoteProperty -name 'DynamicStartupRequired' -Value $totalstartupmem -Force
            Write-Verbose -Message "staticmemory: $staticmemory"
            $object | Add-Member -MemberType NoteProperty -name 'StaticRAMRequired' -Value $staticmemory -Force
            #________________________________________________________________________
            $totalramrequired = $totalstartupmem + $staticmemory
            Write-Verbose -Message "totalramrequired: $totalramrequired"
            $object | Add-Member -MemberType NoteProperty -name 'TotalRAMRequired' -Value $totalramrequired -Force
            #________________________________________________________________________
            if ($totalramrequired -lt $availVMMemory) {
                Write-Verbose -Message "Minimum RAM: $totalramrequired GB does not exceed available RAM: $availVMMemory GB"
                $ramHealth = 'Healthy'
            }#if_Healthy
            elseif ($totalramrequired -eq $availVMMemory) {
                Write-Verbose -Message "Minimum RAM: $totalramrequired GB is exactly at available RAM: $availVMMemory GB"
                $ramHealth = 'Warning'
            }#elseif_Warning
            else {
                Write-Verbose -Message "Minimum RAM: $totalramrequired GB exceeds available RAM: $availVMMemory GB"
                $ramHealth = 'UNHEALTHY'
            }#else_Unhealthy
            Write-Verbose -Message "ramHealth: $ramHealth"
            $object | Add-Member -MemberType NoteProperty -name 'RAMAllocation' -Value $ramHealth -Force
            #________________________________________________________________________
            Write-Verbose -Message "totalDynamicMaxMem: $totalDynamicMaxMem"
            $object | Add-Member -MemberType NoteProperty -name 'DynamicMaxPotential' -Value $totalDynamicMaxMem -Force
            #________________________________________________________________________
            if ($totalDynamicMaxMem -ne 0) {
                if ($totalDynamicMaxMem -lt $availVMMemory) {
                    Write-Verbose -Message "Maximum potential RAM: $totalDynamicMaxMem GB does not exceed available RAM: $availVMMemory GB"
                    $maxDynamicRamPotential = 'Good'
                }#if_Good
                else {
                    Write-Verbose -Message "Maximum potential RAM: $totalDynamicMaxMem GB exceeds available RAM: $availVMMemory GB"
                    $maxDynamicRamPotential = 'Warning'
                }#else_Warning
            }#if_Totalmax-ne-0
            else {
                Write-Verbose -Message 'No Dynamic VMs detected.'
                $maxDynamicRamPotential = 'NA'
            }#else_noDynamic
            Write-Verbose -Message "maxDynamicRamPotential: $maxDynamicRamPotential"
            $object | Add-Member -MemberType NoteProperty -name 'DynamicMaxAllocation' -Value $maxDynamicRamPotential -Force
            ##########################################################################################
            $results += $object
            ##########################################################################################
            if ($null -ne $drives) {
                foreach ($drive in $drives) {
                    #____________________________________________________
                    $totalSize = 0
                    $driveLetter = ''
                    $spaceFree = 0
                    $percentFree = 0
                    $size = 0
                    $expectations = 20
                    $object = New-Object -TypeName PSObject
                    $driveHealth = ''
                    #____________________________________________________
                    $totalSize = [int]($drive.Size / 1GB)
                    if ($totalSize -gt 10) {
                        $driveLetter = $drive.DeviceID
                        $spaceFree = [int]($drive.Freespace / 1GB)
                        $percentFree = [math]::round(($spaceFree / $totalSize) * 100)
                        #expectations:
                        #15% For less than 1TB
                        #10 % For greater than 1TB
                        $size = [math]::Round($drive.Size / 1GB, 0)
                        if ($size -le 1000) {
                            $expectations = 15
                        }
                        elseif ($size -gt 1000) {
                            $expectations = 10
                        }
                        Write-Verbose -Message "driveLetter: $driveLetter"
                        Write-Verbose -Message "totalSize: $totalSize"
                        Write-Verbose -Message "spaceFree: $spaceFree"
                        Write-Verbose -Message "percentFree: $percentFree"
                        Write-Verbose -Message "size: $size"
                        Write-Verbose -Message "expectations: $expectations"

                        $object | Add-Member -MemberType NoteProperty -name Drive -Value $driveLetter -Force
                        $object | Add-Member -MemberType NoteProperty -name 'Size(GB)' -Value $totalSize -Force
                        $object | Add-Member -MemberType NoteProperty -name 'FreeSpace(GB)' -Value $spaceFree -Force
                        $object | Add-Member -MemberType NoteProperty -name 'FreeSpace(%)' -Value $percentFree -Force

                        if ($percentFree -lt $expectations) {
                            $driveHealth = 'UNHEALTHY'
                        }
                        else {
                            $driveHealth = 'HEALTHY'
                        }
                        Write-Verbose -Message "driveHealth: $driveHealth"
                        $object | Add-Member -MemberType NoteProperty -name 'DriveHealth' -Value $driveHealth -Force
                    }#if_Drive-gt10
                    $results += $object
                }#foreach_Drive
            }#drive_nullCheck
            else {
                Write-Verbose -Message "No additional storage other than OS drive deteceted"
            }#else_nullCheck
            ##########################################################################################
            #return $results

            #######################################################################################
            #######################################################################################
            #######################################################################################
            #######################################################################################
            #######################################################################################
        }#clusterEval
    }#administrator check
    else {
        Write-Warning -Message 'Not running as administrator. No further action can be taken.'
        return
    }#administrator check
    return $results
}#Test-HyperVAllocation