Convert.psm1

$script:EPOCH_TIME = Get-Date -Year 1970 -Month 1 -Day 1


<#
    .SYNOPSIS
        Converts a base64 encoded string to a string.

    .DESCRIPTION
        Converts a base64 encoded string to a string.

    .PARAMETER Base64
        A Base64 Encoded String.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER ToString
        Switch parameter to specify a conversion to a string object.

    .PARAMETER Decompress
        If supplied, the output will be decompressed using Gzip.

    .EXAMPLE
        ConvertFrom-Base64 -Base64 'QSBzdHJpbmc=' -ToString

        A string

    .EXAMPLE
        ConvertTo-Base64 -Base64 'A string','Another string' -ToString

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        'QSBzdHJpbmc=' | ConvertFrom-Base64 -ToString

        A string

    .EXAMPLE
        'QSBzdHJpbmc=','QW5vdGhlciBzdHJpbmc=' | ConvertFrom-Base64 -ToString

        A string
        Another string

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Base64/
#>

function ConvertFrom-Base64 {
    [CmdletBinding(
        DefaultParameterSetName = 'Default',
        HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Base64/')]
    [OutputType('String')]
    param
    (
        [Parameter(
            ParameterSetName = 'Default',
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [Parameter(
            ParameterSetName = 'ToString',
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('String', 'Base64String')]
        [String[]]
        $Base64,

        [Parameter(ParameterSetName = 'ToString')]
        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Parameter(ParameterSetName = 'ToString')]
        [Parameter(Mandatory = $false)]
        [Switch]
        $ToString,

        [Parameter(ParameterSetName = 'ToString')]
        [Parameter(Mandatory = $false)]
        [Switch]
        $Decompress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($b64 in $Base64) {
            try {
                $bytes = [System.Convert]::FromBase64String($b64)

                if ($ToString) {
                    if ($Decompress) {
                        ConvertFrom-CompressedByteArrayToString -ByteArray $bytes -Encoding $Encoding
                    } else {
                        [System.Text.Encoding]::$Encoding.GetString($bytes)
                    }
                } else {
                    $bytes
                }
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
    Converts a Base 64 Encoded String to a Byte Array

    .DESCRIPTION
    Converts a Base 64 Encoded String to a Byte Array

    .PARAMETER String
    The Base 64 Encoded String to be converted

    .EXAMPLE
    PS C:\> ConvertFrom-Base64ToByteArray -String 'dGVzdA=='
    116
    101
    115
    116

    Converts the base64 string to its byte array representation.

    .LINK
    https://msdn.microsoft.com/en-us/library/system.convert.frombase64string%28v=vs.110%29.aspx
#>

function ConvertFrom-Base64ToByteArray {
    [CmdletBinding()]
    [Alias('ConvertFrom-Base64StringToByteArray')]
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('Base64String')]
        [String]$String
    )
    [System.Convert]::FromBase64String($String)
}


<#
    .SYNOPSIS
        Converts a base64 encoded string to a MemoryStream.

    .DESCRIPTION
        Converts a base64 encoded string to a MemoryStream.

    .PARAMETER String
        A Base64 Encoded String

    .EXAMPLE
        ConvertFrom-Base64ToMemoryStream -String 'QSBzdHJpbmc='

    .EXAMPLE
        ConvertFrom-Base64ToMemoryStream -String 'A string','Another string'

    .EXAMPLE
        'QSBzdHJpbmc=' | ConvertFrom-Base64ToMemoryStream

    .EXAMPLE
        'QSBzdHJpbmc=','QW5vdGhlciBzdHJpbmc=' | ConvertFrom-Base64ToMemoryStream

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Base64ToMemoryStream/
#>

function ConvertFrom-Base64ToMemoryStream {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Base64ToMemoryStream/')]
    [OutputType('System.IO.MemoryStream')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('Base64String')]
        [String[]]
        $String
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($s in $String) {
            try {
                $byteArray = ConvertFrom-Base64ToByteArray -String $s
                ConvertFrom-ByteArrayToMemoryStream -ByteArray $byteArray
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts a base64 encoded string to a string.

    .DESCRIPTION
        Converts a base64 encoded string to a string.

    .PARAMETER String
        A Base64 Encoded String

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER Decompress
        If supplied, the output will be decompressed using Gzip.

    .EXAMPLE
        ConvertFrom-Base64ToString -String 'QSBzdHJpbmc='

        A string

    .EXAMPLE
        ConvertTo-Base64 -String 'A string','Another string'

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        'QSBzdHJpbmc=' | ConvertFrom-Base64ToString

        A string

    .EXAMPLE
        'QSBzdHJpbmc=','QW5vdGhlciBzdHJpbmc=' | ConvertFrom-Base64ToString

        A string
        Another string

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Base64ToString/
#>

function ConvertFrom-Base64ToString {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Base64ToString/')]
    [OutputType('String')]
    [Alias('ConvertFrom-Base64StringToString')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('Base64String')]
        [String[]]
        $String,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Parameter(Mandatory = $false)]
        [Switch]
        $Decompress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($s in $String) {
            try {
                $bytes = [System.Convert]::FromBase64String($s)

                if ($Decompress) {
                    ConvertFrom-CompressedByteArrayToString -ByteArray $bytes -Encoding $Encoding
                } else {
                    [System.Text.Encoding]::$Encoding.GetString($bytes)
                }
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts a byte array to a base64 encoded string.

    .DESCRIPTION
        Converts a byte array to a base64 encoded string.

    .PARAMETER ByteArray
        A byte array object for conversion.

    .PARAMETER Compress
        If supplied, the output will be compressed using Gzip.

    .EXAMPLE
        $bytes = ConvertFrom-StringToCompressedByteArray -String 'A string'
        ConvertFrom-ByteArrayToBase64 -ByteArray $bytes

        H4sIAAAAAAAAC3NUKC4pysxLBwCMN9RgCAAAAA==

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-ByteArrayToBase64/
#>

function ConvertFrom-ByteArrayToBase64 {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-ByteArrayToBase64/')]
    [Alias('ConvertFrom-ByteArrayToBase64String')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('Bytes')]
        [Byte[]]
        $ByteArray,

        [Switch]
        $Compress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        try {
            if ($Compress) {
                [System.IO.MemoryStream] $output = [System.IO.MemoryStream]::new()
                $gzipStream = [System.IO.Compression.GzipStream]::new($output, ([IO.Compression.CompressionMode]::Compress))
                $gzipStream.Write( $ByteArray, 0, $ByteArray.Length )
                $gzipStream.Close()
                $output.Close()

                [System.Convert]::ToBase64String($output.ToArray())
            } else {
                [System.Convert]::ToBase64String($ByteArray)
            }
        } catch {
            Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
        }
    }
}


<#
    .SYNOPSIS
    Converts a Byte Array to a MemoryStream

    .DESCRIPTION
    Converts a Byte Array to a MemoryStream

    .PARAMETER ByteArray
    The Byte Array to be converted

    .LINK
    https://msdn.microsoft.com/en-us/library/system.io.memorystream(v=vs.110).aspx

    .NOTES
    Additional information:
    https://msdn.microsoft.com/en-us/library/63z365ty(v=vs.110).aspx

    .EXAMPLE
    ConvertFrom-ByteArrayToMemoryStream -ByteArray ([Byte[]] (,0xFF * 100))

    This command uses the ConvertFrom-ByteArrayToMemoryStream cmdlet to convert a Byte Array into a Memory Stream.
#>

function ConvertFrom-ByteArrayToMemoryStream {
    param
    (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('Bytes')]
        [System.Byte[]]$ByteArray
    )
    [System.IO.MemoryStream]::new($ByteArray, 0, $ByteArray.Length)
}


<#
    .SYNOPSIS
        Converts Clixml to an object.

    .DESCRIPTION
        Converts Clixml to an object.

    .PARAMETER String
        Clixml as a string object.

    .EXAMPLE
        $xml = @"
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<S>ThisIsMyString</S>
</Objs>
"@
        ConvertFrom-Clixml -String $xml

        ThisIsMyString

    .EXAMPLE
        $xml = @"
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<S>ThisIsMyString</S>
</Objs>
"@
        $xml | ConvertFrom-Clixml

        ThisIsMyString

    .EXAMPLE
        $xml = @"
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<S>ThisIsMyString</S>
</Objs>
"@
        $xml2 = @"
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<S>This is another string</S>
</Objs>
"@
        ConvertFrom-Clixml -String $xml,$xml2

        ThisIsMyString
        This is another string

    .EXAMPLE
        $xml = @"
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<S>ThisIsMyString</S>
</Objs>
"@
        $xml2 = @"
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<S>This is another string</S>
</Objs>
"@
        $xml,$xml2 | ConvertFrom-Clixml

        ThisIsMyString
        This is another string

    .OUTPUTS
        [Object[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Clixml/
#>

function ConvertFrom-Clixml {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-Clixml/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
        Set-Variable -Name 'SPLIT' -Value '(?<!^)(?=<Objs)' -Option 'Constant'
    }

    process {
        foreach ($s in $String) {
            try {
                foreach ($record in ($s -split $SPLIT)) {
                    [System.Management.Automation.PSSerializer]::Deserialize($record)
                }
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts a string to a byte array object.

    .DESCRIPTION
        Converts a string to a byte array object.

    .PARAMETER ByteArray
        The array of bytes to convert.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .EXAMPLE
        $bytes = ConvertFrom-CompressedByteArrayToString -String 'A string'
        $bytes.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Object[] System.Array

        $bytes[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Byte System.ValueType

    .OUTPUTS
        [Byte[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-CompressedByteArrayToString/
#>

function ConvertFrom-CompressedByteArrayToString {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-CompressedByteArrayToString/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [Byte[]]
        $ByteArray,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8'
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        try {
            $inputStream = [System.IO.MemoryStream]::new($ByteArray)
            $output = [System.IO.MemoryStream]::new()

            $gzipStream = [System.IO.Compression.GzipStream]::new($inputStream, ([IO.Compression.CompressionMode]::Decompress))
            $gzipStream.CopyTo($output)
            $gzipStream.Close()
            $inputStream.Close()

            [System.Text.Encoding]::$Encoding.GetString($output.ToArray())
        } catch {
            Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
        }
    }
}

<#
    .SYNOPSIS
    Converts an escaped URL back to a standard Url.

    .DESCRIPTION
    Converts an escaped URL back to a standard Url.

    .PARAMETER Url
    The escaped URL to convert.

    .EXAMPLE
    PS> ConvertFrom-EscapedUrl -Url 'http%3A%2F%2Ftest.com%3Fvalue%3Dmy%20value'

    Returns the string `http://test.com?value=my value`.

    .OUTPUTS
    [string]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertFrom-EscapedUrl/
#>

function ConvertFrom-EscapedUrl {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Url
    )

    process {
        foreach ($u in $Url) {
            [System.Uri]::UnescapeDataString($u)
        }
    }
}


<#
    .SYNOPSIS
    Converts HashTable objects to PSCustomObject objects.

    .DESCRIPTION
    Converts HashTable objects to PSCustomObject objects.

    .PARAMETER HashTable
    A list of HashTable objects to convert

    .EXAMPLE
    PS> ConvertFrom-HashTable -HashTable @{'foo'='bar'}

    Returns a PSCustomObject with the property 'foo' with value 'bar'.

    .EXAMPLE
    PS> @{'foo'='bar'} | ConvertFrom-HashTable

    Returns a PSCustomObject with the property 'foo' with value 'bar'.

    .OUTPUTS
    [PSCustomObject[]]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertFrom-HashTable/
#>

function ConvertFrom-HashTable {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [HashTable[]]$HashTable
    )

    process {
        foreach ($h in $HashTable) {
            [PSCustomObject]$h
        }
    }
}


<#
    .SYNOPSIS
        Converts MemoryStream to a base64 encoded string.

    .DESCRIPTION
        Converts MemoryStream to a base64 encoded string.

    .PARAMETER MemoryStream
        A MemoryStream object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER ToString
        (Deprecated) Switch parameter to specify a conversion to a string object. This switch will be removed from future revisions to simplify cmdlet parameters.

    .PARAMETER ToBase64
        Switch parameter to specify a conversion to a Base64 encoded string object.

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        ConvertFrom-MemoryStream -MemoryStream $stream -ToBase64

        QSBzdHJpbmc=

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        $stream | ConvertFrom-MemoryStream -ToBase64

        QSBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertFrom-MemoryStream -MemoryStream $stream1,$stream2 -ToBase64

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertFrom-MemoryStream -ToBase64

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        ConvertFrom-MemoryStream -MemoryStream $stream -ToString

        A string

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        $stream | ConvertFrom-MemoryStream -ToString

        A string

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertFrom-MemoryStream -MemoryStream $stream1,$stream2 -ToString

        A string
        Another string

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertFrom-MemoryStream -ToString

        A string
        Another string

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStream/
#>

function ConvertFrom-MemoryStream {
    [CmdletBinding(
        HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStream/',
        DefaultParameterSetName = 'ToString'
    )]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Parameter(ParameterSetName = 'ToString')]
        [Switch]
        $ToString,

        [Parameter(ParameterSetName = 'ToBase64')]
        [Switch]
        $ToBase64
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($m in $MemoryStream) {
            try {
                $string = ConvertFrom-MemoryStreamToString -MemoryStream $m -ErrorAction Stop

                if ($ToString) {
                    $string
                } elseif ($ToBase64) {
                    ConvertFrom-StringToBase64 -String $string -Encoding $Encoding
                }
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts MemoryStream to a base64 encoded string.

    .DESCRIPTION
        Converts MemoryStream to a base64 encoded string.

    .PARAMETER MemoryStream
        A MemoryStream object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        ConvertFrom-MemoryStreamToBase64 -MemoryStream $stream

        QSBzdHJpbmc=

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        $stream | ConvertFrom-MemoryStreamToBase64

        QSBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertFrom-MemoryStreamToBase64 -MemoryStream $stream1,$stream2

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertFrom-MemoryStreamToBase64

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStreamToBase64/
#>

function ConvertFrom-MemoryStreamToBase64 {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStreamToBase64/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($m in $MemoryStream) {
            try {
                $byteArray = ConvertFrom-MemoryStreamToByteArray -MemoryStream $m
                ConvertFrom-ByteArrayToBase64 -ByteArray $byteArray
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts MemoryStream to a byte array.

    .DESCRIPTION
        Converts MemoryStream to a byte array.

    .PARAMETER MemoryStream
        A System.IO.MemoryStream object for conversion.

    .PARAMETER Stream
        A System.IO.Stream object for conversion.

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        ConvertFrom-MemoryStreamToByteArray -MemoryStream $stream

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        $stream | ConvertFrom-MemoryStreamToByteArray

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertFrom-MemoryStreamToByteArray -MemoryStream $stream1,$stream2

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertFrom-MemoryStreamToByteArray

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStreamToByteArray/
#>

function ConvertFrom-MemoryStreamToByteArray {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStreamToByteArray/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'MemoryStream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream,

        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'Stream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.Stream[]]
        $Stream
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        switch ($PSCmdlet.ParameterSetName) {
            'MemoryStream' {
                $inputObject = $MemoryStream
            }
            'Stream' {
                $inputObject = $Stream
            }
        }

        foreach ($object in $inputObject) {
            try {
                $reader = [System.IO.StreamReader]::new($object)
                if ($PSCmdlet.ParameterSetName -eq 'MemoryStream') {
                    $object.Position = 0
                }
                $object.ToArray()
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            } finally {
                if ($reader) {
                    $reader.Dispose()
                }
            }
        }
    }
}


<#
    .SYNOPSIS
    Converts a Memory Stream to a Secure String

    .DESCRIPTION
    This cmdlet converts a Memory Stream to a Secure String using a Stream Reader object.

    .PARAMETER MemoryStream
    A System.IO.MemoryStream object for conversion.

    .PARAMETER Stream
    A System.IO.Stream object for conversion.

    .EXAMPLE
    $string = 'My Super Secret Value'
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($string)
    $memoryStream = [System.IO.MemoryStream]::new($bytes, 0, $bytes.Length)
    $secure = ConvertFrom-MemoryStreamToSecureString -MemoryStream $memoryStream
    $credential = [PSCredential]::new('MyValue', $secure)

    Converts the provided MemoryStream to a SecureString.

    .LINK
    https://msdn.microsoft.com/en-us/library/system.io.memorystream.aspx

    .NOTES
    Additional information:
    https://msdn.microsoft.com/en-us/library/system.io.streamreader%28v=vs.110%29.aspx
    https://msdn.microsoft.com/en-us/library/system.security.securestring%28v=vs.110%29.aspx
#>

function ConvertFrom-MemoryStreamToSecureString {
    [CmdletBinding(DefaultParameterSetName = 'MemoryStream')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'MemoryStream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream,

        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'Stream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.Stream[]]
        $Stream
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        switch ($PSCmdlet.ParameterSetName) {
            'MemoryStream' {
                $inputObject = $MemoryStream
            }
            'Stream' {
                $inputObject = $Stream
            }
        }

        foreach ($object in $inputObject) {
            try {
                $secureString = [System.Security.SecureString]::new()
                $reader = [System.IO.StreamReader]::new($object)

                while ($reader.Peek() -ge 0) {
                    $secureString.AppendChar($reader.Read())
                }
                $secureString.MakeReadOnly()

                $secureString
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            } finally {
                $reader.Dispose()
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts MemoryStream to a string.

    .DESCRIPTION
        Converts MemoryStream to a string.

    .PARAMETER MemoryStream
        A System.IO.MemoryStream object for conversion.

    .PARAMETER Stream
        A System.IO.Stream object for conversion.

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        ConvertFrom-MemoryStreamToString -MemoryStream $stream

        A string

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        $stream | ConvertFrom-MemoryStreamToString

        A string

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertFrom-MemoryStreamToString -MemoryStream $stream1,$stream2

        A string
        Another string

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertFrom-MemoryStreamToString

        A string
        Another string

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStreamToString/
#>

function ConvertFrom-MemoryStreamToString {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-MemoryStreamToString/')]
    [Alias('ConvertFrom-StreamToString')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'MemoryStream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream,

        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'Stream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.Stream[]]
        $Stream
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        switch ($PSCmdlet.ParameterSetName) {
            'MemoryStream' {
                $inputObject = $MemoryStream
            }
            'Stream' {
                $inputObject = $Stream
            }
        }

        foreach ($object in $inputObject) {
            try {
                $reader = [System.IO.StreamReader]::new($object)
                if ($PSCmdlet.ParameterSetName -eq 'MemoryStream') {
                    $object.Position = 0
                }
                $reader.ReadToEnd()
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            } finally {
                if ($reader) {
                    $reader.Dispose()
                }
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts a string to a base64 encoded string.

    .DESCRIPTION
        Converts a string to a base64 encoded string.

    .PARAMETER String
        A string object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER Compress
        If supplied, the output will be compressed using Gzip.

    .EXAMPLE
        ConvertFrom-StringToBase64 -String 'A string'
        QSBzdHJpbmc=

    .EXAMPLE
        'A string' | ConvertFrom-StringToBase64
        QSBzdHJpbmc=

    .EXAMPLE
        ConvertFrom-StringToBase64 -String 'A string' -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        'A string' | ConvertFrom-StringToBase64 -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        ConvertFrom-StringToBase64 -String 'A string','Another string'
        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        'A string','Another string' | ConvertFrom-StringToBase64
        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        ConvertFrom-StringToBase64 -String 'A string','Another string' -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==
        QQBuAG8AdABoAGUAcgAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        'A string','Another string' | ConvertFrom-StringToBase64 -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==
        QQBuAG8AdABoAGUAcgAgAHMAdAByAGkAbgBnAA==

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToBase64/
#>

function ConvertFrom-StringToBase64 {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToBase64/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Parameter(Mandatory = $false)]
        [Switch]
        $Compress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($s in $String) {
            try {
                if ($Compress) {
                    $bytes = ConvertFrom-StringToCompressedByteArray -String $s -Encoding $Encoding
                } else {
                    $bytes = [System.Text.Encoding]::$Encoding.GetBytes($s)
                }

                [System.Convert]::ToBase64String($bytes)
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts a string to a byte array object.

    .DESCRIPTION
        Converts a string to a byte array object.

    .PARAMETER String
        A string object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .EXAMPLE
        $bytes = ConvertFrom-StringToByteArray -String 'A string'
        $bytes.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Byte[] System.Array

        $bytes[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Byte System.ValueType

    .EXAMPLE
        $bytes = 'A string','Another string' | ConvertFrom-StringToByteArray

        $bytes.Count
        2

        $bytes.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Object[] System.Array

        $bytes[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Byte[] System.Array

    .OUTPUTS
        [System.Collections.Generic.List[Byte[]]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToByteArray/
#>

function ConvertFrom-StringToByteArray {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToByteArray/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8'
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($s in $String) {
            # Creating a generic list to ensure an array of string being handed in
            # outputs an array of Byte arrays, rather than a single array with both
            # Byte arrays merged.
            $byteArrayObject = [System.Collections.Generic.List[Byte[]]]::new()
            try {
                $byteArray = [System.Text.Encoding]::$Encoding.GetBytes($s)
                $null = $byteArrayObject.Add($byteArray)
                $byteArrayObject
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}

<#
    .SYNOPSIS
        Converts a string to a compressed byte array object.

    .DESCRIPTION
        Converts a string to a compressed byte array object.

    .PARAMETER String
        A string object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .EXAMPLE
        $bytes = ConvertFrom-StringToCompressedByteArray -String 'A string'
        $bytes.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Byte[] System.Array

        $bytes[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Byte System.ValueType

    .OUTPUTS
        [System.Collections.Generic.List[Byte[]]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToCompressedByteArray/
#>

function ConvertFrom-StringToCompressedByteArray {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToCompressedByteArray/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8'
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($s in $String) {
            # Creating a generic list to ensure an array of string being handed in
            # outputs an array of Byte arrays, rather than a single array with both
            # Byte arrays merged.
            $byteArrayObject = [System.Collections.Generic.List[Byte[]]]::new()
            try {
                $byteArray = [System.Text.Encoding]::$Encoding.GetBytes($s)

                [System.IO.MemoryStream] $output = [System.IO.MemoryStream]::new()
                $gzipStream = [System.IO.Compression.GzipStream]::new($output, ([IO.Compression.CompressionMode]::Compress))
                $gzipStream.Write( $byteArray, 0, $byteArray.Length )
                $gzipStream.Close()
                $output.Close()

                $null = $byteArrayObject.Add($output.ToArray())
                $byteArrayObject
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}

<#
    .SYNOPSIS
        Converts a string to a MemoryStream object.

    .DESCRIPTION
        Converts a string to a MemoryStream object.

    .PARAMETER String
        A string object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER Compress
        If supplied, the output will be compressed using Gzip.

    .EXAMPLE
        $stream = ConvertFrom-StringToMemoryStream -String 'A string'
        $stream.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $stream = 'A string' | ConvertFrom-StringToMemoryStream
        $stream.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $streams = ConvertFrom-StringToMemoryStream -String 'A string','Another string'
        $streams.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Object[] System.Array

        $streams[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $streams = 'A string','Another string' | ConvertFrom-StringToMemoryStream
        $streams.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Object[] System.Array

        $streams[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $stream = ConvertFrom-StringToMemoryStream -String 'This string has two string values'
        $stream.Length

        33

        $stream = ConvertFrom-StringToMemoryStream -String 'This string has two string values' -Compress
        $stream.Length

        10

    .OUTPUTS
        [System.IO.MemoryStream[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToMemoryStream/
#>

function ConvertFrom-StringToMemoryStream {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToMemoryStream/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Switch]
        $Compress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($s in $String) {
            try {
                [System.IO.MemoryStream]$stream = [System.IO.MemoryStream]::new()
                if ($Compress) {
                    $byteArray = [System.Text.Encoding]::$Encoding.GetBytes($s)
                    $gzipStream = [System.IO.Compression.GzipStream]::new($stream, ([IO.Compression.CompressionMode]::Compress))
                    $gzipStream.Write( $byteArray, 0, $byteArray.Length )
                } else {
                    $writer = [System.IO.StreamWriter]::new($stream)
                    $writer.Write($s)
                    $writer.Flush()
                }
                $stream
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}

<#
    .SYNOPSIS
    Converts a date time represented in Unix time to a PowerShell DateTime object.

    .DESCRIPTION
    Converts a date time represented in Unix time to a PowerShell DateTime object.

    Supports Unix time in seconds by default, or a switch to support Unix time in milliseconds.

    .OUTPUTS
    [datetime]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertFrom-UnixTime/

    .EXAMPLE
    ConvertFrom-UnixTime -UnixTime 1674712047

    Thursday, January 26, 2023 5:47:27 AM

    .EXAMPLE
    1674712047 | ConvertFrom-UnixTime

    Thursday, January 26, 2023 5:47:27 AM

    .EXAMPLE
    ConvertFrom-UnixTime -UnixTime 1674712048705 -FromMilliseconds

    Thursday, January 26, 2023 5:47:28 AM

    .EXAMPLE
    1674712048705 | ConvertFrom-UnixTime -FromMilliseconds

    Thursday, January 26, 2023 5:47:28 AM
#>

function ConvertFrom-UnixTime {
    [CmdletBinding()]
    param (
        # The Unix time to convert. Represented in seconds by default, or in milliseconds if the FromMilliseconds
        # parameter is specified.
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [long]$UnixTime,

        # If specified, returns the time in milliseconds that have elapsed since 00:00:00 UTC on 1 January, 1970.
        [switch]$FromMilliseconds
    )

    process {
        if ($FromMilliseconds) {
            [datetime]($script:EPOCH_TIME + [System.TimeSpan]::FromMilliseconds($UnixTime))
        } else {
            [datetime]($script:EPOCH_TIME + [System.TimeSpan]::FromSeconds($UnixTime))
        }
    }
}


<#
    .SYNOPSIS
        Converts a string to a base64 encoded string.

    .DESCRIPTION
        Converts a string to a base64 encoded string.

    .PARAMETER String
        A string object for conversion.

    .PARAMETER MemoryStream
        A MemoryStream object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER Compress
        If supplied, the output will be compressed using Gzip.

    .EXAMPLE
        $string = 'A string'
        ConvertTo-Base64 -String $string
        QSBzdHJpbmc=

    .EXAMPLE
        (Get-Module -Name PowerShellGet | ConvertTo-Clixml | ConvertTo-Base64).Length
        1057480

        (Get-Module -Name PowerShellGet | ConvertTo-Clixml | ConvertTo-Base64 -Compress).Length
        110876

    .EXAMPLE
        $string = 'A string'
        $string | ConvertTo-Base64
        QSBzdHJpbmc=

    .EXAMPLE
        $string = 'A string'
        ConvertTo-Base64 -String $string -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        $string = 'A string'
        $string | ConvertTo-Base64 -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'
        ConvertTo-Base64 -String $string1,$string2
        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'
        $string1,$string2 | ConvertTo-Base64
        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'
        ConvertTo-Base64 -String $string1,$string2 -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==
        QQBuAG8AdABoAGUAcgAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'
        $string1,$string2 | ConvertTo-Base64 -Encoding Unicode
        QQAgAHMAdAByAGkAbgBnAA==
        QQBuAG8AdABoAGUAcgAgAHMAdAByAGkAbgBnAA==

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        ConvertTo-Base64 -MemoryStream $stream

        QSBzdHJpbmc=

    .EXAMPLE
        $string = 'A string'
        $stream = [System.IO.MemoryStream]::new()
        $writer = [System.IO.StreamWriter]::new($stream)
        $writer.Write($string)
        $writer.Flush()

        $stream | ConvertTo-Base64

        QSBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertTo-Base64 -MemoryStream $stream1,$stream2

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertTo-Base64

        QSBzdHJpbmc=
        QW5vdGhlciBzdHJpbmc=

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertTo-Base64/
#>

function ConvertTo-Base64 {
    [CmdletBinding(
        DefaultParameterSetName = 'String',
        HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertTo-Base64/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'String')]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'MemoryStream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Parameter(Mandatory = $false)]
        [Switch]
        $Compress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference

        $convertSplat = @{
            ErrorAction = $userErrorActionPreference
        }
    }

    process {
        switch ($PSCmdlet.ParameterSetName) {
            'String' {
                foreach ($s in $string) {
                    if ($Compress) {
                        ConvertFrom-StringToBase64 -String $s -Encoding $Encoding @convertSplat -Compress
                    } else {
                        ConvertFrom-StringToBase64 -String $s -Encoding $Encoding @convertSplat
                    }
                }
                break
            }

            'MemoryStream' {
                foreach ($m in $MemoryStream) {
                    if ($Compress) {
                        $string = ConvertFrom-MemoryStreamToString -MemoryStream $m @convertSplat
                        $byteArray = ConvertFrom-StringToCompressedByteArray -String $string @convertSplat
                        ConvertFrom-ByteArrayToBase64 -ByteArray $byteArray @convertSplat
                    } else {
                        ConvertFrom-MemoryStreamToBase64 -MemoryStream $m @convertSplat
                    }
                }
                break
            }

            default {
                Write-Error -Message 'Invalid ParameterSetName' -ErrorAction $userErrorActionPreference
                break
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts an object to Clixml.

    .DESCRIPTION
        Converts an object to Clixml.

    .PARAMETER InputObject
        The input object to serialize

    .PARAMETER Depth
        The depth of the members to serialize

    .EXAMPLE
        $string = 'A string'
        ConvertTo-Clixml -InputObject $string

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <S>A string</S>
</Objs>

    .EXAMPLE
        $string = 'A string'
        $string | ConvertTo-Clixml

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <S>A string</S>
</Objs>

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'
        ConvertTo-Clixml -InputObject $string1,$string2

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <S>A string</S>
</Objs>
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <S>Another string</S>
</Objs>

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'
        $string1,$string2 | ConvertTo-Clixml

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <S>A string</S>
</Objs>
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <S>Another string</S>
</Objs>

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertTo-Clixml/
#>

function ConvertTo-Clixml {
    [CmdletBinding(HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertTo-Clixml/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [PSObject]
        $InputObject,

        [Parameter(Mandatory = $false)]
        [ValidateRange(1, [Int32]::MaxValue)]
        [Int32]
        $Depth = 1
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        foreach ($io in $InputObject) {
            try {
                [System.Management.Automation.PSSerializer]::Serialize($io, $Depth)
            } catch {
                Write-Error -ErrorRecord $_ -ErrorAction $userErrorActionPreference
            }
        }
    }
}


<#
    .SYNOPSIS
    Converts a URL to an escaped Url.

    .DESCRIPTION
    Converts a URL to an escaped Url.

    .PARAMETER Url
    The URL to escape.

    .EXAMPLE
    PS> ConvertTo-EscapedUrl -Url 'http://test.com?value=my value'

    Returns the string `http%3A%2F%2Ftest.com%3Fvalue%3Dmy%20value`.

    .OUTPUTS
    [string]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertTo-EscapedUrl/
#>

function ConvertTo-EscapedUrl {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Url
    )

    process {
        foreach ($u in $Url) {
            $escaped = [System.Uri]::EscapeDataString($u)
            $escaped.Replace("~", '%7E').Replace("'", '%27')
        }
    }
}


<#
    .SYNOPSIS
    Converts a string to a hash.

    .DESCRIPTION
    Converts a string to a hash.

    .PARAMETER String
    A string to convert.

    .PARAMETER Algorithm
    The hashing algorithm to use. Defaults to 'SHA256'.

    .EXAMPLE
    ConvertTo-Hash -String 'MyString'
    38F92FF0761E08356B7C51C5A1ED88602882C2768F37C2DCC3F0AC6EE3F950F5

    .OUTPUTS
    [String[]]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertTo-Hash/
#>

function ConvertTo-Hash {
    [CmdletBinding()]
    [Alias('Get-Hash')]
    param (
        [Parameter(ParameterSetName='String', ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string]$String,

        [ValidateSet('MD5', 'SHA1', 'SHA256', 'SHA384', 'SHA512')]
        [string]$Algorithm = 'SHA256'
    )

    begin {
        $hashAlgorithm = [System.Security.Cryptography.HashAlgorithm]::Create($Algorithm)
    }

    process {
        foreach ($s in $String) {
            $sb = [System.Text.StringBuilder]::new()
            $hashAlgorithm = [System.Security.Cryptography.HashAlgorithm]::Create($Algorithm)
            $hashAlgorithm.ComputeHash([System.Text.Encoding]::ASCII.GetBytes($s)) | ForEach-Object {
                $null = $sb.Append('{0:X2}' -f $_)
            }
            $sb.ToString()
        }
    }
}


<#
    .SYNOPSIS
        Converts an object to a MemoryStream object.

    .DESCRIPTION
        Converts an object to a MemoryStream object.

    .PARAMETER String
        A string object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER Compress
        If supplied, the output will be compressed using Gzip.

    .EXAMPLE
        $string = 'A string'
        $stream = ConvertTo-MemoryStream -String $string
        $stream.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $string = 'A string'
        $stream = $string | ConvertTo-MemoryStream
        $stream.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'

        $streams = ConvertTo-MemoryStream -String $string1,$string2
        $streams.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Object[] System.Array

        $streams[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .EXAMPLE
        $string1 = 'A string'
        $string2 = 'Another string'

        $streams = $string1,$string2 | ConvertTo-MemoryStream
        $streams.GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True Object[] System.Array

        $streams[0].GetType()

        IsPublic IsSerial Name BaseType
        -------- -------- ---- --------
        True True MemoryStream System.IO.Stream

    .OUTPUTS
        [System.IO.MemoryStream[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertTo-MemoryStream/
#>

function ConvertTo-MemoryStream {
    [CmdletBinding(
        DefaultParameterSetName = 'String',
        HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertTo-MemoryStream/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'String')]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $String,

        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Switch]
        $Compress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
        $eaSplat = @{
            ErrorAction = $userErrorActionPreference
        }
    }

    process {
        switch ($PSCmdlet.ParameterSetName) {
            'String' {
                foreach ($s in $string) {
                    $params = @{
                        String   = $s
                        Encoding = $Encoding
                    }

                    if ($Compress) {
                        ConvertFrom-StringToMemoryStream @params -Compress @eaSplat
                    } else {
                        ConvertFrom-StringToMemoryStream @params @eaSplat
                    }
                }
                break
            }

            default {
                Write-Error -Message 'Invalid ParameterSetName' @eaSplat
                break
            }
        }
    }
}


<#
    .SYNOPSIS
        Converts a base64 encoded string to a string.

    .DESCRIPTION
        Converts a base64 encoded string to a string.

    .PARAMETER Base64EncodedString
        A Base64 Encoded String

    .PARAMETER MemoryStream
        A MemoryStream object for conversion.

    .PARAMETER Stream
        A System.IO.Stream object for conversion.

    .PARAMETER Encoding
        The encoding to use for conversion.
        Defaults to UTF8.
        Valid options are ASCII, BigEndianUnicode, Default, Unicode, UTF32, UTF7, and UTF8.

    .PARAMETER Decompress
        If supplied, the output will be decompressed using Gzip.

    .EXAMPLE
        ConvertTo-String -Base64EncodedString 'QSBzdHJpbmc='

        A string

    .EXAMPLE
        ConvertTo-String -Base64EncodedString 'QSBzdHJpbmc=','QW5vdGhlciBzdHJpbmc='

        A string
        Another string

    .EXAMPLE
        'QSBzdHJpbmc=' | ConvertTo-String

        A string

    .EXAMPLE
        'QSBzdHJpbmc=','QW5vdGhlciBzdHJpbmc=' | ConvertTo-String

        A string
        Another string

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        ConvertTo-String -MemoryStream $stream1,$stream2

        A string
        Another string

    .EXAMPLE
        $string1 = 'A string'
        $stream1 = [System.IO.MemoryStream]::new()
        $writer1 = [System.IO.StreamWriter]::new($stream1)
        $writer1.Write($string1)
        $writer1.Flush()

        $string2 = 'Another string'
        $stream2 = [System.IO.MemoryStream]::new()
        $writer2 = [System.IO.StreamWriter]::new($stream2)
        $writer2.Write($string2)
        $writer2.Flush()

        $stream1,$stream2 | ConvertTo-String

        A string
        Another string

    .OUTPUTS
        [String[]]

    .LINK
        http://convert.readthedocs.io/en/latest/functions/ConvertTo-String/
#>

function ConvertTo-String {
    [CmdletBinding(
        DefaultParameterSetName = 'Base64String',
        HelpUri = 'http://convert.readthedocs.io/en/latest/functions/ConvertFrom-StringToMemoryStream/')]
    param
    (
        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'Base64String')]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $Base64EncodedString,

        [Parameter(
            Mandatory = $true,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'MemoryStream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.MemoryStream[]]
        $MemoryStream,

        [Parameter(
            Mandatory = $true,
            ValueFromPipelineByPropertyName = $true,
            ParameterSetName = 'Stream')]
        [ValidateNotNullOrEmpty()]
        [System.IO.Stream[]]
        $Stream,

        [Parameter(ParameterSetName = 'Base64String')]
        [ValidateSet('ASCII', 'BigEndianUnicode', 'Default', 'Unicode', 'UTF32', 'UTF7', 'UTF8')]
        [String]
        $Encoding = 'UTF8',

        [Parameter(Mandatory = $false, ParameterSetName = 'Base64String')]
        [Switch]
        $Decompress
    )

    begin {
        $userErrorActionPreference = $ErrorActionPreference
    }

    process {
        $splat = @{}
        switch ($PSCmdlet.ParameterSetName) {
            'Base64String' {
                $InputObject = $Base64EncodedString
                $Function = 'ConvertFrom-Base64ToString'
                $splat.Add('Encoding', $Encoding)
                if ($Decompress) {
                    $splat.Add('Decompress', $true)
                }
                break
            }

            'MemoryStream' {
                $InputObject = $MemoryStream
                $Function = 'ConvertFrom-MemoryStreamToString'
                break
            }

            'Stream' {
                $InputObject = $Stream
                $Function = 'ConvertFrom-MemoryStreamToString'
                break
            }
        }

        if ($InputObject) {
            $InputObject | & $Function @splat -ErrorAction $userErrorActionPreference
        }
    }
}


<#
    .SYNOPSIS
    Convert a string to title case.

    .DESCRIPTION
    Convert a string to title case.

    .PARAMETER String
    The string to convert.

    .EXAMPLE
    PS> ConvertTo-TitleCase -String 'my string'

    Returns the string `My String`.

    .OUTPUTS
    [string]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertTo-TitleCase/
#>

function ConvertTo-TitleCase {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [string[]]$String
    )

    process {
        foreach ($s in $String) {
            ([CultureInfo]::CurrentCulture).TextInfo.ToTitleCase($s)
        }
    }
}


<#
    .SYNOPSIS
    Converts a date time to the date time represented in Unix time.

    .DESCRIPTION
    Converts a date time to the date time represented in Unix time, which is the time in seconds that have elapsed since
    00:00:00 UTC on 1 January, 1970.

    A switch is provided to return the time value represented in milliseconds.

    .OUTPUTS
    [long]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/ConvertTo-UnixTime/

    .EXAMPLE
    ConvertTo-UnixTime

    1674712201

    .EXAMPLE
    Get-Date | ConvertTo-UnixTime

    1674683490

    .EXAMPLE
    ConvertTo-UnixTime -DateTime (Get-Date).AddMonths(6)

    1690321833

    .EXAMPLE
    ConvertTo-UnixTime -AsMilliseconds

    1674712253812
#>

function ConvertTo-UnixTime {
    [CmdletBinding()]
    param (
        # A DateTime object representing the time to convert. Defaults to `[datetime]::UtcNow`.
        [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [DateTime]$DateTime = [datetime]::UtcNow,

        # If specified, returns the time in milliseconds that have elapsed since 00:00:00 UTC on 1 January, 1970.
        [switch]$AsMilliseconds
    )

    process {
        if ($AsMilliseconds) {
            [long][System.Math]::Round(($DateTime - $script:EPOCH_TIME).TotalMilliseconds)
        } else {
            [long][System.Math]::Round(($DateTime - $script:EPOCH_TIME).TotalSeconds)
        }
    }
}


<#
    .SYNOPSIS
    Gets the current date time represented in Unix time.

    .DESCRIPTION
    Gets the current date time represented in Unix time, which is the time in seconds that have elapsed since 00:00:00 UTC on
    1 January, 1970.

    A switch is provided to return the time value represented in milliseconds.

    .OUTPUTS
    [long]

    .LINK
    http://convert.readthedocs.io/en/latest/functions/Get-UnixTime/

    .EXAMPLE
    Get-UnixTime

    1674712340

    .EXAMPLE
    Get-UnixTime -AsMilliseconds

    1674712353731
#>

function Get-UnixTime {
    [CmdletBinding()]
    param (
        # If specified, returns the time in milliseconds that have elapsed since 00:00:00 UTC on 1 January, 1970.
        [switch]$AsMilliseconds
    )

    if ($AsMilliseconds) {
        ConvertTo-UnixTime -DateTime ([datetime]::UtcNow) -AsMilliseconds
    } else {
        ConvertTo-UnixTime -DateTime ([datetime]::UtcNow)
    }
}