ClipboardTools.psm1
<#
.Synopsis This function gets clipboard data and sets it back to clipboard removing any metadata .DESCRIPTION This function gets clipboard data and sets it back to clipboard. This trick should remove metadata from clipboard data. For example from http smartlinks it will paste full url instead of url smartlink (url name and url) Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER PassThru PassThru parameter will also output clipboard data to Powershell pipeline. Usually this is used with saving results to variable. For example $FromClipboard = ClipboardTools-CopyPaste -PassThru .EXAMPLE ClipboardTools-CopyPaste .EXAMPLE $FromClipboard = ClipboardTools-CopyPaste -PassThru .INPUTS Reads clipboard data .OUTPUTS Outputs data to clipboard With parameter -PassThru output is sent to Powershell pipeline .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-CopyPaste { [CmdletBinding()] Param ( [Parameter(Mandatory=$false)] [Switch]$PassThru ) if(Get-Clipboard) { Get-Clipboard | Set-Clipboard if(-not $PassThru) { Write-Host "Clipboard ready to paste:" -Foregroundcolor Green Get-Clipboard } } else { Write-Host "Clipboard was empty" -ForeGroundColor Yellow return $null } if($PassThru) { return Get-Clipboard } } <# .Synopsis This function extracs smart html link's title and url and pastes them back to clipboard .DESCRIPTION This function extracs smart html link's title and url and pastes them back to clipboard in 2 separate lines This is good trick to paste smart html link title and url separately to document. Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-CopyPasteUrl .INPUTS Reads clipboard data .OUTPUTS Outputs extracted smart html link's title and url to clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-CopyPasteUrl { # Example string in Array # <!--StartFragment--><a href="https://learn.microsoft.com/en-us/powershell/module/psreadline/about/about_psreadline?source=recommendations&view=powershell-7.3">about PSReadLine - PowerShell | Microsoft Learn</a><!--EndFragment--> $Clipboard = Get-Clipboard -TextFormatType Html # Get line containing html fragment using normal Array filtering $HtmlFragment = $Clipboard | Where-Object { $_ -like "<!--StartFragment-->*<!--EndFragment-->" } if($HtmlFragment) { # Use -Match (regex) to extract Title and Url # Test regex in https://regex101.com # Using String: # <!--StartFragment--><a href="https://learn.microsoft.com/en-us/powershell/module/psreadline/about/about_psreadline?source=recommendations&view=powershell-7.3">about PSReadLine - PowerShell | Microsoft Learn</a><!--EndFragment--> $Matches = $null $regex = '^<!--StartFragment--><a href="(.*)">(.*)<\/a><!--EndFragment-->$' if($HtmlFragment -Match $regex) { $Topic = $Matches[2] Set-Clipboard $Topic $url = $Matches[1] Set-Clipboard $url -Append Write-Host "Clipboard ready to paste:" -Foregroundcolor Green Get-Clipboard } else { Write-Host "Warning: did not find url type clipboard information" -Foregroundcolor Yellow } } else { Write-Host "Did not find url type clipboard information" -Foregroundcolor Yellow } } <# .Synopsis This function creates new GUID and copies it to clipboard .DESCRIPTION This function creates new GUID and copies it to clipboard. You can then paste it to anywhere. Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-NewGuidToClipboard .INPUTS Reads clipboard data .OUTPUTS Outputs new GUID to clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-NewGuidToClipboard { $Guid = (New-Guid).Guid $Guid | Set-Clipboard $Success = $? if($Success) { Write-Host "$Guid copied to clipboard" -ForegroundColor Green } } <# .Synopsis This function reads JSON data from clipboard and sets uncompressed JSON back to clipboard .DESCRIPTION This function reads JSON data from clipboard and sets uncompressed JSON back to clipboard This is good trick to extract compressed JSON and also do JSON syntax validation. Conversion checks that JSON syntax is valid at the same time. With -PassThru parameter converted JSON data is sent to Powershell pipeline and can be saved to Powershell variable. Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER PassThru PassThru parameter will also output converted JSON data to Powershell pipeline. Usually this is used with saving results to variable. For example $FromJson = ClipboardTools-JsonUncompress -PassThru .PARAMETER RemovePowershellEscapes Remove Powershell escape character ` from JSON before converting data We can get escaped JSON for example from Edge Debugger This is for special cases .PARAMETER RemoveDoubleJsonEscapes Replace double JSON escape \\\\ to \\ from JSON data before converting JSON This is super rare case but sometimes when original JSON data has nested JSON data in properties they get double escaped which causes problems later. .EXAMPLE ClipboardTools-JsonUncompress .EXAMPLE $FromJson = ClipboardTools-JsonUncompress -PassThru .EXAMPLE ClipboardTools-JsonUncompress -RemovePowershellEscapes .EXAMPLE ClipboardTools-JsonUncompress -RemoveDoubleJsonEscapes .INPUTS Reads clipboard JSON data .OUTPUTS Outputs syntax checked and uncompressed JSON to clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-JsonUncompress { Param ( [Parameter(Mandatory=$false)] [Switch] $PassThru, [Parameter(Mandatory=$false)] [Switch] $RemovePowershellEscapes, [Parameter(Mandatory=$false)] [Switch] $RemoveDoubleJsonEscapes ) $Clipboard = Get-Clipboard if($Clipboard) { # Remove Powershell ` escape characters if($RemoveEscapes) { $Clipboard = $Clipboard.Replace('`','') } # Remove Json double escapes \\\\ -> \\ if($RemoveDoubleJsonEscapes) { $Clipboard = $Clipboard -replace('\\\\', '\\') } # Convert Clipboard Json data to variable Try { $json = $Clipboard | ConvertFrom-Json $Success = $? if($Success) { $json | ConvertTo-Json -Depth 10 | Set-Clipboard if($PassThru) { return $json } else { Write-Host "Paste uncompressed JSON to text editor with Ctrl-v" -Foregroundcolor Green } } else { Write-Host "Warning: Could not convert JSON data from clipboard" -ForegroundColor Yellow } } Catch { Write-Host "Warning: Clipboard data is not valid JSON" -ForegroundColor Yellow return $null } } else { Write-Host "Clipboard was empty" -ForeGroundColor Yellow } } <# .Synopsis This function reads JSON data from clipboard and puts compressed JSON back to clipboard .DESCRIPTION This function reads JSON data from clipboard and puts compressed JSON back to clipboard Conversion also checks that JSON syntax is valid. With -PassThru parameter compressed JSON data is sent to Powershell pipeline and can be saved to Powershell variable. Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER PassThru PassThru parameter will also output converted JSON data to Powershell pipeline. Usually this is used with saving results to variable. For example $CompressedJson = ClipboardTools-JsonCompress -PassThru .EXAMPLE ClipboardTools-JsonCompress .EXAMPLE $FromJson = ClipboardTools-JsonCompress -PassThru .INPUTS Reads clipboard JSON data .OUTPUTS Outputs syntax checked and compressed JSON to clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-JsonCompress { Param ( [Parameter(Mandatory=$false)] [Switch] $PassThru ) $Clipboard = Get-Clipboard if($Clipboard) { # Convert Compressed Clipboard Json data to variable Try { $json = $Clipboard | ConvertFrom-Json $Success = $? if($Success) { $json | ConvertTo-Json -Depth 10 -Compress | Set-Clipboard if($PassThru) { return $json } else { Write-Host "Paste compressed JSON to text editor with Ctrl-v" -Foregroundcolor Green } } else { Write-Host "Warning: Could not convert JSON data from clipboard" -ForegroundColor Yellow } } Catch { Write-Host "Warning: Clipboard data is not valid JSON" -ForegroundColor Yellow return $null } } else { Write-Host "Clipboard was empty" -ForeGroundColor Yellow } } <# .Synopsis This function reads image from clipboard and saves image to image file .DESCRIPTION This function reads image from clipboard and saves image to image file You can specify filename and folder with parameters -FileName and -FilePath By default file is saved to current directory and filename is {timestamp}-ImageCapture Example Filename: 20230922-ImageCapture.png Timestamp is always added before FileName. With parameter -OpenFileAfterSave file is opened to default image viewer application Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER FileName FileName for saved image .PARAMETER FilePath FilePath for saved image .PARAMETER OpenImageAfterSave Opens saved image in default image application .EXAMPLE ClipboardTools-SaveImageToFile .EXAMPLE ClipboardTools-SaveImageToFile -Name 'ImageFileName' .EXAMPLE ClipboardTools-SaveImageToFile -Name 'ImageFileName' -FilePath D:\ScreenCaptures .EXAMPLE ClipboardTools-SaveImageToFile -OpenFileAfterSave .INPUTS Reads clipboard picture data .OUTPUTS Outputs image to file .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-SaveImageToFile { Param( [Parameter(Mandatory=$false)] $FileName = 'ImageCapture', [Parameter(Mandatory=$false)] $FilePath, [Parameter(Mandatory=$false)] [switch]$OpenFileAfterSave ) # Get image from clipboard $ImageFromClipboard = Get-Clipboard -Format Image if($ImageFromClipboard) { # Set image path, timestamp and filename to saved image file $timestamp = Get-Date -Format yyyyMMdd-HHmmss # Set current path for FilePath if parameter was not specified if(-not $FilePath) { $FilePath = $pwd.Path } # Check if destination folder exists if(-not (Test-Path $FilePath)) { Write-Host "Warning: destination directory $FilePath does not exist!" -ForegroundColor Yellow Write-Host "Defaulting to current folder $($pwd.Path)" $FilePath = $pwd.Path } $FileSavePath = "$($FilePath)\$($timestamp)-$($FileName).png" $ImageFromClipboard.Save($FileSavePath) $Success = $? if($Success) { Write-Host "Successfully saved file: $FileSavePath" -ForegroundColor Green if($OpenFileAfterSave) { Write-Host "Opening image to default image application`n" # Sleep 1 seconds to make sure image file is saved to folder # For example saving to slow USB drive may take some time to complete Start-Sleep -Seconds 1 if(Test-Path $FileSavePath) { # Open image to default image application Invoke-Item $FileSavePath } else { Write-Host "Warning: File save was not completed before opening image" -ForeGroundColor Yellow Write-Host "Skipping image opening...`n" } } } else { Write-Host "Failed to save file: $FileSavePath`n" -ForegroundColor Red } } else { Write-Host "Did not detect image from clipboard`n" -ForeGroundColor Yellow } } <# .Synopsis This function reads text from clipboard and saves text to text file .DESCRIPTION This function reads text from clipboard and saves text to text file You can specify filename and folder with parameters -FileName and -FilePath Default FileName is textfile.txt and default FilePath is current working directory With parameter -Append you can add text data to (new or) existing files With parameter -Force you can overwrite existing file With parameter -OpenFileAfterSave file is opened to default text editor Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER FileName FileName for saved text file .PARAMETER FilePath FilePath for saved text file .PARAMETER Append Append text to existing file or create new text file .PARAMETER Force Overwrite existing file .PARAMETER OpenFileAfterSave Opens saved text file in default text editor .EXAMPLE ClipboardTools-SaveTextToFile .EXAMPLE ClipboardTools-SaveTextToFile -Name 'TextFile.txt' .EXAMPLE ClipboardTools-SaveTextToFile -Name 'TextFile.txt' -FilePath D:\temp .EXAMPLE ClipboardTools-SaveTextToFile -OpenFileAfterSave .EXAMPLE ClipboardTools-SaveTextToFile -Name 'TextFile.txt' -FilePath D:\temp -Append .EXAMPLE ClipboardTools-SaveTextToFile -Name 'TextFile.txt' -FilePath D:\temp -Force .INPUTS Reads clipboard text data .OUTPUTS Outputs clipboard text to file .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-SaveTextToFile { Param( [Parameter(Mandatory=$false)] $FileName = 'textfile.txt', [Parameter(Mandatory=$false)] $FilePath, [Parameter(Mandatory=$false)] [Switch]$Append, [Parameter(Mandatory=$false)] [Switch]$Force, [Parameter(Mandatory=$false)] [switch]$OpenFileAfterSave ) # Get Clipboard text $TextFromClipboard = Get-Clipboard -Format Text if($TextFromClipboard) { if(-not $FilePath) { $FilePath = $pwd.Path } $FileSavePath = "$FilePath\$FileName" if(((Test-Path $FileSavePath) -and (-not $Force)) -and ((Test-Path $FileSavePath) -and (-not $Append))){ Write-Host "Warning: Destination file already exists and -Force or -Append parameter NOT specified." -ForeGroundColor Yellow Write-Host "Will not overwrite file $filePath`n" } else { if($Append) { # Append clipboard text to possible existing file $TextFromClipboard | Add-Content -Path $FileSavePath $Success = $? if($Success) { Write-Host "Successfully appended text to file: $FileSavePath`n" -ForegroundColor Green } else { Write-Host "Failed to append text to file: $FileSavePath`n" -ForegroundColor Red } } elseif ($Force -and (-not $Append)) { # Overwrite possible existing files $TextFromClipboard | Set-Content -Path $FileSavePath -Force $Success = $? if($Success) { Write-Host "Successfully saved file: $FileSavePath`n" -ForegroundColor Green } else { Write-Host "Failed to save file: $FileSavePath`n" -ForegroundColor Red } } else { $TextFromClipboard | Set-Content -Path $FileSavePath $Success = $? if($Success) { Write-Host "Successfully saved file: $FileSavePath`n" -ForegroundColor Green } else { Write-Host "Failed to save file: $FileSavePath`n" -ForegroundColor Red } } Start-Sleep -Seconds 1 Write-Host "Opening text file to default text editor`n" # Sleep 1 seconds to make sure text file is saved to folder # For example saving to slow USB drive may take some time to complete if($OpenFileAfterSave) { if(Test-Path $FileSavePath) { # Open text file to default text editor Invoke-Item $FileSavePath } else { Write-Host "Warning: File save was not completed before opening" -ForeGroundColor Yellow Write-Host "Skipping text file opening...`n" } } } } else { Write-Host "Did not detect text from clipboard`n" -ForeGroundColor Yellow } } <# .Synopsis This function sorts text in clipboard either ascending (default) or descending order .DESCRIPTION This function sorts text in clipboard either ascending (default) or descending order With parameter -Descending you can set descending sort Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER Descending Sort clipboard text descending .EXAMPLE ClipboardTools-Sort .EXAMPLE ClipboardTools-Sort -Descending .INPUTS Reads clipboard text data .OUTPUTS Outputs sorted clipboard text back to clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-Sort { Param( [Parameter(Mandatory=$false)] [Switch]$Descending = $false ) if(Get-Clipboard -Format Text) { if(-not $Descending) { Get-Clipboard -Format Text| Sort-Object | Set-Clipboard $Success = $? } else { Get-Clipboard -Format Text| Sort-Object -Descending | Set-Clipboard $Success = $? } if($Success) { if($Descending) { Write-Host "Clipboard text is now sorted in descending order`n" -ForegroundColor Green } else { Write-Host "Clipboard text is now sorted`n" -ForegroundColor Green } } else { Write-Host "Failed to sort Clipboard text`n" -ForegroundColor Red } } else { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow } } <# .Synopsis This function checks if clipboard text has valid JSON syntax .DESCRIPTION This function checks if clipboard text has valid JSON syntax Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-ValidateJson .INPUTS Reads clipboard text .OUTPUTS None .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-ValidateJson { # Read Clipboard text $ClipboardText = Get-Clipboard -Format Text if($ClipboardText) { try { $json = $ClipboardText | ConvertFrom-Json $Success = $? if($Success) { Write-Host "Clipboard text has valid JSON syntax" -ForegroundColor Green } else { Write-Host "Clipboard text is NOT valid JSON syntax" -ForegroundColor Red } } catch { Write-Host "Clipboard text is NOT valid JSON syntax" -ForegroundColor Red } } else { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow } } <# .Synopsis This function checks if XML file in clipboard has valid xml syntax .DESCRIPTION This function checks if XML file in clipboard has valid xml syntax With parameter -PassThru converted XML is sent to Powershell pipeline and can be saved to Powershell variable. Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER PassThru PassThru parameter outputs converted XML text to Powershell pipeline. Usually this is used with saving results to variable. .EXAMPLE ClipboardTools-ValidateXml .EXAMPLE $xml = ClipboardTools-ValidateXml -PassThru .INPUTS Reads clipboard data .OUTPUTS With parameter -PassThru converted XML is sent to Powershell pipeline. .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-ValidateXml { Param( [Parameter(Mandatory=$false)] [Switch]$PassThru ) # Read Clipboard text $ClipboardText = Get-Clipboard -Format Text if($ClipboardText) { try { [xml]$xml = $ClipboardText $Success = $? if($Success) { Write-Host "Clipboard text has valid XML syntax" -ForegroundColor Green if($PassThru) { return $xml } } else { Write-Host "Clipboard text is NOT valid XML syntax" -ForegroundColor Red } } catch { Write-Host "Clipboard text is NOT valid XML syntax`n" -ForegroundColor Red Write-Host "$($_.Exception.Message)" -ForegroundColor Red } } else { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow } } <# .Synopsis This function checks if Powershell script copied to clipboard has valid Powershell syntax .DESCRIPTION This function checks if Powershell script copied to clipboard has valid Powershell syntax This is done by using command: Get-Command -Syntax temporary_scriptfile.ps1 Text/Powershell script from clipboard is saved to temporary file in TEMP directory Powershell Syntax check is done to this temporary .ps1 file Temporary file is deleted after syntax check. This will NOT run the script. Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-ValidatePowershellSyntax .INPUTS Reads Powershell script from clipboard .OUTPUTS None But script will create temporary Powershell script file to $env:temp which is deleted after syntax check .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-ValidatePowershellSyntax { # Copy Clipboard text $PowershellScriptFromClipboard = Get-Clipboard -Format Text if($PowershellScriptFromClipboard) { # Copy file to temp directory and run it from there $PowershellScriptPath = "$env:Temp\TestPowershellScriptSyntax_$((New-Guid).Guid).ps1" $PowershellScriptFromClipboard | Out-String | Set-Content -Path $PowershellScriptPath $Success = $? if($Success) { # Do Powershell syntax check to temporary Powershell file $GetCommand = Get-Command -Syntax $PowershellScriptPath $Success = $? if($Success) { Write-Host "Powershell syntax is valid`n" -ForegroundColor Green } else { Write-Host "Powershell syntax is NOT valid`n" -ForegroundColor Red } # Delete Powershell script from Temp folder Remove-Item -Path $PowershellScriptPath -Force } else { Write-Host "Something went wrong when saving temporary file: $PowershellScriptPath" -ForeGroundColor Red Write-Host "Powershell syntax validation was aborted" -ForeGroundColor Yellow } } else { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow } } <# .Synopsis This function converts base64 encoded text in clipboard to clear text .DESCRIPTION This function converts base64 encoded text in clipboard to clear text and copies converted text back to clipboard Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .PARAMETER PassThru PassThru parameter will output converted base64 text to Powershell pipeline. Usually this is used with saving results to variable. .EXAMPLE ClipboardTools-ConvertFromBase64 .EXAMPLE $ClearTextFromBase64 = ClipboardTools-ConvertFromBase64 -PassThru .INPUTS Reads clipboard base64 text and converts it to clear text .OUTPUTS Converted base64 text is copied to clipboard With parameter -PassThru converted base64 text is sent to Powershell pipeline. .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-ConvertFromBase64 { Param( [Parameter(Mandatory=$false)] [Switch]$PassThru ) [String]$Base64 = Get-Clipboard -Format Text $Success = $? if($Success) { if($Base64) { $ConvertedString = [Text.Encoding]::Utf8.GetString([Convert]::FromBase64String($Base64)) $Success = $? if($Success) { Write-Host "Converted base64 is copied to clipboard`n" -ForegroundColor Green $ConvertedString | Set-Clipboard if($PassThru) { return $ConvertedString } } else { Write-Host "Error converting from base64`n" -ForegroundColor Red } } else { Write-Host "Clipboard did not contain any data to convert`n" -ForeGroundColor Yellow } } else { Write-Host "Clipboard did not contain any data to convert`n" -ForeGroundColor Yellow } } <# .Synopsis This function converts Intune report format JSON from clipboard to "objectified" data .DESCRIPTION This function converts Intune report format JSON from clipboard to "objectified" data and then sets converted JSON report back to clipboard With parameter -PassThru processed JSON report data is sent to Powershell pipeline where you can for example save data to variable Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-24 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-ObjectifyIntuneJsonReport .EXAMPLE $IntuneReport = ClipboardTools-ObjectifyIntuneJsonReport -PassThru .INPUTS Reads clipboard (Intune report format) JSON data .OUTPUTS With parameter -PassThru processed Intune report JSON data is sent to Powershell pipeline. .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> function ClipboardTools-ObjectifyIntuneJsonReport { Param( [Parameter(Mandatory=$false)] [Switch]$PassThru ) # Read Clipboard text $ClipboardJSON = Get-Clipboard -Format Text if($ClipboardJSON) { try { $json = $ClipboardJSON | ConvertFrom-Json $Success = $? if($Success) { Write-Host "Clipboard text has valid JSON syntax" -ForegroundColor Green if($Json.Schema) { $JsonSchema = $Json.Schema } else { Write-Host "Warning: Did not detect valid Intune/Graph API report formatted JSON data" -ForeGroundColor Yellow Write-Host "Warning: Schema property missing." -ForeGroundColor Yellow return $null } if($Json.Values) { $JsonValues = $Json.Values } else { Write-Host "Warning: Did not detect valid Intune/Graph API report formatted JSON data" Write-Host "Warning: Values property missing." -ForeGroundColor Yellow return $null } # Create empty arrayList # ArrayList should be quicker if we have a huge data set # because using array and += always creates new array with added array value/object $JsonObjectArrayList = New-Object -TypeName "System.Collections.ArrayList" # Convert json data to Powershell objects in $JsonObjectArrayList foreach($Value in $JsonValues) { # We use this counter to get property name value from Schema array $i=0 # Add values to HashTable which we use to create custom Powershell object later $ValuesHashTable = @{} foreach($ValueEntry in $Value) { # Create variables $PropertyName = $JsonSchema[$i].Column $ValuePropertyType = $JsonSchema[$i].PropertyType $PropertyValue = $ValueEntry -as $ValuePropertyType # Add hashtable entry $ValuesHashTable.add($PropertyName, $PropertyValue) # Create Powershell custom object from hashtable $CustomObject = new-object psobject -Property $ValuesHashTable $i++ } # Add custom Powershell object to ArrayList $JsonObjectArrayList.Add($CustomObject) | Out-Null } # Set processed report JSON data to clipboard $JsonObjectArrayList | ConvertTo-Json -Depth 10 | Set-Clipboard if($PassThru) { $JsonObjectArrayList } } else { Write-Host "Clipboard text is NOT valid JSON syntax" -ForegroundColor Red } } catch { Write-Host "Clipboard text is NOT valid JSON syntax" -ForegroundColor Red } } else { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow } } <# .Synopsis This function converts Edge Debugger Save as Powershell -script to "real" Powershell script syntax .DESCRIPTION This function converts Edge Debugger Save as Powershell -script to "real" Powershell script syntax This function version creates Microsoft.Graph.Intune Powershell Module compatible code. "Real" Powershell syntax means real Powershell commands you can use in your scripts. Commands will do same Graph API call which you copied from Edge debugger data. Converted commands are set to clipboard so you can paste actual Powershell code to your code editor. And you can also run Powershell commands in Powershell console. Prerequisite for created Powershell code to work you need to install Intune Powershell Module You can install module with command: Install-Module -Name Microsoft.Graph.Intune -Scope CurrentUser Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-27 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-EdgeDebuggerGraphAPIExtractPowershellIntuneModule .INPUTS Reads clipboard text (Edge Debugger -> Save as Powershell -data) .OUTPUTS "Powershell script ready" Powershell code is sent to Clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-EdgeDebuggerGraphAPIExtractPowershellIntuneModule { # We will get array of strings $Clipboard = Get-Clipboard -Format Text if(-not $Clipboard) { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow return $null } # Remove escapes $Clipboard = $Clipboard.Replace('`','') # Find Invoke-WebRequest string $InvokeWebRequest = $Clipboard | Where-Object { $_ -like "Invoke-WebRequest *" } # Find uri $regex = '^Invoke-WebRequest.*-Uri "(.*)".*$' if($InvokeWebRequest -match $regex) { $Uri = $Matches[1] # Add escapes before $ character $Uri = $Uri.Replace('$','`$') } else { $Uri=$null Write-Host "Could not parse Uri from Edge Debugger Powershell copy" -ForegroundColor Red return $null } # Extract Method (=POST, PATCH, PUT, DELETE) $MethodString = $Clipboard | Where-Object { $_ -like "-Method *" } if($MethodString) { $regex = '^-Method "(.*)".*$' if($MethodString -match $regex) { $Method = $Matches[1] } else { # There is no Method parameter with Get method $Method="Get" } } else { # There is no Method parameter with Get method $Method="Get" } # Extract body json $BodyString = $Clipboard | Where-Object { $_ -like "-Body *" } if($BodyString) { # Examples # -Body ([System.Text.Encoding]::UTF8.GetBytes("{`"@odata.type`":`"#microsoft.graph.winGetApp`"}}")) if(($BodyString -match '^-Body "(.*)".*$') -or ($BodyString -match '^-Body \(\[System.Text.Encoding\]::UTF8\.GetBytes\("(.*)"\)\)$')) { $Body = $Matches[1] $BodyJson = $Body | ConvertFrom-Json | ConvertTo-Json -Depth 10 # Add escapes to $ characters $BodyJson = $BodyJson.Replace('$','`$') } else { # There is no Body parameter with Get method $Body=$null } } else { # There is no Body parameter with Get method $Body=$null } # DEBUG #Write-Host "Uri=$Uri" #Write-Host "Method=$Method" #Write-Host "Body=$Body" #Write-Host "BodyJson=$BodyJson" if($BodyJson){ # Method is POST, PUT, PATCH or DELETE with Body information $Paste = @" # Connect to Graph API using Microsoft Intune module Update-MSGraphEnvironment -SchemaVersion 'beta' Connect-MSGraph `$Url = `"$Uri`" `$Body = `@`" $BodyJson `"`@ # Get data from Graph API `$MSGraphRequest = `$null `$MSGraphRequest = Invoke-MSGraphRequest -Url `$url -Content `$Body.ToString() -HttpMethod '$Method' if(`$MSGraphRequest) { # Print results `$MSGraphRequest } else { Write-Host "Did not get any results from Graph API!" -ForegroundColor Yellow } "@ } else { # Method is GET or DELETE without Body in request $Paste = @" # Connect to Graph API using Microsoft Intune module Update-MSGraphEnvironment -SchemaVersion 'beta' Connect-MSGraph `$Url = `"$Uri`" # Get data from Graph API `$MSGraphRequest = `$null `$MSGraphRequest = Invoke-MSGraphRequest -Url `$url -HttpMethod '$Method' if(`$MSGraphRequest) { # Print results `$MSGraphRequest } else { Write-Host "Did not get any results from Graph API!" -ForegroundColor Yellow } # Get all data from Graph API (gets all paged data) # This can be used to get all paged results from Graph API #`$AllMSGraphRequest = Get-MSGraphAllPages -SearchResult `$MSGraphRequest # # Or if you used Get-MSGraphAllPages #`$AllMSGraphRequest "@ } # DEBUG #Write-Host "Paste=$Paste" # Set edited info back to Clipboard $Paste | Set-Clipboard } <# .Synopsis This function converts Edge Debugger Save as Powershell -script to "real" Powershell script syntax .DESCRIPTION This function converts Edge Debugger Save as Powershell -script to "real" Powershell script syntax This function version creates Microsoft.Graph Powershell Module compatible code. "Real" Powershell syntax means real Powershell commands you can use in your scripts. Commands will do same Graph API call which you copied from Edge debugger data. Converted commands are set to clipboard so you can paste actual Powershell code to your code editor. And you can also run Powershell commands in Powershell console. Prerequisite for created Powershell code to work you need to install Intune Powershell Module You can install module with command: Install-Module Microsoft.Graph -Scope CurrentUser Author: Petri.Paavola@yodamiitti.fi Senior Modern Management Principal Microsoft MVP - Windows and Devices 2023-09-27 https://github.com/petripaavola/ClipboardTools .EXAMPLE ClipboardTools-EdgeDebuggerGraphAPIExtractPowershellMGGraphModule .INPUTS Reads clipboard text (Edge Debugger -> Save as Powershell -data) .OUTPUTS "Powershell script ready" Powershell code is sent to Clipboard .NOTES None .LINK https://github.com/petripaavola/ClipboardTools #> Function ClipboardTools-EdgeDebuggerGraphAPIExtractPowershellMGGraphModule { # We will get array of strings $Clipboard = Get-Clipboard -Format Text if(-not $Clipboard) { Write-Host "Clipboard did not contain any text`n" -ForeGroundColor Yellow return $null } # Remove escapes $Clipboard = $Clipboard.Replace('`','') # Find Invoke-WebRequest string $InvokeWebRequest = $Clipboard | Where-Object { $_ -like "Invoke-WebRequest *" } # Find uri $regex = '^Invoke-WebRequest.*-Uri "(.*)".*$' if($InvokeWebRequest -match $regex) { $Uri = $Matches[1] # Add escapes before $ character $Uri = $Uri.Replace('$','`$') } else { $Uri=$null Write-Host "Could not parse Uri from Edge Debugger Powershell copy" -ForegroundColor Red return $null } # Extract Method (=POST, PATCH, PUT, DELETE) $MethodString = $Clipboard | Where-Object { $_ -like "-Method *" } if($MethodString) { $regex = '^-Method "(.*)".*$' if($MethodString -match $regex) { $Method = $Matches[1] } else { # There is no Method parameter with Get method $Method="Get" } } else { # There is no Method parameter with Get method $Method="Get" } # Extract body json $BodyString = $Clipboard | Where-Object { $_ -like "-Body *" } if($BodyString) { # Examples # -Body ([System.Text.Encoding]::UTF8.GetBytes("{`"@odata.type`":`"#microsoft.graph.winGetApp`"}}")) if(($BodyString -match '^-Body "(.*)".*$') -or ($BodyString -match '^-Body \(\[System.Text.Encoding\]::UTF8\.GetBytes\("(.*)"\)\)$')) { $Body = $Matches[1] $BodyJson = $Body | ConvertFrom-Json | ConvertTo-Json -Depth 10 # Add escapes to $ characters $BodyJson = $BodyJson.Replace('$','`$') } else { # There is no Body parameter with Get method $Body=$null } } else { # There is no Body parameter with Get method $Body=$null } # DEBUG #Write-Host "Uri=$Uri" #Write-Host "Method=$Method" #Write-Host "Body=$Body" #Write-Host "BodyJson=$BodyJson" if($BodyJson){ # Method is POST, PUT, PATCH or DELETE with Body information $Paste = @" # Connect to Graph API using Microsoft Graph module # Install Microsoft Graph module with command # Install-Module Microsoft.Graph -Scope CurrentUser #Connect-MgGraph Connect-MgGraph -Scopes "DeviceManagementManagedDevices.Read.All", "DeviceManagementApps.Read.All", "DeviceManagementConfiguration.Read.All", "User.Read.All", "Group.Read.All", "GroupMember.Read.All", "Directory.Read.All" # Install Graph Beta module with command # Install-Module Microsoft.Graph.Beta -Scope CurrentUser #Select-MgProfile beta `$Uri = `"$Uri`" `$Body = `@`" $BodyJson `"`@ # Note! There seems to be either a bug or a feature with POST requests with Invoke-MgGraphRequest # In some testings command succeeds but does not return anything to Powershell pipeline # but with -Debug option you can see that the data has been fetched from Graph API # For now one workaround is to save data to text file which we'll do here # Get data from Graph API # Original request #`$MgGraphRequest = Invoke-MgGraphRequest -Uri `$Uri -Body `$Body.ToString() -Method '$Method' -OutputType PSObject # Workaround to save data to random named text file first with parameter -OutputFilePath `$OutputFilePath = `"`$(`$pwd.path)/MgGraphRequest_`$(Get-Random).json`" `$MgGraphRequest = Invoke-MgGraphRequest -Uri `$Uri -Body `$Body.ToString() -Method '$Method' -OutputFilePath `$OutputFilePath # Read and convert json data from temporary text file `$MgGraphRequest = Get-Content `$OutputFilePath -Raw | ConvertFrom-Json # Remove temporary file Remove-Item -Path `$OutputFilePath if(`$MgGraphRequest) { # Print results # Usually you want to check values from `$MgGraphRequest.value Write-Host `"Print variable: MgGraphRequest`" `$MgGraphRequest } else { Write-Host "Did not get any results from Graph API!" -ForegroundColor Yellow } "@ } else { # Method is GET or DELETE without Body in request $Paste = @" # Connect to Graph API using Microsoft Graph module # Install Microsoft Graph module with command # Install-Module Microsoft.Graph -Scope CurrentUser #Connect-MgGraph Connect-MgGraph -Scopes "DeviceManagementManagedDevices.Read.All", "DeviceManagementApps.Read.All", "DeviceManagementConfiguration.Read.All", "User.Read.All", "Group.Read.All", "GroupMember.Read.All", "Directory.Read.All" # Install Graph Beta module with command # Install-Module Microsoft.Graph.Beta -Scope CurrentUser #Select-MgProfile beta `$Uri = `"$Uri`" # Get data from Graph API `$MgGraphRequest = Invoke-MgGraphRequest -Uri `$Uri -Method '$Method' -OutputType PSObject if(`$MgGraphRequest) { # Print results # Usually you want to check values from `$MgGraphRequest.value Write-Host `"Print variable: MgGraphRequest`" `$MgGraphRequest } else { Write-Host "Did not get any results from Graph API!" -ForegroundColor Yellow } "@ } # DEBUG #Write-Host "Paste=$Paste" # Set edited info back to Clipboard $Paste | Set-Clipboard } |