Private/Wissen/C_Advance/C12_CLR.ps1

<#
 
# CLR (Common Language Runtime)
 
CLR ist eine .NET Laufzeitumgebung die in der PowerShell zu 100% genutzt werden kann.
 
- **Hashtags** CLR .NET Framework Assembly Namespace Class Beep
- **Version** 2019.11.08
 
#>


# TODO Weiterführende und Nachschlage-Informationen
Get-Help -Name about_Class -ShowWindow
Start-Process -FilePath https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_using
Start-Process -FilePath https://docs.microsoft.com/de-de/powershell/developer/cmdlet/how-to-write-a-simple-cmdlet

#region 1. .NET Assembly

# ! 1. Die .NET-Typen sind in Namespaces organisiert, diese wiederum in Assemblies (.DLL-Datei)
# ! 2. Ein Assembly muss geladen werden um des Inhalt nutzbar zu machen

# ? Welche Assemblies sind z.Zt. geladene
[System.AppDomain]::CurrentDomain.GetAssemblies()

# ? Weitere Assemblies aus dem GAC laden
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName System.Speech -PassThru # ! Zeigt z.Zt. die Inhalte an

$speaker = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer -Property @{ Rate = 2; Volume = 100 }
$speaker.SpeakAsync('ALARM! ALARM! ALARM! ALARM!')

# ? Eine CLR-DLL-Datei laden die nicht im GAC liegt
[System.Reflection.Assembly]::LoadFile("c:\temp\Blub.dll")

#endregion

#region 2. Namespace

# ! 1. Typenangaben müssen immer mit dem vollqualifizierten Namen erfolgen:
[Stopwatch]::StartNew()
[System.Diagnostics.Stopwatch]::StartNew()

# ! 2. Es seiden der Namespace wurde bekannt gemacht
# ! 3. Die using-Anweisung müssen am Anfang einer Skript-Datei stehen
using namespace System.Diagnostics

# ? Praktischer Nutzen ist eine Verkürzte Schreibweise
$sw = [System.Diagnostics.Stopwatch]::StartNew() # Geht!
$sw = [Stopwatch]::StartNew() # Geht NICHT, wenn die o.a. using-Anweisung gesetzt wird
$sw.Elapsed

using namespace System.Management.Automation
[ActionPreference]::Stop

#endregion

#region .NET-Typen benutzen

# ! Sollte für die Lösung kein Cmdlet zur Verfügung stehen
# ! so lässt sich mit einem weniger oder mehr Aufwand
# ! das Problem über .NET lösen.

# ? Einen statischen Member aufrufen
[System.Math] | Get-Member -Static
[System.Math]::Round([System.Math]::PI, 2)
[System.Environment] | Get-Member -Static

#endregion

#region OOP in der PowerShell

# ! Ab PowerShell 5.0 kann OOP Code direkt in PowerShell ausgeführt werden
# * früher s. Add-Type

enum Color {
    Blue
    Green
    Red
}
$myColor = [Color]::Blue
$myColor | Get-Member

class Car {
    [Color]$Color
    [int]$HP
}

# ? Ein Objekt vom Typ Car erstellen
$myCar = New-Object -TypeName Car

# ? Oder ein Objekt über den Konstruktor von Typ Car erstellen
$myColor = [Car]::new()

$myCar | Get-Member
$myCar.Color = [Color]::Green
$myCar.HP = 100

#region BEISPIEL Get-EuroExchange

enum Currency {
    AUD
    BGN
    BRL
    CAD
    CHF
    CNY
    CZK
    DKK
    GBP
    HKD
    HRK
    HUF
    IDR
    ILS
    INR
    ISK
    JPY
    KRW
    MXN
    MYR
    NOK
    NZD
    PHP
    PLN
    RON
    RUB
    SEK
    SGD
    THB
    TRY
    USD
    ZAR
}

class EuroExchange {
    [Currency]$Currency
    [decimal]$Rate
    [decimal]$Euros
    [decimal]$CurrencySum
}
function Get-EuroExchange2 {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Currency]$Currency,
        
        [decimal]$Euros = 1
    )
    $response = Invoke-WebRequest -Uri 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'
    [xml]$xml = $response | Select-Object -ExpandProperty Content
    [decimal]$rate = $xml.Envelope.Cube.Cube.Cube | 
        Where-Object -Property currency -EQ -Value $Currency | 
        Select-Object -ExpandProperty rate
    New-Object -TypeName EuroExchange -Property @{
        Currency    = $Currency
        Rate        = $rate
        Euros       = $Euros
        CurrencySum = $Euros * $rate
    }
}
Get-EuroExchange2 -Currency USD
Get-EuroExchange2 -Currency USD | Get-Member
Get-Help -Name Get-EuroExchange2 -ShowWindow

#endregion

#endregion

#region Sound-/Sprach-Wiedergabe

# ? Beep
[System.Console]::Beep()
[System.Console]::Beep(10000,1000)
[System.Console]::Beep(5000,1000)
[System.Console]::Beep(200,1000)

# ? Default-Sounds
[System.Media.SystemSounds]::Beep.Play()
[System.Media.SystemSounds]::Asterisk.Play()
[System.Media.SystemSounds]::Exclamation.Play()
[System.Media.SystemSounds]::Hand.Play()

# ? .WAV-Dateien
$player = New-Object -TypeName System.Media.SoundPlayer -Property @{SoundLocation = "c:\Windows\Media\Ring05.wav"}
$player.Play()

#region Beep StarWars

[console]::beep(440,500) 
[console]::beep(440,500) 
[console]::beep(440,500) 
[console]::beep(349,350) 
[console]::beep(523,150) 
[console]::beep(440,500) 
[console]::beep(349,350) 
[System.Console]::beep(523,150) 
[System.Console]::beep(440,1000)
[System.Console]::beep(659,500) 
[System.Console]::beep(659,500) 
[System.Console]::beep(659,500) 
[System.Console]::beep(698,350) 
[System.Console]::beep(523,150) 
[System.Console]::beep(415,500) 
[System.Console]::beep(349,350) 
[System.Console]::beep(523,150) 
[System.Console]::beep(440,1000)

#endregion

Add-Type -AssemblyName System.Speech
$speaker = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$speaker.Rate = -2
$speaker.Volume = 100
$speaker.SpeakAsync('Mit dem Wissen wächst der Zweifel.')

#endregion