Private/Wissen/A01_PSEinführung.ps1

# ? TITEL PS Einführung
# ? DESCRIPTION PowerShell-Einführung
# ? TAGS Version Befehlskonzepte Terminologie Alias Pipelining Parsing EscapeCharacters Delimiters Quotes Console
# ? VERSION 2019.12.25

using namespace System.Diagnostics.CodeAnalysis

[SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
[SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '')]
param()

#region Wie Sie mit meinen Dateien verfahren können

#TODO: Noch weiter ausarbeiten

# ? Ordnerstruktur und deren Bedeutung:
Get-ChildItem -Path .\_SCHNIPPSEL.ps1
Get-ChildItem -Path .\.Einarbeiten -Recurse
Get-ChildItem -Path .\.vscode
Get-ChildItem -Path .\Modules\AKPT
Get-ChildItem -Path .\Wissen\A??_*.ps1
Get-ChildItem -Path .\Wissen\B??_*.ps1
Get-ChildItem -Path .\Wissen\C??_*.ps1
Get-ChildItem -Path .\Wissen\X??_*.ps1

# ! Wissen von ca. 8.700 Zeilen, 42.000 Wörter und 580.000 Zeichen (Stand: November 2019)
Get-ChildItem -Path .\ -Recurse -File -Force | Where-Object Extension -in '.ps1', '.md' | Get-Content | Measure-Object -Line -Character -Word

#endregion

#region Was ist die PowerShell?

# ? Die PS ist ein Kommandozeileninterpreter!
# Die Windows PowerShell ist ein Kommandozeileninterpreter von Microsoft
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -?

# ? Die PS unterstützt und basiert auf dem .NET-Framework!
# Die auf dem Microsoft .NET-Framework basierende PowerShell verbindet die
# aus Unix-Shells bekannte Philosophie von Pipes und Filtern mit dem Paradigma
# der objektorientierten Programmierung (OOP).
Get-Service | Where-Object Status -EQ Running 
Get-Service | Where-Object Status -EQ Running | Get-Member

# ? Die PowerShell arbeitet objektorientiert!
# PowerShell ist objektorientiert und mit .NET erweiterbar
$file = Get-ChildItem C:\Windows\notepad.exe
$file.LastAccessTime
$file.Length
$file.CopyTo("c:\temp\notepad.exe")
$file | Add-Member -MemberType ScriptProperty -Name LengthKb -Value {$this.Length / 1KB}
$file.LengthKb

#? Die PS arbeit als 32bit oder 64bit!
# Unterstützt 32/64bit, um auf 32/64bit-Komponenten (z.B. Drucker, DB, etc.) zugreifen zu können
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
C:\Windows\syswow64\WindowsPowerShell\v1.0\powershell.exe

#? Die PS steht für Windows und Linux zur Verfügung!
# "Windows PowerShell" für Windows Systeme (akt. Version 5.0)
# "PowerShell Core" für Windows/Unix/Linux Systeme (akt. Version 6.0; z.Zt. geringer Funktionsumfang)

#? PS-Entwicklung per GUI!
# Enthält eine grafische Entwicklungsumgebung PowerShell ISE (Integrated Scripting Environment)
powershell_ise.exe
# ! Die aber nicht mehr weiter entwickelt wird.
# ! (Microsoft)-Empfehlung => Visual Studio Code

#endregion

#region PowerShell-Versionen / -History

# Seit Windows 7 / Server 2008 ist die PowerShell fester Bestandteil des Betriebssystems

# ? Welche Version ist installiert?
$PSVersionTable

#region Windows PowerShell 1.0

# Markteinführung

#endregion

#region Windows PowerShell 2.0

# Remoting via RPC
Get-Help -Name * -Parameter ComputerName # Nur diese Cmdlets können remote zugreifen

#endregion

#region Windows PowerShell 3.0

# Default in: Windows7
# Windows Server 2008 R2

# Min. OS: >XP, >VISTA

# Remoting via WinRM
# Workflows
# Scheduled[Jobs]
# Windows PowerShell Web Access
# Netzlaufwerke verbinden (New-PSDrive)
# Aktualisierbare Hilfe
# Web Cmdlet's
# ZZGL. Vereinfachte Syntax
Get-Process | Where-Object -FilterScript {$_.Handles -gt 500}
Get-Process | Where-Object -Property Handles -GT -Value 500

#endregion

#region Windows PowerShell 4.0

