Wissen/B06_Eingabe.ps1

# ? TITEL (Benutzer-)-eingabe
# ? DESCRIPTION Vom Benutzer eine Eingabe einfordern.
# ? TAGS UI Read-Host Out-GridView Show-Command
# ? VERSION 2019.10.12.0800

# ! ACHTUNG siehe auch ConvertFrom-*-Cmdlets

#region Read-Host

# ! Funktioniert nur wenn die ISO-Datum-Schreibweise eingehalten wird
$benutzereingabe = Read-Host -Prompt "Bitte Datum eingeben (yyyy-MM-dd)"
[DateTime]$benutzereingabe

# ! Besser so:
$ci = New-Object -TypeName System.Globalization.CultureInfo -ArgumentList $PSCulture
$benutzereingabe = Read-Host -Prompt "Bitte Datum eingeben ($($ci.DateTimeFormat.ShortDatePattern))"
$benutzereingabe.ToDateTime($ci)

# z.B. Credential verschlüsselt speichern
$username = Read-Host -Prompt "Benutzername eingaben"
$password = Read-Host -Prompt "Passwort für $username eingeben" -AsSecureString
[PSCustomObject]@{
    Username = $username
    Password = $password | ConvertFrom-SecureString
} | ConvertTo-Json | Set-Content -Path C:\Temp\Credential_Admin.json -Force
$admin = Get-Content -Path C:\Temp\Credential_Admin.json | ConvertFrom-Json | Select-Object Username, @{Label="Password"; Expression={$_.Password | ConvertTo-SecureString}}
$cred = [System.Management.Automation.PSCredential]::new($admin.Username, $admin.Password)
Enter-PSSession -ComputerName $ZielComputer -Credential $cred

#endregion

#region Out-GridView

Get-Help -Name about_* | Out-GridView -OutputMode Multiple | Get-Help -ShowWindow

Get-Process -IncludeUserName | 
    Where-Object -Property UserName -eq "$env:COMPUTERNAME\$env:USERNAME" | 
    Out-GridView -OutputMode Single | 
    Stop-Process -WhatIf

"Ja", "NEIN", "TEL-JOKER" | Out-GridView -OutputMode Single

$antwort = "JA, Dateien archivieren", "NEIN, Dateien am Ort belassen" | Out-GridView -OutputMode Single
$antwort.StartsWith('NEIN')

Import-Module -Name .\AKPT
Get-EuroExchange -ListCurrency | 
    Out-GridView -OutputMode Multiple | 
    Get-EuroExchange | 
    Out-GridView

#endregion

#region Show-Command

Import-Module -Name .\AKPT

Get-EuroExchange -Currency AUD -Euros 100

Show-Command -Name Get-EuroExchange -NoCommonParameter -ErrorPopup | Out-GridView
Show-Command -Name Test-NetConnection -NoCommonParameter -ErrorPopup | Out-GridView
Show-Command

function Get-About {
    param ($Keyword)
    Get-Help -Name about_*$Keyword* | Out-GridView -OutputMode Multiple | Get-Help -ShowWindow
}
Get-About -Keyword "if"
Show-Command -Name Get-About -ErrorPopup -NoCommonParameter

#endregion

#region PromptForChoice

$titel      = "Aktion wählen"
$nachricht  = "Wie lautet Ihre Entscheidung?"
$ja         = New-Object System.Management.Automation.Host.ChoiceDescription "&Ja"        , "Hilfetext zu JA"
$nein       = New-Object System.Management.Automation.Host.ChoiceDescription "&Nein"      , "Hilfetext zu NEIN"
$vielleicht = New-Object System.Management.Automation.Host.ChoiceDescription "&Vielleicht", "Hilfetext zu VIELLEICHT"
$optionen   = [System.Management.Automation.Host.ChoiceDescription[]]($ja, $nein, $vielleicht)
$ergebnis   = $host.UI.PromptForChoice($titel, $nachricht, $optionen, 1) 
switch ($ergebnis)
{
    0 {"Die Auswahl ist JA"}
    1 {"Die Auswahl ist NEIN"}
    2 {"Die Auswahl ist VIELLEICHT"}
}

#endregion

#region .NET Framework MessageBox

# ? Beispiel A
using namespace System.Windows.Forms # Betr. Namespace bekannt machen; MUSS IN DEN ERSTEN ZEILEN STEHEN
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null # Betr. DLL-Datei wird geladen
[MessageBox]::Show('Hallo Köln!')

