Last active
April 9, 2023 21:17
-
-
Save schittli/9134de0b34ab18229b2fedf8f9fac2ab to your computer and use it in GitHub Desktop.
LibGist: Use-Gists.ps1 #PowerShell #LibGist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Funktionen, um LibGists zu nützen: | |
# • LibGist-Update-GistFiles | |
# Aktualisiert die LibGists alle (per default) 30 Tage | |
# | |
# • LibGist-Load-Gists | |
# Bindet die LibGists in ein Script ein | |
# | |
# • LibGist-List-Files | |
# Listet die verfügbaren LibGist Files | |
# | |
# • LibGist-Download-Files | |
# Lädt alle verfügbaren LibGist Files herunter | |
# | |
# | |
# | |
# Aktualisiert die Gists im gleichen Verzeichnis von LibGist-Use-Gists.ps1 | |
# Arbeitet mit dem gleichnamigen json-File | |
# um die Aktualisierung nicht bei jedem ScriptStart zu steuern | |
# | |
# ℹ Getting started | |
# LibGist files in Scripts einbinden | |
# Download der verfügbaren LibGist Files | |
# c:\Scripts\PowerShell\-Gist\LibGist-Get-Gist.ps1 -DownloadFile -Verbose -ZielDir .\LibGistFiles | |
# Die LibGists Files löschen, die nicht benötigt werden | |
# Zwingend benötigt werden | |
# LibGist-Get-Gist.ps1 | |
# LibGist-Update-GistFiles.ps1 | |
# Die LibGist Files ins Verzeichnis vom Script kopieren, | |
# das sie nützen will | |
# LibGist ins Script einbinden | |
# | |
# | |
# | |
# | |
# | |
# Ex | |
# Alle Files gem. Zeitplan (default alle 30 Tage) auf Updates prüfen | |
# C:\Scripts\PowerShell\-Gist\LibGist-Update-GistFiles.ps1 -Now | |
# | |
# Alle Files auf Updates prüfen | |
# C:\Scripts\PowerShell\-Gist\LibGist-Update-GistFiles.ps1 -Now | |
# | |
# Die vorhandenen Gist-Files auflisten | |
# C:\Scripts\PowerShell\-Gist\LibGist-Update-GistFiles.ps1 -ListFiles | |
# | |
# Files herunterladen | |
# C:\Scripts\PowerShell\-Gist\LibGist-Update-GistFiles.ps1 -DownloadFiles file1.txt | |
# | |
# | |
# 001, 220126, tom-agplv3@jig.ch | |
# 002, 220127, tom-agplv3@jig.ch | |
# Json Config neu mit: UpdateScheduleDays | |
# 003, 220127, tom-agplv3@jig.ch | |
# Neu mit Funktionen | |
# • LibGist-Get-UseGists-Cfg | |
# • LibGist-List-Files | |
# • LibGist-Download-Files | |
# • LibGist-Update-GistFiles | |
# 004, 220128 | |
# Fixed: Load-Json | |
# 005, 220129 | |
# LibGist-Update-GistFiles -Now aktiviert Verbose | |
# $LibGistVersion_LibGist_Use_Gists_ps1 | |
# Zeigt bei Verbose die geladenen Libversionen an | |
# LibGist-Get-UseGists-Cfg | |
# Liefert neu das ZielDir und GistsFilesPattern separat | |
# | |
# Für Tests in der Shell müssen wir den $MyInvocation Pfad speichern, um ihn später wieder zu haben | |
$Script:LibGistUseGistsPath = $MyInvocation.MyCommand.Path | |
### Config | |
$LibGistVersion_LibGist_Use_Gists_ps1 = '005' | |
# Erzeugt die Config für dieses Script | |
# $ZielDir | |
# Optional kann ein Zielverzeichnis definiert werden, in dem das Update / Laden durchgeführt wird | |
# Default: ScriptDir | |
Function LibGist-Get-UseGists-Cfg() { | |
[CmdletBinding()] | |
Param ( | |
[String]$ZielDir, | |
[String]$GitHubUserName = 'schittli' | |
) | |
If ([String]::IsNullOrWhiteSpace($MyInvocation.MyCommand.Path)) { | |
$ThisLibGistUseGistsPath = $Script:LibGistUseGistsPath | |
} Else { | |
$ThisLibGistUseGistsPath = $MyInvocation.MyCommand.Path | |
} | |
$ScriptDir = [IO.Path]::GetDirectoryName($ThisLibGistUseGistsPath) | |
$ScriptName = [IO.Path]::GetFileName($ThisLibGistUseGistsPath) | |
If ([String]::IsNullOrWhiteSpace($MyInvocation.MyCommand.Path)) { | |
$ThisLibGistUseGistsPath = $Script:LibGistUseGistsPath | |
} Else { | |
$ThisLibGistUseGistsPath = $MyInvocation.MyCommand.Path | |
} | |
If ([String]::IsNullOrEmpty($ZielDir)) { | |
$ZielDir = $ScriptDir | |
} | |
$GistsUrl_ListPublicGists = "https://api.github.com/users/$GitHubUserName/gists" | |
$LibGistGetGist_ps1 = 'LibGist-Get-Gist.ps1' | |
$GistsFilesPattern = 'LibGist-*.ps1' | |
$ScriptNameWithoutExtension = [IO.Path]::GetFileNameWithoutExtension($ThisLibGistUseGistsPath) | |
$StateJsonFileName = { Join-Path $ZielDir ("{0}.json" -f $ScriptNameWithoutExtension) } | |
$StateJsonFileName = Invoke-Command $StateJsonFileName | |
$LibGistGetGist_ps1 = Join-Path $ZielDir $LibGistGetGist_ps1 | |
Return [PSCustomObject][Ordered]@{ | |
GistsUrl_ListPublicGists = $GistsUrl_ListPublicGists | |
LibGistGetGist_ps1 = $LibGistGetGist_ps1 | |
ZielDir = $ZielDir | |
GistsFilesPattern = $GistsFilesPattern | |
GistsFilesDirAndPattern = (Join-Path $ZielDir $GistsFilesPattern) | |
ScriptDir = $ScriptDir | |
ScriptName = $ScriptName | |
ScriptNameWithoutExtension = $ScriptNameWithoutExtension | |
StateJsonFileName = $StateJsonFileName | |
} | |
} | |
# Ein schnelles Ping | |
# 220127 | |
Function Test-Connection-Fast { | |
<# | |
.DESCRIPTION | |
Test-ComputerConnection sends a ping to the specified computer or IP Address specified in the ComputerName parameter. Leverages the System.Net object for ping | |
and measures out multiple seconds faster than Test-Connection -Count 1 -Quiet. | |
.PARAMETER ComputerName | |
The name or IP Address of the computer to ping. | |
.EXAMPLE | |
Test-ComputerConnection -ComputerName "THATPC" | |
Tests if THATPC is online and returns a custom object to the pipeline. | |
.EXAMPLE | |
$MachineState = Import-CSV .\computers.csv | Test-ComputerConnection -Verbose | |
Test each computer listed under a header of ComputerName, MachineName, CN, or Device Name in computers.csv and | |
and stores the results in the $MachineState variable. | |
.NOTES | |
001, 220127 | |
#> | |
[CmdletBinding()] | |
Param ( | |
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName)] | |
[Alias('CN', 'MachineName', 'Device Name')] | |
[String]$ComputerName, | |
[Int]$TimeoutMs = 500, | |
[Int]$NoOfPings = 5, | |
# Versucht stilldie Pings und bricht bei Erfolg ab | |
[Switch]$TestForSuccess, | |
# Maximum number of times the ICMP echo message can be forwarded before reaching its destination. | |
# Results in: TtlExpired | |
# Range is 1-255. Default is 64 | |
[Int]$TTL = 64, | |
# Buffer used with this command. Default 32 | |
[Int]$Buffersize = 32, | |
# Wenn true und das Paket ist für einen Router oder gateway zum Host | |
# grösser als die MTU: Status: PacketTooBig | |
[Switch]$DontFragment = $false, | |
[Switch]$PassThru | |
) | |
Begin { | |
$options = New-Object System.Net.Networkinformation.PingOptions | |
$options.TTL = $TTL | |
$options.DontFragment = $DontFragment | |
$buffer=([System.Text.Encoding]::ASCII).getbytes('a' * $Buffersize) | |
$ping = New-Object System.Net.NetworkInformation.Ping | |
# mind. 1 Ping | |
$NoOfPings = [Math]::Max($NoOfPings, 1) | |
$DestinationReachedOnce = $False | |
$ResPing = @() | |
} | |
Process { | |
For ($Cnt = 0; $Cnt -lt $NoOfPings; $Cnt++) { | |
Try { | |
$reply = $ping.Send($ComputerName, $TimeoutMs, $buffer, $options) | |
} Catch { | |
$ErrorMessage = $_.Exception.Message | |
Write-Host ($_ | Out-String) | |
$Res = [PSCustomObject][Ordered]@{ | |
Message = ($_.ToString()) | |
ComputerName = $ComputerName | |
Success = $False | |
Timeout = $True | |
Status = $ErrorMessage | |
} | |
} | |
If ($reply.status -eq 'Success') { | |
$Res = @{ | |
ComputerName = $ComputerName | |
Success = $True | |
Timeout = $False | |
Status = $reply.status | |
} | |
} Else { | |
$Res = [PSCustomObject][Ordered]@{ | |
ComputerName = $ComputerName | |
Success = $False | |
Timeout = $True | |
Status = $reply.status | |
} | |
} | |
If ($Res.Success) { $DestinationReachedOnce = $True } | |
If ($TestForSuccess) { | |
# Die Resultate sammeln | |
$ResPing +=$Res | |
# Bei Erfolg stoppen | |
If ($DestinationReachedOnce) { | |
If ($PassThru) { | |
Return $ResPing | |
} Else { | |
Return $True | |
} | |
} | |
} Else { | |
If ($PassThru) { | |
$Res | |
} Else { | |
$Res.Success | |
} | |
} | |
} | |
If ($TestForSuccess) { | |
If ($PassThru) { | |
Return $ResPing | |
} Else { | |
Return $DestinationReachedOnce | |
} | |
} | |
} | |
End{} | |
} | |
Function Test-Host-Reachable([URI]$Uri) { | |
Test-Connection-Fast $Uri.Host -TimeoutMs 500 -TestForSuccess -NoOfPings 3 | |
} | |
# Listet die verfügbaren LibGist Files | |
Function LibGist-List-Files { | |
[CmdletBinding()] | |
Param ( | |
[String]$ZielDir | |
) | |
## Config | |
$GistsCfg = LibGist-Get-UseGists-Cfg -ZielDir $ZielDir | |
# Prüfen, ob Github erreichbar ist | |
If (!(Test-Host-Reachable ([URI]$GistsCfg.GistsUrl_ListPublicGists))) { | |
Write-Host "Host nicht erreichbar: $(([URI]$GistsCfg.GistsUrl_ListPublicGists).Host)" | |
Return | |
} | |
## Main | |
$SplatArgs = @{ ListPublicGistsFiles = $True } | |
If ($VerbosePreference) { $SplatArgs += @{ Verbose = $True} } | |
$GistData = & $GistsCfg.LibGistGetGist_ps1 @SplatArgs | |
Return $GistData | select Description, ` | |
@{ Name='FileNames'; Ex={ $_.Files | Select -ExpandProperty filename } } | |
} | |
# Lädt alle verfügbaren LibGist Files herunter | |
Function LibGist-Download-Files { | |
[CmdletBinding()] | |
Param ( | |
[String]$ZielDir, | |
[String[]]$FileNames, | |
# Lädt zwingend alle Files wieder herunter | |
[Switch]$Force | |
) | |
## Config | |
$GistsCfg = LibGist-Get-UseGists-Cfg -ZielDir $ZielDir | |
# Prüfen, ob Github erreichbar ist | |
If (!(Test-Host-Reachable ([URI]$GistsCfg.GistsUrl_ListPublicGists))) { | |
Write-Host "Host nicht erreichbar: $(([URI]$GistsCfg.GistsUrl_ListPublicGists).Host)" | |
Return | |
} | |
## Main | |
$SplatArgs = @{ | |
DownloadFile = $True | |
FileNames = $FileNames | |
ZielDir = $GistsCfg.ScriptDir | |
Verbose = $Force | |
} | |
Return & $GistsCfg.LibGistGetGist_ps1 @SplatArgs | |
} | |
# Aktualisiert die lokal vorhandenen LibGist- Files | |
# Die Aktualisierung erfolgt nur alle per Default 30 Tage (siehe .json) | |
# Returns $true if files were updated | |
Function LibGist-Update-GistFiles { | |
[CmdletBinding()] | |
[OutputType([Boolean])] | |
Param ( | |
[String]$ZielDir, | |
# Startet das Update | |
[Switch]$Now, | |
# Lädt zwingend alle Fileswieder herunter | |
[Switch]$Force | |
) | |
Try { | |
$VerbosePreferenceBackup = $VerbosePreference | |
# Allenfalls Verbose aktivieren | |
If ($Now) { $VerbosePreference = Continue } | |
## Config | |
$GistsCfg = LibGist-Get-UseGists-Cfg -ZielDir $ZielDir | |
# Prüfen, ob Github erreichbar ist | |
If (!(Test-Host-Reachable ([URI]$GistsCfg.GistsUrl_ListPublicGists))) { | |
Write-Host "Host nicht erreichbar: $(([URI]$GistsCfg.GistsUrl_ListPublicGists).Host)" | |
Return $False | |
} | |
# Delayed expansion of variables String | |
# Alias: Expand-String | |
Function Invoke-String($str) { | |
$escapedString = $str -replace '"', '`"' | |
Invoke-Expression "Write-Output `"$escapedString`"" | |
} | |
Function Load-Json($JsonFileName) { | |
$Json = Get-Content -LiteralPath $JsonFileName -Encoding utf8 -ErrorAction SilentlyContinue | ConvertFrom-Json | |
# Default initialisieren | |
If ($null -eq $Json) { | |
[PSCustomObject][Ordered]@{ | |
LastUpdated = [DateTime]::MinValue | |
UpdateScheduleDays = 30 | |
} | |
} Else { | |
# Korrektur der DateTime | |
Try { | |
If ([String]::IsNullOrWhiteSpace($Json.LastUpdated.Value)) { | |
[DateTime]$LastUpdated = $Json.LastUpdated | |
} Else { | |
[DateTime]$LastUpdated = $Json.LastUpdated.Value | |
} | |
} Catch { | |
[DateTime]$LastUpdated = [datetime]::MinValue | |
} | |
$Json.LastUpdated = $LastUpdated | |
$Json | |
} | |
} | |
Function Save-Json($Data, $JsonFileName) { | |
$Data | ConvertTo-Json | Out-File -LiteralPath $JsonFileName -Encoding utf8 | |
} | |
## Prepare | |
# Das Status-File laden / initialisieren | |
$StateJson = Load-Json $GistsCfg.StateJsonFileName | |
## Main | |
# Müssen wir updaten? | |
If ((!$Now) -and ($StateJson.LastUpdated + (New-TimeSpan -Days $StateJson.UpdateScheduleDays)) -gt (Get-Date)) { | |
Write-Verbose "Updatezeitpunkt erst am: $($StateJson.LastUpdated + (New-TimeSpan -Days $StateJson.UpdateScheduleDays))" | |
Return $False | |
} | |
## Die Files aktualisieren | |
# Alle LibGist-* Files holen | |
$LocalGistLibFileNames = Get-ChildItem $GistsCfg.GistsFilesDirAndPattern | Select -ExpandProperty Name | |
# Allenfalls die LibGist-* Files aktualisieren | |
Write-Verbose 'Allenfalls die LibGist-* Files aktualisieren' | |
$SplatArgs = @{ | |
DownloadFile = $True | |
FileNames = $LocalGistLibFileNames | |
ZielDir = $GistsCfg.ScriptDir | |
} | |
If ($Force) { $SplatArgs += @{ Force = $True} } | |
If ($VerbosePreference) { $SplatArgs += @{ Verbose = $True} } | |
$ResUpdate = & $GistsCfg.LibGistGetGist_ps1 @SplatArgs | |
# Die Config aktualisieren | |
$StateJson.LastUpdated = Get-Date | |
Save-Json $StateJson $GistsCfg.StateJsonFileName | |
Write-Verbose 'done.' | |
Return $ResUpdate | |
} Finally { | |
$VerbosePreference = $VerbosePreferenceBackup | |
} | |
} | |
# Bindet die LibGists in ein Script ein | |
Function LibGist-Load-Gists() { | |
[CmdletBinding()] | |
Param ( | |
[String]$ZielDir | |
) | |
## Config | |
$GistsCfg = LibGist-Get-UseGists-Cfg -ZielDir $ZielDir | |
# Diese LibGists Scripts werden mit LibGist-Load-Gists nicht in andere Scripts eingebunden | |
$LibGistsBlacklist = @( [IO.Path]::GetFileName($GistsCfg.LibGistGetGist_ps1), ` | |
[IO.Path]::GetFileName($GistsCfg.ScriptName) ) | |
## Main | |
Get-ChildItem $GistsCfg.GistsFilesDirAndPattern | ? { $LibGistsBlacklist -notcontains $_.Name } | % { | |
Write-Verbose "Lade: $_.FullName" | |
. $_.FullName | |
} | |
## Allenfalls die geladenen Versionsinformationen anzeigen | |
# 'SilentlyContinue' | |
If ($VerbosePreference -eq 'Continue') { | |
Get-Variable -Name '$LibGistVersion_*' | % { | |
Write-Verbose ("{0}: {1}" -f $_.Name, $_.Value) | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment