├── Convert-ListToString.ps1
├── Extract-HTMLTable.ps1
├── Get-ClipboardHistory.ps1
├── Get-MSIFileInformation.ps1
├── Get-ObjectUnique.ps1
├── Get-ObjectsInTwoArrays.ps1
├── Invoke-AutoType.ps1
├── Invoke-ConcatenateCSV.ps1
├── New-FlatObject.ps1
├── README.md
├── Save-Download.ps1
├── Uninstall-PowerShellModuleAndDependencies.ps1
├── Update-AllPowerShellModules.ps1
├── VideoAndAudio
├── Concatenate-VideoWithFFMpeg.ps1
└── Trim-VideoWithFFMpeg.ps1
└── Windows
└── Block-OutboundConnectionsForAnApp.ps1
/Convert-ListToString.ps1:
--------------------------------------------------------------------------------
1 | function Convert-ListToString {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter()]
5 | $InputArray
6 | )
7 |
8 | $string = New-Object -TypeName System.Text.StringBuilder
9 | foreach ($object in $InputArray) {
10 | [void]$string.Append($object)
11 | }
12 |
13 | return $string.ToString()
14 | }
--------------------------------------------------------------------------------
/Extract-HTMLTable.ps1:
--------------------------------------------------------------------------------
1 | function Extract-HTMLTable {
2 | param(
3 | [Parameter(Mandatory)]
4 | [String] $URL,
5 |
6 | [Parameter(Mandatory = $false)]
7 | [int] $TableNumber,
8 |
9 | # Either we know the table number, otherwise we extract all tables
10 | [Parameter(Mandatory = $false)]
11 | [switch] $AllTables,
12 |
13 | [Parameter(Mandatory = $false)]
14 | [boolean] $LocalFile
15 |
16 | )
17 |
18 | [System.Collections.Generic.List[PSObject]]$tablesArray = @()
19 |
20 | if ($LocalFile) {
21 | $html = New-Object -ComObject 'HTMLFile'
22 | $source = Get-Content -Path $URL -Raw
23 | $html.IHTMLDocument2_write($source)
24 |
25 | # html does not have ParseHTML because it already an HTMLDocumentClass
26 | # Cast in array in case of only one element
27 | $tables = @($html.getElementsByTagName('TABLE'))
28 | }
29 | else {
30 | $WebRequest = Invoke-WebRequest $URL
31 |
32 | # Cast in array in case of only one element
33 | $tables = @($WebRequest.ParsedHtml.getElementsByTagName('TABLE'))
34 | }
35 |
36 | ## Extract the tables out of the web request
37 | if ($TableNumber) {
38 | #$table = $tables[$TableNumber]
39 | # Cast in array because only one element
40 | $tables = @($tables[$TableNumber])
41 | }
42 |
43 | ## Go through all of the rows in the table
44 | $tableNumber = 0
45 | foreach ($table in $tables) {
46 | $titles = @()
47 | $rows = @($table.Rows)
48 |
49 | $tableNumber++
50 |
51 | foreach ($row in $rows) {
52 | $cells = @($row.Cells)
53 |
54 | ## If we've found a table header, remember its titles
55 | if ($cells[0].tagName -eq 'TH') {
56 | $titles = @($cells | ForEach-Object { ('' + $_.InnerText).Trim() })
57 | continue
58 | }
59 |
60 | ## If we haven't found any table headers, make up names "P1", "P2", etc.
61 | if (-not $titles) {
62 | $titles = @(1..($cells.Count + 2) | ForEach-Object { "P$_" })
63 | }
64 |
65 | ## Now go through the cells in the the row. For each, try to find the
66 | ## title that represents that column and create a hashtable mapping those
67 | ## titles to content
68 | $resultObject = [Ordered] @{
69 | "TableNumber" = $tableNumber
70 | }
71 |
72 | for ($counter = 0; $counter -lt $cells.Count; $counter++) {
73 | $title = $titles[$counter]
74 | if (-not $title) { continue }
75 | $resultObject[$title] = ('' + $cells[$counter].InnerText).Trim()
76 | }
77 |
78 | ## And finally cast that hashtable to a PSCustomObject and add to $array
79 | $tablesArray.Add([PSCustomObject] $resultObject)
80 | }
81 | }
82 |
83 | return $tablesArray
84 | }
--------------------------------------------------------------------------------
/Get-ClipboardHistory.ps1:
--------------------------------------------------------------------------------
1 | <#
2 |
3 | from: https://gist.githubusercontent.com/mutaguchi/019ad33e156637585a22a656d8fd3f46/raw/38cba2de838e52004e75c400c254877a4f8e6ad3/ClipboardHistory.ps1
4 | Get-ClipboardHistory: Get the texts contained in the clipboard history.
5 | Clear-ClipboardHistory: Clearing the clipboard history
6 |
7 | In PowerShell 7.1 or later, use the following command to install Microsoft.Windows.SDK.NET.Ref with administrative privileges.
8 | Find-Package -ProviderName NuGet -Source https://www.nuget.org/api/v2 -Name Microsoft.Windows.SDK.NET.Ref | Install-Package
9 | #>
10 |
11 | $needsSDK = $PSVersionTable.PSVersion -ge "7.1.0"
12 |
13 | if ($needsSDK) {
14 | $sdkLib = Split-Path -Path (Get-Package -ProviderName NuGet -Name Microsoft.Windows.SDK.NET.Ref | Select-Object -ExpandProperty Source) -Parent | Join-Path -ChildPath "\lib"
15 | Add-Type -Path "$sdkLib\Microsoft.Windows.SDK.NET.dll"
16 | Add-Type -Path "$sdkLib\WinRT.Runtime.dll"
17 | }
18 | else {
19 | Add-Type -AssemblyName System.Runtime.WindowsRuntime
20 | }
21 |
22 | $clipboard = if ($needsSDK) {
23 | [Windows.ApplicationModel.DataTransfer.Clipboard]
24 | }
25 | else {
26 | [Windows.ApplicationModel.DataTransfer.Clipboard, Windows.ApplicationModel.DataTransfer, ContentType = WindowsRuntime]
27 | }
28 | get-
29 | function await {
30 | param($AsyncTask, [Type]$ResultType)
31 |
32 | $method = [WindowsRuntimeSystemExtensions].GetMember("GetAwaiter") | Where-Object { $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' } | Select-Object -First 1 $method.MakeGenericMethod($ResultType).Invoke($null, @($AsyncTask)).GetResult()
33 | }
34 |
35 | function Get-ClipboardHistory {
36 | $type = if ($script:needsSDK) {
37 | [Windows.ApplicationModel.DataTransfer.ClipboardHistoryItemsResult]
38 | }
39 | else {
40 | [Windows.ApplicationModel.DataTransfer.ClipboardHistoryItemsResult, Windows.ApplicationModel.DataTransfer, ContentType = WindowsRuntime]
41 | }
42 |
43 | $result = await $script:clipboard::GetHistoryItemsAsync() $type
44 |
45 | $outItems = if ($script:needsSDK) {
46 | @($result.Items.AdditionalTypeData.Values)
47 | }
48 | else {
49 | @($result.Items)
50 | }
51 |
52 | $outItems | Where-Object { $_.Content.Contains("Text") } | ForEach-Object {
53 | await $_.Content.GetTextAsync() ([string])
54 | }
55 | }
56 |
57 | function Clear-ClipboardHistory {
58 | $null = $script:clipboard::ClearHistory()
59 | }
--------------------------------------------------------------------------------
/Get-MSIFileInformation.ps1:
--------------------------------------------------------------------------------
1 | function Get-MSIFileInformation {
2 | param(
3 | [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
4 | [ValidateNotNullOrEmpty()]
5 | [System.IO.FileInfo[]]$FilePath
6 | )
7 |
8 | # https://learn.microsoft.com/en-us/windows/win32/msi/installer-opendatabase
9 | $msiOpenDatabaseModeReadOnly = 0
10 |
11 | $productLanguageHashTable = @{
12 | '1025' = 'Arabic'
13 | '1026' = 'Bulgarian'
14 | '1027' = 'Catalan'
15 | '1028' = 'Chinese - Traditional'
16 | '1029' = 'Czech'
17 | '1030' = 'Danish'
18 | '1031' = 'German'
19 | '1032' = 'Greek'
20 | '1033' = 'English'
21 | '1034' = 'Spanish'
22 | '1035' = 'Finnish'
23 | '1036' = 'French'
24 | '1037' = 'Hebrew'
25 | '1038' = 'Hungarian'
26 | '1040' = 'Italian'
27 | '1041' = 'Japanese'
28 | '1042' = 'Korean'
29 | '1043' = 'Dutch'
30 | '1044' = 'Norwegian'
31 | '1045' = 'Polish'
32 | '1046' = 'Brazilian'
33 | '1048' = 'Romanian'
34 | '1049' = 'Russian'
35 | '1050' = 'Croatian'
36 | '1051' = 'Slovak'
37 | '1053' = 'Swedish'
38 | '1054' = 'Thai'
39 | '1055' = 'Turkish'
40 | '1058' = 'Ukrainian'
41 | '1060' = 'Slovenian'
42 | '1061' = 'Estonian'
43 | '1062' = 'Latvian'
44 | '1063' = 'Lithuanian'
45 | '1081' = 'Hindi'
46 | '1087' = 'Kazakh'
47 | '2052' = 'Chinese - Simplified'
48 | '2070' = 'Portuguese'
49 | '2074' = 'Serbian'
50 | }
51 |
52 | $summaryInfoHashTable = @{
53 | 1 = 'Codepage'
54 | 2 = 'Title'
55 | 3 = 'Subject'
56 | 4 = 'Author'
57 | 5 = 'Keywords'
58 | 6 = 'Comment'
59 | 7 = 'Template'
60 | 8 = 'LastAuthor'
61 | 9 = 'RevisionNumber'
62 | 10 = 'EditTime'
63 | 11 = 'LastPrinted'
64 | 12 = 'CreationDate'
65 | 13 = 'LastSaved'
66 | 14 = 'PageCount'
67 | 15 = 'WordCount'
68 | 16 = 'CharacterCount'
69 | 18 = 'ApplicationName'
70 | 19 = 'Security'
71 | }
72 |
73 | $properties = @('ProductVersion', 'ProductCode', 'ProductName', 'Manufacturer', 'ProductLanguage', 'UpgradeCode')
74 |
75 | try {
76 | $file = Get-ChildItem $FilePath -ErrorAction Stop
77 | }
78 | catch {
79 | Write-Warning "Unable to get file $FilePath $($_.Exception.Message)"
80 | return
81 | }
82 |
83 | $object = [PSCustomObject][ordered]@{
84 | FileName = $file.Name
85 | FilePath = $file.FullName
86 | 'Length(MB)' = $file.Length / 1MB
87 | }
88 |
89 | # Read property from MSI database
90 | $windowsInstallerObject = New-Object -ComObject WindowsInstaller.Installer
91 |
92 | # open read only
93 | $msiDatabase = $windowsInstallerObject.GetType().InvokeMember('OpenDatabase', 'InvokeMethod', $null, $windowsInstallerObject, @($file.FullName, $msiOpenDatabaseModeReadOnly))
94 |
95 | foreach ($property in $properties) {
96 | $view = $null
97 | $query = "SELECT Value FROM Property WHERE Property = '$($property)'"
98 | $view = $msiDatabase.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $msiDatabase, ($query))
99 | $view.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $view, $null)
100 | $record = $view.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $view, $null)
101 |
102 | try {
103 | $value = $record.GetType().InvokeMember('StringData', 'GetProperty', $null, $record, 1)
104 | }
105 | catch {
106 | Write-Verbose "Unable to get '$property' $($_.Exception.Message)"
107 | $value = ''
108 | }
109 |
110 | if ($property -eq 'ProductLanguage') {
111 | $value = "$value ($($productLanguageHashTable[$value]))"
112 | }
113 |
114 | $object | Add-Member -MemberType NoteProperty -Name $property -Value $value
115 | }
116 |
117 | $summaryInfo = $msiDatabase.GetType().InvokeMember('SummaryInformation', 'GetProperty', $null, $msiDatabase, $null)
118 | $summaryInfoPropertiesCount = $summaryInfo.GetType().InvokeMember('PropertyCount', 'GetProperty', $null, $summaryInfo, $null)
119 |
120 | (1..$summaryInfoPropertiesCount) | ForEach-Object {
121 | $value = $SummaryInfo.GetType().InvokeMember("Property", "GetProperty", $Null, $SummaryInfo, $_)
122 |
123 | if ($null -eq $value) {
124 | $object | Add-Member -MemberType NoteProperty -Name $summaryInfoHashTable[$_] -Value ''
125 | }
126 | else {
127 | $object | Add-Member -MemberType NoteProperty -Name $summaryInfoHashTable[$_] -Value $value
128 | }
129 | }
130 |
131 | #$msiDatabase.GetType().InvokeMember('Commit', 'InvokeMethod', $null, $msiDatabase, $null)
132 | $view.GetType().InvokeMember('Close', 'InvokeMethod', $null, $view, $null)
133 |
134 | # Run garbage collection and release ComObject
135 | $null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($windowsInstallerObject)
136 | [System.GC]::Collect()
137 |
138 | return $object
139 | }
--------------------------------------------------------------------------------
/Get-ObjectUnique.ps1:
--------------------------------------------------------------------------------
1 | function Get-ObjectUnique {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter()]
5 | $InputArray
6 | )
7 |
8 | return [System.Collections.Generic.HashSet[string]]$InputArray
9 | }
--------------------------------------------------------------------------------
/Get-ObjectsInTwoArrays.ps1:
--------------------------------------------------------------------------------
1 | function Get-ObjectsInTwoArrays {
2 | [CmdletBinding()]
3 | param (
4 | [Parameter()]
5 | $Array,
6 | [Parameter()]
7 | $ArrayToCompare,
8 | [Parameter(Mandatory)]
9 | [ValidateSet('In', 'NotIn')]
10 | $ComparisonMethod,
11 | [Parameter(Mandatory)]
12 | [ValidateSet('String', 'int','PSObject')]
13 | $ObjectType
14 | )
15 |
16 | if($ObjectType -eq 'String'){
17 | $arrayIndex = [System.Collections.Generic.HashSet[String]]$Array
18 | }
19 | elseif($ObjectType -eq 'int'){
20 | $arrayIndex = [System.Collections.Generic.HashSet[int]]$Array
21 | }
22 | elseif($ObjectType -eq 'PSObject'){
23 | $arrayIndex = [System.Collections.Generic.HashSet[PSObject]]$Array
24 | }
25 |
26 | [System.Collections.Generic.List[PSObject]]$res = @()
27 |
28 | if ($ComparisonMethod -eq 'In') {
29 | foreach ($object in $ArrayToCompare) {
30 | if ($arrayIndex.Contains($object)) {
31 | $res.Add($object)
32 | }
33 | }
34 | }
35 | elseif ($ComparisonMethod -eq 'NotIn') {
36 | foreach ($object in $ArrayToCompare) {
37 | if (-not($arrayIndex.Contains($object))) {
38 | $res.Add($object)
39 | }
40 | }
41 | }
42 |
43 | Write-Host "$($res.count) $ComparisonMethod two arrays"
44 | return $res
45 | }
--------------------------------------------------------------------------------
/Invoke-AutoType.ps1:
--------------------------------------------------------------------------------
1 |
2 | <#
3 | feat: Add PowerShell script for automating typing
4 |
5 | This commit adds a new PowerShell script, `Invoke-AutoType.ps1`, which allows for automating typing on both Windows and macOS operating systems. The script takes a string as input and types it character by character with a small delay between each character.
6 |
7 | The script includes separate logic for Windows and macOS, utilizing the `System.Windows.Forms.SendKeys` class for Windows and AppleScript for macOS.
8 |
9 | This feature will be useful for automating repetitive typing tasks, such as filling out forms or entering text in applications.
10 | #>
11 |
12 | # The string to type
13 | $type = ''
14 |
15 | $sleepMillisecondsBetweenCharacters = 1
16 |
17 | # Sleep for 5 seconds before starting to type to go to the right window
18 | Start-Sleep -Seconds 5
19 |
20 | # If Operating System is Windows
21 | if ($IsWindows) {
22 | # Loop over each character in the string
23 | foreach ($char in $type.ToCharArray()) {
24 | # Send the character
25 | [System.Windows.Forms.SendKeys]::SendWait($char)
26 |
27 | # Sleep for 5 milliseconds between characters
28 | Start-Sleep -Milliseconds $sleepMillisecondsBetweenCharacters
29 | }
30 | }
31 |
32 | if ($IsMacOS) {
33 | # Boucle sur chaque caractère de la chaîne
34 | foreach ($char in $type.ToCharArray()) {
35 | $script = @"
36 | tell application "System Events"
37 | keystroke "$char"
38 | end tell
39 | "@
40 | }
41 |
42 | # Exécution du script AppleScript pour chaque caractère
43 | osascript -e $script
44 |
45 | # Pause de 5 millisecondes entre les caractères
46 | Start-Sleep -Milliseconds $sleepMillisecondsBetweenCharacters
47 | }
--------------------------------------------------------------------------------
/Invoke-ConcatenateCSV.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This script concatenates multiple CSV files into a single CSV file.
4 |
5 | .DESCRIPTION
6 | The Invoke-ConcatenateCSV.ps1 script concatenates multiple CSV files from a specified directory into a single CSV file, adding the source filename as the first column.
7 | A oneliner exists:
8 | Get-ChildItem -Filter *.csv | Select-Object -ExpandProperty FullName | Import-Csv | Export-Csv .\merged.csv -NoTypeInformation -Append
9 | But we don't have the source file name in the output file and we can handle different properties in the CSV files.
10 |
11 | .PARAMETER InputDirectory
12 | Specifies the directory containing the CSV files to be concatenated.
13 |
14 | .PARAMETER OutputFile
15 | Specifies the path and name of the output CSV file that will contain the concatenated data.
16 |
17 | .EXAMPLE
18 | PS C:\> .\Invoke-ConcatenateCSV.ps1 -InputDirectory "C:\CSVFiles" -OutputFile "C:\Output\Combined.csv"
19 |
20 | .NOTES
21 | Author: Bastien Perez
22 | Date: 2024/11/22
23 | Version: 1.2
24 | #>
25 |
26 | function Invoke-ConcatenateCSV {
27 | [CmdletBinding()]
28 | param(
29 | [Parameter(Mandatory = $false)]
30 | [string]$InputDirectory = '.',
31 |
32 | [Parameter(Mandatory = $false)]
33 | [string]$OutputFile = 'Concatenated.csv',
34 |
35 | [Parameter(Mandatory = $false)]
36 | [string]$Delimiter = ';' ,
37 |
38 | [Parameter(Mandatory = $false)]
39 | [switch]$AddSourceFile
40 | )
41 |
42 | # Create empty array to store all data
43 | [System.Collections.Generic.List[Object]]$allData = @()
44 | # Get all CSV files in the specified directory
45 | $files = Get-ChildItem -Path $InputDirectory -Filter '*.csv'
46 |
47 | if ($files.Count -eq 0) {
48 | Write-Warning "No CSV files found in directory: $InputDirectory"
49 | return
50 | }
51 |
52 | foreach ($file in $files) {
53 | Write-Verbose "Processing file: $($file.Name)"
54 |
55 | try {
56 | # Import CSV content
57 | Write-Verbose "Importing CSV content from: $($file.FullName)"
58 | $csvContent = Import-Csv -Path $file.FullName -Delimiter $Delimiter
59 |
60 | # Add source filename to each row
61 | foreach ($row in $csvContent) {
62 | if ($AddSourceFile) {
63 | Write-Verbose "Adding source file = $($file.Name) to the row"
64 | $row.PSObject.Properties.Add('SourceFile', $file.Name)
65 | }
66 |
67 | $newRow = @{}
68 | # Add all other properties from the original row
69 | foreach ($property in $row.PSObject.Properties) {
70 | Write-Verbose "Adding property: $($property.Name) = $($property.Value)"
71 | $newRow[$property.Name] = $property.Value
72 | }
73 |
74 | # Add the modified row to our collection
75 | $allData.Add([PSCustomObject]$newRow)
76 | }
77 | }
78 | catch {
79 | Write-Warning "Error processing file $($file.Name): $_"
80 | continue
81 | }
82 | }
83 |
84 | if ($allData.Count -gt 0) {
85 | try {
86 | # Export all data to the output file
87 | $allData | Export-Csv -Path $OutputFile -NoTypeInformation -Encoding UTF8
88 | Write-Host "Successfully concatenated $($files.Count) files to: $OutputFile"
89 | Write-Host "Total rows: $($allData.Count)"
90 | }
91 | catch {
92 | Write-Error "Error writing output file: $_"
93 | }
94 | }
95 | else {
96 | Write-Warning 'No data was collected from the CSV files'
97 | }
98 | }
--------------------------------------------------------------------------------
/New-FlatObject.ps1:
--------------------------------------------------------------------------------
1 | function New-FlatObject {
2 | Param
3 | (
4 | [Parameter(Mandatory, ValueFromPipeline)]
5 | $object
6 | )
7 |
8 | process {
9 | $returnHashTable = [ordered]@{ }
10 | foreach ($prop in $object.psobject.Properties) {
11 | if ($prop.Value -is [array]) {
12 | #if (($prop.Value -ne $null) -and (-not $prop.Value.GetType().isValueType))
13 | $counter = 0
14 | foreach ($value in $prop.Value) {
15 | if ($value -is [array]) {
16 | #if (($prop.Value -ne $null) -and (-not $prop.Value.GetType().isValueType))
17 | foreach ($recurse in (New-FlatObject -object $value).psobject.Properties) {
18 | $returnHashTable["$($prop.Name)-$($recurse.Name)"] = $recurse.Value
19 | }
20 | }
21 | $returnHashTable["$($prop.Name)-$counter"] = $value
22 | $counter++
23 | }
24 | }
25 | else {
26 | $returnHashTable[$prop.Name] = $prop.Value
27 | }
28 | }
29 | return [PSCustomObject]$returnHashTable | Sort-Object @{Expression = { (($_.psobject.properties) | Measure-Object).count } } -Descending
30 | }
31 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerShell-Toolbox
2 | Some useful scripts
3 |
--------------------------------------------------------------------------------
/Save-Download.ps1:
--------------------------------------------------------------------------------
1 | function Save-Download {
2 | <#
3 | .SYNOPSIS
4 | Given a the result of WebResponseObject, will download the file to disk without having to specify a name.
5 | .DESCRIPTION
6 | Given a the result of WebResponseObject, will download the file to disk without having to specify a name.
7 | .PARAMETER WebResponse
8 | A WebResponseObject from running an Invoke-WebRequest on a file to download
9 | .EXAMPLE
10 | # Download Microsoft Edge
11 | $download = Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=2109047&Channel=Stable&language=en&consent=1"
12 | $download | Save-Download
13 | #>
14 | [CmdletBinding()]
15 | param (
16 | [Parameter(Mandatory = $true, ValueFromPipeline)]
17 | [Microsoft.PowerShell.Commands.WebResponseObject]
18 | $WebResponse,
19 |
20 | [Parameter(Mandatory = $false)]
21 | [string]
22 | $Directory = '.'
23 | )
24 |
25 | $errorMessage = 'Cannot determine filename for download.'
26 |
27 | if (!($WebResponse.Headers.ContainsKey('Content-Disposition'))) {
28 | Write-Error $errorMessage -ErrorAction Stop
29 | }
30 |
31 | $content = [System.Net.Mime.ContentDisposition]::new($WebResponse.Headers['Content-Disposition'])
32 |
33 | $fileName = $content.FileName
34 |
35 | if (!$fileName) {
36 | Write-Error $errorMessage -ErrorAction Stop
37 | }
38 |
39 | if (!(Test-Path -Path $Directory)) {
40 | New-Item -Path $Directory -ItemType Directory
41 | }
42 |
43 | $fullPath = Join-Path -Path $Directory -ChildPath $fileName
44 |
45 | Write-Verbose "Downloading to $fullPath"
46 |
47 | $file = [System.IO.FileStream]::new($fullPath, [System.IO.FileMode]::Create)
48 | $file.Write($WebResponse.Content, 0, $WebResponse.RawContentLength)
49 | $file.Close()
50 | }
--------------------------------------------------------------------------------
/Uninstall-PowerShellModuleAndDependencies.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | do{
3 | $mod=Get-InstalledModule Vmware* -ErrorAction SilentlyContinue
4 | $mod | % {$_.Name
5 | $_ | Uninstall-Module}}until($(Get-InstalledModule Vmware* -ErrorAction SilentlyContinue) -eq $null)
6 | #>
7 |
8 | function Uninstall-PowerShellModuleAndDependencies {
9 | param (
10 | [Parameter(Mandatory = $true)]
11 | [string]$Module
12 | )
13 |
14 | [System.Collections.Generic.List[String]] $script:modulesOrDependencies = @()
15 |
16 | function Get-RecursivePowerShellDepencies {
17 | param (
18 | [Parameter(Mandatory = $true)]
19 | [string]$Module
20 | )
21 |
22 | $target = Find-Module $Module
23 |
24 | if ($target.Dependencies.count -eq 0) {
25 | if ($script:modulesOrDependencies -notcontains $target.Name) {
26 | $script:modulesOrDependencies.Add($target.name)
27 | }
28 | }
29 | else {
30 | $target.Dependencies | ForEach-Object {
31 | # add current dependency
32 | if ($script:modulesOrDependencies -notcontains $target.Name) {
33 | $script:modulesOrDependencies.Add($target.name)
34 | }
35 |
36 | # search for dependencies of current dependency
37 | Get-RecursivePowerShellDepencies -Module $_.name
38 | }
39 | }
40 | }
41 |
42 | Write-Host "$module - Creating list of dependencies" -ForegroundColor Cyan
43 |
44 | Get-RecursivePowerShellDepencies -Module $Module
45 |
46 | foreach ($mod in $modulesOrDependencies) {
47 | Write-Host "$mod - Uninstalling" -ForegroundColor Cyan
48 |
49 | try {
50 | Uninstall-Module -Name $mod -Force -ErrorAction Stop
51 | }
52 | catch {
53 | Write-Warning "modulesOrDependency $($_.Exception.Message)"
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/Update-AllPowerShellModules.ps1:
--------------------------------------------------------------------------------
1 | # https://itpro-tips.com/2020/update-all-powershell-modules-at-once/
2 | # https://itpro-tips.com/2020/mettre-a-jour-tous-les-modules-powershell-en-une-fois/
3 | [CmdletBinding()]
4 | param (
5 | [Parameter()]
6 | # To exclude modules from the update process
7 | [String[]]$ExcludedModules,
8 | # To include only these modules for the update process
9 | [String[]]$IncludedModules,
10 | [switch]$SkipPublisherCheck,
11 | [switch]$SimulationMode
12 | )
13 | <#
14 | /!\/!\/!\ PLEASE READ /!\/!\/!\
15 |
16 | /!\ If you look for a quick way to update, please keep in mind Microsoft has a built-in CMDlet to update ALL the PowerShell modules installed:
17 | /!\ Update-Module [-Verbose]
18 |
19 | /!\ This script is intended as a replacement of the Update-Module:
20 | /!\ - to provide more human readable output than the -Verbose option of Update-Module
21 | /!\ - to force install with -SkipPublisherCheck (Authenticode change) because Update-Module has not this option
22 | /!\ - to exclude some modules from the update process
23 | /!\ - to remove older versions because Update-Module does not remove older versions (it only installs a new version in the $env:PSModulePath\ and keep the old module)
24 |
25 | This script provides informations about the module version (current and the latest available on PowerShell Gallery) and update to the latest version
26 | If you have a module with two or more versions, the script delete them and reinstall only the latest.
27 |
28 | #>
29 |
30 | #Requires -Version 5.0
31 | #Requires -RunAsAdministrator
32 |
33 | Write-Host -ForegroundColor cyan 'Define PowerShell to add TLS1.2 in this session, needed since 1st April 2020 (https://devblogs.microsoft.com/powershell/powershell-gallery-tls-support/)'
34 | [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
35 |
36 | # if needed, register PSGallery
37 | # Register PSGallery PSprovider and set as Trusted source
38 | # Register-PSRepository -Default -ErrorAction SilentlyContinue
39 | # Set-PSRepository -Name PSGallery -InstallationPolicy trusted -ErrorAction SilentlyContinue
40 |
41 | if ($SimulationMode) {
42 | Write-Host -ForegroundColor yellow 'Simulation mode is ON, nothing will be installed / removed / updated'
43 | }
44 |
45 | function Remove-OldPowerShellModules {
46 | param (
47 | [string]$ModuleName,
48 | [string]$GalleryVersion
49 | )
50 |
51 | try {
52 | $oldVersions = Get-InstalledModule -Name $ModuleName -AllVersions -ErrorAction Stop | Where-Object { $_.Version -ne $GalleryVersion }
53 |
54 | foreach ($oldVersion in $oldVersions) {
55 | Write-Host -ForegroundColor Cyan "$ModuleName - Uninstall previous version" -NoNewline
56 | Write-Host -ForegroundColor White " ($($oldVersion.Version))"
57 |
58 | if (-not($SimulationMode)) {
59 | Remove-Module $ModuleName -ErrorAction SilentlyContinue
60 | Uninstall-Module $oldVersion -Force -ErrorAction Stop
61 | }
62 | }
63 | }
64 | catch {
65 | Write-Warning "$module - $($_.Exception.Message)"
66 | }
67 | }
68 |
69 | if ($IncludedModules) {
70 | Write-Host -ForegroundColor Cyan "Get PowerShell modules like $IncludedModules"
71 | $modules = Get-InstalledModule | Where-Object { $_.Name -like $IncludedModules }
72 | }
73 | else {
74 | Write-Host -ForegroundColor Cyan 'Get all PowerShell modules'
75 | $modules = Get-InstalledModule
76 | }
77 |
78 | foreach ($module in $modules.Name) {
79 | if ($ExcludedModules -contains $module) {
80 | Write-Host -ForegroundColor Yellow "Module $module is excluded from the update process"
81 | continue
82 | }
83 | elseif ($module -like "$excludedModules") {
84 | Write-Host -ForegroundColor Yellow "Module $module is excluded from the update process (match $excludeModules)"
85 | continue
86 | }
87 |
88 | $currentVersion = $null
89 |
90 | try {
91 | $currentVersion = (Get-InstalledModule -Name $module -AllVersions -ErrorAction Stop).Version
92 | }
93 | catch {
94 | Write-Warning "$module - $($_.Exception.Message)"
95 | continue
96 | }
97 |
98 | try {
99 | $moduleGalleryInfo = Find-Module -Name $module -ErrorAction Stop
100 | }
101 | catch {
102 | Write-Warning "$module not found in the PowerShell Gallery. $($_.Exception.Message)"
103 | continue
104 | }
105 |
106 | # $current version can also be a version follow by -preview
107 | if ($currentVersion -like '*-preview') {
108 | Write-Warning "The module installed is a preview version, it will not tested by this script"
109 | }
110 |
111 | if ($moduleGalleryInfo.Version -like '*-preview') {
112 | Write-Warning "The module in PowerShell Gallery is a preview version, it will not tested bt this script"
113 | continue
114 | }
115 | else {
116 | $moduleGalleryVersion = $moduleGalleryInfo.Version
117 | }
118 |
119 | # Convert published date to YYYY/MM/DD HH:MM:SS format
120 | $publishedDate = [datetime]$moduleGalleryInfo.PublishedDate
121 | $publishedDate = $publishedDate.ToString("yyyy/MM/dd HH:mm:ss")
122 |
123 | if ($null -eq $currentVersion) {
124 | Write-Host -ForegroundColor Cyan "$module - Install from PowerShellGallery version $($moduleGalleryInfo.Version) - Release date: $publishedDate"
125 |
126 | if (-not($SimulationMode)) {
127 | try {
128 | Install-Module -Name $module -Force -SkipPublisherCheck -ErrorAction Stop
129 | }
130 | catch {
131 | Write-Warning "$module - $($_.Exception.Message)"
132 | }
133 | }
134 | }
135 | elseif ($moduleGalleryInfo.Version -eq $currentVersion) {
136 | Write-Host -ForegroundColor Green "$module - already in latest version: " -NoNewline
137 | Write-Host -ForegroundColor White "$currentVersion" -NoNewline
138 | Write-Host -ForegroundColor Green " - Release date:" -NoNewline
139 | Write-Host -ForegroundColor White " $publishedDate"
140 | }
141 | elseif ($currentVersion.count -gt 1) {
142 | Write-Host -ForegroundColor Yellow "$module is installed in $($currentVersion.count) versions:" -NoNewline
143 | Write-Host -ForegroundColor White " $($currentVersion -join ' | ')"
144 | Write-Host -ForegroundColor Cyan "$module - Uninstall previous $module version(s) below the latest version" -NoNewline
145 | Write-Host -ForegroundColor White " ($($moduleGalleryInfo.Version))"
146 |
147 | Remove-OldPowerShellModules -ModuleName $module -GalleryVersion $moduleGalleryInfo.Version
148 |
149 | # Check again the current Version as we uninstalled some old versions
150 | $currentVersion = (Get-InstalledModule -Name $module).Version
151 |
152 | if ($moduleGalleryVersion -ne $currentVersion) {
153 | Write-Host -ForegroundColor Cyan "$module - Install from PowerShellGallery version" -NoNewline
154 | Write-Host -ForegroundColor White " $($moduleGalleryInfo.Version)" -NoNewline
155 | Write-Host -ForegroundColor Cyan " - Release date:" -NoNewline
156 | Write-Host -ForegroundColor White " $publishedDate"
157 |
158 | if (-not($SimulationMode)) {
159 | try {
160 | Install-Module -Name $module -Force -ErrorAction Stop
161 |
162 | Remove-OldPowerShellModules -ModuleName $module -GalleryVersion $moduleGalleryInfo.Version
163 | }
164 | catch {
165 | Write-Warning "$module - $($_.Exception.Message)"
166 | }
167 | }
168 | }
169 | }
170 | # https://invoke-thebrain.com/2018/12/comparing-version-numbers-powershell/
171 | elseif ([version]$currentVersion -gt [version]$moduleGalleryVersion) {
172 | Write-Host -ForegroundColor Yellow "$module - the current version $currentVersion is newer than the version available on PowerShell Gallery $($moduleGalleryInfo.Version) (Release date: $publishedDate). Sometimes happens when you install a module from another repository or via .exe/.msi or if you change the version number manually."
173 | }
174 | elseif ([version]$currentVersion -lt [version]$moduleGalleryVersion) {
175 | Write-Host -ForegroundColor Cyan "$module - Update from PowerShellGallery version" -NoNewline
176 | Write-Host -ForegroundColor White " $currentVersion -> $($moduleGalleryInfo.Version)" -NoNewline
177 | Write-Host -ForegroundColor Cyan " - Release date:" -NoNewline
178 | Write-Host -ForegroundColor White " $publishedDate"
179 |
180 | if (-not($SimulationMode)) {
181 | try {
182 | Update-Module -Name $module -Force -ErrorAction Stop
183 | Remove-OldPowerShellModules -ModuleName $module -GalleryVersion $moduleGalleryInfo.Version
184 | }
185 | catch {
186 | if ($_.Exception.Message -match 'Authenticode') {
187 | Write-Host -ForegroundColor Yellow "$module - The module certificate used by the creator is either changed since the last module install or the module sign status has changed."
188 |
189 | if ($SkipPublisherCheck.IsPresent) {
190 | Write-Host -ForegroundColor Cyan "$module - SkipPublisherCheck Parameter is present, so install will run without Authenticode check"
191 | Write-Host -ForegroundColor Cyan "$module - Install from PowerShellGallery version $($moduleGalleryInfo.Version) - Release date: $publishedDate"
192 | try {
193 | Install-Module -Name $module -Force -SkipPublisherCheck
194 | }
195 | catch {
196 | Write-Warning "$module - $($_.Exception.Message)"
197 | }
198 |
199 | Remove-OldPowerShellModules -ModuleName $module -GalleryVersion $moduleGalleryInfo.Version
200 | }
201 | else {
202 | Write-Warning "$module - If you want to update this module, run again with -SkipPublisherCheck switch, but please keep in mind the security risk"
203 | }
204 | }
205 | else {
206 | Write-Warning "$module - $($_.Exception.Message)"
207 | }
208 | }
209 | }
210 | }
211 | }
--------------------------------------------------------------------------------
/VideoAndAudio/Concatenate-VideoWithFFMpeg.ps1:
--------------------------------------------------------------------------------
1 | # Get the list of video files from a specific directory
2 | $videoDirectory = "."
3 | $videoFiles = Get-ChildItem -Path $videoDirectory -Filter "*.mp4"
4 |
5 | # Create a temporary file to list all video files for ffmpeg
6 | $tempFile = New-TemporaryFile
7 | foreach ($videoFile in $videoFiles) {
8 | Add-Content -Path $tempFile.FullName -Value "file '$($videoFile.FullName)'"
9 | }
10 |
11 | # Output file name
12 | $outputVideo = "outputVideo.mp4"
13 |
14 | # Concatenate videos using ffmpeg
15 | & ffmpeg -f concat -safe 0 -i $tempFile.FullName -c copy $outputVideo
16 |
17 | # Clean up the temporary file
18 | Remove-Item -Path $tempFile.FullName
--------------------------------------------------------------------------------
/VideoAndAudio/Trim-VideoWithFFMpeg.ps1:
--------------------------------------------------------------------------------
1 | Param(
2 | [Parameter(Mandatory = $false)]
3 | [string]$InputVideo,
4 | [Parameter(Mandatory = $false)]
5 | [string]$OutputVideo,
6 | [Parameter(Mandatory = $true)]
7 | [string]$StartCut,
8 | [Parameter(Mandatory = $false)]
9 | [string]$EndCut
10 | )
11 |
12 | # function to get time in hh:mm:ss format
13 | function Get-TimeInHHMMSSFormat {
14 | param(
15 | [string]$Time
16 | )
17 |
18 | $timeParts = $time.Split(':')
19 |
20 | switch ($timeParts.Count) {
21 | 1 { return [TimeSpan]::FromSeconds([int]$timeParts[0]) }
22 | 2 { return [TimeSpan]::FromMinutes([int]$timeParts[0]).Add([TimeSpan]::FromSeconds([int]$timeParts[1])) }
23 | 3 { return [TimeSpan]::FromHours([int]$timeParts[0]).Add([TimeSpan]::FromMinutes([int]$timeParts[1])).Add([TimeSpan]::FromSeconds([int]$timeParts[2])) }
24 | default { throw 'Invalid time format. Please use one of the following formats: SS, MM:SS, or HH:MM:SS.' }
25 | }
26 | }
27 |
28 | # Get video duration using FFmpeg
29 | $duration = & ffmpeg -i $InputVideo 2>&1 | Select-String -Pattern 'Duration: (\d+):(\d+):(\d+\.\d+)' | ForEach-Object { $_.Matches.Groups[1].Value, $_.Matches.Groups[2].Value, $_.Matches.Groups[3].Value -join ':' }
30 |
31 | # Use the custom Parse-Time function
32 | $startCutTimeSpan = Get-TimeInHHMMSSFormat -Time $StartCut
33 |
34 | # If no end cut time is provided, set it to the duration of the video
35 | if ([string]::IsNullOrWhitespace($EndCut)) {
36 | Write-Host -ForegroundColor Cyan "No end cut time provided. Using the full duration of the video $duration"
37 | $endCut = $duration
38 | }
39 |
40 | $endCutTimeSpan = Get-TimeInHHMMSSFormat -Time $EndCut
41 |
42 | # Calculate new duration by subtracting start cut from end cut
43 | $newDuration = $endCutTimeSpan.Subtract($startCutTimeSpan)
44 |
45 | # Format new duration for FFmpeg
46 | $newDuration = '{0:00}:{1:00}:{2:00}.{3:000}' -f $newDuration.Hours, $newDuration.Minutes, $newDuration.Seconds, $newDuration.Milliseconds
47 |
48 | # Use FFmpeg to cut the video
49 | & ffmpeg -ss $StartCut -i $InputVideo -t $newDuration -c copy $OutputVideo
--------------------------------------------------------------------------------
/Windows/Block-OutboundConnectionsForAnApp.ps1:
--------------------------------------------------------------------------------
1 | # block outbound connections for an .exe path
2 | [CmdletBinding()]
3 | param (
4 | [Parameter(Mandatory = $true, HelpMessage = "The path to the application")]
5 | [String]$ApplicationPath
6 | )
7 |
8 |
9 | # Test if application exists
10 | if (-not (Test-Path $ApplicationPath)) {
11 | Write-Warning "'$ApplicationPath' does not exist"
12 | return
13 | }
14 |
15 | $fileInfo = Get-Item $ApplicationPath
16 | $appName = $fileInfo.Name
17 | $productName = $fileInfo.VersionInfo.ProductName
18 | $string = ""
19 |
20 | if (-not [string]::IsNullOrEmpty($productName)) {
21 | $string = $productName.Trim()
22 | }
23 | else {
24 | $string = $fileInfo.BaseName.Trim()
25 | }
26 |
27 | if (-not [string]::IsNullOrEmpty($appName)) {
28 | $string = $string + " - " + $appName
29 | }
30 |
31 | $ruleName = "[Custom] Block outbound access for $string ($applicationPath)"
32 |
33 | # Test if the rule already exists
34 | try {
35 | $ruleExists = [boolean](Get-NetFirewallRule -Direction Outbound | Where-Object { $_.DisplayName -eq "$ruleName" })
36 | }
37 | catch {
38 | Write-Warning "Failed to check if the rule already exists $($_.Exception.Message)."
39 | }
40 |
41 | if ($ruleExists) {
42 | Write-Warning "The rule '$ruleName' already exists"
43 | return
44 | }
45 |
46 | # create a new rule
47 | try {
48 | Write-Host -ForegroundColor Cyan "Creating a new rule to block outbound connections for the application: $ApplicationPath"
49 | New-NetFirewallRule -DisplayName $ruleName -Direction Outbound -Program $ApplicationPath -Action Block -Enabled True -ErrorAction Stop
50 | Write-Host -ForegroundColor Green "The rule has been created successfully."
51 | }
52 | catch {
53 | Write-Host "Failed to create the rule. The rule may already exist."
54 | }
--------------------------------------------------------------------------------