Public/Get-PdqCustomField.ps1

<#
.SYNOPSIS
Retrieves Custom Field data from the Inventory database.
 
.NOTES
The Value property is converted to the datatype specified by the Type property.
 
.INPUTS
None.
 
.OUTPUTS
System.Management.Automation.PSCustomObject
System.Object[]
 
.EXAMPLE
Get-PdqCustomField
Outputs all Custom Fields for all computers.
 
.EXAMPLE
Get-PdqCustomField -Name 'Department' -ComputerName 'CEO-LT', 'SALLY-PC'
Outputs the Department Custom Field for CEO-LT and SALLY-PC.
#>

function Get-PdqCustomField {

    [CmdletBinding(DefaultParameterSetName = 'ComputerName')]
    param (
        [ArgumentCompleter( {
                param ($CommandName, $ParameterName, $WordToComplete, $CommandAst, $FakeBoundParameters)

                $Params = @{
                    'Product' = 'Inventory'
                    'Table'   = 'CustomComputerItems'
                }
        
                if ( $FakeBoundParameters.ContainsKey('DatabasePath') ) {

                    $Params += @{
                        'DatabasePath' = $FakeBoundParameters.DatabasePath
                    }

                }

                (Get-PdqDatabaseData @Params).Name | Where-Object { $_ -like "$WordToComplete*" } | ForEach-Object {

                    # Custom Field names can have spaces, so wrap them in single quotes.
                    "'$_'"

                }
            })]
        # The names of the Custom Fields you would like to retrieve.
        [String[]]$Name,

        [Parameter(ParameterSetName = 'ComputerName')]
        # The names or hostnames of the computers you would like to retrieve Custom Fields for.
        [String[]]$ComputerName,

        [Parameter(ParameterSetName = 'ComputerId')]
        # The ComputerIDs you would like to retrieve Custom Fields for.
        [UInt32[]]$ComputerId,

        # Don't throw an error if no data is returned.
        [Switch]$AllowNull,

        # The path to the currently active database will be retrieved by default.
        # You can use this parameter if you wish to run this function against a different database.
        [String]$DatabasePath
    )

    $TypeTable = @{
        'Boolean'  = 'Boolean'
        'Date'     = 'DateTime'
        'DateTime' = 'DateTime'
        'Integer'  = 'Int32'
        'String'   = 'String'
    }

    try {

        $CloseConnection = Open-PdqSqlConnection -Product 'Inventory' -DatabasePath $DatabasePath

        # Make sure all entries in $Name are a valid Custom Field name.
        if ( $Name ) {

            $NameParams = @{
                'Product'      = 'Inventory'
                'Table'        = 'CustomComputerItems'
                'DatabasePath' = $DatabasePath
            }
            $CustomFieldNames = (Get-PdqDatabaseData @NameParams).Name

            foreach ( $DesiredName in $Name ) {

                if ( $DesiredName -notin $CustomFieldNames ) {

                    throw "Could not find a Custom Field named: $DesiredName"

                }

            }

        }

        $DataParams = @{
            'Table'        = 'CustomComputerItems', 'CustomComputerValues'
            'AllowNull'    = $AllowNull
            'DatabasePath' = $DatabasePath
        }
        
        if ( $ComputerName ) {
            
            $DataParams += @{
                'Name' = $ComputerName
            }

        } else {

            $DataParams += @{
                'Id' = $ComputerId
            }

        }

        # Get all Custom Field items and values.
        Get-PdqInventoryComputerData @DataParams | ForEach-Object {

            $CustomFieldData = $_

            # Skip Custom Fields that aren't in $Name.
            if ( (-not $Name) -or ($CustomFieldData.Name -in $Name) ) {

                # Translate Type to a PowerShell-compatible value.
                $TypeName = $TypeTable[$CustomFieldData.Type]

                # Casting numbers to Boolean only works properly if they are a numeric type, not a string.
                if ( $TypeName -eq 'Boolean' ) {

                    $CustomFieldData.Value = [Int32]$CustomFieldData.Value

                }
            
                # Cast Value to the datatype specified by Type.
                $CustomFieldData.Value = $CustomFieldData.Value -as $TypeName

                $CustomFieldData

            }

        }

    } finally {

        Close-PdqSqlConnection -Product 'Inventory' -CloseConnection $CloseConnection

    }

}