# DEFAULT: Windows 8, Windows Server 2012

# Desired State of Configuration (DSC)

#endregion

#region Windows PowerShell 5.0

# Default OS: Windows 10, Windows Server 2016

# Softwarepakete installieren
# Switch-Verwaltung
# OOP

#region Details zu Neuerungen

# Alle Details zur 5.0 Version unter:
Get-Help about_Windows_PowerShell_5.0 -ShowWindow
Start-Process http://msdn.microsoft.com/de-de/powershell/scripting/whats-new/what-s-new-in-windows-powershell-50

#region Get-ItemPropertyValue

#NEU: Get-ItemPropertyValue
#FRÜHER:
(Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine -Name ApplicationBase).ApplicationBase
#JETZT:
Get-ItemPropertyValue -Path HKLM:\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine -Name ApplicationBase

#endregion

#region Einfache String-Operationen
"Hallo Welt" | ConvertFrom-String
"Hallo Welt" | ConvertFrom-String -Delimiter "ll"
"Hallo Welt" | ConvertFrom-String -PropertyNames FirstWord, SecondWord

"Lee Holmes", "Steve Lee", "Jeffrey Schmitt" | Convert-String -Example "Bill Gates=Gates, B.","John Smith=Smith, J."

"Hallo Welt" | Format-Hex
#endregion

#region ZIP-Archive

#
#Test-Daten erzeugen
#
New-Item -Path C:\temp\ZipMich -ItemType Directory -Force
1..1MB -join ";" | Set-Content -Path "C:\temp\ZipMich\LogFile1.txt" -Force
1..1MB -join ";" | Set-Content -Path "C:\temp\ZipMich\LogFile2.txt" -Force

#
# Compress-Archive
#
"C:\temp\ZipMich" | Compress-Archive -DestinationPath C:\temp\ZipMich.zip -CompressionLevel Optimal -Force
Get-Help Compress-Archive -ShowWindow

#
# Expand-Archive
#
"C:\temp\ZipMich.zip" | Expand-Archive -DestinationPath C:\temp\Backup -Force
Get-Help Expand-Archive -Full

#endregion

#region Software-Installation

Set-ExecutionPolicy -ExecutionPolicy AllSigned

Get-Command -Module PowerShellGet, PackageManagement

Find-Package | Out-GridView
Install-Package -Name AKPT -Force
Get-Module -ListAvailable 
Get-Command * -Module AKPT
Get-AKAbout
Uninstall-Package -Name AKPT

Register-PSRepository -Name "myNuGetSource" â€“SourceLocation "https://www.myget.org/F/powershellgetdemo/api/v2" -PublishLocation "https://www.myget.org/F/powershellgetdemo/api/v2/Packages" -InstallationPolicy Trusted
Get-PSRepository
Unregister-PSRepository -Name "myNuGetSource"

#endregion

#region Kryptographie

Get-Command -Module Microsoft.PowerShell.Security 

$MyCertInf = @"
[Version]
Signature = "$Windows NT$"
 
[Strings]
szOID_ENHANCED_KEY_USAGE = "2.5.29.37"
szOID_DOCUMENT_ENCRYPTION = "1.3.6.1.4.1.311.80.1"
 
[NewRequest]
Subject = "cn=me@example.com"
MachineKeySet = false
KeyLength = 2048
KeySpec = AT_KEYEXCHANGE
HashAlgorithm = Sha1
Exportable = true
RequestType = Cert
 
KeyUsage = "CERT_KEY_ENCIPHERMENT_KEY_USAGE | CERT_DATA_ENCIPHERMENT_KEY_USAGE"
ValidityPeriod = "Years"
ValidityPeriodUnits = "1000"
 
[Extensions]
2.5.29.37="{text}1.3.6.1.4.1.311.80.1"
"@

Set-Content -Path C:\temp\MyCert.inf -Value $MyCertInf
CertReq -new C:\temp\MyCert.inf C:\temp\MyCert.cer
$cert = Get-ChildItem -pv Cert:\CurrentUser\My | Where-Object -Property Subject -EQ -Value "cn=me@example.com"

$crypt = "Hallo Welt" | Protect-CmsMessage -To $cert
Unprotect-CmsMessage -Content $crypt -To $cert

#endregion

#region OOP

Get-Help about_Classes -ShowWindow

enum Farbe
{
    Blau
    Grün
    Rot
}
$meineFarbe = [Farbe]::Grün
$meineFarbe 