# ? Beispiel B
using namespace System.Windows.Forms # Betr. Namespace bekannt machen; MUSS IN DEN ERSTEN ZEILEN STEHEN
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null # Betr. DLL-Datei wird geladen
$title         = "Dateien archivieren"
$message       = "Alte Dateien archivieren? (Werden am Ursprungsort gelöscht auf ... kopiert)"
$buttons       = [MessageBoxButtons]::YesNo
$icon          = [MessageBoxIcon]::Question
$defaultButton = [MessageBoxDefaultButton]::Button1
$antwort       = [MessageBox]::Show($message, $title, $buttons, $icon, $defaultButton)
if($antwort -eq [DialogResult]::Yes)
{
    "OK, die Dateien werden archiviert..."
}

#endregion

#region .NET Framework Common Dialogs

# ! .NET Framework OpenFileDialog

using namespace System.Windows.Forms # Betr. Namespace bekannt machen; MUSS IN DEN ERSTEN ZEILEN STEHEN
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null # Betr. DLL-Datei wird geladen
$ofd = New-Object OpenFileDialog
$ofd.Filter = "PowerShell-Skripten (*.ps1)|*.ps1|Text-Dateien (*.txt)|*.txt|Alle Dateien (*.*)|*.*"
$ofd.InitialDirectory = "C:\Temp"
$dialogResult = $ofd.ShowDialog()
if ($dialogResult -eq [DialogResult]::OK) {
    $ofd.Filename
}

# ! .NET Framework FolderBrowserDialog

using namespace System.Windows.Forms # Betr. Namespace bekannt machen; MUSS IN DEN ERSTEN ZEILEN STEHEN
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null # Betr. DLL-Datei wird geladen
$fbd = New-Object FolderBrowserDialog
$fbd.Description = "Bitte Ordner für das Archivieren auswählen"
$fbd.RootFolder = [Environment+SpecialFolder]::Desktop
$fbd.ShowNewFolderButton = $true
$dialogResult = $fbd.ShowDialog()
if ($dialogResult -eq [DialogResult]::OK) {
    $fbd.SelectedPath
}

# TODO s.a. SaveAsDialog, ColorPicker, FontPicker

#endregion

# ! Einfache GUI sind mit der PS problemlos mit geringen Aufwand möglich.
# ! Bei komplexen GUI stößt die PS an Ihre Grenzen da der Aufwand unverhältnismäßig ist.
# !FAUSTSFORMEL: Eingabe- und Ausgabe-GUI = OK
# TODO Cmdlet-Grundgerüst per GUI bauen => https://poshgui.com/Editor

#region .NET Framework WinForms 'Euro Rechner'

# * WYSIWYG-Editor für ein WinForm-Grundgerüst => https://poshgui.com/Editor

using namespace System.Windows.Forms # Betr. Namespace bekannt machen; MUSS IN DATEIKOPF

Add-Type -AssemblyName System.Windows.Forms

$url = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"
$xml = [xml](Invoke-WebRequest -Uri $url | Select-Object -exp Content) 
$cubes = $xml.Envelope.Cube.Cube.Cube
$currencys = $cubes | Sort-Object currency | Select-Object -exp currency

function EuroRateRechnen() {
    try {
        $aktWährung = $währungComboBox.SelectedItem
        [decimal]$rate = $cubes | Where-Object currency -eq $aktWährung | Select-Object -exp rate
        $euro = $euroTextBox.Text
        $ergebnis = $rate * $euro
    }
    catch {
        $rate = 0
        $ergebnis = 0
    }

    $eregbnisTextBox.Text = $ergebnis
    $rateTextBox.Text = $rate
}

$währungLabel = New-Object -TypeName System.Windows.Forms.Label
$währungLabel.Text = "&Währung:"
$währungLabel.Top  = 15
$währungLabel.Left = 15

$währungComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$währungComboBox.Top                = $währungLabel.Top + $währungLabel.Height
$währungComboBox.Left               = 15
$währungComboBox.AutoCompleteSource = [System.Windows.Forms.AutoCompleteSource]::ListItems
$währungComboBox.AutoCompleteMode   = [System.Windows.Forms.AutoCompleteMode]::SuggestAppend
$währungComboBox.Items.AddRange($currencys)
$währungComboBox.Add_TextChanged({EuroRateRechnen})

$rateLabel = New-Object -TypeName System.Windows.Forms.Label
$rateLabel.Text = "&Rate:"
$rateLabel.Top  = $währungComboBox.Top + $währungComboBox.Height + 10
$rateLabel.Left = 15

$rateTextBox = New-Object -TypeName System.Windows.Forms.TextBox
$rateTextBox.TextAlign = [System.Windows.Forms.HorizontalAlignment]::Right
$rateTextBox.ReadOnly  = $true
$rateTextBox.Top       = $rateLabel.Top + $rateLabel.Height
$rateTextBox.Left      = 15
$rateTextBox.Text      = "0"

$euroLabel = New-Object -TypeName System.Windows.Forms.Label
$euroLabel.Text = "&Euro(s):"
$euroLabel.Top  = $rateTextBox.Top + $rateTextBox.Height + 10
$euroLabel.Left = 15

