PwSh.Fw.Computer.psm1

$Script:computer = $null

<#
.SYNOPSIS
Statically create a new computer
 
.DESCRIPTION
We do not use class object for the time being. Think of this function as if it were the constructor of the Computer object.
 
.EXAMPLE
$myComputer = New-ComputerObject
 
.NOTES
General notes
#>

function New-ComputerObject {
    [CmdletBinding()]Param (
    )
    Begin {
        Write-EnterFunction
    }

    Process {
        $Script:computer = [PSCustomObject]@{
            name = ""
            domain = ""
            fqdn = ""
            manufacturer = ""
            eth = @()
            interfaces = @()
            model = ""
            serial = ""
            firmware = ""
            version = ""
            arch = ""
            disks = @()
            partitions = @()
            ethByName = @{}
            ethByIndex = @()
        }
        return $Script:computer
    }

    End {
        Write-LeaveFunction
    }
}

<#
.SYNOPSIS
Analyse localhost to detect various things at computer (hardware) level
 
.DESCRIPTION
Get-Computer return hardware informations. To get software infos, please see PwSh.Fw.OS powershell module.
 
.EXAMPLE
An example
 
.NOTES
General notes
#>


function Get-Computer {
    [CmdletBinding()]Param (
        # Force reload/redetect things
        [switch]$Force
    )
    Begin {
        Write-EnterFunction
        # we first need to known what OS we are running to load appropriate dictionaries
        $os = Get-OperatingSystem -Online
        $os | Load-Dictionaries -Prefix "Computer" -Path "$PSScriptRoot/Dictionaries"
    }

    Process {
        if (($null -eq $Script:computer) -or $Force) {
            $Script:computer = New-ComputerObject
            $Script:computer.name = Get-ComputerName
            $Script:computer.domain = Get-ComputerDomain
            $Script:computer.fqdn = $Script:computer.name + '.' + $Script:computer.domain
            $Script:computer.manufacturer = Get-ComputerManufacturer
            $Script:computer.eth = Get-ComputerNetAdapter
            # $Script:computer.interfaces = Get-ComputerNetAdapter
            $Script:computer.model = Get-ComputerModel
            $Script:computer.serial = Get-ComputerSerialNumber
            $Script:computer.firmware = Get-ComputerFirmwareType
            $Script:computer.version = Get-ComputerVersion
            $Script:computer.arch = Get-ComputerArch
            $Script:computer.disks = Get-ComputerDisk -All
            $Script:computer.partitions = Get-ComputerDiskPartition -All
            # $Script:computer.ethByName = @{}

            ForEach ($e in (Get-ComputerEthernet -ListAvailable 'Name')) {
                $Script:computer.ethByName[$e] = @{}
                try {
                    $Script:computer.ethByName[$e]["IPv4"] = Get-EthernetObject -AdapterName $e -Family IPv4
                } catch {
                    ewarn "On $e (IPv4):"
                    ewarn $_
                }
                try {
                    $Script:computer.ethByName[$e]["IPv6"] = Get-EthernetObject -AdapterName $e -Family IPv6
                } catch {
                    ewarn "On $e (IPv6):"
                    ewarn $_
                }
                if ($Script:computer.ethByName[$e]["IPv4"].default -eq $true) {
                    $Script:computer.ethByName["default"] = $Script:computer.ethByName[$e]
                }
                if ($Script:computer.ethByName[$e]) {
                    $Script:computer.ethByName[$e].ifindex = $Script:computer.ethByIndex.Count
                    $Script:computer.ethByIndex += @($Script:computer.ethByName[$e])
                }
            }
        }

        return $Script:computer
    }

    End {
        Write-LeaveFunction
    }
}

# <#
# .SYNOPSIS
# Create a new [computer] object from an existing computer

# .DESCRIPTION
# Long description

# .PARAMETER name
# Parameter description

# .PARAMETER Localhost
# Parameter description

# .EXAMPLE
# An example

# .NOTES
# General notes
# #>

# function Get-ComputerClass {
# [CmdletBinding()]Param (
# [Parameter(ValueFromPipeLine = $true)][string]$name
# )
# Begin {
# Write-EnterFunction
# }

# Process {
# . "$Global:PWSHFW_PATH/classes/disk/diskObject.ps1"
# . "$Global:PWSHFW_PATH/classes/ethernet/ethernetObject.ps1"
# . "$Global:PWSHFW_PATH/classes/computer/computerObject.ps1"

# $obj = [computer]::new($Localhost)
# if ($name) {
# $obj.name = $name
# }
# return $obj
# }

# End {
# # eleave($MyInvocation.MyCommand)
# }
# }