class Auto
{
    [Farbe]$Farbe
    $PS
}

$meinAuto = New-Object -TypeName Auto

$meinAuto.Farbe = [Farbe]::Grün
$meinAuto.PS = 100
$meinAuto | Get-Member

#endregion

#region Weitere neue Cmdlet's

Set-Clipboard -Value "Hallo Köln!"
Get-Clipboard

Clear-RecycleBin -DriveLetter c: -Confirm:$false

New-TemporaryFile

New-Guid

# symbolischer Verknüpfungen
New-Item -ItemType SymbolicLink -Name MySymLinkDir -Target $pshome 

# -Depth 2
Get-ChildItem c:\ -Recurse -Depth 2 -Force

#endregion

#region DataCenter Abstraction Layer (DAL)

<#
    Mit dieser Technologie können Sie direkt auf bestimmte
    Netzwerkkomponenten wie Switches und Router zugreifen.
 
    Dazu muss die Hardware diese Technik aber auch unterstützen.
    In diesem Bereich spielen vor allem
    Cisco und Huawei eine wichtige Rolle.
#>


$Session = New-CimSession -ComputerName $MyNetworkSwitchName
Get-NetworkSwitchFeature -CimSession $Session

<#
    Name IsEnabled InstanceID PSComputerName
    ---- --------- ---------- --------------
    SSH True Contoso:Feature:2 10.19.26.49
    Tacacs True Contoso:Feature:3 10.19.26.49
    BGP False Contoso:Feature:4 10.19.26.49
    VLAN True Contoso:Feature:5 10.19.26.49
    LACP True Contoso:Feature:6 10.19.26.49
    DHCP False Contoso:Feature:7 10.19.26.49
    LLDP True Contoso:Feature:8 10.19.26.49
#>


Get-Help Get-NetworkSwitchFeature -Full

Get-Command -Module NetworkSwitchManager | Out-GridView

#endregion

#region Open Data Protocol

<# Das Open Data Protocol, kurz OData ist ein von Microsoft veröffentlichtes HTTP-basiertes Protokoll
   für den Datenzugriff zwischen kompatiblen Softwaresystemen. Aufbauend auf älteren Protokollen wie
   ODBC und JDBC kann OData u.a. innerhalb von Cloud-Diensten (Azure), MySQL, Java und Rails
   eingebunden werden und ist in der Lage, in der Client-Server-Kommunikation eine einheitliche Semantik
   für den Datenaustausch zur Verfügung zu stellen.
#>


Export-ODataEndpointProxy -Uri 'http://services.odata.org/v3/(S(snyobsk1hhutkb2yulwldgf1))/odata/odata.svc' `
                          -MetadataUri 'http://services.odata.org/v3/(S(snyobsk1hhutkb2yulwldgf1))/odata/odata.svc/$metadata' `
                          -AllowUnsecureConnection `
                          -OutputModule C:\Temp\GeneratedScript.psm1 `
                          -ResourceNameMapping @{Products = 'Merchandise'}

#endregion

#region Optimierte Unterstützung für 'Desired State Configuration' (DSC)

<#
    Weitere Neuerungen in der PowerShell betreffen die mit der
    PowerShell 4.0 eingeführte Technologie Desired State Configuration (DSC).
     
    Hauptsächlich gibt es neue Optionen um festzulegen auf wievielen Computern
    gleichzeitig die Änderungen implementiert werden sollen.
      
    Mit dem Modul 'PowerShellGet' können Sie DSC-Ressourcen in der
    'PowerShell Resource Gallery' nutzen, installieren oder hochladen.
#>


#endregion

#endregion

#region PowerShell Core 6.0

#endregion

#endregion

#region Windows PowerShell 5.1

# ! # Neue Funktionen in diesem Modul
Get-Command -Module Microsoft.PowerShell.LocalAccounts
Get-Command -Module PowerShellGet
Get-Command -Module PackageManagement 
Get-ComputerInfo # Neu

# ! Besseres Debugging für DSC und PowerShell-Klassen

#endregion

#region PowerShell 7 (Stand: Release Candidate 1, Januar 2020)

