diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..45754bd --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.test/dist/ diff --git a/.test/dist/.gitkeep b/.test/dist/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/settings.json b/.vscode/settings.json index d2ab49a..1a5e063 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,13 +1,15 @@ { - "editor.fontSize": 18, - "workbench.colorTheme": "PowerShell ISE", - "workbench.colorCustomizations": { - "editor.selectionBackground": "#99c8ef96", - "editor.selectionHighlightBackground": "#99C9EF", - "editor.lineHighlightBackground": "#ffffff" - }, - "files.defaultLanguage": "powershell", - "files.associations": { - "*.wsb": "xml" - } + // "editor.fontFamily": "Cascadia Code, jetbrains mono, 'Courier New', monospace", // fallback fonts + "editor.fontSize": 18, + "workbench.colorTheme": "Default Dark Modern", + "workbench.colorCustomizations": { + "editor.lineHighlightBackground": "#202020", + "editor.selectionHighlightBackground": "#141414", + "editor.selectionHighlightBorder": "#b3ff00", + "editor.background": "#0A0A0A" + }, + "files.defaultLanguage": "powershell", + "files.associations": { + "*.wsb": "xml" + } } \ No newline at end of file diff --git a/azure/crate-azure-vm.ps1 b/azure/crate-azure-vm.ps1 new file mode 100644 index 0000000..ea5f8a4 --- /dev/null +++ b/azure/crate-azure-vm.ps1 @@ -0,0 +1,71 @@ +# Azure VM Creation Script - Debian 11 +# This script creates a Debian 11 VM in Azure with a predefined network security group allowing SSH access. +# Prerequisites: +# - Azure CLI installed and logged in (`az login`) +# - A resource group named "Playground" with a network security group "ssh-common-ngs" allowing SSH on port 22. + +$SUBSCRIPTION_ID = '7f796072-6602-418a-8ba9-92ebc9a4797d' +$VM_NAME = 'vmDebian11' +$USER = 'alan' +$PASSWORD = 'F897cab3c9f1475d8a7ff96d549358f2.#1A' +$LOC = 'polandcentral' # `az account list-locations -o table` +$NGS = "/subscriptions/$SUBSCRIPTION_ID/resourcegroups/Playground/providers/Microsoft.Network/networkSecurityGroups/ssh-common-ngs" # Pre-created NSG with SSH allowed on port 22. +$RG = "playground-azure-vm-rg-001" + +az account set --subscription $SUBSCRIPTION_ID + +Write-Host "Deleting old resource group" -ForegroundColor Magenta +Start-Job -ScriptBlock { + az group delete -n "playground-azure-vm-rg-000" -y +} | Out-Null + +Write-Host "Creating resource group: $RG" -ForegroundColor Green +az group create -n $RG -l $LOC | Out-Null + +Write-Host "Creating VNet and Public IP in parallel" -ForegroundColor Green +$vnetJob = Start-Job { + az network vnet create ` + -g $using:RG ` + -n "$using:VM_NAME-vnet" ` + --address-prefix 10.0.0.0/16 ` + --subnet-name "$using:VM_NAME-subnet" ` + --subnet-prefix 10.0.0.0/24 | Out-Null +} + +$ipJob = Start-Job { + az network public-ip create ` + -g $using:RG ` + -n "$using:VM_NAME-pip" ` + --sku Standard ` + --allocation-method Static | Out-Null +} + +Wait-Job $vnetJob, $ipJob | Receive-Job + +Write-Host "Creating NIC" -ForegroundColor Green +az network nic create ` + -g $RG ` + -n "$VM_NAME-nic" ` + --vnet-name "$VM_NAME-vnet" ` + --subnet "$VM_NAME-subnet" ` + --public-ip-address "$VM_NAME-pip" ` + --network-security-group $NGS | Out-Null + +Write-Host "Creating VM" -ForegroundColor Green +az vm create ` + -g $RG ` + -n $VM_NAME ` + --nics "$VM_NAME-nic" ` + --image Debian11 ` + --admin-username $USER ` + --admin-password $PASSWORD ` + --size Standard_B1ms | Out-Null + +Write-Host "Done. You can connect to the VM using:" -ForegroundColor Green +$publicIP = az network public-ip show ` + -g $RG ` + -n "$VM_NAME-pip" ` + --query "ipAddress" ` + -o tsv + +ssh $USER@$publicIP -o StrictHostKeyChecking=no user@$publicIP \ No newline at end of file diff --git a/choco/choco upgrade update all and hibernate.bat b/choco/choco upgrade update all and hibernate.bat new file mode 100644 index 0000000..815444f --- /dev/null +++ b/choco/choco upgrade update all and hibernate.bat @@ -0,0 +1,3 @@ +choco upgrade all -y +%windir%\system32\rundll32.exe powrprof.dll,SetSuspendState +pause \ No newline at end of file diff --git a/debian/gen-cpu-load.sh b/debian/gen-cpu-load.sh new file mode 100644 index 0000000..4c8645f --- /dev/null +++ b/debian/gen-cpu-load.sh @@ -0,0 +1,3 @@ +yes > /dev/null & +sleep 50 +kill $! diff --git a/debian/install-docker.sh b/debian/install-docker.sh new file mode 100644 index 0000000..4c2fc6a --- /dev/null +++ b/debian/install-docker.sh @@ -0,0 +1,17 @@ +# Add Docker's official GPG key: +sudo apt-get update +sudo apt-get install ca-certificates curl +sudo install -m 0755 -d /etc/apt/keyrings +sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc +sudo chmod a+r /etc/apt/keyrings/docker.asc + +# Add the repository to Apt sources: +ARCH=$(dpkg --print-architecture) +CODENAME=$(source /etc/os-release && echo "$VERSION_CODENAME") +REPO_URL="deb [arch=$ARCH signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $CODENAME stable" +echo "$REPO_URL" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + +sudo apt-get update + +# Install latest version +sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin \ No newline at end of file diff --git a/debian/tmux.md b/debian/tmux.md new file mode 100644 index 0000000..0590dbb --- /dev/null +++ b/debian/tmux.md @@ -0,0 +1,53 @@ +# Cheat Sheet: tmux + +### ๐Ÿ† **Basic Commands:** + +```bash +tmux new -s abc # Create a new session named "abc" +tmux ls # List all sessions +tmux attach -t abc # Attach to a session +tmux detach # Detach (Ctrl + B, then D also works) +tmux switch-client -t abc # switch to the other session without nesting +tmux kill-session -t abc # Kill a session +tmux kill-server # Kill all sessions +``` + +--- + +### โš™๏ธ **Pane Management:** + +| Action | Shortcut | +| ----------------------------------- | ---------------------- | +| **Split vertically (left/right)** | `Ctrl + B` โ†’ `%` | +| **Split horizontally (top/bottom)** | `Ctrl + B` โ†’ `"` | +| **Switch panes** | `Ctrl + B` โ†’ Arrow key | +| **Close current pane** | `Ctrl + D` | +| **Resize pane** | `Ctrl + B` โ†’ `:` then: | +| Shrink down | `resize-pane -D 5` | +| Shrink up | `resize-pane -U 5` | +| Shrink left | `resize-pane -L 5` | +| Shrink right | `resize-pane -R 5` | + +--- + +### ๐ŸŒ **Window (Tab) Management:** + +| Action | Shortcut | +| -------------------- | ---------------- | +| **List windows** | `Ctrl + B` โ†’ `W` | +| **Rename window** | `Ctrl + B` โ†’ `,` | +| **New window (tab)** | `Ctrl + B` โ†’ `C` | +| **Next window** | `Ctrl + B` โ†’ `N` | +| **Previous window** | `Ctrl + B` โ†’ `P` | +| **Close window** | `Ctrl + B` โ†’ `&` | + +--- + +### ๐Ÿ“Œ **Session Management:** + +| Action | Shortcut | +| ----------------------- | ------------------------------------- | +| **Detach from session** | `Ctrl + B` โ†’ `D` | +| **Switch sessions** | `Ctrl + B` โ†’ `S` | +| **Rename session** | `Ctrl + B` โ†’ `$` | +| **Kill session** | `Ctrl + B` โ†’ `:` then: `kill-session` | diff --git a/development/.net/dotnet-publish.ps1 b/development/.net/dotnet-publish.ps1 new file mode 100644 index 0000000..b79516d --- /dev/null +++ b/development/.net/dotnet-publish.ps1 @@ -0,0 +1,3 @@ +dotnet publish -r win-x64 --self-contained -p:PublishSingleFile=true -c Release -o ./publish/win +dotnet publish -r linux-x64 --self-contained -p:PublishSingleFile=true -c Release -o ./publish/linux +dotnet publish -r osx-x64 --self-contained -p:PublishSingleFile=true -c Release -o ./publish/osx \ No newline at end of file diff --git a/development/ci/get-nuget.ps1 b/development/ci/get-nuget.ps1 new file mode 100644 index 0000000..1666945 --- /dev/null +++ b/development/ci/get-nuget.ps1 @@ -0,0 +1,3 @@ +$nugetVersion = "6.7.0" # Change to your required version +$nugetUrl = "https://dist.nuget.org/win-x86-commandline/v$nugetVersion/nuget.exe" +Invoke-WebRequest -Uri $nugetUrl -OutFile "nuget.exe" \ No newline at end of file diff --git a/development/environment-variables.ps1 b/development/environment-variables.ps1 new file mode 100644 index 0000000..47aeb99 --- /dev/null +++ b/development/environment-variables.ps1 @@ -0,0 +1,23 @@ +# Environment Variable Lifetimes + +# 1. Session ($env:VARIABLE) +$env:MY_VAR = "value1" +Write-Host $env:MY_VAR + +# 1.1. Environment variable with dynamic key +$key = "MY_VAR" +Set-Item "env:$key" "value2" + +# 2. Process-Level Inheritance +# when you set an environment variable in PowerShell, +# it is inherited by child processes (like dotnet run, git, or other spawned applications). + +# 3. Permanent Environment Variables (Registry) +[System.Environment]::SetEnvironmentVariable("MY_VAR", "value1", "User") +Write-Host $env:MY_VAR + +# 4. Environment Variables in GitHubs Actions +# Environment variables set during one step are not automatically available in subsequent steps in GitHub Actions. +# To persist environment variables between steps, you need to explicitly use the GITHUB_ENV file. +$value = "value1" +echo "$key=$value" >> $env:GITHUB_ENV \ No newline at end of file diff --git a/development/ps/generic.ps1 b/development/ps/generic.ps1 new file mode 100644 index 0000000..a7d2dfa --- /dev/null +++ b/development/ps/generic.ps1 @@ -0,0 +1,12 @@ +# Workaround to call to a generic method OfType() in PowerShell, when PowerShell cannot figure out from the context + +# Method 1 - using OfType method +[System.Linq.Enumerable]::OfType[int](@(1, 2, 'a')) + +# Method 2 - using reflection +$method = [System.Linq.Enumerable].GetMethod('OfType') +$genericMethod = $method.MakeGenericMethod([int]) +$genericMethod.Invoke($null, @(, @(1, 2, 'a'))) + +# Example of using Distinct method +[System.Linq.Enumerable]::Distinct([int[]]@(1, 2, 3, 1, 2)) \ No newline at end of file diff --git a/development/ps/reflection.ps1 b/development/ps/reflection.ps1 new file mode 100644 index 0000000..02b3afe --- /dev/null +++ b/development/ps/reflection.ps1 @@ -0,0 +1,25 @@ +# constructor +$constructorInfo = [System.IO.FileInfo].GetConstructor([string].AsType()) +$constructorInfo = [System.IO.FileInfo].GetConstructor("public,instance", $types) +$constructorInfo.Invoke('C:\Windows') + +# private field +$obj = [System.IO.FileInfo]::new('C:\Windows') +$field = [System.IO.FileInfo].GetField("_name", "nonpublic,instance") +# longer version +$field = [System.IO.FileInfo].GetField("_name", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance) +$field.GetValue($obj) + +# private method - static +$obj = $null +$privMethod = [System.DateTime].GetMember("DateToTicks", "nonpublic,static") +$privMethod.Invoke($obj, @(2023, 10, 10)) + +# private method - instance +$obj = [System.DateTime]::Now +$privMethod = [System.DateTime].GetMember("GetDatePart", "nonpublic,instance") +$privMethod.Invoke($obj, @(0)) + +# private method - args requirements +$privMethod = [System.DateTime].GetMethod("DateToTicks", "nonpublic,static", $null, @([int], [int], [int]), @()) +$privMethod.Invoke($obj, @(2023, 10, 10)) \ No newline at end of file diff --git a/dsc/README.md b/dsc/README.md new file mode 100644 index 0000000..f326fc4 --- /dev/null +++ b/dsc/README.md @@ -0,0 +1,3 @@ +# Desired State Configuration 3.0 + +- [ExtensionManifestV2Availability.dsc](https://developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline) - enable support for chrome extensions V2 \ No newline at end of file diff --git a/dsc/run.ps1 b/dsc/run.ps1 new file mode 100644 index 0000000..c188cce --- /dev/null +++ b/dsc/run.ps1 @@ -0,0 +1,32 @@ +$validation = dsc config test -f .\validate.dsc.yml -o json | ConvertFrom-Json +foreach ($r in $validation.results) { + if ($r.result.inDesiredState -eq $false) { + throw "[FAIL] $($r.name) [$($r.type)]" + } +} + +Get-ChildItem .\steps -Filter '*.dsc.yml' -Recurse | ForEach-Object { + $step = $_.FullName + Write-Host "[INFO] Running step: $step" -ForegroundColor DarkGray + $test = dsc config test -f $step -o json | ConvertFrom-Json + $test.results | % { + if ($_.result.inDesiredState -eq $true) { + Write-Host "[OK] $($_.name) [$($_.type)]" -ForegroundColor Green + } + else { + Write-Host "[APPLY] $($_.name) [$($_.type)]" -ForegroundColor Yellow + } + } + + [bool[]]$states = $test.results.result.inDesiredState + if ( $states.Contains($false)) { + $setResult = dsc config set -f $step -o json | ConvertFrom-Json + if ($LASTEXITCODE -ne 0) { + throw "[FATAL] Couldn't set the desired state for $step" + } + } +} + +if ($LASTEXITCODE -eq 0) { + Write-Host "[PASS] All resources are in desired state" -ForegroundColor Green +} \ No newline at end of file diff --git a/dsc/steps/ExtensionManifestV2Availability.dsc.yml b/dsc/steps/ExtensionManifestV2Availability.dsc.yml new file mode 100644 index 0000000..8b2470b --- /dev/null +++ b/dsc/steps/ExtensionManifestV2Availability.dsc.yml @@ -0,0 +1,9 @@ +$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json +resources: + - name: Manifest V2 Availability + type: Microsoft.Windows/Registry + properties: + keyPath: HKLM\SOFTWARE\Policies\Google\Chrome\ + valueName: ExtensionManifestV2Availability + valueData: + DWord: 2 \ No newline at end of file diff --git a/dsc/validate.dsc.yml b/dsc/validate.dsc.yml new file mode 100644 index 0000000..c1b57aa --- /dev/null +++ b/dsc/validate.dsc.yml @@ -0,0 +1,8 @@ +$schema: https://raw.githubusercontent.com/PowerShell/DSC/main/schemas/2023/08/config/document.json + +resources: + - name: Validate the OS is Windows + type: Microsoft/OSInfo + properties: + family: Windows + diff --git a/excel/convert-xlsx-to-csv.ps1 b/excel/convert-xlsx-to-csv.ps1 index 2da3374..ec00332 100644 --- a/excel/convert-xlsx-to-csv.ps1 +++ b/excel/convert-xlsx-to-csv.ps1 @@ -50,6 +50,6 @@ $wsEmpty.Activate() 1..2 | % { $wsEmpty.Rows(1).Delete() | Out-Null } # save file as csv -$wsEmpty.SaveAs("$scriptPath\..\.test\excel.csv", 6) +$wsEmpty.SaveAs("$scriptPath\..\.test\dist\excel.csv", 6) # close excel application $Excel.Quit() \ No newline at end of file diff --git a/file-processing/split kml.ps1 b/file-processing/split kml.ps1 new file mode 100644 index 0000000..512ea54 --- /dev/null +++ b/file-processing/split kml.ps1 @@ -0,0 +1,27 @@ +$kmlPath = 'C:\big.kml' +$max = 240 +$partsFolder = "$PSScriptRoot\parts" + +[xml]$doc = Get-Content -Path $kmlPath +mkdir $partsFolder -ErrorAction SilentlyContinue | Out-Null +$i = 1 +do { + [xml]$clone = $doc.Clone() + $clone.ChildNodes[0].Encoding = $null + + # remove everything except max number count (i.e 240, 480, 720) + $clone.kml.Document.Folder.Placemark | Select-Object -Skip ($max * $i) | % { + $clone.kml.Document.Folder.RemoveChild($_) | Out-Null + } + + # buffering - selecting last max number count + while ($clone.kml.Document.Folder.Placemark.Count -gt $max) { + $clone.kml.Document.Folder.Placemark | Select-Object -First 1 | % { + $clone.kml.Document.Folder.RemoveChild($_) | Out-Null + } + } + + $clone.Save("$partsFolder\_part2_$($i).kml") + $i++ +} +while ($max * $i -le $doc.kml.Document.Folder.Placemark.Count) \ No newline at end of file diff --git a/filesystem/gzip.ps1 b/filesystem/gzip.ps1 new file mode 100644 index 0000000..d7063b2 --- /dev/null +++ b/filesystem/gzip.ps1 @@ -0,0 +1,33 @@ +function ConvertFrom-Gzip { + Param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [ValidateScript( { (Get-Item $_).Name.EndsWith(".gz") })] + [System.IO.FileInfo] + $InputObject, + + [Parameter(Mandatory = $false)] + [switch] + $RemoveInputFile + ) + Process { + # Create a new file and open a filestream for it + $NewFilename = $InputObject.FullName.Remove($InputObject.FullName.Length - $InputObject.Extension.Length) + $DecompressedFileStream = [System.IO.File]::Create($NewFilename) + + # Open the compressed file and copy the file to the decompressed stream + $CompressedFileStream = $InputObject.OpenRead() + $GZipStream = [System.IO.Compression.GZipStream]::new($CompressedFileStream, [System.IO.Compression.CompressionMode]::Decompress) + $GZipStream.CopyTo($DecompressedFileStream) + + # Cleanup + $DecompressedFileStream.Dispose() + $GZipStream.Dispose() + $CompressedFileStream.Dispose() + $DecompressedFileStream, $GZipStream, $CompressedFileStream = $null + + # Remove the initial file if requested. + if ($PSBoundParameters.ContainsKey('RemoveInputFile')) { + $InputObject.Delete() + } + } +} \ No newline at end of file diff --git a/filesystem/rename-files-lastwritetime.ps1 b/filesystem/rename-files-lastwritetime.ps1 new file mode 100644 index 0000000..68c3790 --- /dev/null +++ b/filesystem/rename-files-lastwritetime.ps1 @@ -0,0 +1,5 @@ +Get-ChildItem "D:\___to backup\" | % { + $date = $_.LastWriteTime.ToString("yyyy-MM-dd") + $name = $_.Name + $_ | Rename-Item -NewName "$date-$name" +} \ No newline at end of file diff --git a/git/add-submodule.ps1 b/git/add-submodule.ps1 new file mode 100644 index 0000000..853cfe8 --- /dev/null +++ b/git/add-submodule.ps1 @@ -0,0 +1,3 @@ +# Add new submodule +git submodule add git://github.com/jquery/jquery.git externals/jquery +git submodule update --init --recursive \ No newline at end of file diff --git a/git/find-large-files.sh b/git/find-large-files.sh new file mode 100644 index 0000000..347b7ca --- /dev/null +++ b/git/find-large-files.sh @@ -0,0 +1,21 @@ +git rev-list --objects --all | + git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | + sed -n 's/^blob //p' | + awk '$2 >= 2^20' | + sort --numeric-sort --key=2 | + cut -c 1-12,41- | + $(command -v gnumfmt || echo numfmt) --field=2 --to=iec-i --suffix=B --padding=7 --round=nearest + +# example output +# 22c19f287836 1.0MiB images/posts/1.gif +# 0e15a02b835a 1.2MiB images/posts/2.gif +# f48d3086bf1d 1.5MiB images/posts/3.gif +# eecf2e1d46a7 1.6MiB images/posts/4.gif +# a267f286e7f2 1.7MiB images/posts/5.gif +# 225cba92676b 3.4MiB images/posts/6.gif + +# to find commits with SHA use +# git log --raw --all --find-object=225cba92676b + +# to find all files with given extension +# git log --all --full-history -- *.gif \ No newline at end of file diff --git a/git/git-snippets.ps1 b/git/git-snippets.ps1 new file mode 100644 index 0000000..168d02b --- /dev/null +++ b/git/git-snippets.ps1 @@ -0,0 +1,2 @@ +# create a new Git branch based on a specific commit SHA +git checkout -b BRANCH_NAME COMMIT_SHA \ No newline at end of file diff --git a/git/github-api.ps1 b/git/github-api.ps1 new file mode 100644 index 0000000..8734b15 --- /dev/null +++ b/git/github-api.ps1 @@ -0,0 +1,14 @@ +Clear-Host +$PersonalAccessToken = "github_pat_[your_personal_access_token]" + +$GitHubApiUrl = "https://api.github.com/user/repos" +# $GitHubApiUrl = "https://api.github.com/orgs/PowerShellLibrary/repos" +# $GitHubApiUrl = "https://api.github.com/repositories" + +$Headers = @{ + Authorization = "token $PersonalAccessToken" + "User-Agent" = "PowerShell" # GitHub API requires a User-Agent header +} + +$response = Invoke-RestMethod -Uri $GitHubApiUrl -Method Get -Headers $Headers +$response diff --git a/git/setup-ssh-for-git.ps1 b/git/setup-ssh-for-git.ps1 new file mode 100644 index 0000000..4e21da6 --- /dev/null +++ b/git/setup-ssh-for-git.ps1 @@ -0,0 +1,34 @@ +# Prerequisites - you need to get SSH key supported by your git hosting service. +# deploy it into: c:\id_rsa + +# generate SSH key +ssh-keygen -t rsa -b 4096 -C "key-comment" # 4096 RSA key (SHA256) +ssh-keygen -t ed25519 -C "key-comment" + +# install choco +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + +# install dependencies +choco install git -y + +# deploy SSH key into keys store +$userName = [Environment]::UserName +Write-Host "Username: $userName" -ForegroundColor Green +Get-Item c:\id_rsa | Copy-Item -Destination "C:\Users\$userName\.ssh\id_rsa" + +# enable ssh service +Get-Service -Name ssh-agent | Set-Service -StartupType Manual +Start-Service ssh-agent + +# register ssh key +ssh-add "C:\Users\$userName\.ssh\id_rsa" + +# register known_hosts +ssh-keyscan bitbucket.org >> "C:\Users\$userName\.ssh\known_hosts" +ssh-keyscan github.com >> "C:\Users\$userName\.ssh\known_hosts" +ssh-keyscan vs-ssh.visualstudio.com >> "C:\Users\$userName\.ssh\known_hosts" + +# test connection to git repositories +ssh -T ssh://alan-null@vs-ssh.visualstudio.com +ssh -T git@bitbucket.org +ssh -T git@github.com \ No newline at end of file diff --git a/git/specify-user.ps1 b/git/specify-user.ps1 new file mode 100644 index 0000000..4bac4be --- /dev/null +++ b/git/specify-user.ps1 @@ -0,0 +1,3 @@ +## Specify user +git config user.name "AuthorExample" +git config user.email "ae@duck.com" \ No newline at end of file diff --git a/git/worktree.ps1 b/git/worktree.ps1 new file mode 100644 index 0000000..fa9e9f4 --- /dev/null +++ b/git/worktree.ps1 @@ -0,0 +1,8 @@ +# list all worktrees +git worktree list + +# add a worktree to folder _branch using branch 'issues/templates_enabled_flag' +git worktree add _branch issues/templates_enabled_flag + +# remove a worktree from folder _branch +git worktree remove _branch diff --git a/good-practices/add-to-array.ps1 b/good-practices/add-to-array.ps1 new file mode 100644 index 0000000..00595cf --- /dev/null +++ b/good-practices/add-to-array.ps1 @@ -0,0 +1,17 @@ +๏ปฟ# Adding to an array with += is much slower: + +$list = @() +Measure-Command { + foreach ($number in $(1..10000)) { + $list += $number + } +} + +# than capturing the output of the loop directly: + +Measure-Command { + $list = foreach ($number in $(1..10000)) { + $number + } +} + diff --git a/good-practices/foreach-object.ps1 b/good-practices/foreach-object.ps1 new file mode 100644 index 0000000..c07fe8d --- /dev/null +++ b/good-practices/foreach-object.ps1 @@ -0,0 +1,9 @@ +# BAD +@(1, 2, 3) | Foreach-Object { + # do stuff +} + +# GOOD - 2x faster +foreach ($i in @(1, 2, 3)) { + # do stuff +} \ No newline at end of file diff --git a/good-practices/return.ps1 b/good-practices/return.ps1 new file mode 100644 index 0000000..aa812fb --- /dev/null +++ b/good-practices/return.ps1 @@ -0,0 +1,64 @@ +Clear-Host +$tmpFile = 'd:\temp\tmp.mp4' + +function Get-Obj { + [byte[]]$payload = [System.IO.File]::ReadAllBytes($tmpFile) + $payload +} + +function Get-Wrapped { + [byte[]]$payload = [System.IO.File]::ReadAllBytes($tmpFile) + @{ wrap = $payload } +} + +function Get-Operator { + [byte[]]$payload = [System.IO.File]::ReadAllBytes($tmpFile) + ,$payload +} + +function Get-WriteOutput { + [byte[]]$payload = [System.IO.File]::ReadAllBytes($tmpFile) + Write-Output $payload -NoEnumerate +} + +Measure-Command { + [byte[]]$out1 = Get-Obj + Write-Host "Size: $($out1.Length)" +} + +Measure-Command { + $out2 = Get-Wrapped + Write-Host "Size: $($out2.wrap.Length)" +} + +Measure-Command { + $out3 = Get-Operator + Write-Host "Size: $($out3.Length)" +} + +Measure-Command { + $out4 = Get-WriteOutput + Write-Host "Size: $($out4.Length)" +} + +# OUTPUT for 6.5 MB file + +##### Get-Obj ##### +# Size: 6 439 243 +# TotalSeconds : 2.4369009 +# TotalMilliseconds : 2436.9009 + +##### Get-Wrapped ##### +# Size: 6 439 243 +# TotalSeconds : 0.0087145 +# TotalMilliseconds : 8.7145 + +##### Get-Operator ##### +# Size: 6 439 243 +# TotalSeconds : 0.025268 +# TotalMilliseconds : 25.268 + +##### Get-WriteOutput ##### +# Size: 6 439 243 +# TotalSeconds : 0.0205171 +# TotalMilliseconds : 20.5171 \ No newline at end of file diff --git a/good-practices/where-object.ps1 b/good-practices/where-object.ps1 new file mode 100644 index 0000000..4a6dd44 --- /dev/null +++ b/good-practices/where-object.ps1 @@ -0,0 +1,11 @@ +# BAD +$array = @(1, 2, 3, 1, 3, 4) | Where-Object { $_ -eq 1 } + +# GOOD - x17 faster +$array = @( + foreach ($i in @(1, 2, 3, 1, 3, 4)) { + if ($i -eq 1) { + $i + } + } +) \ No newline at end of file diff --git a/media/color-inversion.md b/media/color-inversion.md new file mode 100644 index 0000000..927a9ce --- /dev/null +++ b/media/color-inversion.md @@ -0,0 +1,43 @@ +# Color inversion with ffmpeg + +```powershell +ffmpeg -i input.mp4 -vf "negate,hue=h=180,eq=contrast=1.2:saturation=1.1" output.mp4 +``` +## Demo +#### Before + + + + +https://github.com/user-attachments/assets/a6969533-a1f9-4a8f-9203-dd151f4c6aa7 + +#### After + + + + +https://github.com/user-attachments/assets/16785da7-4ed3-48c5-ad3e-b1223987c49e + + +## Explanation +The `-i input.mp4` part specifies the input file. + +The `-vf` flag stands for "video filter," and it is followed by a series of filters applied to the video. + +The filters are: + +- `negate`: This filter inverts the colors of the video, creating a negative effect. +- `hue=h=180`: This filter adjusts the hue of the video by 180 degrees, effectively rotating the color wheel to change the overall color tone. +- `eq=contrast=1.2:saturation=1.1`: This filter adjusts the contrast and saturation of the video. The contrast=1.2 increases the contrast by 20%, making the darks darker and the lights lighter. The saturation=1.1 increases the saturation by 10%, making the colors more vivid. + + + +Combining these filters results in a video with inverted colors, a shifted hue, and enhanced contrast and saturation. The processed video is then saved as output.mp4. + + +*[source: +Rubber Duck Thursdays!](https://www.youtube.com/watch?v=o7b6t6uZJPA)* \ No newline at end of file diff --git a/media/ffmpeg.ps1 b/media/ffmpeg.ps1 index 3e8de0a..898ab7c 100644 --- a/media/ffmpeg.ps1 +++ b/media/ffmpeg.ps1 @@ -1,4 +1,5 @@ # https://ffmpeg.org/ffmpeg.html + # Takes two files (audio, video) and combine them together into mp4 file. # As audio is shorter add offset to the video so it can sync with audio # @@ -19,4 +20,46 @@ ffmpeg -y -itsoffset 0.2 -i v.webm -i a.mp4 -map 0:0 -map 1:0 -c copy oFilename. # -ar rate set audio sampling rate (in Hz) # -ac channels set number of audio channels # -ab bitrate audio bitrate (please use -b:a) -ffmpeg -i "$($_.FullName)" -vn -ar 44100 -ac 2 -b:a 192k "$($_.FullName.Replace('.wav','.mp3'))" \ No newline at end of file +ffmpeg -i "$($_.FullName)" -vn -ar 44100 -ac 2 -b:a 192k "$($_.FullName.Replace('.wav','.mp3'))" + + +# Takes two files (audio, image) and combine them together into mp4 file. +# -loop 1 - loop the input image infinitely (1 - loop, 0 - no loop) +# -i img.jpg - specifies an input file (image) +# -i audio.mp3 - second input file (MP3 audio) +# -c:v libx264 - specifies the video codec +# -c:a aac - specifies the audio codec. aac is a standard codec for MP4 files, offering good quality at lower bitrates. +# -b:a 320k - sets the audio bitrate +# -shortest - this option ensures that the output video will be as long as the shortest input. +# output.mp4 - name of the output video file +ffmpeg -loop 1 -i img.jpg -i audio.mp3 -c:v libx264 -c:a aac -b:a 320k -shortest output.mp4 + + +# Crop video from the top +# This command crops the video by removing 440 pixels from the top, effectively shifting the video down by that amount. +# -i input.mp4 - specifies the input video file +# -vf "crop=iw:ih-440:0:440" - applies a video filter (vf) to crop the video. +# - iw Input width (keeps the full width of the video). +# - ih-440 Input height minus 440 pixels +# - 0 X offset (starts cropping from the left edge). +# - 440 Y offset (starts cropping from 440 pixels down from the top). +# -c:a copy - copies the audio stream without re-encoding it +# output.mp4 - name of the output video file +ffmpeg -i .\input.mp4 -vf "crop=iw:ih-440:0:440" -c:a copy output.mp4 + + +# Inspect media file streams +# ffprobe prints detailed information about the input file, including +# codec, format, bitrate, duration, and stream indexes (video, audio, +# subtitles, etc.). +ffprobe .\input.mp4 + + +# Extract a specific audio stream from a video file to MP3 +# -i input.mp4 - input file containing video and audio streams +# -map 0:2 - select stream index 2 from input 0 +# -c:a libmp3lame - use the LAME MP3 encoder for the audio stream +# -q:a 2 - set variable bitrate (VBR) audio quality level 2 +# (lower is better quality, typical range 0โ€“9) +# out0.mp3 - output MP3 file containing the selected audio stream +ffmpeg -i .\input.mp4 -map 0:2 -c:a libmp3lame -q:a 2 out0.mp3 \ No newline at end of file diff --git a/media/touch-image.ps1 b/media/touch-image.ps1 new file mode 100644 index 0000000..0b94ddc --- /dev/null +++ b/media/touch-image.ps1 @@ -0,0 +1,16 @@ +# Use case: modify media items without changing their visual content + +# Usage: touch all PNG files in the images directory +# Get-ChildItem ".\themes\images\" -Filter *.png -Recurse | ForEach-Object { Touch-File $_.FullName } + + +function Touch-File { + param ([string]$filePath) + + $bytes = [System.IO.File]::ReadAllBytes($filePath) + + # Append a harmless zero byte + $bytes += 0x00 + + [System.IO.File]::WriteAllBytes($filePath, $bytes) +} \ No newline at end of file diff --git a/monitoring/procmon/ProcmonConfigurationObsidian.pmc b/monitoring/procmon/ProcmonConfigurationObsidian.pmc new file mode 100644 index 0000000..26c162d Binary files /dev/null and b/monitoring/procmon/ProcmonConfigurationObsidian.pmc differ diff --git a/monitoring/procmon/procmon-cli.ps1 b/monitoring/procmon/procmon-cli.ps1 new file mode 100644 index 0000000..45b6612 --- /dev/null +++ b/monitoring/procmon/procmon-cli.ps1 @@ -0,0 +1,17 @@ +# This script is used to start Process Monitor in the background with a specific configuration file. +# https://learn.microsoft.com/en-us/sysinternals/downloads/procmon + +procmon.exe /Quiet /Minimized /LoadConfig ProcmonConfigurationObsidian.pmc /Backingfile MonitorLog.pml + +# Configuration File: ProcmonConfigurationObsidian.pmc + +# Monitoring Activities +# Show Process and Thread Activity +# Show Network Activity + +# Capture Events (Drop filtered events) +# Filters +# - โœ…Process Name is Obsidian.exe +# - โŒOperation is NOT Thread Create +# - โŒOperation is NOT Thread Exit +# - โŒOperation is NOT Load Image \ No newline at end of file diff --git a/security/local-https-dev-setup.ps1 b/security/local-https-dev-setup.ps1 new file mode 100644 index 0000000..44c7f1a --- /dev/null +++ b/security/local-https-dev-setup.ps1 @@ -0,0 +1,134 @@ +# --------------------------------------------- +# LOCAL HTTPS SETUP FOR DEVELOPMENT +# --------------------------------------------- + +$ErrorActionPreference = "Stop" + +# --- CONFIG --- +$dns = "localhost" +$port = 19456 +$friendlyName = "Dev Local HTTPS Cert" + +$storeLocationRoot = "LocalMachine" +$storeNameRoot = "Root" + +$storeLocationMy = "LocalMachine" +$storeNameMy = "My" + +$prefix = "https://$dns`:$port/" + +Write-Host "==============================================" +Write-Host " HTTPS Setup for Local Secure Communication " +Write-Host "==============================================" +Write-Host "" + +# Ensure administrator +if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { + + Write-Host "[ERROR] This script must be run as Administrator." -ForegroundColor Red + exit 1 +} + +# --------------------------------------------- +# Step 1 โ€” Check/create certificate +# --------------------------------------------- +Write-Host "๐Ÿ” Checking for existing certificate..." -ForegroundColor Cyan + +$myStore = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeNameMy, $storeLocationMy) +$myStore.Open("ReadWrite") + +$existingCert = $myStore.Certificates | ? { $_.FriendlyName -eq $friendlyName } + +if ($existingCert) { + Write-Host "โœ” Found existing certificate: $friendlyName" -ForegroundColor Green + $cert = $existingCert +} +else { + Write-Host "โณ Creating new self-signed certificate for '$dns'..." -ForegroundColor Yellow + + $cert = New-SelfSignedCertificate ` + -DnsName $dns, "127.0.0.1" ` + -FriendlyName $friendlyName ` + -CertStoreLocation "Cert:\$storeLocationMy\$storeNameMy" ` + -KeyExportPolicy Exportable ` + -NotAfter (Get-Date).AddYears(5) + + Write-Host "โœ” Certificate created successfully!" -ForegroundColor Green +} + +$myStore.Close() + +# --------------------------------------------- +# Step 2 โ€” Ensure certificate is trusted +# --------------------------------------------- +Write-Host "" +Write-Host "๐Ÿ” Ensuring certificate is trusted..." -ForegroundColor Cyan + +$rootStore = New-Object System.Security.Cryptography.X509Certificates.X509Store($storeNameRoot, $storeLocationRoot) +$rootStore.Open("ReadWrite") + +$alreadyInRoot = $rootStore.Certificates | +Where-Object { $_.Thumbprint -eq $cert.Thumbprint } + +if ($alreadyInRoot) { + Write-Host "โœ” Certificate already trusted (Root store)." -ForegroundColor Green +} +else { + Write-Host "โณ Adding certificate to Trusted Root..." -ForegroundColor Yellow + $rootStore.Add($cert) + Write-Host "โœ” Certificate trusted successfully!" -ForegroundColor Green +} + +$rootStore.Close() + +# --------------------------------------------- +# Step 3 โ€” Clean old HTTPS bindings +# --------------------------------------------- +Write-Host "" +Write-Host "๐Ÿงน Cleaning old HTTPS bindings on port $port..." -ForegroundColor Cyan + +try { + netsh http delete sslcert ipport=0.0.0.0:$port | Out-Null + Write-Host "โœ” Old bindings removed." -ForegroundColor Green +} +catch { + Write-Host "โ„น No old bindings found." -ForegroundColor DarkGray +} + +# --------------------------------------------- +# Step 4 โ€” Bind certificate to port +# --------------------------------------------- +Write-Host "" +Write-Host "๐Ÿ”— Binding certificate to port $port..." -ForegroundColor Cyan + +$thumb = $cert.Thumbprint +$appid = [guid]::NewGuid() + +netsh http add sslcert ipport=0.0.0.0:$port certhash=$thumb certstorename=$storeNameMy appid="{$appid}" | Out-Null + +Write-Host "โœ” HTTPS binding added successfully!" -ForegroundColor Green + +# --------------------------------------------- +# Step 5 โ€” Summary +# --------------------------------------------- +Write-Host "" +Write-Host "==============================================" +Write-Host " SETUP COMPLETE ๐ŸŽ‰" +Write-Host "==============================================" +Write-Host "" +Write-Host "๐Ÿ”’ HTTPS is now enabled for your local server." +Write-Host "" +Write-Host "๐Ÿ“œ Details:" +Write-Host " - Hostname: $dns" +Write-Host " - Port: $port" +Write-Host " - Prefix: $prefix" +Write-Host " - Thumbprint: $thumb" +Write-Host " - Cert Name: $friendlyName" +Write-Host "" +Write-Host "๐Ÿงช Test it in your browser:" +Write-Host " $prefix" -ForegroundColor Yellow +Write-Host "" +Write-Host "โœ” Your Chrome extension should now work without certificate errors." +Write-Host "" +Write-Host "==============================================" +Write-Host "" diff --git a/sql/pihole/adlist-unique-domains.sql b/sql/pihole/adlist-unique-domains.sql new file mode 100644 index 0000000..8a8b4f7 --- /dev/null +++ b/sql/pihole/adlist-unique-domains.sql @@ -0,0 +1,25 @@ +-- This SQL query retrieves the number of unique domains and total domains for each adlist from the vw_gravity view. +-- It calculates the uniqueness percentage and orders the results by this percentage in ascending order. + +SELECT + adlist_id, + COUNT(DISTINCT domain) AS unique_domains, + COUNT(domain) AS total_domains, + ROUND(CAST(COUNT(DISTINCT domain) AS FLOAT) / COUNT(domain) * 100, 2) AS uniqueness_percent +FROM + vw_gravity +GROUP BY + adlist_id +ORDER BY + uniqueness_percent ASC; + + +-- Example output: +-- adlist_id unique_domains total_domains uniqueness_percent +-- 7 30873 31461 98.13 +-- 6 42363 42536 99.59 +-- 1 106610 106611 100.0 +-- 2 2194 2194 100.0 +-- 3 162079 162079 100.0 +-- 4 319548 319548 100.0 +-- 5 307383 307383 100.0 \ No newline at end of file diff --git a/sql/pihole/globally-unique-domains.sql b/sql/pihole/globally-unique-domains.sql new file mode 100644 index 0000000..060fe39 --- /dev/null +++ b/sql/pihole/globally-unique-domains.sql @@ -0,0 +1,28 @@ +-- This SQL query calculates the percentage of globally unique domains in each adlist from the vw_gravity view. +-- Run trim-domain.sql before executing this query to ensure that the domain field is clean and trimmed. +SELECT + g1.adlist_id, + COUNT(*) AS total_domains, + SUM(CASE WHEN dup_counts.domain_count = 1 THEN 1 ELSE 0 END) AS globally_unique_domains, + ROUND(SUM(CASE WHEN dup_counts.domain_count = 1 THEN 1.0 ELSE 0 END) / COUNT(*) * 100, 2) AS uniqueness_percent +FROM + vw_gravity g1 +JOIN ( + SELECT domain, COUNT(DISTINCT adlist_id) AS domain_count + FROM vw_gravity + GROUP BY domain +) dup_counts ON g1.domain = dup_counts.domain +GROUP BY + g1.adlist_id +ORDER BY + uniqueness_percent DESC; + +-- Example output: +-- adlist_id total_domains globally_unique_domains uniqueness_percent +-- 4 319548 319548 100.0 +-- 2 2194 2194 100.0 +-- 7 31461 29665 94.29 +-- 1 106611 100485 94.25 +-- 6 42536 38253 89.93 +-- 5 307383 249377 81.13 +-- 3 162079 96220 59.37 \ No newline at end of file diff --git a/sql/pihole/trim-domain.sql b/sql/pihole/trim-domain.sql new file mode 100644 index 0000000..1c66bb1 --- /dev/null +++ b/sql/pihole/trim-domain.sql @@ -0,0 +1,6 @@ +-- Trim leading and trailing characters from the domain field in the gravity table +UPDATE gravity +SET domain = TRIM( + TRIM(SUBSTR(domain, CASE WHEN domain LIKE '||%' THEN 3 ELSE 1 END), '^') + ) +WHERE adlist_id = 26; \ No newline at end of file diff --git a/strings/remove-non-ASCII-characters.ps1 b/strings/remove-non-ASCII-characters.ps1 new file mode 100644 index 0000000..6397047 --- /dev/null +++ b/strings/remove-non-ASCII-characters.ps1 @@ -0,0 +1,2 @@ +$inputString = "ลผรณล‚ฤ‡ gฤ™ล›lฤ… jaลบล„" +[Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes($inputString)) \ No newline at end of file diff --git a/system-maintenance/create-file-snapshot.ps1 b/system-maintenance/create-file-snapshot.ps1 index c809a0b..baeb5f4 100644 --- a/system-maintenance/create-file-snapshot.ps1 +++ b/system-maintenance/create-file-snapshot.ps1 @@ -20,6 +20,9 @@ try { git commit -m "$date" } } +catch{ + Write-Error $_.Exception +} finally { Set-Location $current } diff --git a/system-setup/disable-connected-devices-platform-services.ps1 b/system-setup/disable-connected-devices-platform-services.ps1 new file mode 100644 index 0000000..f9d5144 --- /dev/null +++ b/system-setup/disable-connected-devices-platform-services.ps1 @@ -0,0 +1,51 @@ +# Potential problems: +# WON'T WORK +# - timeline WIN+TAB +# MIGHT NOT WORK +# - clipboard history sharing between devices +# - Bluetooth file sharing +# - Windows Night Light + +Clear-Host +$Error.Clear() + +function Disable-CDPUserSvcViaRegistry { + $baseRegistryPath = "HKLM:\SYSTEM\CurrentControlSet\Services" + $cdpServices = Get-ChildItem -Path $baseRegistryPath | Where-Object { $_.Name -match "CDPUserSvc" } + + foreach ($service in $cdpServices) { + Write-Host "Processing service: $($service.PSChildName)" -ForegroundColor Yellow + try { + # Set the 'Start' value to 4 (Disabled) at the root of the service key + Set-ItemProperty -Path $service.PSPath -Name "Start" -Value 4 -ErrorAction Stop + Write-Host "`tSuccessfully disabled service: $($service.PSChildName)" -ForegroundColor Green + } + catch { + Write-Host "`tFailed to modify service: $($service.PSChildName). Error: $($_.Exception.Message)" -ForegroundColor Red + } + } +} + +# Disable and stop CDPUserSvc +Get-Service -Name 'CDPUserSvc*' | ForEach-Object { + Stop-Service -Name $_.Name -Force + try { + Set-Service -Name $_.Name -StartupType Disabled -ErrorAction Stop + } + catch [Microsoft.PowerShell.Commands.ServiceCommandException] { + Disable-CDPUserSvcViaRegistry + } +} + +# Disable and stop CDPSvc +Write-Host "Processing service: CDPSvc" -ForegroundColor Yellow +Stop-Service -Name CDPSvc -Force + +try { + Set-Service -Name CDPSvc -StartupType Disabled + Write-Host "`tSuccessfully disabled service: CDPSvc" -ForegroundColor Green + +} +catch [Microsoft.PowerShell.Commands.ServiceCommandException] { + write-host "`tFailed to modify service: CDPSvc. Error: $($_.Exception.Message)" -ForegroundColor Red +} \ No newline at end of file diff --git a/system-setup/firewall-rules.ps1 b/system-setup/firewall-rules.ps1 new file mode 100644 index 0000000..9660b8f --- /dev/null +++ b/system-setup/firewall-rules.ps1 @@ -0,0 +1,17 @@ +# Block a ABCD.exe from accessing the Internet using Windows Defender Firewall +$exePath = "C:\Users\Alan\AppData\Local\Programs\ABCD\ABCD.exe" + +# Add outbound rule to block ABCD.exe +New-NetFirewallRule -DisplayName "[Block] ABCD Out" -Direction Outbound -Program $exePath -Action Block + +# Add inbound rule to block ABCD.exe +New-NetFirewallRule -DisplayName "[Block] ABCD In" -Direction Inbound -Program $exePath -Action Block + +# Enable rules +Get-NetFirewallRule -DisplayName "[Block] ABCD" | Set-NetFirewallRule -Enabled True + +# Disable the inbound rule +Get-NetFirewallRule -DisplayName "*Block* ABCD In" | Set-NetFirewallRule -Enabled False + +# Remove rules +Get-NetFirewallRule -DisplayName '*ABCD*' | Remove-NetFirewallRule \ No newline at end of file diff --git a/system-setup/set-env-PATH.ps1 b/system-setup/set-env-PATH.ps1 new file mode 100644 index 0000000..1a3d9e0 --- /dev/null +++ b/system-setup/set-env-PATH.ps1 @@ -0,0 +1,4 @@ +# This script will add a tool folder path to the system environment variable (PATH) +$tool = "C:\tools\dsc" +$PATH = [Environment]::GetEnvironmentVariable("PATH") +[Environment]::SetEnvironmentVariable("PATH", "$PATH;$tool", [System.EnvironmentVariableTarget]::Machine) \ No newline at end of file diff --git a/tasks/register-scheduled-task.ps1 b/tasks/register-scheduled-task.ps1 new file mode 100644 index 0000000..8c4db3d --- /dev/null +++ b/tasks/register-scheduled-task.ps1 @@ -0,0 +1,21 @@ +$name = [guid]::NewGuid() +$trigger = New-ScheduledTaskTrigger -Once -At 9am +$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest + +# inline script +$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -command "& { Write-Host 1 }"' +# file script +$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoLogo -WindowStyle hidden -file C:\script.ps1' + +$task = Register-ScheduledTask ` + -TaskName $name ` + -Description "Background task" ` + -Trigger $trigger ` + -Action $action ` + -TaskPath '\Alan\jobs' ` + -Principal $principal + +Write-Host "Created: $($task.TaskName) under $($task.TaskPath)" + +# display tasks in folder +Get-ScheduledTask -TaskPath "\Alan\*" \ No newline at end of file diff --git a/windows/identify-motherboard.ps1 b/windows/identify-motherboard.ps1 new file mode 100644 index 0000000..17a4321 --- /dev/null +++ b/windows/identify-motherboard.ps1 @@ -0,0 +1 @@ +wmic baseboard get product, Manufacturer, version, serialnumber \ No newline at end of file diff --git a/windows/ui interaction with powershell.ps1 b/windows/ui interaction with powershell.ps1 new file mode 100644 index 0000000..2ead253 --- /dev/null +++ b/windows/ui interaction with powershell.ps1 @@ -0,0 +1,13 @@ +๏ปฟ# Focus Assist Off +Add-Type -AssemblyName System.Windows.Forms +[System.Windows.Forms.SendKeys]::SendWait("(^{ESC})") +Start-Sleep -Milliseconds 500 +[System.Windows.Forms.SendKeys]::SendWait("(Focus Assist)") +Start-Sleep -Milliseconds 200 +[System.Windows.Forms.SendKeys]::SendWait("{ENTER}") +Start-Sleep -Milliseconds 700 +[System.Windows.Forms.SendKeys]::SendWait("{TAB}{TAB} ") +Start-Sleep -Milliseconds 500 +[System.Windows.Forms.SendKeys]::SendWait("{ENTER}") +Start-Sleep -Milliseconds 500 +[System.Windows.Forms.SendKeys]::SendWait("(%{F4})") \ No newline at end of file diff --git a/wsl/install-pwsh.sh b/wsl/install-pwsh.sh new file mode 100644 index 0000000..b33e0d4 --- /dev/null +++ b/wsl/install-pwsh.sh @@ -0,0 +1,22 @@ +# Source: https://learn.microsoft.com/en-us/powershell/scripting/install/install-debian?view=powershell-7.5 + +# Update the list of packages +sudo apt-get update + +# Install pre-requisite packages. +sudo apt-get install -y wget + +# Download the PowerShell package file +wget https://github.com/PowerShell/PowerShell/releases/download/v7.5.0/powershell_7.5.0-1.deb_amd64.deb + +# Install the PowerShell package +sudo dpkg -i powershell_7.5.0-1.deb_amd64.deb + +# Resolve missing dependencies and finish the install (if necessary) +sudo apt-get install -f + +# Delete the downloaded package file +rm powershell_7.5.0-1.deb_amd64.deb + +# Start PowerShell +pwsh \ No newline at end of file diff --git a/wsl/refresh-debian.ps1 b/wsl/refresh-debian.ps1 new file mode 100644 index 0000000..3cb0449 --- /dev/null +++ b/wsl/refresh-debian.ps1 @@ -0,0 +1,6 @@ +# Refresh Debian WSL distribution by unregistering and reinstalling it. +# This is useful when the distribution is corrupted or when you want to reset it. + +wsl -l -v +wsl --unregister Debian +wsl --install -d Debian \ No newline at end of file