$euroTextBox = New-Object -TypeName System.Windows.Forms.TextBox
$euroTextBox.TextAlign = [System.Windows.Forms.HorizontalAlignment]::Right
$euroTextBox.Top       = $euroLabel.Top + $euroLabel.Height
$euroTextBox.Left      = 15
$euroTextBox.Add_TextChanged({EuroRateRechnen})

$ergebnisLabel = New-Object -TypeName System.Windows.Forms.Label
$ergebnisLabel.Text = "&Ergebnis:"
$ergebnisLabel.Top  = $euroTextBox.Top + $euroTextBox.Height + 10
$ergebnisLabel.Left = 15

$eregbnisTextBox = New-Object -TypeName System.Windows.Forms.TextBox
$eregbnisTextBox.TextAlign = [System.Windows.Forms.HorizontalAlignment]::Right
$eregbnisTextBox.ReadOnly  = $true
$eregbnisTextBox.Top       = $ergebnisLabel.Top + $ergebnisLabel.Height
$eregbnisTextBox.Left      = 15

$HauptForm = New-Object -TypeName System.Windows.Forms.Form
$HauptForm.Text          = "EURO EXCHANGER XP V10.9.1 NT PLUS PROF EDITION LIGHT"
$HauptForm.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
$HauptForm.Height        = 350
$HauptForm.Controls.AddRange(( `
    $währungLabel,  $währungComboBox, `
    $rateLabel,     $rateTextBox, `
    $euroLabel,     $euroTextBox, `
    $ergebnisLabel, $eregbnisTextBox))

    $währungComboBox.SelectedIndex      = 0
    $euroTextBox.Text        = "1"
$HauptForm.ShowDialog()

#endregion

#region .NET Framework WPF 'Euro Rechner'

# Betr. Namespace bekannt machen; MUSS IN DATEIKOPF
using namespace System.PresentationFramework
using namespace System.Windows.Markup
using namespace System.Xml

Add-Type -AssemblyName PresentationFramework

$url = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"
$xml = [xml](Invoke-WebRequest -Uri $url | Select-Object -exp Content) 
$cubes = $xml.Envelope.Cube.Cube.Cube
$currencys = $cubes | Sort-Object currency | Select-Object -exp currency

function EuroRateRechnen() {
    try {
        $aktWährung    = $WährungenCtrl.SelectedItem
        [decimal]$rate = $cubes | Where-Object currency -eq $aktWährung | Select-Object -exp rate
        $euro          = $eurosCtrl.Text
        $ergebnis      = $rate * $euro
    }
    catch {
        $rate     = 0
        $ergebnis = 0
    }
    $RateCtrl.Text     = "{0:#,##0.0000} {1}" -f $rate    , $WährungenCtrl.SelectedItem
    $ErgebnisCtrl.Text = "{0:#,##0.0000} {1}" -f $ergebnis, $WährungenCtrl.SelectedItem
}

[XML]$xaml = @"
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="€CALC"
    Width="220"
    Height="280"
    WindowStartupLocation="CenterScreen">
    <Grid Margin="20">
        <StackPanel>
            <Label Margin="-4 0 0 -2">Währungssymbol</Label>
            <ComboBox x:Name="Währungen" />
            <Label Margin="-4 8 0 -2">Rate</Label>
            <TextBox x:Name="Rate" IsReadOnly="True" TextAlignment="Right" />
            <Label Margin="-4 8 0 -2">€ (Euros)</Label>
            <TextBox x:Name="Euros" TextAlignment="Right" />
            <Label Margin="-4 8 0 -2">Ergebnis</Label>
            <TextBox x:Name="Ergebnis" IsReadOnly="True" TextAlignment="Right" FontWeight="Bold" />
        </StackPanel>
    </Grid>
</Window>
"@


$reader = New-Object System.Xml.XmlNodeReader $xaml
$window = [System.Windows.Markup.XamlReader]::Load($Reader)

$WährungenCtrl = $window.FindName('Währungen')
$RateCtrl      = $window.FindName('Rate')
$EurosCtrl     = $window.FindName('Euros')
$ErgebnisCtrl  = $window.FindName('Ergebnis')

$currencys | ForEach-Object { $WährungenCtrl.Items.Add($_) | Out-Null }
$WährungenCtrl.Add_SelectionChanged({EuroRateRechnen})
$WährungenCtrl.SelectedIndex = 0

$EurosCtrl.Add_TextChanged({EuroRateRechnen})
$EurosCtrl.Text = "1"

$window.ShowDialog()

#endregion

#region .NET: Read-Window (Install-Module -Name AKPT)

Import-Module .\AKPT
Read-Window -Title "Alte Dateien finden" -Message "Alte Dateien sind älter als?" -Default "01.01.2010"

#endregion