<#
Windows PowerShell (für Windows) und PowerShell Core (für Windows, MacOS und Linux) wurden in PowerShell 7 zusammengeführt und bilden deren Nachfolger.
PowerShell 7 basiert und ist kompatibel mit .NET Core 3.1 (LTS).
PowerShell 7.0 steht als Release Candidate bereit und wird offiziell unterstützt.
Das finale Release mit General Availability ist für Januar/Februar angekündigt.
PowerShell 7 ist abwärtskompatibel und kann auch parallel zu Windows PowerShell produktiv genutzt werden.
PowerShell 7 ist auch für .NET-Entwickler attraktiv, da man in einer einzigen Skriptsprache plattformübergreifend .NET-Anwendungen schreiben kann.
#>


# ? PowerShell Version 7 steht über folgenden Download-Link zur Verfügung:
# ! https://github.com/PowerShell/PowerShell/releases/tag/v7.0.0-rc.1
# * z.B. für Windows 64bit-System: PowerShell-7.0.0-rc.1-win-x64.msi

# ? Alle Funktionen die sich noch Experimentierstatus befinden einschalten:
Get-ExperimentalFeature | Enable-ExperimentalFeature

# ? PowerShell-Version des aktuellen Host ermitteln:
$PSVersionTable

# ? Standard-Installationsort der PowerShell 7:
& 'file://C:\Program Files\PowerShell\7-preview\pwsh.exe'

# ? Web-Adresse der offiziellen PowerShell Microsoft Online-Dokumentation
# ! https://aka.ms/powershell

# ? OS-übergreifende GUI-Elemente installieren und importieren:
Install-Module -Name Microsoft.PowerShell.GraphicalTools -Scope CurrentUser -AllowClobber -Force
Import-Module -Name Microsoft.PowerShell.GraphicalTools -Force

#region Allgemeine und übergreifende Änderungen in PowerShell 7

# ! Beim starten des PowerShell-7-Host informiert dieser über das Vorhandensein einer neuen PowerShell-Version
& pwsh.exe

# ! Windows-PowerShell-Module stehen durch den "Windows Compatibility Wrapper" auch in PowerShell 7 zur Verfügungen
# * Windows PowerShell 5.1 ist jedoch zusätzlich nötig. Wenn das Modulmanifest nicht angibt ob dass Modul mit Core kompatibel ist, wird das Modul in einen Windows PowerShell-Prozess geladen und mittels Remoting in Ihrer PowerShell 7-Sitzung widerspiegelt wird.

# ! Invoke-DscResource arbeit jetzt OS-übergreifende (experimental)
Get-ExperimentalFeature -Name PSDesiredStateConfiguration.InvokeDscResource | Enable-ExperimentalFeature

# ! PowerShell Remoting-Zugriff über SSH:
# ? https://docs.microsoft.com/de-de/powershell/scripting/learn/remoting/ssh-remoting-in-powershell-core?view=powershell-7

# ! Neue Module-Installationsorte:
$env:PSModulePath -split ";"
Get-Module -Name * -ListAvailable | Select-Object -Property Name, PowerShellVersion, CompatiblePSEditions, CompanyName, ExperimentalFeatures, Path | Out-GridView

#endregion

#region Neue und geänderte Cmdlets in PowerShell 7

# ! Das neue Cmdlet Clear-RecycleBin leert den Papierkorb
Clear-RecycleBin -Force

# ! Das neue Cmdlet Update-List aktualisiert Listen-Einträge (Add / Remove) von Listen-Objekt-Eigenschaften.
class OsDetails {
    [System.Collections.ArrayList]$ProcessItems
    OsDetails() {
        $this.ProcessItems = New-Object -TypeName System.Collections.ArrayList
    }
}
$osd = New-Object -TypeName OsDetails
$osd.ProcessItems.AddRange((Get-Process | Select-Object -First 3))
$notepad = Start-Process notepad -PassThru

$osd | Update-List -Property ProcessItems -Add $notepad | Out-Null
$osd.ProcessItems # Enthält notepad

$osd | Update-List -Property ProcessItems -Remove $notepad | Out-Null
$osd.ProcessItems # notepad wurde entfernt

# ! Für die Fehler-Analyse/-Auswertung liefert das neue Cmdlet Get-Error wichtige Informationen
Get-ExperimentalFeature -Name Microsoft.PowerShell.Utility.PSGetError | Enable-ExperimentalFeature

Get-Process -FileVersionInfo # * Fehler provozieren!

Get-Error
Get-Error -Newest 2

Get-Process -FileVersionInfo -ErrorAction SilentlyContinue -ErrorVariable gpErrors
$gpErrors | Get-Error