function Get-EthernetObject {
    [CmdletBinding()]Param (
        [Parameter(ValueFromPipeLine = $true)]
        [string]$AdapterName,
        [ValidateSet('IPv4', 'IPv6')]
        [string]$Family = 'IPv4'
    )
    Begin {
        Write-EnterFunction
        # $eth = New-Object -TypeName PSObject -Property @{
        # # name of network interface
        # name = "lo"
        # # inner index in array eth
        # index = 0
        # # index of interface in operating system
        # ifIndex = 0
        # manufacturer = ""
        # model = ""
        # description = ""
        # mac = "aa:bb:cc:dd:ee:ff"
        # # link status of ethernet interface
        # # $false is link down
        # # $true is link up
        # link = $false
        # speed = 0
        # dhcpIpAddress = $null
        # ipaddress = [ipaddress]"0.0.0.0"
        # netmask = [ipaddress]"255.255.255.255"
        # broadcast = [ipaddress]"255.255.255.255"
        # gateway = [ipaddress]"0.0.0.0"
        # # the score for this interface to be the default
        # scoreDefault = 0
        # default = $false
        # }
        $eth = @{}
    }

    Process {
        $eth.name = $AdapterName
        $eth.ifindex = Get-EthIndex -AdapterName $AdapterName
        $eth.mac = Get-EthMacAddress -AdapterName $AdapterName
        $eth.link = Get-EthLinkStatus -AdapterName $AdapterName
        if ($eth.link -eq $true) {
            $eth.ipaddress = Get-EthIPAddress -AdapterName $AdapterName -Family:$Family
            $eth.netmask = Get-EthNetmask -AdapterName $AdapterName -Family:$Family
            $eth.broadcast = Get-EthBroadcast -AdapterName $AdapterName -Family:$Family
            $eth.gateway = Get-EthGateway -AdapterName $AdapterName -Family:$Family
        }

        # return $eth
        return [PwShFwEthernet]::new($eth)
    }

    End {
        Write-LeaveFunction
    }
}

<#
.SYNOPSIS
Convert a command output to a hashtable
 
.DESCRIPTION
Long description
 
.PARAMETER Command
command to invoke
 
.PARAMETER sep
separator char of key/value pair
 
.PARAMETER SkipFirstLines
skip the first lines
 
.EXAMPLE
dmidecode | New-HashtableFromCommand
 
.NOTES
General notes
#>

function New-HashtableFromCommand {
    [CmdletBinding()]Param (
        [string]$Command = "",
        [char]$sep = ":",
        [int]$SkipFirstLines = 0
    )
    Begin {
        eenter($MyInvocation.MyCommand)
    }

    Process {
        $hash = New-Object System.Collections.Hashtable
        Invoke-Expression -Command $command | Select-Object -Skip $SkipFirstLines | Foreach {
            # skip empty lines
            # if ($_.trim() -eq "") { continue }
            # # skip headers (lines that do not contains $sep char)
            # if ($_.IndexOf($sep) -eq -1) { continue }
            $key = $_.Split($sep)[0]
            # echo "key = $key"
            # if ($key -eq $null) { echo "key is null" }
            # if ($key -eq '') { echo "key is empty" }

            # handle null value
            $value = $_.Split($sep)[1]
            if ($value -eq $null) {
                $value = ""
            } else {
                $value = $value.Trim('" ')
            }

            # add key/value to hash
            # handle null keys and empty keys
            if ($key -ne $null -and $key -ne '' ) {
                # echo "value = $value"
                $hash.Add($key.Trim().ToLower(), $value)
                # $prevKey = $key
            # } else {
            # # maybe we are facing a multiline output,
            # # try to handle it, modifying previous key's value
            # $prevValue = $hash[$prevKey]
            # $newValue = $($prevValue + " | " + $value)
            # $hash[$prevKey] = $newValue
            }
        }

        return $hash
    }

    End {
        eleave($MyInvocation.MyCommand)
    }
}

function Load-ComputerDictionaries {
    [CmdletBinding()]
    [OutputType([void])]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "", Justification="Load-Dictionaries is a more intuitive verb for this function.")]
    Param (
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Mainstream,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Platform,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Kernel,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Family,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Distrib,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$ReleaseId,
        [string]$Path = "$PSScriptRoot/Dictionaries",
        # Prefix to prepend to search for dictionaries
        [string]$Prefix = "Computer",
        [Parameter()][switch]$Force
    )
    Begin {
        Write-EnterFunction
    }

    Process {
        PwSh.Fw.OS\Load-Dictionaries @PSBoundParameters
    }

    End {
        Write-LeaveFunction
    }
}

function Load-ComputerLibraries {
    [CmdletBinding()]
    [OutputType([void])]
    [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseApprovedVerbs", "", Justification="Load-Dictionaries is a more intuitive verb for this function.")]
    Param (
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Mainstream,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Platform,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Kernel,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Family,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$Distrib,
        [AllowNull()][AllowEmptyString()][Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)][string]$ReleaseId,
        [string]$Path = "$PSScriptRoot/Libraries",
        # Prefix to prepend to search for Libraries
        [string]$Prefix,
        [Parameter()][switch]$Force
    )
    Begin {
        Write-EnterFunction
    }

    Process {
        PwSh.Fw.OS\Load-Dictionaries @PSBoundParameters -Path "$PSScriptRoot/Libraries" -Prefix "Computer"
    }

    End {
        Write-LeaveFunction
    }
}