# ! Ein Module für OS-Übergreifende GUI's (Out-GridView, Show-Command, Get-Help -ShowWindow)
Install-Module -Name Microsoft.PowerShell.GraphicalTools -Scope CurrentUser -AllowClobber -Force # ! Muss vorher installiert werden
Import-Module -Name Microsoft.PowerShell.GraphicalTools
Get-Process | Out-GridView
Show-Command
Get-Help -Name Update-List -ShowWindow

# ! Parallele Verarbeitung mittels ForEach-Object -Parallel ist möglich
Get-Help -Name ForEach-Object -ShowWindow
1..8 | ForEach-Object -Process  { "Hallo $_"; Start-Sleep -Seconds 1 }                  # ! Langsam !
1..8 | ForEach-Object -Parallel { "Hallo $_"; Start-Sleep -Seconds 1 } -ThrottleLimit 4 # ? Schnell !

# ! Für die hexadezimale Darstellung von unterschiedlichen Pipeline-Objekten wurde Format-Hex verbessert
123, "Hallo Würzburg!", (Get-Item C:\Windows\win.ini) | Format-Hex

# ! Verbesserung von Select-String um die visuelle Hervorhebung von Fundstellen
Get-ChildItem -Path C:\Windows\Logs\DISM\dism.log | Select-String -Pattern "Error" | Select-Object -First 10
Get-ChildItem -Path C:\Windows\Logs\DISM\dism.log | Select-String -Pattern "Error" -NoEmphasis | Select-Object -First 10 # * -NoEmphasis deaktiviert die hervorhebung

#endregion

#region Neue und geänderte PowerShell-Variablen

# ! Standard-Fehlerausgabe-Menge über $ErrorView bestimmen
Get-help -Name ABOUT_PREFERENCE_VARIABLES -ShowWindow

$ErrorView = [System.Management.Automation.ErrorView]::NormalView # ! Default; Umfassende Fehler-Ausgabe
1/0 # * Fehler provozieren!
$ErrorView = [System.Management.Automation.ErrorView]::ConciseView # ! Fehler-Ausgabe enthält nur eine Kurzfassung
1/0 # * Fehler provozieren!
$ErrorView = [System.Management.Automation.ErrorView]::CategoryView # ! Nur Fehler-Ausgabe enthält nur die Kategorie
1/0 # * Fehler provozieren!

# ! Wird der ErrorAction der neue Wert 'Break' zugewiesen, hält die Ausführung an und es wird den DEBUG-Modus gewechselt
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Break
Get-Process -FileVersionInfo -ErrorAction Break

#endregion

#region Änderungen an den PowerShell-Operatoren

# ! Split-Operator wurde erweitert
"a b c d e" -split " ",  3 # * Splittet nur 3 Elemente von Links
"a b c d e" -split " ", -3 # ! Neu Splittet nur 3 Elemente von Rechts

# ! Ein dreiteiliger Inline-If-Operator (Ternary-Operator (a ? b : c))
$PSCulture -ieq "de-DE" ? "Die PS-Sprache steht auf deutsch-Deutschland." : "Die PS-Sprache steht auf $PSCulture."

# ! Pipeline-Verkettung-Operatoren && und || (Pipeline chain operators)
1/0.1 && "Ich werde ausgeführt wenn die vorherige Anweisung ERFOLGREICH war."
1/0   || "Ich werde ausgeführt wenn die vorherige Anweisung ERFOLGLOS war."

# ! NULL-Sammel-Operator (??)
$a = $null # $a = 123
if($null -ne $a) {
    return $a
} else {
    return "Ohne Inhalt!"
}
# ! vs.
$a = $null # $a = 123
$a ?? "Ohne Inhalt!"

$a = $null
$b = $null
$c = 3
$a ?? $b ?? $c
# * Die NULL-Sammeloperatoren sind rechtsassoziativ d.h. $a ?? $b ?? $c wird wie folgt abgearbeitet:
$a ?? ($b ?? $c)

# ! NULL-Zuweisungs-Operatoren (??= ?)
$a = $null # $a = 123
if($null -eq $a) {
    $a = 'Default-Wert wenn Ausdruck -eq $null ist'
}
return $a
# ! vs.
$a = $null # $a = 123
$a ??=  'Default-Wert wenn Ausdruck -eq $null ist'
return $a

# ! NULL-Bedingung-Operator (${a}?.MemberName)
Get-ExperimentalFeature -Name PSNullConditionalOperators | Enable-ExperimentalFeature

$t = Get-Process ; $t.Count
$t = $null       ; $t.Count # ! Löst eine Exception aus da $t NULL
# ! vs.
$t = Get-Process ; ${t}?.Count
$t = $null       ; ${t}?.Count # ! Löst keinen Exception aus, wenn $t NULL ist


#endregion

#region PowerShell-Verhalten

# ! DBNull und NullString werden ab PowerShell 7 gleichbehandelt wie $null
$null -eq [DBNull]::Value
$null -eq [NullString]::Value

#endregion

#region PowerShell-Handling und Objekt-Dokumentation

# ! Dokumentation einer Methoden-Signatur von COM-Objekten
$excel = New-Object -ComObject "Excel.Application"
$excel.Save # ! Methode ohne Klammern d.h. unvollständig ausführen um weitere Details zu erhalten

# ! Es gibt eine Autovervollständigung (CTRL + SPACE) für das Zuweisen von Aufzählungs-Werten (Enum) zu Variablen
$ErrorActionPreference = 
# ? ^ An dieser Stelle in der Console CTRL+SPACE drücken.

#endregion

#endregion

#region BEFEHLSKONZEPT: Cmdlets

# ! Cmdlet => Command-Let besteht aus Verb(Verb, Tätigkeit), einem Bindestrich '-' und Substantiv (Noun, Nomen, Tätigkeitsbereich)
# * => Verb-Noun
# * => Verb-Substantiv
# * => Tätigkeit-Tätigkeitsbereich
Get-Service
Stop-Process

# ? Welche Verben/Tätigkeit gibt es:
Get-Verb

# ? Welche Informationen können noch ermittelt werden:
Get-Command -Verb Get

 # ? Was kann ich im Tätigkeitsbereich Diensten machen:
Get-Command -Noun Service

# ! 1. Cmdlets sind keine EXE-Dateien, sie sind *.dll oder in *.ps1 definiert
# ! 2. Cmdlets sind in Module zusammengefasst
# ! 3. Neu Cmdlets können durch die Installation eines Moduls hinzugefügt werden
Get-Module -Name *locker* -ListAvailable
Get-Command -Module BitLocker
Get-ADUser # Ist in dem Module ActiveDirectory

# ! Ein Cmdlet wird nur über dessen Parameter gesteuert,
# ! dabei unterscheidet man Parameter die ein Argument erwarten...
Get-ChildItem -Path C:\Windows -Filter "*.exe"
# ! ... und SwitchParameter die durch das Setzen das Verhalten des Cmdlets ändern:
Get-ChildItem -Recurse
Get-ChildItem -Recurse -File

# ! Das Benennen eines Parameters kann vollständig erfolgen,
# ! oder es kann soweit verkürzt werden das die rechtlichen Buchstaben
# ! eindeutig einem Parameter zugeordnet werden können:
Get-ChildItem -LiteralPath C:\Windows
Get-ChildItem -Literal C:\Windows
Get-ChildItem -Li C:\Windows
Get-ChildItem -l C:\Windows

# ! Ein Parameter kann auch über dessen Alias angesprochen werden:
Get-ChildItem -PSPath C:\Users -s -ea SilentlyContinue -af -ah -as
# ! Welche Parameter-Aliase ein Cmdlet unterstützt ist in der Cmdlet-Hilfe
# ! NICHT ersichtlich, aber wie folgt schon:
Get-Command -Name Get-ChildItem | 
    Select-Object -ExpandProperty Parameters | 
    Select-Object -ExpandProperty Values | 
    Select-Object -Property Name, Aliases

# ! Ein Cmdlet kann auch dynamische Parameter besitzen die nur dann zur Verfügung stehen wenn div. Konstellationen eingetreten sind
Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert # ! Den Parameter '-CodeSigningCert' gibt es nur im PowerShell-Provider 'Certificate'
Get-ChildItem -Path C:\Temp              -Directory       # ! Den Parameter '-Directory' gibt es nur im PowerShell-Provider 'FileSystem'

#endregion

#region BEFEHLSKONZEPT: PowerShell Parsing

# Ein PowerShell Kommando wird beim parsen in Token aufgeteilt und analysiert.
# Die Tokens werden mit einem SPACE getrennt
# z.B. Token 'Write-Output', Token '-InputObject' und Token 'Buch'
Write-Output -InputObject Buch 
# z.B. Token 'Get-ChildItem', Token 'C:\Database' und Token 'Backups'
Get-ChildItem -Path C:\Database Backups # !PROBLEM, Lösung => "C:\Database Backups"
Get-ChildItem -Path "C:\Database Backups" # ? Lösung

# Token werden wie folgt analysiert:
# Example Mode Result
# ------------------ ---------- ----------------
2+2                 # Expression 4 (integer)
Write-Output 2+2    # Argument "2+2" (string)
Write-Output (2+2)  # Expression 4 (integer)
$a = 2+2            # Expression $a = 4 (integer)
Write-Output $a     # Expression 4 (integer)
Write-Output $a/2   # Argument "4/2" (string)
Write-Output ($a/2) # Argument 2 (integer)
Write-Output !1     # Argument "!1" (string)
Write-Output (!1)   # expression False (Boolean)

#! Parsing-Problem:
icacls X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

#! Lösung 1
icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F   

#! Lösung 2: Stop das parsing nach --% =>
icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F

#
# Weitere wichtige Schreibweisen:
#

$true                                            # Boolean
$false                                           # Boolean
10                                               # Integer
10.5                                             # Double
'PowerShell-Kultur $PSCulture'                   # String ' => Variablen werden NICHT aufgelöst
"PowerShell-Kultur $PSCulture"                   # String " => Variablen werden aufgelöst
"Köln", "München", "Berlin", "Stuttgart"         # Array , => Trennt Array-Elemente
(Get-Service)[8]                                 # 9. Array-Element [ ]
(Test-NetConnection 192.168.50.10).PingSucceeded # Ausdruck-Auswerten () zzgl. Eigenschaft des Objektes
(Get-Process -Name notepad).Kill()               # Aufruf von Methoden
Get-Process ; Get-Service                        # Abschluss einer Befehlskette mit ;
[datetime]"2016-12-31"                           # DateTime [typenname]Objekt => Konvertierung
[DateTime]::Today                                # :: Ruft STATISCHE Member eines Types ab

#endregion

#region TERMINOLOGIE: Alias

Get-ChildItem # Default-Aliase sind ls, dir und gci

#? Übersicht ALLER Aliase
Get-Alias

#? ls ist ein Alias für?
Get-Alias -Name ls

#? Gibt es ein Alias für Get-ChildItem?
Get-Alias -Definition Get-ChildItem

#! Console => Alias nutzen
#! PS-Skripte => Alias NICHT nutzen (bzgl. Lesbarkeit, Änderbarkeit)
 
#endregion

#region TERMINOLOGIE: Pipelining

Get-Service | Sort-Object -Property Name | ConvertTo-Html -Property Name, Status, StartType | Set-Content -Path c:\temp\OverviewServices.html 
Start-Process -FilePath C:\temp\OverviewServices.html

#endregion

#region Escape characters, Delimiters and Quotes

http://ss64.com/ps/syntax-esc.html

"Hallo `n Köln!"
"`n`r `n `t"

#endregion

#region PowerShell Console

# -> Mehrzeilig schreiben = Ausdrücke in Klammern "()" setzen
    
# Tastaturbefehle (<= 4.0)
# TAB ...................... Befehlszeilenergänzung
# STRG + C ................. Abbruch
# PFEIL-OBEN/-UNTEN ........ Blättert im Befehls-Cache
# MARKIERUNG + ENTER ....... Kopiert die Markierung in die Zwischenablage
# RECHTS-KLICK ............. Fügt dir Zwischenablage ein

# Tastaturbefehle (>= 5.0)
# STRG + C ................. Kopieren
# STRG + V ................. Einfügen

Get-History
$MaximumHistoryCount = 50 # Default: 4096

#region Konsolen-Ein-/Ausgabe protokollieren

Start-Transcript -Path C:\Temp\PowerShellConsole.log
Get-Process | Stop-Process -Force -WhatIf
Remove-Item c:\ -Recurse -Force -WhatIf
Stop-Transcript
Get-Content -Path C:\Temp\PowerShellConsole.log

#endregion

#region max. Anzeige von Enumerationen (-1 ohne Grenze, Default: 4)
Get-Command -Name ForEach-Object | Select-Object -First 1 | Format-List -Property * # Siehe Eigenschaft: Parameters
$FormatEnumerationLimit
$FormatEnumerationLimit = -1
Get-Service -Name RpcSs | Format-List -Property Name, DependentServices
#endregion

#endregion