{"id":15203030,"url":"https://github.com/jdhitsolutions/psscripttools","last_synced_at":"2025-05-15T01:07:11.827Z","repository":{"id":41203323,"uuid":"112522235","full_name":"jdhitsolutions/PSScriptTools","owner":"jdhitsolutions","description":":wrench: :hammer: A set of PowerShell functions you might use to enhance your own functions and scripts or to facilitate working in the console. Most should work in both Windows PowerShell and PowerShell 7, even cross-platform. Any operating system limitations should be handled on a per command basis. The Samples folder contains demonstration script files","archived":false,"fork":false,"pushed_at":"2025-03-26T18:02:52.000Z","size":85266,"stargazers_count":953,"open_issues_count":1,"forks_count":114,"subscribers_count":40,"default_branch":"main","last_synced_at":"2025-05-12T06:45:53.095Z","etag":null,"topics":["powershell","powershell-core","powershell7","scripting"],"latest_commit_sha":null,"homepage":"","language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdhitsolutions.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"license.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":"https://paypal.me/jdhitsolutions?locale.x=en_US"}},"created_at":"2017-11-29T20:07:04.000Z","updated_at":"2025-05-08T13:39:54.000Z","dependencies_parsed_at":"2024-04-12T23:45:53.367Z","dependency_job_id":"21ad7503-2467-4c58-8e72-7f1015f1d3fe","html_url":"https://github.com/jdhitsolutions/PSScriptTools","commit_stats":null,"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdhitsolutions%2FPSScriptTools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdhitsolutions%2FPSScriptTools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdhitsolutions%2FPSScriptTools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdhitsolutions%2FPSScriptTools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdhitsolutions","download_url":"https://codeload.github.com/jdhitsolutions/PSScriptTools/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254254041,"owners_count":22039792,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["powershell","powershell-core","powershell7","scripting"],"created_at":"2024-09-28T04:22:25.068Z","updated_at":"2025-05-15T01:07:06.818Z","avatar_url":"https://github.com/jdhitsolutions.png","language":"PowerShell","readme":"# PSScriptTools Overview\n\n![PSGallery Version](https://img.shields.io/powershellgallery/v/PSScripttools.png?style=for-the-badge\u0026logo=powershell\u0026label=PowerShell%20Gallery)![PSGallery Downloads](https://img.shields.io/powershellgallery/dt/PSScripttools.png?style=for-the-badge\u0026label=Downloads)\n\n![PowerShell Toolbox](images/pstoolbox-256.jpeg)\n\n## Abstract\n\nThis module contains a collection of functions, variables, and format files that you can use to enhance your PowerShell scripting work or get more done from a PowerShell prompt with less typing. Most of the commands are designed to work cross-platform. Please post any questions, problems, or feedback in the [Issues](https://github.com/jdhitsolutions/PSScriptTools/issues) section of this module's GitHub repository. Feedback is greatly appreciated.\n\nThe contents of this file and other documentation can be viewed using the `Open-PSScriptToolsHelp` command. You can also use `Get-PSScriptTools` to see a summary of module commands.\n\nPlease note that code samples have been formatted to _fit an *80-character_ width.* Some example code breaks lines without using line continuation characters. I'm trusting that you can figure out how to run the example.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [General Tools](#general-tools)\n- [File Tools](#file-tools)\n- [Editor Integrations](#editor-integrations)\n- [Graphical Tools](#graphical-tools)\n- [Hashtable Tools](#hashtable-tools)\n- [Select Functions](#select-functions)\n- [Time Functions](#time-functions)\n- [Console Utilities](#console-utilities)\n- [Format Functions](#format-functions)\n- [Scripting Tools](#scripting-tools)\n- [CIM Tools](#cim-tools)\n- [ANSI Tools](#ansi-tools)\n- [Other Module Features](#other-module-features)\n- [Related Modules](#related-modules)\n- [Compatibility](#compatibility)\n\n## Installation\n\nYou can get the current release from this repository or install this from the [PowerShell Gallery](https://powershellgallery.com):\n\n```powershell\nInstall-Module PSScriptTools\n```\n\nor in PowerShell 7:\n\n```powershell\nInstall-Module PSScriptTools [-scope CurrentUser] [-force]\n```\n\nStarting in v2.2.0, the module was restructured to better support `Desktop` and `Core` editions. However, starting with v2.13.0, the module design has reverted. All module commands will be exported. Anything that is platform-specific should be handled on a per-command basis. It is assumed you will be running this module in Windows PowerShell 5.1 or PowerShell 7.\n\nIt is recommended to install this module from the PowerShell Gallery and not GitHub.\n\nTo remove the module from your system, you can easily uninstall it with common PowerShell commands.\n\n```powershell\nGet-Module PSScriptTools | Remove-Module\nUninstall-Module PSScriptTools -AllVersions\n```\n\n## General Tools\n\n### [Get-MyCounter](docs/Get-MyCounter.md)\n\n`Get-MyCounter` is an enhanced version of the legacy `Get-Counter` cmdlet, which is available on Windows platforms to retrieve performance counter data. One of the challenges with using `Get-Counter` is how it formats results. The information may be easy to read on the screen, but it is cumbersome to use in a pipelined expression.\n\n`Get-MyCounter` takes the same information and writes a custom object to the pipeline that is easier to work with. You can pipe counters from `Get-Counter` to `Get-MyCounter`.\n\n![Get-MyCounter](images/get-mycounter1.png)\n\n![Get-MyCounter Remote](images/get-mycounter2.png)\n\nOne advantage of `Get-MyCounter` over `Get-Counter` is that the performance data is easier to work with.\n\n```powershell\nGet-MyCounter '\\IPv4\\datagrams/sec' -MaxSamples 60 -SampleInterval 5 -computer SRV1 | Export-CSV  c:\\work\\srv1_ipperf.csv -NoTypeInformation\n ```\n\nIn this example, the performance counter is sampled 60 times every 5 seconds and the data is exported to a CSV file which could easily be opened in Microsoft Excel. Here's a sample of the output object.\n\n```dos\nComputername : SRV1\nCategory     : ipv4\nCounter      : datagrams/sec\nInstance     :\nValue        : 66.0818918347238\nTimestamp    : 11/4/2022 11:31:29 AM\n```\n\n`Get-MyCounter` writes a custom object to the pipeline which has an associated formatting file with custom views.\n\n![Get-MyCounter view](images/get-mycounter3.png)\n\n### [Get-DirectoryInfo](docs/Get-DirectoryInfo.md)\n\nThis command, which has an alias of _dw_, is designed to provide quick access to top-level directory information. The default behavior is to show the total number of files in the immediate directory. Although, the command will also capture the total file size in the immediate directory. You can use the Depth parameter to recurse through a specified number of levels. The default displays use ANSI escape sequences.\n\n![Get-DirectoryInfo](images/dw-1.png)\n\nThe command output will use a wide format by default. However, other wide views are available.\n\n![Get-DirectoryInfo MB](images/dw-2.png)\n\nYou can use the object in other ways.\n\n![Get-DirectoryInfo table](images/dw-3.png)\n\n### [Get-FormatView](docs/Get-FormatView.md)\n\nPowerShell's formatting system includes several custom views that display objects in different ways. Unfortunately, this information is not readily available to a typical PowerShell user. This command displays the available views for a given object type.\n\n![Get-FormatView](images/get-formatview.png)\n\nThis command has an alias of `gfv`.\n\n### [Copy-PSFunction](docs/Copy-PSFunction.md)\n\nThis command is designed to solve the problem when you want to run a function loaded locally on a remote computer. `Copy-PSFunction` will copy a PowerShell function that is loaded in your current PowerShell session to a remote PowerShell session. The remote session must already be created. The copied function only exists remotely for the duration of the remote PowerShell session.\n\n```powershell\n$s = New-PSSession -ComputerName win10 -cred $art\nCopy-PSFunction Get-Status -Session $s\n```\n\nOnce copied, you might use `Invoke-Command` to run it.\n\n```powershell\nInvoke-Command { Get-Status -AsString } -session $s\n```\n\nIf the function relies on external or additional files, you will have to copy them to the remote session separately.\n\n### [Get-PSProfile](docs/Get-PSProfile.md)\n\nThis command is designed for Windows systems and makes it easy to identify all possible PowerShell profile scripts. Including those for hosts such as VSCode or the PowerShell ISE. The command writes a custom object to the pipeline which has defined formatting. The default view is a table.\n\n```dos\nPS C:\\\u003e Get-PSProfile\n\n   Name: PowerShell\n\nScope                  Path                                                                Exists\n-----                  ----                                                                ------\nAllUsersCurrentHost    C:\\Program Files\\PowerShell\\7\\Microsoft.PowerShell_profile.ps1      False\nAllUsersAllHosts       C:\\Program Files\\PowerShell\\7\\profile.ps1                           False\nCurrentUserAllHosts    C:\\Users\\Jeff\\Documents\\PowerShell\\profile.ps1                      True\nCurrentUserCurrentHost C:\\Users\\Jeff\\Documents\\PowerShell\\Microsoft.PowerShell_profile.ps1 True\n\n\n   Name: Windows PowerShell\n\nScope                  Path                                                                Exists\n-----                  ----                                                                ------\nAllUsersCurrentHost    C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\Microsoft.PowerShell...  True\nAllUsersAllHosts       C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\profile.ps1              True\nCurrentUserAllHosts    C:\\Users\\Jeff\\Documents\\WindowsPowerShell\\profile.ps1               True\nCurrentUserCurrentHost C:\\Users\\Jeff\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_p... True\n```\n\nThere is also a list view.\n\n```dos\nPS C:\\\u003e Get-PSProfile | Where-Object {$_.name -eq 'powershell'} | Format-List\n\n\n   Name: PowerShell\n\n\nScope        : AllUsersCurrentHost\nPath         : C:\\Program Files\\PowerShell\\7\\Microsoft.PowerShell_profile.ps1\nExists       : False\nLastModified :\n\nScope        : AllUsersAllHosts\nPath         : C:\\Program Files\\PowerShell\\7\\profile.ps1\nExists       : False\nLastModified :\n\nScope        : CurrentUserAllHosts\nPath         : C:\\Users\\Jeff\\Documents\\PowerShell\\profile.ps1\nExists       : True\nLastModified : 9/9/2024 2:35:45 PM\n\nScope        : CurrentUserCurrentHost\nPath         : C:\\Users\\Jeff\\Documents\\PowerShell\\Microsoft.PowerShell_profile.ps1\nExists       : True\nLastModified : 9/9/2024 2:03:44 PM\n```\n\n### [Get-MyAlias](docs/Get-MyAlias.md)\n\nOften you might define aliases for functions and scripts you use all of the time. It may be difficult sometimes to remember them all or to find them in the default `Get-Alias` output. This command will list all currently defined aliases that are not part of the initial PowerShell state.\n\n![Get-MyAlias](images/gma-1.png)\n\nThese are all aliases defined in the current session that aren't part of the initial session state. You can filter aliases to make it easier to find those that aren't defined in a module. These aliases should be ones created in your stand-alone scripts or PowerShell profile.\n\n![Get-MyAlias No Module](images/gma-2.png)\n\nThe PSScriptTools module also includes a custom formatting file for alias objects which you can use with `Get-Alias` or `Get-MyAlias`.\n\n```powershell\nGet-Alias | Sort-Object Source | Format-Table -View source\n```\n\n![Alias source](images/alias-source.png)\n\nThis command has an alias of `gma`.\n\n### [Get-ModuleCommand](docs/Get-ModuleCommand.md)\n\nThis is an alternative to `Get-Command` to make it easier to see at a glance what commands are contained within a module and what they can do. By default, `Get-ModuleCommand` looks for loaded modules. Use `-ListAvailable` to see commands in the module not currently loaded. Note that if the help file is malformed or missing, you might get oddly formatted results.\n\n```dos\nPS C:\\\u003e Get-ModuleCommand PSCalendar -ListAvailable\n\n   ModuleName: PSCalendar [v2.9.0]\n\nName                        Alias Synopsis\n----                        ----- --------\nGet-Calendar                cal   Displays a visual representation of a\n                                  calendar.\nGet-MonthName                     Get the list of month names.\nGet-NCalendar               ncal  Display a Linux-style ncal calendar.\nGet-PSCalendarConfiguration       Get the current PSCalendar ANSI configuration.\nSet-PSCalendarConfiguration       Modify the PSCalendar ANSI configuration.\nShow-Calendar               scal  Display a colorized calendar month in the\n                                  console.\nShow-GuiCalendar            gcal  Display a WPF-based calendar.\nShow-PSCalendarHelp               Display a help PDF file for the PSCalendar\n                                  module.\n```\n\nThere are also alternate table views.\n\n```dos\nPS C:\\\u003e Get-ModuleCommand PSCalendar | Format-Table -View verb\n\n   Verb: Get\n\nName                           Alias           Type        Synopsis\n----                           -----           ----        --------\nGet-Calendar                   cal             Function    Displays a visual\n                                                           representation of a\n                                                           calendar.\nGet-MonthName                                  Function    Get the list of\n                                                           month names.\nGet-NCalendar                  ncal            Function    Display a\n                                                           Linux-style ncal\n                                                           calendar.\nGet-PSCalendarConfiguration                    Function    Get the current\n                                                           PSCalendar ANSI\n                                                           configuration.\n\n\n   Verb: Set\n\nName                           Alias           Type        Synopsis\n----                           -----           ----        --------\nSet-PSCalendarConfiguration                    Function    Modify the\n                                                           PSCalendar ANSI\n                                                           configuration.\n\n\n   Verb: Show\n\nName                           Alias           Type        Synopsis\n----                           -----           ----        --------\nShow-Calendar                  scal            Function    Display a colorized\n                                                           calendar month in\n                                                           the console.\nShow-GuiCalendar               gcal            Function    Display a WPF-based\n                                                           calendar.\nShow-PSCalendarHelp                            Function    Display a help PDF\n                                                           file for the\n                                                           PSCalendar module.\n```\n\nGet module commands using the default formatted view. There is also a default view for `Format-List`.\n\n### [Get-PSScriptTools](docs/Get-PSScriptTools.md)\n\nYou can use this command to get a summary list of functions in this module.\n\n```dos\n\nPS C:\\\u003e Get-PSScriptTools\n\n   Verb: Add\n\nName             Alias                Synopsis\n----             -----                --------\nAdd-Border                            Create a text border around a string.\n\n\n   Verb: Compare\n\nName            Alias                Synopsis\n----            -----                --------\nCompare-Module  cmo                  Compare PowerShell module versions.\n...\n```\n\nHere's another way you could use this command to list functions with defined aliases in the PSScriptTools module.\n\n```dos\nPS C:\\\u003e Get-PSScriptTools | Where-Object alias |\nSelect-Object Name,alias,Synopsis\n\nName                   Alias Synopsis\n----                   ----- --------\nCompare-Module         cmo   Compare PowerShell module versions.\nConvert-EventLogRecord clr   Convert EventLogRecords to structured objects\nConvertFrom-Text       cft   Convert structured text to objects.\nConvertFrom-UTCTime    frut  Convert a datetime value from universal\nConvertTo-LocalTime    clt   Convert a foreign time to local\n...\n```\n\n### [Convert-EventLogRecord](docs/Convert-EventLogRecord.md)\n\nWhen you use [Get-WinEvent](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.diagnostics/get-winevent?view=powershell-7\u0026WT.mc_id=ps-gethelp), the results are objects you can work with in PowerShell. However, often, there is additional information that is part of the event log record, such as replacement strings, that are used to construct a message. This additional information is not readily exposed. You can use this command to convert the results of a `Get-WinEvent` command into a PowerShell custom object with additional information.\n\n```dos\nPS C:\\\u003e Get-WinEvent -FilterHashtable @{LogName='System';ID=7045} -MaxEvents 1|\nConvert-EventLogRecord\n\n\nLogName      : System\nRecordType   : Information\nTimeCreated  : 1/21/2024 3:49:46 PM\nID           : 7045\nServiceName  : Netwrix Account Lockout Examiner\nImagePath    : \"C:\\Program Files (x86)\\Netwrix\\Account Lockout Examiner\n              \\ALEService.exe\"\nServiceType  : user mode service\nStartType    : auto start\nAccountName  : bovine320\\jeff\nMessage      : A service was installed in the system.\n\n               Service Name:  Netwrix Account Lockout Examiner\n               Service File Name:  \"C:\\Program Files (x86)\\Netwrix\\Account\n               Lockout Examiner\\ALEService.exe\"\n               Service Type:  user mode service\n               Service Start Type:  auto start\n               Service Account:  bovine320\\jeff\nKeywords     : {Classic}\nSource       : Service Control Manager\nComputername : Bovine320\n```\n\n### [Get-WhoIs](docs/Get-WhoIs.md)\n\nThis command will retrieve WhoIs information from the ARIN database for a given IPv4 address.\n\n```dos\nPS C:\\\u003e Get-WhoIs 208.67.222.222 | Select-Object -Property *\n\nIP                     : 208.67.222.222\nName                   : OPENDNS-NET-1\nRegisteredOrganization : Cisco OpenDNS, LLC\nCity                   : San Jose\nStartAddress           : 208.67.216.0\nEndAddress             : 208.67.223.255\nNetBlocks              : 208.67.216.0/21\nUpdated                : 12/14/2024 8:28:33 PM\n\nPS C:\\\u003e '1.1.1.1','8.8.8.8','208.67.222.222'| Get-WhoIs | Format-List\n\nIP                     : 1.1.1.1\nName                   : APNIC-1\nRegisteredOrganization : Asia Pacific Network Information Centre\nCity                   : South Brisbane\nStartAddress           : 1.0.0.0\nEndAddress             : 1.255.255.255\nNetBlocks              : 1.0.0.0/8\nUpdated                : 7/30/2010 9:23:43 AM\n\nIP                     : 8.8.8.8\nName                   : GOGL\nRegisteredOrganization : Google LLC\nCity                   : Mountain View\nStartAddress           : 8.8.8.0\nEndAddress             : 8.8.8.255\nNetBlocks              : 8.8.8.0/24\nUpdated                : 12/28/2023 5:24:56 PM\n\nIP                     : 208.67.222.222\nName                   : OPENDNS-NET-1\nRegisteredOrganization : Cisco OpenDNS, LLC\nCity                   : San Jose\nStartAddress           : 208.67.216.0\nEndAddress             : 208.67.223.255\nNetBlocks              : 208.67.216.0/21\nUpdated                : 12/14/2024 8:28:33 PM\n```\n\nThis module includes a custom format file for these results.\n\n### [Compare-Module](docs/Compare-Module.md)\n\nUse this command to compare module versions between what is installed against an online repository like the PSGallery\n\n```dos\nPS C:\\\u003e Compare-Module Platyps\n\nName             : platyPS\nOnlineVersion    : 0.14.2\nInstalledVersion : 0.14.2\nPublishedDate    : 7/2/2024 10:53:28 PM\nUpdateNeeded     : False\n```\n\nOr you can compare and manage multiple modules.\n\n```powershell\nCompare-Module | Where UpdateNeeded |\nOut-GridView -title \"Select modules to update\" -outputMode multiple |\nForeach { Update-Module $_.name }\n```\n\nThis example compares modules and sends the results to `Out-GridView`. Use `Out-GridView` as an object picker to decide what modules to update.\n\n### [Get-WindowsVersion](docs/Get-WindowsVersion.md)\n\nThis is a PowerShell version of the `winver.exe` utility. This command uses PowerShell remoting to query the registry on a remote machine to retrieve Windows version information.\n\n```powershell\nGet-WindowsVersion -Computername win10,srv1,srv2 -Credential company\\artd\n```\n\n![get windows version](images/get-windowsversion.png)\n\nThe output has a default table view but there are other properties you might want to use.\n\n```dos\nPS C:\\\u003e Get-WindowsVersion | Select-Object *\n\nProductName    : Microsoft Windows 11 Pro\nReleaseVersion : 24H2\nEditionID      : Professional\nReleaseID      : 2009\nBuild          : 26100.3613\nBranch         : ge_release\nInstalledUTC   : 6/17/2024 1:30:52 AM\nComputername   : PROSPERO\n```\n\nBeginning with version 2.45.0, `Get-WindowsVersion` will use the command-line tool `systeminfo.exe` to retrieve the operating system name. If this fails, then the registry value will be used. Windows 11 systems don't yet reflect with Windows 11 name in the registry.\n\n#### [Get-WindowsVersionString](docs/Get-WindowsVersionString.md)\n\nThis command is a variation of `Get-WindowsVersion` that returns a formatted string with version information.\n\n```dos\nPS C:\\\u003e Get-WindowsVersionString\nPROSPERO Microsoft Windows 11 Pro Version Professional (OS Build 26100.3613)\n```\n\n### [New-PSDriveHere](docs/New-PSDriveHere.md)\n\nThis function will create a new PSDrive at the specified location. The default is the current location, but you can specify any PSPath. by default, the function will take the last word of the path and use it as the name of the new PSDrive.\n\n```dos\nPS C:\\users\\jeff\\documents\\Enterprise Mgmt Webinar\u003e New-PSDriveHere -SetLocation\nPS Webinar:\\\u003e\n```\n\nYou can use the first word in the leaf location or specify something completely different.\n\n```PowerShell\nNew-PSDriveHere \\\\ds416\\backup\\ Backup\n```\n\n### [Get-MyVariable](docs/Get-MyVariable.md)\n\nThis function will return all variables not defined by PowerShell or by this function itself. The default is to return all user-created variables from the global scope, but you can also specify a scope such as `script`, `local`, or a number 0 through 5.\n\n```dos\nPS C:\\\u003e Get-MyVariable\n\nNName Value                  Type\n---- -----                  ----\na    bits                   ServiceController\ndt   10/22/2024 10:49:38 AM DateTime\nfoo  123                    Int32\nr    {1, 2, 3, 4...}        Object[]\n...\n```\n\nDepending on the value and how PowerShell chooses to display it, you may not see the type.\n\n### [ConvertFrom-Text](docs/ConvertFrom-Text.md)\n\nThis command can be used to convert text from a file or a command-line tool into objects. It uses a regular expression pattern with named captures and turns the result into a custom object. You have the option of specifying a type name in case you are using custom format files.\n\n```dos\nPS C:\\\u003e $arp = '(?\u003cIPAddress\u003e(\\d{1,3}\\.){3}\\d{1,3})\\s+(?\u003cMAC\u003e(\\w{2}-){5}\\w{2})\\s+(?\u003cType\u003e\\w+$)'\nPS C:\\\u003e arp -g -N 172.16.10.22 | Select-Object -skip 3 |\nforeach {$_.Trim()} | ConvertFrom-Text $arp -TypeName arpData -NoProgress\n\nIPAddress          MAC                        Type\n---------          ---                        ----\n172.16.10.1        b6-fb-e4-16-41-be       dynamic\n172.16.10.100      00-11-32-58-7b-10       dynamic\n172.16.10.115      5c-aa-fd-0c-bf-fa       dynamic\n172.16.10.120      5c-1d-d9-58-81-51       dynamic\n172.16.10.159      3c-e1-a1-17-6d-0a       dynamic\n172.16.10.162      00-0e-58-ce-8b-b6       dynamic\n172.16.10.178      00-0e-58-8c-13-ac       dynamic\n172.16.10.185      d0-04-01-26-b5-61       dynamic\n172.16.10.186      e8-b2-ac-95-92-98       dynamic\n172.16.10.197      fc-77-74-9f-f4-2f       dynamic\n172.16.10.211      14-20-5e-93-42-fb       dynamic\n172.16.10.222      28-39-5e-3b-04-33       dynamic\n172.16.10.226      00-0e-58-e9-49-c0       dynamic\n172.16.10.227      48-88-ca-e1-a6-00       dynamic\n172.16.10.239      5c-aa-fd-83-f1-a4       dynamic\n172.16.255.255     ff-ff-ff-ff-ff-ff        static\n224.0.0.2          01-00-5e-00-00-02        static\n224.0.0.7          01-00-5e-00-00-07        static\n224.0.0.22         01-00-5e-00-00-16        static\n224.0.0.251        01-00-5e-00-00-fb        static\n224.0.0.252        01-00-5e-00-00-fc        static\n239.255.255.250    01-00-5e-7f-ff-fa        static\n```\n\nThis example uses a previously created and imported format.ps1xml file for the custom type name.\n\n### [Get-PSWho](docs/Get-PSWho.md)\n\nThis command will provide a summary of relevant information for the current user in a PowerShell Session. You might use this to troubleshoot an end-user problem running a script or command.\n\n```dos\nPS C:\\\u003e Get-PSWho\n\nUser            : COMPANY\\ArtD\nElevated        : True\nComputername    : WIN10\nOperatingSystem : Microsoft Windows 10 Enterprise [64-bit]\nOSVersion       : 10.0.19045\nPSVersion       : 5.1.19041.5607\nEdition         : Desktop\nPSHost          : ConsoleHost\nWSMan           : 3.0\nExecutionPolicy : RemoteSigned\nCulture         : English (United States)\n```\n\nYou can also turn this into a text block using the `AsString` parameter. This is helpful when you want to include the output in some type of report.\n\n![PSWho Report](images/Add-Border-ansi2.png)\n\n### [Out-VerboseTee](docs/Out-VerboseTee.md)\n\nThis command is intended to let you see your verbose output and write the verbose messages to a log file. It will only work if the verbose pipeline is enabled, usually when your command is run with -Verbose. This function is designed to be used within your scripts and functions. You either have to hard-code a file name or find some other way to define it in your function or control script. You could pass a value as a parameter or set it as a `PSDefaultParameterValue`.\n\nThis command has aliases `Tee-Verbose` and `tv`.\n\n```powershell\nBegin {\n    $log = New-RandomFilename -useTemp -extension log\n    Write-Detail \"Starting $($MyInvocation.MyCommand)\" -Prefix begin |\n    Tee-Verbose $log\n    Write-Detail \"Logging verbose output to $log\" -prefix begin |\n    Tee-Verbose -append\n    Write-Detail \"Initializing data array\" -Prefix begin |\n    Tee-Verbose $log -append\n    $data = @()\n} #begin\n```\n\nWhen the command is run with -Verbose you will see the verbose output **and** it will be saved to the specified log file.\n\n### [Remove-Runspace](docs/Remove-Runspace.md)\n\nThroughout your PowerShell work, you may discover that some commands and scripts can leave behind runspaces such as `ConvertTo-WPFGrid`. You may even deliberately be creating additional runspaces. These runspaces will remain until you exit your PowerShell session. Or use this command to cleanly close and dispose of runspaces.\n\n```powershell\nGet-RunSpace | where ID -gt 1 | Remove-RunSpace\n```\n\nGet all runspaces with an ID greater than 1, which is typically your current session, and remove the runspace.\n\n### [Get-PSLocation](docs/Get-PSLocation.md)\n\nA simple function to get common locations. This can be useful with cross-platform scripting.\n\n![Windows locations](images/pslocation-win.png)\n\n![Linux locations](images/pslocation-linux.png)\n\n### [Get-PowerShellEngine](docs/Get-PowerShellEngine.md)\n\nUse this command to quickly get the path to the PowerShell executable. In Windows, you should get a result like this:\n\n```dos\nPS C:\\\u003e Get-PowerShellEngine\nC:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\n```\n\nBut PowerShell on non-Windows platforms is a bit different:\n\n```dos\nPS /home/jhicks\u003e Get-PowerShellEngine\n/opt/microsoft/powershell/7/pwsh\n```\n\nYou can also get detailed information.\n\n![Windows PowerShell](images/get-powershellengine1.png)\n\n![PowerShell Core on Windows](images/get-powershellengine2.png)\n\n![PowerShell Core on Linux](images/get-powershellengine3.png)\n\nResults will vary depending on whether you are running PowerShell on Windows or non-Windows systems.\n\n### [Get-PathVariable](docs/Get-PathVariable.md)\n\nOver time, as you add and remove programs, your `%PATH%` might change. An application may add a location but not remove it when you uninstall the application. This command makes it easier to identify locations and whether they are still good.\n\n```dos\nPS C:\\\u003e Get-PathVariable\n\nScope   UserName Path                                                    Exists\n-----   -------- ----                                                    ------\nUser    Jeff     C:\\Program Files\\kdiff3                                   True\nUser    Jeff     C:\\Program Files (x86)\\Bitvise SSH Client                 True\nUser    Jeff     C:\\Program Files\\OpenSSH                                  True\nUser    Jeff     C:\\Program Files\\Intel\\WiFi\\bin\\                          True\nUser    Jeff     C:\\Program Files\\Common Files\\Intel\\WirelessCommon\\       True\nUser    Jeff     C:\\Users\\Jeff\\AppData\\Local\\Programs\\Microsoft VS Co...   True\nUser    Jeff     C:\\Program Files (x86)\\Vale\\                              True\n...\n```\n\n## File Tools\n\n### [Get-LastModifiedFile](docs/Get-LastModifiedFile.md)\n\nGet files last modified within a certain interval. The default is 24 hours.\n\n```dos\nPS C:\\\u003e Get-LastModifiedFile -Path c:\\work\n\n    Directory: C:\\work\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a---          11/30/2024  1:52 PM           2010 a.txt\n-a---          11/30/2024  1:52 PM           5640 b.txt\n```\n\nBut you can specify other ranges.\n\n```dos\nPS C:\\\u003e Get-LastModifiedFile -Path c:\\scripts -filter *.xml -Interval Months -IntervalCount 6\n\n    Directory: C:\\Scripts\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a---           8/31/2024  7:12 PM          17580 DefaultDomainPolicy.xml\n-a---           8/31/2024  7:12 PM          17290 PKIAutoEnroll.xml\n-a---           8/31/2024  8:43 PM           9786 sample-gpo.xml\n-a---           8/31/2024  7:24 PM          50062 TestUser.xml\n-a---           6/22/2024  7:47 PM           4628 vaults.xml\n```\n\nYou might use this command with other PowerShell commands to get usage statistics.\n\n```dos\nPS C:\\\u003e Get-LastModifiedFile -Path c:\\scripts -Recurse -Interval Years -IntervalCount 1 |\nGroup-Object {$_.LastWriteTime.month} |\nSelect-Object @{Name=\"Month\";Expression = {\"{0:MMM}\" -f (Get-Date -Month $_.Name)}},\nCount\n\nMonth Count\n----- -----\nJan     152\nFeb     200\nMar     228\nApr     169\nMay     106\nJun      92\nJul      86\nAug     112\nSep     109\nOct     136\nNov     225\nDec     216\n```\n\n### [Get-FileExtensionInfo](docs/Get-FileExtensionInfo.md)\n\nThis command will search a given directory and produce a report of all files based on their file extension. This command is only available in PowerShell 7. The extension with the largest total size will be highlighted in color.\n\n![Get-FileExtensionInfo](images/gfei.png)\n\n### [Test-EmptyFolder](docs/Test-EmptyFolder.md)\n\nThis command will test if a given folder path is empty of all files anywhere in the path. This includes hidden files. The command will return True even if there are empty sub-folders. The default output is True or False but you can use -PassThru to get more information.\n\n```dos\nPS C:\\\u003e Get-ChildItem c:\\work -Directory | Test-EmptyFolder -PassThru |\nWhere-Object {$_.IsEmpty} |\nForeach-Object { Remove-Item -LiteralPath $_.path -Recurse -force -WhatIf}\n\nWhat if: Performing the operation \"Remove Directory\" on target \"C:\\work\\demo3\".\nWhat if: Performing the operation \"Remove Directory\" on target \"C:\\work\\installers\".\nWhat if: Performing the operation \"Remove Directory\" on target \"C:\\work\\new\".\nWhat if: Performing the operation \"Remove Directory\" on target \"C:\\work\\sqlback\".\nWhat if: Performing the operation \"Remove Directory\" on target \"C:\\work\\todd\".\nWhat if: Performing the operation \"Remove Directory\" on target \"C:\\work\\[data]\".\n```\n\nFind all empty sub-folders under `C:\\Work` and pipe them to `Remove-Item`. This is one way to remove empty folders. The example is piping objects to `ForEach-Object` so that `Remove-Item` can use the -LiteralPath parameter because `C:\\work\\[data]` is a non-standard path.\n\n### [Get-FolderSizeInfo](docs/Get-FolderSizeInfo.md)\n\nUse this command to quickly get the size of a folder. You also have the option to include hidden files. The command will measure all files in all subdirectories.\n\n```dos\nPS C:\\\u003e Get-FolderSizeInfo c:\\work\n\nComputername    Path                        TotalFiles     TotalSize\n------------    ----                        ----------     ---------\nBOVINE320       C:\\work                            931     137311146\n\n\nPS C:\\\u003e Get-FolderSizeInfo c:\\work -Hidden\n\nComputername    Path                         TotalFiles     TotalSize\n------------    ----                         ----------     ---------\nBOVINE320       C:\\work                            1375     137516856\n```\n\nThe command includes a format file with an additional view to display the total size in KB, MB, GB, or TB.\n\n```dos\nPS C:\\\u003e Get-ChildItem D:\\ -Directory | Get-FolderSizeInfo -Hidden |\nWhere-Object TotalSize -gt 1gb | Sort-Object TotalSize -Descending |\nFormat-Table -View gb\n\nComputername    Path                               TotalFiles   TotalSizeGB\n------------    ----                              ----------   -----------\nBOVINE320       D:\\Autolab                               159      137.7192\nBOVINE320       D:\\VMDisks                                18      112.1814\nBOVINE320       D:\\ISO                                    17       41.5301\nBOVINE320       D:\\FileHistory                        104541       36.9938\nBOVINE320       D:\\Vagrant                                13       19.5664\nBOVINE320       D:\\Vms                                    83        5.1007\nBOVINE320       D:\\2016                                 1130        4.9531\nBOVINE320       D:\\video                                 125         2.592\nBOVINE320       D:\\blog                                21804        1.1347\nBOVINE320       D:\\pstranscripts                      122092        1.0914\n```\n\nOr you can use the `name` view.\n\n```dos\nPS C:\\\u003e Get-ChildItem c:\\work -Directory | Get-FolderSizeInfo -Hidden |\nWhere-Object {$_.TotalSize -ge 2mb} | Format-Table -view name\n\n\n   Path: C:\\work\n\nName                    TotalFiles      TotalKB\n----                    ----------      -------\nA                               20    5843.9951\nkeepass                         15     5839.084\nPowerShellBooks                 26    4240.3779\nsunday                          47   24540.6523\n```\n\n### [Optimize-Text](docs/Optimize-Text.md)\n\nUse this command to clean and optimize content from text files. Sometimes text files have blank lines, or the content has trailing spaces. These sorts of issues can cause problems when passing the content to other commands.\n\nThis command will strip out any lines that are blank or have nothing by white space, and trim leading and trailing spaces. The optimized text is then written back to the pipeline. Optionally, you can specify a property name. This can be useful when your text file is a list of computer names and you want to take advantage of pipeline binding.\n\n### [Get-FileItem](docs/Get-FileItem.md)\n\nA PowerShell version of the CLI `where.exe` command. You can search with a simple or regex pattern.\n\n```dos\nPS C:\\\u003e pswhere winword.exe -Path c:\\ -Recurse -first\n\nC:\\Program Files\\Microsoft Office\\root\\Office16\\WINWORD.EXE\n```\n\nNote that you might see errors for directories where you don't have access permission. This is normal.\n\n### [New-CustomFileName](docs/New-CustomFileName.md)\n\nThis command will generate a custom file name based on a template string that you provide.\n\n```dos\nPS C:\\\u003e New-CustomFileName %computername_%day%monthname%yr-%time.log\nPC_28Nov19-142138.log\n\nPS C:\\\u003e New-CustomFileName %dayofweek-%####.dat\nTuesday-3128.dat\n```\n\nYou can create a template string using any of these variables. Most of these should be self-explanatory.\n\n- %username\n- %computername\n- %year  - 4-digit year\n- %yr  - 2-digit year\n- %monthname - The abbreviated month name\n- %month  - The month number\n- %dayofweek - The full name of the weekday\n- %day\n- %hour\n- %minute\n- %time\n- %string - A random string\n- %guid\n\nYou can also insert a random number using `%` followed by a `#` character for each digit you want.\n\n```dos\n22 = %##\n654321 = %######\n```\n\n### [New-RandomFilename](docs/New-RandomFilename.md)\n\nCreate a new random file name. The default is a completely random name, including the extension.\n\n```dos\nPS C:\\\u003e New-RandomFilename\nfykxecvh.ipw\n```\n\nBut you can specify an extension.\n\n```dos\nPS C:\\\u003e New-RandomFilename -extension dat\nemevgq3r.dat\n```\n\nOptionally you can create a random file name using the TEMP folder or your HOME folder. On Windows platforms, this will default to your Documents folder.\n\n```dos\nPS C:\\\u003e New-RandomFilename -extension log -UseHomeFolder\nC:\\Users\\Jeff\\Documents\\kbyw4fda.log\n```\n\nOn Linux machines, it will be the home folder.\n\n```dos\nPS /mnt/c/scripts\u003e New-RandomFilename -home -Extension tmp\n/home/jhicks/oces0epq.tmp\n```\n\n### [ConvertTo-Markdown](docs/ConvertTo-Markdown.md)\n\nThis command is designed to accept pipelined output and create a markdown document. The pipeline output will be formatted as a text block or a table You can optionally define a title, content to appear before the output, and content to appear after the output. You can run a command like this:\n\n```powershell\nGet-Service Bits,Winrm |\nConvertTo-Markdown -title \"Service Check\" -PreContent \"## $($env:computername)\"\n-PostContent \"_report $(Get-Date)_\"\n ```\n\nwhich generates this markdown:\n\n```markdown\n    # Service Check\n\n    ## THINKX1\n\n    ```dos\n\n    Status   Name               DisplayName\n    ------   ----               -----------\n    Running  Bits               Background Intelligent Transfer Ser...\n    Running  Winrm              Windows Remote Management (WS-Manag...\n    ```\n\n    _report 09/25/2024 09:57:12_\n```\n\nYou also have the option to format the output as a markdown table.\n\n```powershell\nConvertTo-Markdown -title \"OS Summary\" -PreContent \"## $($env:computername)\" -PostContent \"_Confidential_\" -AsTable\n```\n\nWhich creates this markdown output.\n\n```markdown\n# OS Summary\n\n## THINKX1-JH\n\n| ProductName | EditionID | ReleaseID | Build | Branch | InstalledUTC | Computername |\n| ----------- | --------- | --------- | ----- | ------ | ------------ | ------------ |\n| Windows 10 Pro | Professional | 2009 | 22000.376 | co_release | 08/10/2024 00:17:07 | THINKX1-JH |\n\n_Confidential_\n```\n\n![ConvertTo-Markdown table](images/convert-markdown-table.png)\n\nOr you can create a list table with the property name in one column and the value in the second column.\n\n```powershell\nGet-WindowsVersion | ConvertTo-Markdown -title \"OS Summary\" -PreContent \"## $($env:computername)\" -PostContent \"_Confidential_\" -AsList\n```\n\n```markdown\n# OS Summary\n\n## THINKX1-JH\n\n|    |    |\n|----|----|\n|ProductName|Windows 10 Pro|\n|EditionID|Professional|\n|ReleaseID|2009|\n|Build|22000.376|\n|Branch|co_release|\n|InstalledUTC|8/10/2024 12:17:07 AM|\n|Computername|THINKX1-JH|\n\n_Confidential_\n```\n\n![ConvertTo-Markdown list](images/convert-markdown-list.png)\n\nBecause the function writes markdown to the pipeline you will need to pipe it to a command `Out-File` to create a file.\n\n## Editor Integrations\n\nBecause this module is intended to make scripting easier for you, it adds a few editor-specific features if you import this module in either the PowerShell ISE or Visual Studio Code. The VS Code features assume you are using the integrated PowerShell terminal.\n\n### Insert ToDo\n\nOne such feature is the ability to insert ToDo statements into PowerShell files. If you are using the PowerShell ISE or VS Code and import this module, it will add the capability to insert a line like this:\n\n```dos\n    # [12/13/2024 16:52:40] TODO: Add parameters\n```\n\nIn the PowerShell ISE, you will get a new menu under Add-Ons.\n\n![new menu](images/todo-1.png)\n\nYou can use the menu or keyboard shortcut which will launch an input box.\n\n![input box](images/todo-2.png)\n\nThe comment will be inserted at the current cursor location.\n\nIn VS Code, access the command palette (Ctrl+Shift+P) and then `PowerShell: Show Additional Commands from PowerShell Modules`. Select `Insert ToDo` from the list, and you'll get the same input box. Note that this will only work for PowerShell files.\n\n### Set Terminal Location\n\nAnother feature is the ability to set your terminal location to match that of the currently active file. For example, if the current file is located in `C:\\Scripts\\Foo` and your terminal location is `D:\\Temp\\ABC`, you can quickly jump to the file location.\n\n```dos\nPS D:\\Temp\\ABC\\\u003e sd\nPS C:\\Scripts\\Foo\\\u003e\n```\n\nThe full command name is `Set-LocationToFile` but you'll find it easier to use the `sd` or `jmp` aliases. This command will also clear the host.\n\n## Graphical Tools\n\n### [Invoke-InputBox](docs/Invoke-InputBox.md)\n\nThis function is a graphical replacement for `Read-Host`. It creates a simple WPF form that you can use to get user input. The value of the text box will be written to the pipeline.\n\n```powershell\n$name = Invoke-InputBox -Prompt \"Enter a user name\" -Title \"New User Setup\"\n```\n\n![input box](images/ibx-1.png)\n\nYou can also capture a secure string.\n\n```powershell\nInvoke-InputBox -Prompt \"Enter a password for $Name\" -AsSecureString\n -BackgroundColor red\n```\n\n![secure input box](images/ibx-2.png)\n\nThis example also demonstrates that you can change the form's background color. This function will **not** work in PowerShell Core.\n\n### [New-WPFMessageBox](docs/New-WPFMessageBox.md)\n\nThis function creates a Windows Presentation Foundation (WPF) based message box. This is intended to replace the legacy MsgBox function from VBScript and the Windows Forms library. The command uses a set of predefined button sets, each of which will close the form and write a value to the pipeline.\n\n- OK     = 1\n- Cancel = 0\n- Yes    = $True\n- No     = $False\n\nYou can also create an ordered hashtable of buttons and values. It is assumed you will typically use this function in a script where you can capture the output and take some action based on the value.\n\n```powershell\nNew-WPFMessageBox -Message \"Are you sure you want to do this?\"\n-Title Confirm -Icon Question -ButtonSet YesNo\n```\n\n![A YesNo WPF Message box](images/wpfbox-1.png)\n\nYou can also create your a custom button set as well as modify the background color.\n\n```powershell\nNew-WPFMessageBox -Message \"Select a system option from these choices:\"\n-Title \"You Decide\" -Background cornsilk -Icon Warning\n-CustomButtonSet ([ordered]@{\"Reboot\"=1;\"Shutdown\"=2;\"Cancel\"=3})\n```\n\n![A customized WPF Message box](images/wpfbox-2.png)\n\n### [ConvertTo-WPFGrid](docs/ConvertTo-WPFGrid.md)\n\nThis command is an alternative to `Out-GridView`. It works much the same way. Run a PowerShell command and pipe it to this command. The output will be displayed in an auto-sized data grid. You can click on column headings to sort. You can resize columns and you can re-order columns.\n\n```powershell\nGet-Eventlog -list -ComputerName DOM1,SRV1,SRV2 |\nSelect MachineName,Log,MaximumKilobytes,OverflowAction,\n@{Name=\"RetentionDays\";Expression={$_.MinimumRetentionDays}},\n@{Name=\"Entries\";Expression = {$_.entries.count}} |\nConvertTo-WPFGrid -Title \"Event Log Report\"\n```\n\n![Displaying Eventlog Info](images/wpfgrid.png)\n\nYou can also automatically refresh the data.\n\n```powershell\nGet-Process | Sort-Object WS -Descending |\nSelect-Object -first 20 ID,Name,WS,VM,PM,Handles,StartTime |\nConvertTo-WPFGrid -Refresh -timeout 20 -Title \"Top Processes\"\n```\n\n![Displaying Top Processes](images/wpfgrid2.png)\n\nNote that in v2.4.0 the form layout was modified and may not be reflected in these screenshots.\n\n## Hashtable Tools\n\n### [Convert-CommandToHashtable](docs/Convert-CommandToHashtable.md)\n\nThis command is intended to convert a long PowerShell expression with named parameters into a splatting alternative.\n\n```dos\nPS C:\\\u003e Convert-CommandToHashtable -Text \"get-eventlog -listlog\n-computername a,b,c,d -ErrorAction stop\"\n\n$paramHash = @{\n  listlog = $True\n  computername = \"a\",\"b\",\"c\",\"d\"\n  ErrorAction = \"stop\"\n}\n\nGet-EventLog @paramHash\n```\n\nThe idea is that you can copy the output of the command into a script file.\n\n### [Convert-HashtableString](docs/Convert-HashtableString.md)\n\nThis function is similar to `Import-PowerShellDataFile`. But where that command can only process a file, this command will take any hashtable-formatted string and convert it into an actual hashtable.\n\n```dos\nPS C:\\\u003e Get-Content c:\\work\\test.psd1 | Unprotect-CMSMessage |\nConvert-HashtableString\n\nName                           Value\n----                           -----\nCreatedBy                      BOVINE320\\Jeff\nCreatedAt                      10/02/2024 21:28:47 UTC\nComputername                   Think51\nError\nCompleted                      True\nDate                           10/02/2024 21:29:35 UTC\nScriptblock                    restart-service spooler -force\nCreatedOn                      BOVINE320\n```\n\nThe test.psd1 file is protected as a CMS Message. In this example, the contents are decoded as a string which is then in turn converted into an actual hashtable.\n\n### [Convert-HashtableToCode](docs/Convert-HashtableToCode.md)\n\nUse this command to convert a hashtable into its text or string equivalent.\n\n```dos\nPS C:\\\u003e $h = @{Name=\"SRV1\";Asset=123454;Location=\"Omaha\"}\nPS C:\\\u003e Convert-HashtableToCode $h\n@{\n        Name = 'SRV1'\n        Asset = 123454\n        Location = 'Omaha'\n}\n```\n\nConvert a hashtable object to a string equivalent that you can copy into your script.\n\n### [ConvertTo-Hashtable](docs/ConvertTo-Hashtable.md)\n\nThis command will take an object and create a hashtable based on its properties. You can have the hashtable exclude some properties as well as properties that have no value.\n\n```dos\nPS C:\\\u003e Get-Process -id $pid | Select-Object Name,Id,Handles,WorkingSet |\nConvertTo-Hashtable\n\nName                           Value\n----                           -----\nWorkingSet                     418377728\nName                           powershell_ise\nId                             3456\nHandles                        958\n```\n\n### [Join-Hashtable](docs/Join-Hashtable.md)\n\nThis command will combine two hash tables into a single hash table. `Join-Hashtable` will test for duplicate keys. If any of the keys from the first, or primary hashtable are found in the secondary hashtable, you will be prompted for which to keep. Or you can use `-Force` which will always keep the conflicting key from the first hashtable.\n\n```dos\nPS C:\\\u003e $a = @{Name=\"Jeff\";Count=3;Color=\"Green\"}\nPS C:\\\u003e $b = @{Computer=\"HAL\";Enabled=$True;Year=2024;Color=\"Red\"}\nPS C:\\\u003e Join-Hashtable $a $b\nDuplicate key Color\nA Green\nB Red\nWhich key do you want to KEEP \\[AB\\]?: A\n\nName                           Value\n----                           -----\nYear                           2024\nName                           Jeff\nEnabled                        True\nColor                          Green\nComputer                       HAL\nCount                          3\n```\n\n### [Rename-Hashtable](docs/Rename-Hashtable.md)\n\nThis command allows you to rename a key in an existing hashtable or ordered dictionary object.\n\n```dos\nPS C:\\\u003e $h = Get-Service Spooler | ConvertTo-Hashtable\n```\n\nThe hashtable in $h has a MachineName property which can be renamed.\n\n```dos\nPS C:\\\u003e Rename-Hashtable -Name h -Key MachineName -NewKey Computername\n-PassThru\n\nName                           Value\n----                           -----\nServiceType                    Win32OwnProcess, InteractiveProcess\nServiceName                    Spooler\nContainer\nCanPauseAndContinue            False\nRequiredServices               {RPCSS, http}\nServicesDependedOn             {RPCSS, http}\nComputername                   .\nCanStop                        True\nStartType                      Automatic\nSite\nServiceHandle                  SafeServiceHandle\nDisplayName                    Print Spooler\nCanShutdown                    False\nStatus                         Running\nName                           Spooler\nDependentServices              {Fax}\n```\n\n## Select Functions\n\nThe module contains several functions that simplify the use of `Select-Object` or `Select-Object` in conjunction with `Where-Object`. The commands are intended to make it easier to select objects in a pipelined expression. The commands include features so that you can sort the incoming objects on a given property first.\n\n### [Select-First](docs/Select-First.md)\n\nNormally, you might run a command with `Select-Object` like this:\n\n```powershell\nGet-Process | Select-Object -first 5 -Property WS -Descending\n\nHandles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName\n-------  ------    -----      -----     ------     --  -- -----------\n    696      89   615944     426852     391.97   7352   0 sqlservr\n    541      78   262532     274576     278.41   6208   8 Code\n   1015      70   227824     269504     137.39  16484   8 powershell_ise\n   1578     111   204852     254640      98.58  21332   8 firefox\n    884      44   221872     245712     249.23  12456   8 googledrivesync\n```\n\nTo streamline the process a bit, you can use `Select-First`.\n\n```powershell\nGet-Process | Select-First 5 -Property WS -Descending\n\nHandles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName\n-------  ------    -----      -----     ------     --  -- -----------\n    696      89   615944     426852     391.97   7352   0 sqlservr\n    541      78   262532     274576     278.41   6208   8 Code\n   1015      70   227824     269504     137.39  16484   8 powershell_ise\n   1578     111   204852     254640      98.58  21332   8 firefox\n    884      44   221872     245712     249.23  12456   8 googledrivesync\n```\n\nEven better, use the command alias _first_.\n\n```powershell\nGet-Process | Sort-Object ws -Descending | first 5\n```\n\n### [Select-Last](docs/Select-Last.md)\n\nYou can perform a similar operation using `Select-Last` or its alias _last_.\n\n```powershell\nGet-ChildItem -Path c:\\scripts\\*.ps1 | Sort-Object LastWriteTime | last 10\n```\n\n### [Select-After](docs/Select-After.md)\n\n`Select-After` is a simplified version of `Select-Object`. The premise is that you can pipe a collection of objects to this command and select objects after a given `DateTime`, based on a property, like LastWriteTime, which is the default. This command has an alias of _after_.\n\n```powershell\nGet-ChildItem -Path c:\\scripts\\ -file | after 11/1/2024\n\n\n    Directory: C:\\Scripts\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a---           11/2/2024 11:08 AM           3522 Get-ServiceWPFRunspace.ps1\n-a---           11/1/2024 11:05 AM           5321 Trace.ps1\n-a---           11/2/2024 11:39 AM           2321 WinFormDemo2.ps1\n```\n\nOr you can specify property depending on the object.\n\n```powershell\nGet-Process | after (Get-Date).AddMinutes(-1) -Property StartTime\n\n NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName\n ------    -----      -----     ------      --  -- -----------\n     13     3.14      13.73       0.05   19156   2 notepad\n```\n\nThis is selecting all processes that started within the last minute.\n\n### [Select-Before](docs/Select-Before.md)\n\n`Select-Before` is the opposite of `Select-After`.\n\n```powershell\nGet-ChildItem -Path c:\\scripts -file | before 1/1/2008\n\n\n    Directory: C:\\Scripts\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a---           12/5/2007  2:19 PM          29618 1000MaleNames.txt\n-a---            4/8/2006 10:27 AM           3779 530215.ps1\n-a---            8/7/2005  1:00 AM           4286 ADUser.wsc\n-a---           9/18/2006  9:27 PM           1601 allserviceinfo.ps1\n...\n```\n\nAs with `Select-After`, you can specify a property to use.\n\n```powershell\nGet-AdUser -filter * -Properties WhenCreated |\nBefore 11/1/2024 -Property WhenCreated | Select-Object Name,WhenCreated\n\n\nName           WhenCreated\n----           -----------\nAdministrator  10/26/2024 6:47:39 PM\nGuest          10/26/2024 6:47:39 PM\nDefaultAccount 10/26/2024 6:47:39 PM\nkrbtgt         10/26/2024 6:50:47 PM\nMaryL          10/26/2024 6:56:24 PM\nArtD           10/26/2024 6:56:24 PM\nAprilS         10/26/2024 6:56:25 PM\nMikeS          10/26/2024 6:56:25 PM\n...\n```\n\n### [Select-Newest](docs/Select-Newest.md)\n\n`Select-Newest` is designed to make it easier to select X number of objects based on a `DateTime` property. The default property value is LastWriteTime.\n\n```powershell\nGet-ChildItem -Path d:\\temp -file | newest 10\n\n\n    Directory: D:\\temp\n\nMode              LastWriteTime        Length Name\n----              -------------        ------ ----\n-a---        11/4/2024  5:12 PM       5149954 watcherlog.txt\n-a---        11/3/2024 10:00 PM          3215 DailyIncremental_202411031000.txt\n-a---        11/2/2024 10:00 PM         11152 DailyIncremental_202411021000.txt\n-a---        11/2/2024  3:40 PM           852 t.ps1\n-a---        11/1/2024 10:00 PM          2376 DailyIncremental_202411011000.txt\n-a---       10/31/2024 10:00 PM          3150 DailyIncremental_202410311000.txt\n-a---       10/30/2024 10:07 PM         17844 WeeklyFull_202410301000.txt\n-a---       10/30/2024  1:00 PM        208699 datatfile-5.png\n-a---       10/30/2024 12:57 PM       1264567 datatfile-4.png\n-a---       10/30/2024 12:27 PM        421341 datatfile-3.png\n```\n\nOr specify a property.\n\n```powershell\nGet-ADUser -filter * -Properties WhenCreated |\n Select-Newest 5 -Property WhenCreated |\n Select-object DistinguishedName,WhenCreated\n\nDistinguishedName                                WhenCreated\n-----------------                                -----------\nCN=Marcia Brady,OU=Employees,DC=Company,DC=Pri   11/4/2024 3:15:27 PM\nCN=Gladys Kravitz,OU=Employees,DC=Company,DC=Pri 11/4/2024 3:14:45 PM\nCN=S.Talone,OU=Employees,DC=Company,DC=Pri       10/26/2024 3:56:31 PM\nCN=A.Fieldhouse,OU=Employees,DC=Company,DC=Pri   10/26/2024 3:56:31 PM\nCN=K.Moshos,OU=Employees,DC=Company,DC=Pri       10/26/2024 3:56:31 PM\n```\n\n### [Select-Oldest](docs/Select-Oldest.md)\n\n`Select-Oldest` is the opposite of `Select-Newest` and works the same way.\n\n```powershell\nGet-Process | newest 5 -Property StartTime\n\nHandles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName\n-------  ------    -----      -----     ------     --  -- -----------\n    145       8     1692       7396       0.02   9676   0 SearchFilterHost\n    344      13     2604      13340       0.02  33668   0 SearchProtocolHost\n    114       7     1340       6116       0.02  35028   0 svchost\n    140       8     2684       8796       0.03  32552   0 svchost\n    118       8     1580       7476       0.02  35668   0 svchost\n```\n\nThese custom Select commands are not necessarily designed for performance and there may be better ways to achieve the same results from these examples.\n\n## Time Functions\n\nThe module has a couple of date and time-related commands.\n\n### [ConvertTo-UTCTime](docs/ConvertTo-UTCTime.md)\n\nConvert a local `DateTime` value to universal time. The default is to convert the current time, but you can specify a datetime value.\n\n```dos\nPS C:\\\u003e ConvertTo-UTCTime\n\nWednesday, March 26, 2025 5:09:31 PM\n```\n\nConvert a datetime that is UTC-5 to universal time.\n\n### [ConvertFrom-UTCTime](docs/ConvertFrom-UTCTime.md)\n\n```dos\nPS C:\\\u003e ConvertFrom-UTCTime \"3/4/2025 6:00PM\"\n\nTuesday, March 4, 2025 1:00:00 PM\n```\n\nConvert a universal `DateTime` to the local time.\n\n### [Get-MyTimeInfo](docs/Get-MyTimeInfo.md)\n\nDisplay a group of time settings for a collection of locations. This command is a PowerShell equivalent of a world clock. It will display a `DateTime` value against a collection of locations. You can specify an ordered hashtable of locations and time zones. You can run a command like:\n\n```powershell\n[System.TimeZoneinfo]::GetSystemTimeZones() | Out-GridView\n```\n\nor\n\n```powershell\nGet-TimeZone -ListAvailable\n```\n\nTo discover time zone names. Note that the ID is case-sensitive. You can then use the command like this:\n\n```dos\nPS C:\\\u003e Get-MyTimeInfo -Locations ([ordered]@{Seattle=\"Pacific Standard time\";\n\"New Zealand\" = \"New Zealand Standard Time\"}) -HomeTimeZone\n\"central standard time\" | Select Now,Home,Seattle,'New Zealand'\n\nNow                  Home                  Seattle               New Zealand\n---                  ----                  -------               -----------\n3/26/2025 1:10:55 PM 3/26/2025 12:10:55 PM 3/26/2025 10:10:55 AM 3/27/2025 6:10:55 AM\n```\n\nThis is a handy command when traveling and your laptop is using a locally derived time and you want to see the time in other locations. It is recommended that you set a PSDefaultParameter value for the HomeTimeZone parameter in your PowerShell profile.\n\n### [ConvertTo-LocalTime](docs/ConvertTo-LocalTime.md)\n\nIt can be tricky sometimes to see a time in a foreign location and try to figure out the local time. This command attempts to simplify this process. In addition to the remote time, you need the base UTC offset for the remote location.\n\n```dos\nPS C:\\\u003e Get-TimeZone -ListAvailable | Where-Object id -match Hawaii\n\nId                         : Hawaiian Standard Time\nHasIanaId                  : False\nDisplayName                : (UTC-10:00) Hawaii\nStandardName               : Hawaiian Standard Time\nDaylightName               : Hawaiian Daylight Time\nBaseUtcOffset              : -10:00:00\nSupportsDaylightSavingTime : False\n\nPS C:\\\u003e ConvertTo-LocalTime \"10:00AM\" -10:00:00\n\nWednesday, March 26, 2025 4:00:00 PM\n```\n\nIn this example, the user is first determining the UTC offset for Hawaii. Then 10:00 AM, in say Honolulu, is converted to local time, which in this example is in the Eastern Time zone.\n\n### [Get-TZList](docs/Get-TZList.md)\n\nThis command uses a free and publicly available REST API offered by [http://worldtimeapi.org](http://worldtimeapi.org) to get a list of time zone areas. You can get a list of all areas or by geographic location. Use `Get-TZData` to then retrieve details.\n\n```dos\nPS C:\\\u003e Get-TZList Australia\nAustralia/Adelaide\nAustralia/Brisbane\nAustralia/Broken_Hill\nAustralia/Currie\nAustralia/Darwin\nAustralia/Eucla\nAustralia/Hobart\nAustralia/Lindeman\nAustralia/Lord_Howe\nAustralia/Melbourne\nAustralia/Perth\nAustralia/Sydney\n```\n\n### [Get-TZData](docs/Get-TZData.md)\n\nThis command also uses the API from WorldTimeAPI.org to retrieve details about a given time zone area.\n\n```dos\nPS C:\\\u003e Get-TZData Australia/Hobart\n\nTimezone                        Label        Offset     DST                  Time\n--------                        -----        ------     ---                  ----\nAustralia/Hobart                AEDT       11:00:00    True  3/27/2025 4:12:04 AM\n```\n\nThe Time value is the current time at the remote location. The command presents a formatted object but you can also get the raw data.\n\n```dos\nPS C:\\\u003e Get-TZData Australia/Hobart -Raw\n\nweek_number  : 13\nutc_offset   : +11:00\nunixtime     : 1743009143\ntimezone     : Australia/Hobart\ndst_until    : 2025-04-05T16:00:00+00:00\ndst_from     : 2024-10-05T16:00:00+00:00\ndst          : True\nday_of_year  : 86\nday_of_week  : 4\ndatetime     : 2025-03-27T04:12:23.000000+11:00\nabbreviation : AEDT\n```\n\n### [ConvertTo-LexicalTime](docs/ConvertTo-LexicalTime.md)\n\nWhen working with `TimeSpan` objects or durations in XML files, such as those from scheduled tasks, the format is a little different than what you might expect. The specification is described at [https://www.w3.org/TR/xmlschema-2/#duration](https://www.w3.org/TR/xmlschema-2/#duration). Use this command to convert a timespan into a lexical format you can use in an XML file where you need to specify a duration.\n\n```dos\nPS C:\\\u003e ConvertTo-LexicalTimespan (New-TimeSpan -Days 7 -hours 12)\nP7DT12H\n```\n\n### [ConvertFrom-LexicalTime](docs/ConvertFrom-LexicalTime.md)\n\nLikewise, you might need to convert a lexical value back into a timespan.\n\n```dos\nPS C:\\\u003e ConvertFrom-LexicalTimeSpan P7DT12H\n\nDays              : 7\nHours             : 12\nMinutes           : 0\nSeconds           : 0\nMilliseconds      : 0\nTicks             : 6480000000000\nTotalDays         : 7.5\nTotalHours        : 180\nTotalMinutes      : 10800\nTotalSeconds      : 648000\nTotalMilliseconds : 648000000\n```\n\nThese functions were first described at [https://jdhitsolutions.com/blog/powershell/7101/converting-lexical-timespans-with-powershell/](https://jdhitsolutions.com/blog/powershell/7101/converting-lexical-timespans-with-powershell/)\n\n## Console Utilities\n\n### [Get-PSSessionInfo](docs/Get-PSSessionInfo.md)\n\n`Get-PSSessionInfo` will display a summary of your current PowerShell session. It should work on all platforms.\n\n![Windows session](images/pssessioninfo-windows.png)\n\n![Linux session](images/pssessioninfo-linux.png)\n\nIf you are running in a PowerShell console session, and the Elevated value is True, it will be displayed in color. The Memory and Runtime values are calculated `ScriptProperties`.\n\n### [Out-Copy](docs/Out-Copy.md)\n\nThis command is intended for writers and those who need to document with PowerShell. You can pipe any command to this function, and you will get the regular output in your PowerShell session. Simultaneously, a copy of the output will be sent to the Windows clipboard. The copied output will include a prompt constructed from the current location unless you use the `CommandOnly` parameter.\n\nYou can run a command like:\n\n```powershell\nGet-Process | Sort WS -Descending | Select-Object -first 5 | Out-Copy\n```\n\nThis text will be copied to the clipboard.\n\n```dos\nPS C:\\\u003e Get-Process | Sort WS -Descending | Select -first 5\n\nHandles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName\n-------  ------    -----      -----     ------     --  -- -----------\n   1849     253   810320     820112     445.38  17860   1 firefox\n    765      61   949028     758200      23.36   6052   0 sqlservr\n    446     115   441860     471032      28.59  18204   1 Teams\n   2307     192   313204     459616     325.23  15748   1 firefox\n   2050     163   451744     433772      94.63  19780   1 thunderbird\n```\n\n### [Out-More](docs/Out-More.md)\n\nThis command provides a PowerShell alternative to the cmd.exe **MORE** command, which doesn't work in the PowerShell ISE. When you have screens of information, you can page it with this function.\n\n```powershell\nGet-Service | Out-More\n```\n\n![out-more](images/out-more.png)\n\nThis also works in PowerShell 7.\n\n### [Set-ConsoleTitle](docs/Set-ConsoleTitle.md)\n\nSet the title bar of the current PowerShell console window.\n\n```powershell\nif (Test-IsAdministrator) {\n  Set-ConsoleTitle \"Administrator:  $($PSVersionTable.PSVersion)\"\n  }\n```\n\n### [Add-Border](docs/Add-Border.md)\n\nThis command will create a character or text-based border around a line of text. You might use this to create a formatted text report or to improve the display of information on the screen.\n\n```dos\nPS C:\\\u003e Add-Border $env:computername\n\n*********\n* WIN11 *\n*********\n```\n\nStarting in v2.23.0 you can also use ANSI escape sequences to color the text and/or the border.\n\n![ANSI border](images/add-border-ansi.png)\n\n```powershell\n$params =@{\n  TextBlock = (Get-PSWho -AsString ).trim()\n  ANSIBorder = \"`e[38;5;214m\"\n  Character = ([char]0x25CA)\n  ANSIText = \"`e[38;5;225m\"\n}\nAdd-Border @params\n```\n\nThis example assumes you are running PowerShell 7.\n\n![ANSI diamond border](images/add-border-ansi3.png)\n\n### [Show-Tree](docs/Show-Tree.md)\n\n`Show-Tree` will display the specified path as a graphical tree in the console. This is intended as a PowerShell alternative to the DOS `tree` command. This function should work for any type of PowerShell provider and can be used to explore providers used for configuration like the WSMan provider or the registry. By default, the output will only show directory items or equivalent structures. But you can opt to include items as well as item details.\n\n![show file system tree](images/show-tree1.png)\n\nIf you are running Windows PowerShell 5.1 and specifying a file system path, you can display the tree in a colorized format by using the `-InColor` dynamic parameter.\n\n![show file system tree](images/show-tree2.png)\n\nBeginning with module version 2.21.0, this command uses ANSI Color schemes from a JSON file. You can customize the file if you wish. See the [PSAnsiMap](#psansimap) section of this README. If you are using `$PSStyle.FileInfo`, colorization will use these values.$[ps]\n\nThis command has an alias of `pstree`.\n\n```dos\nPS C:\\\u003e pstree c:\\work\\alpha -files -properties LastWriteTime,Length\n\nC:\\work\\Alpha\\\n+-- LastWriteTime = 02/28/2024 11:19:32\n+--bravo\n|  +-- LastWriteTime = 02/28/2024 11:20:30\n|  +--delta\n|  |  +-- LastWriteTime = 02/28/2024 11:17:35\n|  |  +--FunctionDemo.ps1\n|  |  |  +-- Length = 888\n|  |  |  \\-- LastWriteTime = 06/01/2009 15:50:47\n|  |  +--function-form.ps1\n|  |  |  +-- Length = 1117\n|  |  |  \\-- LastWriteTime = 04/17/2024 17:18:28\n|  |  +--function-logstamp.ps1\n|  |  |  +-- Length = 598\n|  |  |  \\-- LastWriteTime = 05/23/2007 11:39:55\n|  |  +--FunctionNotes.ps1\n|  |  |  +-- Length = 617\n|  |  |  \\-- LastWriteTime = 02/24/2016 08:59:03\n|  |  \\--Function-SwitchTest.ps1\n|  |     +-- Length = 242\n|  |     \\-- LastWriteTime = 06/09/2008 15:55:44\n|  +--gamma\n...\n```\n\nThis example uses parameter and command aliases. You can display a tree listing with files including user-specified properties. Use a value of * to show all properties.\n\n### [New-RedGreenGradient](docs/New-RedGreenGradient.md)\n\n`New-RedGreenGradient`, which displays a bar going from red to green. This might be handy when you want to present a visual indicator.\n\n![New-RedGreenGradient](images/redgreen.png)\n\n## Format Functions\n\nThe module contains a set of simple commands to make it easier to format values.\n\n### [Format-Percent](docs/Format-Percent.md)\n\nTreat a value as a percentage. This will write a [double] and not include the % sign.\n\n```dos\nPS C:\\\u003e Format-Percent -Value 123.5646MB -total 1GB -Decimal 4\n12.0669\n```\n\n### [Format-String](docs/Format-String.md)\n\nUse this command to perform one of several string manipulation \"tricks\".\n\n```dos\nPS C:\\\u003e Format-String \"powershell\" -Reverse -Case Proper\nLlehsrewop\nPS C:\\\u003e Format-String PowerShell -Randomize\nwSlhoeePlr\nPS C:\\\u003e Format-String \"!MySecretPWord\" -Randomize\n-Replace @{S=\"$\";e=\u0026{Get-Random -min 1 -max 9};o=\"^\"} -Reverse\nyr7!^7WcMtr$Pd\n```\n\n### [Format-Value](docs/Format-Value.md)\n\nThis command will format a given numeric value. By default, it will treat the number as an integer. Or you can specify a certain number of decimal places. The command will also allow you to format the value in KB, MB, etc.\n\n```dos\nPS C:\\\u003e Format-Value 1235465676 -Unit kb\n1206509\nPS C:\\\u003e Format-Value 123.45 -AsCurrency\n$123.45\nPS C:\\\u003e (Get-Process | Measure-Object ws -sum).sum |\nFormat-Value -Unit mb | Format-Value -AsNumber\n9,437\n```\n\nOr pull it all together:\n\n```powershell\nGet-CimInstance Win32_OperatingSystem |\nSelect-Object @{Name = \"TotalMemGB\";\nExpression={Format-Value $_.TotalVisibleMemorySize -Unit mb}},\n@{Name=\"FreeMemGB\";\nExpression={Format-Value $_.FreePhysicalMemory -unit mb -Decimal 2}},\n@{Name=\"PctFree\";\nExpression={Format-Percent -Value $_.FreePhysicalMemory `\n-Total $_.totalVisibleMemorySize -Decimal 2}}\n```\n\n```dos\nTotalMemGB FreeMemGB PctFree\n---------- --------- -------\n        32     14.05   44.06\n```\n\n## Scripting Tools\n\n### [Get-TypeMember](docs/Get-TypeMember.md)\n\nThis command is an alternative to using `Get-Member`.\nSpecify a type name to see a simple view of an object's members.\nThe output will only show native members, including static methods, but not those added by PowerShell such as ScriptProperties.\n\n![static members](images/typemember-static.png)\n\nThe command will highlight properties that are enumerations.\n\n![enum properties](images/typemember-enum.png)\n\nThe highlighting only works in the console and VSCode.\n\nThe output includes a property set type extension.\n\n```dos\nPS C:\\\u003e Get-TypeMember datetime -MemberType method | Select MethodSyntax\n\nName                 ReturnType      IsStatic Syntax\n----                 ----------      -------- ------\nAdd                  System.DateTime    False $obj.Add([TimeSpan]value)\nAddDays              System.DateTime    False $obj.AddDays([Double]value)\nAddHours             System.DateTime    False $obj.AddHours([Double]value)\nAddMilliseconds      System.DateTime    False $obj.AddMilliseconds([Double]value)\nAddMinutes           System.DateTime    False $obj.AddMinutes([Double]value)\n...\n```\n\nOr you can use the custom view.\n\n```dos\nPS C:\\\u003e Get-TypeMember datetime -MemberType method | Format-Table -View Syntax\n\n\n   Type: System.DateTime\n\nName                 ReturnType Syntax\n----                 ---------- ------\nAdd                  DateTime   $obj.Add([TimeSpan]value)\nAddDays              DateTime   $obj.AddDays([Double]value)\nAddHours             DateTime   $obj.AddHours([Double]value)\nAddMilliseconds      DateTime   $obj.AddMilliseconds([Double]value)\nAddMinutes           DateTime   $obj.AddMinutes([Double]value)\nAddMonths            DateTime   $obj.AddMonths([Int32]months)\nAddSeconds           DateTime   $obj.AddSeconds([Double]value)\nAddTicks             DateTime   $obj.AddTicks([Int64]value)\nAddYears             DateTime   $obj.AddYears([Int32]value)\n...\n```\n\n### [Get-TypeConstructor](docs/Get-TypeConstructor.md)\n\nYou might also want to easily discover constructors for .NET classes. It isn't that difficult to view OverLoadDefinitions for the `New()` method.\n\n```dos\nPS C:\\\u003e [System.Drawing.rectangle]::new.OverloadDefinitions\nSystem.Drawing.Rectangle new(int x, int y, int width, int height)\nSystem.Drawing.Rectangle new(System.Drawing.Point location, System.Drawing.Size size)\n```\n\nThe `Get-TypeConstructor` command will display the same information, but in an easier to read and use format.\n\n![Get-TypeConstructor](images/get-typeconstructor.png)\n\nThe default formatted view highlights the type and variable names using the color values from `Get-PSReadLineOption`. The output is designed so that you could copy and and paste a constructor method into your script.\n\nThe command output is a rich object in the event you want to do something else with the result.\n\n```dos\nPS C:\\\u003e $c = Get-TypeConstructor System.Drawing.Rectangle | Select -first 1\nPS C:\\\u003e $c.type\nSystem.Drawing.Rectangle\nPS C:\\\u003e $c.Parameters\n\nParameterType ParameterName\n------------- -------------\nSystem.Int32  x\nSystem.Int32  y\nSystem.Int32  width\nSystem.Int32  height\n```\n\n### [New-PSDynamicParameter](docs/New-PSDynamicParameter.md)\n\nThis command will create the code for a dynamic parameter that you can insert into your PowerShell script file. You need to specify a parameter name and a condition. The condition value is code that would run inside an If statement. Use a value like $True if you want to add it later in your scripting editor.\n\n```dos\nPS C:\\\u003e New-PSDynamicParameter -Condition \"$PSEdition -eq 'Core'\" -ParameterName ANSI -Alias color -Comment \"Create a parameter to use ANSI if running PowerShell 7\" -ParameterType switch\n\n    DynamicParam {\n    # Create a parameter to use ANSI if running PowerShell 7\n        If (Core -eq 'Core') {\n\n        $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary\n\n        # Defining parameter attributes\n        $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]\n        $attributes = New-Object System.Management.Automation.ParameterAttribute\n        $attributes.ParameterSetName = '__AllParameterSets'\n        $attributeCollection.Add($attributes)\n\n        # Adding a parameter alias\n        $dynalias = New-Object System.Management.Automation.AliasAttribute -ArgumentList 'color'\n        $attributeCollection.Add($dynalias)\n\n        # Defining the runtime parameter\n        $dynParam1 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter('ANSI', [Switch], $attributeCollection)\n        $paramDictionary.Add('ANSI', $dynParam1)\n\n        return $paramDictionary\n    } # end if\n} #end DynamicParam\n```\n\nThis creates dynamic parameter code that you can use in a PowerShell function. Normally you would save this output to a file or copy it to the clipboard so that you can paste it into your scripting editor.\n\nYou can also use a WPF-based front-end command, [New-PSDynamicParameterForm](docs/New-PSDynamicParameterForm.md). You can enter the values in the form. Required values are indicated by an asterisk.\n\n![New-PSDynamicParameterForm](images/new-psdynamicparameter-form.png)\n\nClicking `Create` will generate the dynamic parameter code and copy it to the Windows clipboard. You can then paste it into your scripting editor.\n\n```powershell\nDynamicParam {\n\n    If ($Filter -eq 'domain') {\n\n    $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary\n\n    # Defining parameter attributes\n    $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]\n    $attributes = New-Object System.Management.Automation.ParameterAttribute\n    $attributes.ParameterSetName = '__AllParameterSets'\n    $attributes.ValueFromPipelineByPropertyName = $True\n\n    # Adding ValidatePattern parameter validation\n    $value = '^\\w+-\\w+$'\n    $v = New-Object System.Management.Automation.ValidatePatternAttribute($value)\n    $AttributeCollection.Add($v)\n\n    # Adding ValidateNotNullOrEmpty parameter validation\n    $v = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute\n    $AttributeCollection.Add($v)\n    $attributeCollection.Add($attributes)\n\n    # Adding a parameter alias\n    $dynalias = New-Object System.Management.Automation.AliasAttribute -ArgumentList 'cn'\n    $attributeCollection.Add($dynalias)\n\n    # Defining the runtime parameter\n    $dynParam1 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter('Computername', [String], $attributeCollection)\n    $paramDictionary.Add('Computername', $dynParam1)\n\n    return $paramDictionary\n} # end if\n} #end DynamicParam\n```\n\nIf you import the PSScriptTools module in the PowerShell ISE, you will get a menu shortcut under Add-Ins.\n\n![New-PSDynamicParameter ISE](images/new-psdynamicparameter-ise.png)\n\nIf you import the module in VS Code using the integrated PowerShell terminal, it will a new command. In the command palette, use `PowerShell: Show Additional Commands from PowerShell Modules\".\n\n![New-PSDynamicParameter VSCode](images/new-psdynamicparameter-vscode.png)\n\n### [Get-PSUnique](docs/Get-PSUnique.md)\n\nFor the most part, objects you work with in PowerShell are guaranteed to be unique. But you might import data where there is the possibility of duplicate items. Consider this CSV sample.\n\n```powershell\n$Obj = \"Animal,Snack,Color\nHorse,Quiche,Chartreuse\nCat,Doritos,Red\nCat,Pringles,Yellow\nDog,Doritos,Yellow\nDog,Doritos,Yellow\nRabbit,Pretzels,Green\nRabbit,Popcorn,Green\nMarmoset,Cheeseburgers,Black\nDog,Doritos,White\nDog,Doritos,White\nDog,Doritos,White\n\" | ConvertFrom-Csv\n```\n\nThere are duplicate objects you might want to filter out. For that task, you can use `Get-PSUnique`.\n\n```dos\nPS C:\\\u003e $obj | Get-PSUnique | Sort-Object animal\n\nAnimal   Snack         Color\n------   -----         -----\nCat      Pringles      Yellow\nCat      Doritos       Red\nDog      Doritos       White\nDog      Doritos       Yellow\nHorse    Quiche        Chartreuse\nMarmoset Cheeseburgers Black\nRabbit   Popcorn       Green\nRabbit   Pretzels      Green\n```\n\nThe duplicate items have been removed. This command works best with simple objects. If your objects have nested object properties, you will need to test if this command can properly filter for unique items. For more complex objects, you should use the `Property` parameter.\n\n### [Test-IsElevated](docs/Test-IsElevated.md)\n\nThis simple command will test if the current PowerShell session is running elevated, or as Administrator. On Windows platforms, the function uses the .NET Framework to test. On non-Windows platforms, the command tests the user's UID value.\n\n```dos\nPS C:\\\u003e Test-IsElevated\nFalse\n```\n\nYou can also use the `Get-PSWho` command to get more information.\n\n### [New-FunctionItem](docs/New-FunctionItem.md)\n\n```powershell\n{Get-Date -format g | Set-Clipboard} | New-FunctionItem -name Copy-Date\n```\n\nThe script block has been converted into a function.\n\n```dos\nPS C:\\\u003e Get-Command Copy-Date\n\nCommandType     Name                        Version    Source\n-----------     ----                        -------    ------\nFunction        Copy-Date\n```\n\nYou can use this function to create a quick function definition directly from the console. This lets you quickly prototype a function. If you are happy with it, you can \"export\" to a file with `Show-FunctionItem`.\n\n### [Show-FunctionItem](docs/Show-FunctionItem.md)\n\nThis command will display a loaded function as it might look in a code editor. You could use this command to export a loaded function to a file.\n\n```powershell\nShow-FunctionItem Copy-Date | Out-File c:\\scripts\\Copy-Date.ps1\n```\n\n### [ConvertTo-TitleCase](docs/ConvertToTitleCase.md)\n\nThis is a simple command that uses `[System.Globalization.CultureInfo]` to convert a string to Title casing.\n\n```dos\nPS C:\\\u003e ConvertTo-TitleCase \"disk usage report\"\nDisk Usage Report\n```\n\n### [Trace-Message](docs/Trace-Message.md)\n\n`Trace-Message` is designed to be used with your script or function on a Windows platform. Its purpose is to create a graphical trace window using Windows Presentation Foundation (WPF). Inside the function or script, you can use this command to send messages to the window. When finished, you have the option to save the output to a text file.\n\nThere are three steps to using this function. First, in your code, you need to create a boolean global variable called TraceEnabled. When the value is $True, the Trace-Message command will run. When set to false, the command will be ignored. Second, you need to initialize a form, specifying the title and dimensions. Finally, you can send trace messages to the window. All messages are prepended with a timestamp.\n\nHere is a code excerpt from `$PSSamplePath\\Get-Status.ps1`:\n\n```powershell\nFunction Get-Status {\n    [cmdletbinding(DefaultParameterSetName = 'name')]\n    [alias(\"gst\")]\n    Param(\n        #parameter details...\n        [Parameter(HelpMessage=\"Enable with graphical trace window\")]\n        [switch]$Trace\n    )\n\n    Begin {\n        Write-Verbose \"[$((Get-Date).TimeOfDay) BEGIN  ] Starting $($MyInvocation.MyCommand)\"\n        if ($trace) {\n            $global:TraceEnabled = $True\n            $traceTitle = \"{0} Trace Log\" -f $($MyInvocation.MyCommand)\n            Trace-Message -title $traceTitle\n            Trace \"Starting $($MyInvocation.MyCommand)\"\n        }\n    } #begin\n      Process {\n        Write-Verbose \"[$((Get-Date).TimeOfDay) PROCESS] Using parameter set $($PSCmdlet.ParameterSetName)\"\n        Trace-Message -message \"Using parameter set: $($PSCmdlet.ParameterSetName)\"\n        #code ...\n      } #close function\n    $data = Get-Status -trace\n    #code ...\n}\n```\n\nThe trace window starts with pre-defined metadata.\n\n![Trace Sample](images/trace.png)\n\n_Your output might vary from this screenshot._ You have the option to Save the text. The default location is `$env:temp.`\n\n### [Get-CommandSyntax](docs/Get-CommandSyntax.md)\n\nSome PowerShell commands are provider-aware and may have special syntax or parameters depending on what PSDrive you are using when you run the command. In Windows PowerShell, the help system could show you syntax based on a given path. However, this no longer appears to work. `Get-CommandSyntax` is intended as an alternative and should work in both Windows PowerShell and PowerShell 7.\n\nSpecify a cmdlet or function name, and the output will display the syntax detected when using different providers.\n\n```powershell\nGet-CommandSyntax -Name Get-Item\n```\n\nDynamic parameters will be highlighted with an ANSI-escape sequence.\n\n![Get-CommandSyntax](images/get-commandsyntax.png)\n\nThis command has an alias of _gsyn_.\n\n### [Test-Expression](docs/Test-Expression.md)\n\nThe primary command can be used to test a PowerShell expression or script block for a specified number of times and calculate the average runtime, in milliseconds, over all the tests.\n\nWhen you run a single test with `Measure-Command` the result might be affected by any number of factors. Likewise, running multiple tests may also be influenced by things such as caching. The goal of this module is to provide a test framework where you can run a test repeatedly with either a static or random interval between each test. The results are aggregated and analyzed. Hopefully, this will provide a more meaningful or realistic result.\n\nThe output will also show the median and trimmed values, as well as some metadata about the current PowerShell session.\n\n```dos\nPS C:\\\u003e $cred = Get-Credential Globomantics\\administrator\nPS C:\\\u003e Test-Expression {\n  param($cred)\n  Get-CimInstance win32_LogicalDisk -computer chi-dc01 -credential $cred\n  } -argumentList $cred\n\nTests        : 1\nTestInterval : 0.5\nAverageMS    : 1990.6779\nMinimumMS    : 1990.6779\nMaximumMS    : 1990.6779\nMedianMS     : 1990.6779\nTrimmedMS    :\nPSVersion    :5.1.17763.134\nOS           : Microsoft Windows 10 Pro\n```\n\nYou can also run multiple tests with random time intervals.\n\n```dos\nPS C:\\\u003eTest-Expression {\n  param([string[]]$Names)\n  Get-Service $names\n  } -count 5 -IncludeExpression -ArgumentList @('bits','wuauserv','winrm') `\n  -RandomMinimum .5 -RandomMaximum 5.5\n\nTests        : 5\nTestInterval : Random\nAverageMS    : 1.91406\nMinimumMS    : 0.4657\nMaximumMS    : 7.5746\nMedianMS     : 0.4806\nTrimmedMS    : 0.51\nPSVersion    : 5.1.17763.134\nOS           : Microsoft Windows 10 Pro\nExpression   : param([string[]]$Names) Get-Service $names\nArguments    : {bits, wuauserv, winrm}\n```\n\nFor very long-running tests, you can run them as a background job.\n\n#### Graphical Testing\n\nThe module also includes a graphical command called `Test-ExpressionForm`. This is intended to serve as both an entry and results form.\n\n![Test Expression](images/testexpressionform.png)\n\nWhen you quit the form the last result will be written to the pipeline including all metadata, the scriptblock, and any arguments.\n\n### [Copy-HelpExample](docs/Copy-HelpExample.md)\n\nThis command is designed to make it (slightly) easier to copy code snippets from help examples. Specify the name of a function or cmdlet, presumably one with documented help examples, and you will be offered a selection of code snippets to copy to the clipboard. Code snippets have been trimmed of blank lines, most prompts, and comments. Many examples include command output. You will have to manually remove what you don't want after pasting.\n\nThe default behavior is to use a console-based menu, which works cross-platform.\n\n![Copy-HelpExample](images/copy-helpexample-1.png)\n\nEnter the number of the code to copy to the clipboard. Enter multiple numbers separated by commas.\n\nIf you are running a Windows platform, there is a dynamic help parameter to use `Out-GridView`.\n\n```powershell\nCopy-HelpExample Stop-Service -UseGridView\n```\n\n![Copy-HelpExample GridView](images/copy-helpexample-2.png)\n\nIf you are running this in the PowerShell ISE this is the default behavior, even if you don't specify the parameter.\n\n### [Get-GitSize](docs/Get-GitSize.md)\n\nUse this command to determine how much space the hidden `.git` folder is consuming.\n\n```dos\nPS C:\\scripts\\PSScriptTools\u003e Get-GitSize\n\nPath                                          Files          SizeKB\n----                                          -----          ------\nC:\\scripts\\PSScriptTools                        751       6859.9834\n```\n\nThis is the default formatted view. The object has other properties you can use.\n\n```dos\nName         : PSScriptTools\nPath         : C:\\scripts\\PSScriptTools\nFiles        : 751\nSize         : 7024623\nDate         : 3/5/2024 2:57:06 PM\nComputername : BOVINE320\n```\n\n### [Remove-MergedBranch](docs/Remove-MergedBranch.md)\n\nWhen using `git` you may create some branches. Presumably, you merge these branches into the main or master branch. You can use this command to remove all merged branches other than `master` or `main`, and the current branch. You must be at the root of your project to run this command.\n\n```dos\nPS C:\\MyProject\u003e Remove-MergedBranch\n\nRemove merged branch from MyProject?\n2.1.1\n[Y] Yes  [N] No  [S] Suspend  [?] Help (default is \"Y\"): n\n\nRemove merged branch from MyProject?\ndev1\n[Y] Yes  [N] No  [S] Suspend  [?] Help (default is \"Y\"): y\nDeleted branch dev1 (was 75f6ab8).\n\nRemove merged branch from MyProject?\ndev2\n[Y] Yes  [N] No  [S] Suspend  [?] Help (default is \"Y\"): y\nDeleted branch dev2 (was 75f6ab8).\n\nRemove merged branch from MyProject?\npatch-254\n[Y] Yes  [N] No  [S] Suspend  [?] Help (default is \"Y\"): n\n\nPS C:\\MyProject\u003e\n```\n\nBy default, you will be prompted to remove each branch.\n\n### [Test-WithCulture](docs/Test-WithCulture.md)\n\nWhen writing PowerShell commands, sometimes the culture you are running under becomes critical. For example, European countries use a different `DateTime` format than North Americans, which might present a problem with your script or command. Unless you have a separate computer running under a foreign culture, it is difficult to test. This command will allow you to test a script block or even a file under a different culture, such as DE-DE for German.\n\n```dos\nPS C:\\\u003e Test-WithCulture fr-fr -Scriptblock {\n    Get-winEvent -log system -max 500 |\n    Select-Object -Property TimeCreated,ID,OpCodeDisplayName,Message |\n    Sort-Object -property TimeCreated |\n    Group-Object {$_.TimeCreated.ToShortDateString()} -NoElement}\n\nCount Name\n----- ----\n  165 10/07/2024\n  249 11/07/2024\n   17 12/07/2024\n   16 13/07/2024\n   20 14/07/2024\n   26 15/07/2024\n    7 16/07/2024\n```\n\n### [Copy-Command](docs/Copy-Command.md)\n\nThis command will copy a PowerShell command, including parameters and help to a new user-specified command. You can use this to create a \"wrapper\" function or to easily create a proxy function. The default behavior is to create a copy of the command complete with the original comment-based help block.\n\n### [Get-ParameterInfo](docs/Get-ParameterInfo.md)\n\nUsing `Get-Command`, this function will return information about parameters for any loaded cmdlet or function. Common parameters like `Verbose` and `ErrorAction` are omitted. `Get-ParameterInfo` returns a custom object with the most useful information an administrator might need to know. The custom object includes default format views for a list and table.\n\n![Get-ParameterInfo summary](images/get-parameterinfo-1.png)\n\n![Get-ParameterInfo list](images/get-parameterinfo-2.png)\n\n### [New-PSFormatXML](docs/New-PSFormatXML.md)\n\nWhen defining custom objects with a new type name, PowerShell by default will display all properties. However, you may wish to have a specific default view, be it a table or a list. Or you may want to have different views display the object differently. Format directives are stored in format.ps1xml files which can be tedious to create. This command simplifies that process.\n\nDefine a custom object:\n\n```powershell\n$tName = \"myThing\"\n$obj = [PSCustomObject]@{\n  PSTypeName   = $tName\n  Name         = \"Jeff\"\n  Date         = (Get-Date)\n  Computername = $env:computername\n  OS           = (Get-CimInstance Win32_OperatingSystem).caption\n}\n$upParams = @{\n  TypeName = $tName\n  MemberType = \"ScriptProperty\"\n  MemberName = \"Runtime\"\n  value =  {(Get-Date) - [datetime]\"1/1/2024\"}\n  force = $True\n}\nUpdate-TypeData @upParams\n```\n\nThe custom object looks like this by default:\n\n```dos\nPS C:\\\u003e $obj\n\nName         : Jeff\nDate         : 2/10/2024 8:49:10 PM\nComputername : BOVINE320\nOS           : Microsoft Windows 10 Pro\nRuntime      : 40.20:49:43.9205882\n```\n\nNow you can create new formatting directives.\n\n```powershell\n$tName = \"myThing\"\n$params = @{\n  Properties = \"Name\",\"Date\",\"Computername\",\"OS\"\n  FormatType = \"Table\"\n  Path = \"C:\\scripts\\$tName.format.ps1xml\"\n}\n$obj | New-PSFormatXML @params\n\n$params.Properties= \"Name\",\"OS\",\"Runtime\"\n$params.Add(\"ViewName\",\"runtime\")\n$params.Add(Append,$True)\n$obj | New-PSFormatXML  @params\n\n$params.formatType = \"list\"\n$params.remove(\"Properties\")\n$obj | New-PSFormatXML @params\n\nUpdate-FormatData -AppendPath $params.path\n```\n\nAnd, here is what the object looks like now:\n\n```dos\nPS C:\\\u003e $obj\n\nName Date                 Computername Operating System\n---- ----                 ------------ ----------------\nJeff 2/10/2024 8:49:10 PM BOVINE320    Microsoft Windows 10 Pro\n\nPS C:\\\u003e $obj | Format-Table -View runtime\n\nName OS Runtime\n---- -- -------\nJeff    40.20:56:24.5411481\n\nPS C:\\\u003e $obj | Format-List\n\n\nName            : Jeff\nDate            : Sunday, February 10, 2024\nComputername    : BOVINE320\nOperatingSystem : Microsoft Windows 10 Pro\nRuntime         : 40.21:12:01\n```\n\nStarting with v2.31.0, you can also use a hashtable to define custom properties from script blocks.\n\n```powershell\n $p = @{\n    FormatType = \"List\"\n    ViewName = \"run\"\n    Path  = \"c:\\scripts\\run.ps1xml\"\n    Properties = \"ID\",\"Name\",\"Path\",\"StartTime\",\n    @{Name=\"Runtime\";Expression={(Get-Date) - $_.StartTime}}\n }\n Get-Process -id $pid | New-PSFormatXML @p\n ```\n\nIf you run this command from Visual Studio Code and specify `-PassThru`, the resulting file will be opened in your editor.\n\n### [Test-IsPSWindows](docs/Test-IsPSWindows.md)\n\nPowerShell 7 introduced the `$IsWindows` variable. However, it is not available on Windows PowerShell. Use this command to perform a simple test if the computer is either running Windows or using the `Desktop` PSEdition. The command returns `True` or `False`.\n\n### [Write-Detail](docs/Write-Detail.md)\n\nThis command is designed to be used within your functions and scripts to make it easier to write a detailed message that you can use as verbose output. The assumption is that you are using an advanced function with the `Begin`, `Process`, and `End` script blocks. You can create a detailed message to indicate what part of the code is being executed. The output can be configured to include a `DateTime` stamp or just the time.\n\n```dos\nPS C:\\\u003e Write-Detail \"Getting file information\" -Prefix Process -Date\n3/26/2025 01:23:38 [PROCESS] Getting file information\n```\n\nIn a script. you might use it like this:\n\n```powershell\nBegin {\n    Write-Detail \"Starting $($MyInvocation.MyCommand)\" -Prefix begin -time |\n    Write-Verbose\n    $tabs = \"`t\" * $tab\n    Write-Detail \"Using a tab of $tab\" -Prefix BEGIN -time | Write-Verbose\n} #begin\n```\n\n### [Save-GitSetup](docs/Save-GitSetup.md)\n\nThis command is intended for Windows users to easily download the latest 64-bit version of `Git`.\n\n```dos\nPS C:\\\u003e Save-GitSetup -Path c:\\work -PassThru\n\n    Directory: C:\\work\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a---           1/23/2024  4:31 PM       46476880 Git-2.25.0-64-bit.exe\n```\n\nYou will need to manually install the file. Or you can try something like this:\n\n```powershell\nSave-GitSetup -Path c:\\work -PassThru | Invoke-Item\n```\n\n## CIM Tools\n\nThe module includes a set of commands to work with CIM and are alternatives to `Get-CimClass`. The information from `Get-CimClass` is helpful, but you often need to take steps to format the results to be something meaningful. These commands aim to simplify the process.\n\nMany of these commands have autocompletion features for the `Namespace` and `ClassName` parameters. Note that even though you can query a remote computer, the tab completion uses values from the local computer.\n\n### [Find-CimClass](docs/Find-CimClass.md)\n\nThis function is designed to search an entire CIM repository for a class name. Sometimes, you may guess a class name but not know the full name or even the correct namespace. `Find-CimClass` will recursively search for a given class name. You can use wildcards and search remote computers.\n\n![Find-CimClass](images/find-cimclass.png)\n\n### [Get-CimNamespace](docs/Get-CimNamespace.md)\n\nYou can use this command to enumerate all WMI/CIM namespaces on a computer starting from ROOT. The default behavior is to recursively enumerate on the local machine, but you can query a remote computer. If you need to support alternate credentials, create a CIMSession and pass it to the command.\n\n```dos\nPS C:\\\u003e Get-CimNamespace\nRoot\\subscription\nRoot\\subscription\\ms_41d\nRoot\\subscription\\ms_409\nRoot\\DEFAULT\nRoot\\DEFAULT\\ms_41d\nRoot\\DEFAULT\\ms_409\nRoot\\CIMV2\nRoot\\CIMV2\\mdm\n...\n```\n\nYou can limit the search to top-level namespaces.\n\n```dos\nPS C:\\\u003e Get-CimNamespace -TopLevelOnly -CimSession DOM1\nRoot\\subscription\nRoot\\DEFAULT\nRoot\\MicrosoftDfs\nRoot\\CIMV2\nRoot\\msdtc\nRoot\\Cli\nRoot\\MicrosoftActiveDirectory\nRoot\\SECURITY\nRoot\\RSOP\nRoot\\MicrosoftDNS\nRoot\\PEH\n...\n```\n\n### [Get-CimClassList](docs/Get-CimClassList.md)\n\nSometimes `Get-CimClass` is overkill when all you want is a list of class names under a given namespace. `Get-CimClassList` is designed to quickly give you a list of class names. You can filter by name and exclude.\n\n```dos\nPS C:\\\u003e Get-CimClassListing *usb*  -Exclude cim*\n\n   Namespace: Root/Cimv2\n\nClassName\n---------\nWin32_USBController\nWin32_USBControllerDevice\nWin32_USBHub\n```\n\n### [Get-CimClassProperty](docs/Get-CimClassProperty.md)\n\nUse this command to quickly get a list of class properties.\n\n```dos\nPS C:\\\u003e Get-CimClassProperty win32_USBHub\n\n   Class: Root/Cimv2:Win32_USBHub\n\nProperty                    ValueType   Flags\n--------                    ---------   -----\nAvailability                UInt16      ReadOnly, NullValue\nCaption                     String      ReadOnly, NullValue\nClassCode                   UInt8       NullValue\nConfigManagerErrorCode      UInt32      ReadOnly, NullValue\nConfigManagerUserConfig     Boolean     ReadOnly, NullValue\nCreationClassName           String      ReadOnly, NullValue\nCurrentAlternateSettings    UInt8Array  NullValue\nCurrentConfigValue          UInt8       NullValue\nDescription                 String      ReadOnly, NullValue\nDeviceID                    String      Key, ReadOnly, NullValue\nErrorCleared                Boolean     ReadOnly, NullValue\nErrorDescription            String      ReadOnly, NullValue\nGangSwitched                Boolean     NullValue\nInstallDate                 DateTime    ReadOnly, NullValue\n...\n```\n\nKey properties will be highlighted in green.\n\nOr you can limit output specifying a property name.\n\n```dos\nPS C:\\\u003e Get-CimClassProperty Win32_OperatingSystem -Property *memory*\n\n   Class: Root/Cimv2:Win32_OperatingSystem\n\nProperty               ValueType Flags\n--------               --------- -----\nFreePhysicalMemory     UInt64    ReadOnly, NullValue\nFreeVirtualMemory      UInt64    ReadOnly, NullValue\nMaxProcessMemorySize   UInt64    ReadOnly, NullValue\nTotalVirtualMemorySize UInt64    ReadOnly, NullValue\nTotalVisibleMemorySize UInt64    ReadOnly, NullValue\n```\n\n### [Get-CimClassMethod](docs/Get-CimClassMethod.md)\n\nYou can likewise query for class methods.\n\n```dos\nPS C:\\\u003e Get-CimClassMethod Win32_ComputerSystem\n\n   Class: Root/Cimv2:Win32_ComputerSystem\n\nName                    ResultType Parameters\n----                    ---------- ----------\nJoinDomainOrWorkgroup   UInt32     {Name, Password, UserName, AccountOU…}\nRename                  UInt32     {Name, Password, UserName}\nSetPowerState           UInt32     {PowerState, Time}\nUnjoinDomainOrWorkgroup UInt32     {Password, UserName, FUnjoinOptions}\n```\n\n### [Get-CimMember](docs/Get-CimMember.md)\n\nThis is a wrapper function that will invoke Get-CimClassProperty or Get-CimClassMethod based on the parameter set used. The default is to show all properties for a given class.\n\n```dos\nPS C:\\\u003e Get-CimMember -ClassName win32_bios -Method *\nWARNING: No methods found for Root\\Cimv2:WIN32_BIOS\nPS C:\\\u003e Get-CimMember -ClassName win32_Volume -Property q*\n\n       Class: Root/Cimv2:Win32_Volume\n\n    Property         ValueType Flags\n    --------         --------- -----\n    QuotasEnabled    Boolean   ReadOnly, NullValue\n    QuotasIncomplete Boolean   ReadOnly, NullValue\n    QuotasRebuilding Boolean   ReadOnly, NullValue\n```\n\n### [Get-CimClassPropertyQualifier](docs/Get-CimClassPropertyQualifier.md)\n\nThis command is an alternative to Get-CimClass to make it easier to get information about property qualifiers of a WMI/CIM class.\n\n```dos\nPS C:\\\u003e Get-CimClassPropertyQualifier -ClassName Win32_Service -Property Name\n\n   Property: Root/Cimv2:Win32_Service [Name]\n\nName Value CimType Flags\n---- ----- ------- -----\nkey  True  Boolean DisableOverride, ToSubclass\nread True  Boolean EnableOverride, ToSubclass\n```\n\n## ANSI Tools\n\nNote: ANSI tools related to the filesystem are not loaded on computers where `PSStyle` is detected.\n\nThis module includes several custom format files for common objects like services. You can run `Get-Service` and pipe it to the custom table view.\n\n```powershell\nGet-Service | Format-Table -view ansi\n```\n\nThis will display the service status color-coded.\n\n![ServiceAnsi](images/serviceansi.png)\n\n**ANSI formatting will only work in a PowerShell 5.1 console window or VS Code. It will not display properly in the PowerShell ISE or older versions of PowerShell.**\n\n### PSAnsiMap\n\nI have done something similar for output from `Get-ChildItem`. The module includes a JSON file that is exported as a global variable called `PSAnsiFileMap`.\n\n```dos\nPS C:\\\u003e $PSAnsiFileMap\n\nDescription    Pattern                                Ansi\n-----------    -------                                ----\nPowerShell     \\.ps(d|m)?1$\nText           \\.(txt)|(md)|(log)$\nDataFile       \\.(json)|(xml)|(csv)$\nExecutable     \\.(exe)|(bat)|(cmd)|(sh)$\nGraphics       \\.(jpg)|(png)|(gif)|(bmp)|(jpeg)$\nMedia          \\.(mp3)|(m4v)|(wav)|(au)|(flac)|(mp4)$\nArchive        \\.(zip)|(rar)|(tar)|(gzip)$\nTopContainer\nChildContainer\n```\n\nThe map includes ANSI settings for different file types. You won't see the ANSI value in the output. The module will add a custom table view called `ansi` which you can use to display colorized file results.\n\n![ANSI File listing](images/ansi-file-format.png)\n\nThe mapping file is user-customizable. Copy the `psansifilemap.json` file from the module's root directory to $HOME. When you import this module, if the file is found, it will be imported and used as `psansifilemap`, otherwise, the module's file will be used.\n\nThe file will look like this:\n\n```json\n[\n  {\n    \"Description\": \"PowerShell\",\n    \"Pattern\": \"\\\\.ps(d|m)?1$\",\n    \"Ansi\": \"\\u001b[38;2;252;127;12m\"\n  },\n  {\n    \"Description\": \"Text\",\n    \"Pattern\": \"\\\\.(txt)|(md)|(log)$\",\n    \"Ansi\": \"\\u001b[38;2;58;120;255m\"\n  },\n  {\n    \"Description\": \"DataFile\",\n    \"Pattern\": \"\\\\.(json)|(xml)|(csv)$\",\n    \"Ansi\": \"\\u001b[38;2;249;241;165m\"\n  },\n  {\n    \"Description\": \"Executable\",\n    \"Pattern\": \"\\\\.(exe)|(bat)|(cmd)|(sh)$\",\n    \"Ansi\": \"\\u001b[38;2;197;15;31m\"\n  },\n  {\n    \"Description\": \"Graphics\",\n    \"Pattern\": \"\\\\.(jpg)|(png)|(gif)|(bmp)|(jpeg)$\",\n    \"Ansi\": \"\\u001b[38;2;255;0;255m\"\n  },\n  {\n    \"Description\": \"Media\",\n    \"Pattern\": \"\\\\.(mp3)|(m4v)|(wav)|(au)|(flac)|(mp4)$\",\n    \"Ansi\": \"\\u001b[38;2;255;199;6m\"\n  },\n  {\n    \"Description\": \"Archive\",\n    \"Pattern\": \"\\\\.(zip)|(rar)|(tar)|(gzip)$\",\n    \"Ansi\": \"\\u001b[38;2;118;38;113m\"\n  },\n  {\n    \"Description\": \"TopContainer\",\n    \"Pattern\": \"\",\n    \"Ansi\": \"\\u001b[38;2;0;255;255m\"\n  },\n  {\n    \"Description\": \"ChildContainer\",\n    \"Pattern\": \"\",\n    \"Ansi\": \"\\u001b[38;2;255;255;0m\"\n  }\n]\n```\n\nYou can create or modify file groups. The Pattern value should be a regular expression pattern to match the filename. Don't forget you will need to escape characters for the JSON format. The ANSI value will be an ANSI escape sequence. You can use `\\u001b` for the \\``e` character.\n\nIf you prefer not to edit JSON files, you can use the PSAnsiFileMap commands from this module.\n\n### [Get-PSAnsiFileMap](docs/Get-PSAnsiFileMap.md)\n\nThis command will display the value of the `$PSAnsiFileMap` variable, but will also show the ANSI sequence using the sequence itself.\n\n![Get-PSAnsiFileMap](images/get-psansifilemap.png)\n\n### [Set-PSAnsiFileMap](docs/Set-PSAnsiFileMap.md)\n\nUse this command to modify an existing entry. You need to specify a regular expression pattern to match the filename and/or an ANSI escape sequence. If the entry description doesn't exist, you will need to specify the regex pattern and the ANSI sequence to add the entry to $PSAnsiFileMap.\n\n```powershell\nSet-PSAnsiFileMap Archive -Ansi \"`e[38;5;75m\"\n```\n\n### [Remove-PSAnsiFileEntry](docs/Remove-PSAnsiFileEntry.md)\n\nIf you need to, you can remove an entry from `$PSAnsiFileMap`.\n\n```powershell\nRemove-PSAnsiFileEntry DevFiles\n```\n\n### [Export-PSAnsiFileMap](docs/Export-PSAnsiFileMap.md)\n\nAny changes you make to `$PSAnsiFileMap` will only last until you import the module again. To make the change permanent, use [Export-PSAnsiFileMap](docs/Export-PSAnsiFileMap.md). This will create the `psansifilemap.json` file in your `$HOME` directory. When you import the PSScriptTools module, if this file is found, it will be imported. Otherwise, the default version from the module will be used.\n\n### [Convert-HtmlToAnsi](docs/Convert-HtmlToAnsi.md)\n\nThis simple function is designed to convert an HTML color code like #ff5733 into an ANSI escape sequence.\n\n```dos\nPS C:\\\u003e Convert-HtmlToAnsi \"#ff5733\"\n[38;2;255;87;51m\n```\n\nTo use the resulting value you still need to construct an ANSI string with the escape character and the closing [0m.\n\n![convert HTML to ANSI](images/convert-htmltoansi.png)\n\nIn PowerShell 7 you can use `` `e ``. Or `$([char]27)` which works in all PowerShell versions.\n\n### [New-ANSIBar](docs/New-ANSIBar.md)\n\nYou can use this command to create colorful bars using ANSI escape sequences based on a 256-color scheme. The default behavior is to create a gradient bar that goes from first to last values in the range and then back down again. Or you can create a single gradient that runs from the beginning of the range to the end. You can use one of the default characters or specify a custom one.\n\n![New-ANSIBar](images/ansibar.png)\n\n### [Write-ANSIProgress](docs/Write-ANSIProgress.md)\n\nYou could also use `Write-ANSIProgress` to show a custom ANSI bar.\n\n![Write-ANSIProgress simple](images/write-ansprogress-1.png)\n\n![write-ANSIProgress in code](images/write-ansprogress-2.png)\n\nOr you can use it in your code to display a console progress bar.\n\n```powershell\n$sb = {\n  Clear-Host\n  $top = Get-ChildItem c:\\scripts -Directory\n  $i = 0\n  $out=@()\n  $pos = $host.UI.RawUI.CursorPosition\n  Foreach ($item in $top) {\n      $i++\n      $pct = [math]::round($i/$top.count,2)\n      Write-ANSIProgress -PercentComplete $pct -position $pos\n      Write-Host \"  Processing $(($item.FullName).PadRight(80))\"\n      -ForegroundColor Yellow -NoNewline\n      $out+= Get-ChildItem -Path $item -Recurse -file |\n      Measure-Object -property length -sum |\n      Select-Object @{Name=\"Path\";Expression={$item.FullName}},Count,\n      @{Name=\"Size\";Expression={$_.Sum}}\n  }\n  Write-Host \"\"\n  $out | Sort-Object -property Size -Descending\n    }\n```\n\n![Write-ANSIProgress script](images/write-ansprogress-3.png)\n\n### [Show-ANSISequence](docs/Show-ANSISequence.md)\n\nYou can use `Show-ANSISequence` to preview how it will look in your PowerShell session. You might get a different appearance in Windows Terminal depending on the color scheme you are using.\n\nThe default behavior is to show basic sequences.\n\n![show basic ANSI sequence](images/show-ansi-basic.png)\n\nYou can also view foreground and or background settings.\n\n![show ANSI foreground](images/show-ansi-foreground.png)\n\nYou can even use an RGB value.\n\n![show ANSI RGB sequence](images/show-ansi-rgb.png)\n\nThe escape character will match what is acceptable in your version of PowerShell. These screenshots are showing PowerShell 7.\n\n## Other Module Features\n\nThese are additional items in the module that you might find useful in your PowerShell work.\n\n### Custom Format Views\n\nThe module includes several custom `format.ps1xml` files that define additional views for common objects. Some of these have already been demonstrated elsewhere in this document.\n\nFor example, there is a custom table view for Aliases.\n\n```dos\nPS C:\\\u003e Get-Alias | Sort-Object Source | Format-Table -view Source\n\n   Source:\n\nName                 Definition\n----                 ----------\nnmo                  New-Module\nni                   New-Item\nnpssc                New-PSSessionConfigurationFile\nnv                   New-Variable\nnsn                  New-PSSession\n...\n\n   Source: Microsoft.PowerShell.Management 3.1.0.0\n\nName                 Definition\n----                 ----------\ngtz                  Get-TimeZone\nstz                  Set-TimeZone\n...\n\n\n   Source: Microsoft.PowerShell.Utility 3.1.0.0\n\nName                 Definition\n----                 ----------\nfhx                  Format-Hex\nCFS                  ConvertFrom-String\n\n\n   Source: PSScriptTools 3.0.0\n\nName                 Definition\n----                 ----------\nclr                  Convert-EventLogRecord\ngsi                  Get-FolderSizeInfo\nwver                 Get-WindowsVersion\ngpi                  Get-ParameterInfo\nche                  Copy-HelpExample\n...\n```\n\nSome custom formats use ANSI to highlight information, assuming you are running in PowerShell Console Host.\n\n![alias options](images/get-alias-option.png)\n\nIn this format view, ReadOnly aliases are displayed in Red.\n\nUse [Get-FormatView](docs/Get-FormatView.md) to discover available format views. Or if you'd like to create custom views look at [New-PSFormatXML](docs/New-PSFormatXML.md)\n\n### Custom Type Extensions\n\nThe module includes custom type extensions for several common object types. These are designed to make it easier to work with common objects in PowerShell. Beginning with version `2.50.1`, you must manually import these extensions. You can use [`Get-PSScriptToolsTypeExtension`](docs/Get-PSScriptToolsTypeExtension.md) to see what is available.\n\n![Get-PSScriptToolsTypeExtension](images/get-psscripttoolstypeextension.png)\n\nUse [`Import-PSScriptToolsTypeExtension`](docs/Import-PSScriptToolsTypeExtension.md) to import the extensions.\n\n#### System.IO.FileInfo\n\nThe module will extend file objects with the following alias properties:\n\n| New Alias | Property |\n| --- | --- |\n| Size | Length |\n| Created | CreationTime |\n| Modified | LastWriteTime |\n\nYou also have new script properties\n\n| Script Property | Description |\n| --- | --- |\n| ModifiedAge | A timespan between the current date the and last write time |\n| CreatedAge | A timespan between the current date the and creation time |\n| SizeKB | The file size formatted in KB to 2 decimal places |\n| SizeMB | The file size formatted in MB to 2 decimal places |\n\n```dos\nPS C:\\\u003e Get-ChildItem C:\\Scripts\\SharedProfileDefault.ps1 | Select-Object Name,Size,SizeKB,SizeMB,Created,CreatedAge,Modified,ModifiedAge\n\nName        : SharedProfileDefault.ps1\nSize        : 3288\nSizeKB      : 3.21\nSizeMB      : 0\nCreated     : 8/17/2023 8:47:13 AM\nCreatedAge  : 586.05:33:54.5461727\nModified    : 3/21/2025 9:29:40 AM\nModifiedAge : 4.04:51:27.6225204\n```\n\nThere is also a custom property set.\n\n```dos\nPS C:\\\u003e Get-ChildItem C:\\Scripts\\SharedProfileDefault.ps1 | Select-Object AgeInfo\n\nDirectory     : C:\\Scripts\nName          : SharedProfileDefault.ps1\nSize          : 3288\nLastWriteTime : 3/21/2025 9:29:40 AM\nModifiedAge   : 4.04:52:29.3136140\n```\n\n#### System.Diagnostics.Process\n\nThe module can extend process objects with a `Runtime` script property.\n\n```dos\nPS C:\\\u003e Get-Process | Sort-Object runtime -Descending |\nSelect-Object -first 5 -Property ID,Name,Runtime\n\n Id Name          Runtime\n -- ----          -------\n120 Secure System 20:44:51.6139043\n204 Registry      20:44:51.3661961\n  4 System        20:44:48.2820565\n704 smss          20:44:48.2726401\n820 csrss         20:44:44.7760844\n```\n\nThe Idle process will have a null value for this property.\n\n#### Microsoft.PowerShell.Commands.GenericMeasureInfo\n\nWhen using `Measure-Object`, you often want to format `Sum` or `Average` values to megabytes or kilobytes. If you import the `GenericMeasureInfo` type extension, you will have new script properties for `Sum` and `Average` that will be formatted to MB or KB.\n\n```dos\nPS C:\\\u003e dir c:\\work\\ -file | Measure -Property Size -sum -Average | Select Count,Sum*,Average*\n\nCount     : 378\nSumKB     : 74162.5576\nSumMB     : 72.4244\nSumGB     : 0.0707\nSum       : 75942459\nAverageKB : 196.1972\nAverageMB : 0.1916\nAverageGB : 0.0002\nAverage   : 200905.976190476\n```\n\nThis example is using the `Size` property from the custom `FileInfo` type extension.\n\n### PSSpecialChar\n\nA number of the commands in this module can use special characters. To make it easier, when you import the module, it will create a global variable that is a hash table of common special characters. Because it is a hashtable, you can add to it.\n\n![PSSpecialChar](images/psspecialchar.png)\n\nThe names are the same as used in `CharMap.exe`. Don't let the naming confuse you. It may say `BlackSquare`, but the color will depend on how you use it.\n\n```powershell\nGet-WindowsVersionString |\nAdd-Border -border $PSSpecialChar.BlackSmallSquare `\n-ANSIBorder \"$([char]0x1b)[38;5;214m\"\n```\n\n![PSSpecialChar Border](images/psspecialchar-border.png)\n\n### Sample Scripts\n\nThis PowerShell module contains several functions you might use to enhance your functions and scripts. The [Samples](samples) folder contains demonstration script files. You can access the folder in PowerShell using the `$PSSamplePath`.\n\n```powershell\ndir $PSSamplePath\n```\n\nThe samples provide suggestions on how you might use some of the commands in this module. The scripts are offered **AS-IS** and are for demonstration purposes only.\n\n![ProcessPercent.ps1](images/processpercent.png)\n\n### [Open-PSScriptToolsHelp](docs/Open-PSScriptToolsHelp.md)\n\nI've created a PDF version of this document which I thought you might find useful since it includes screenshots and sample output rendered nicer than what you can get in PowerShell help. Run `Open-PSScriptToolsHelp` to open the PDF using the default associated application.\n\n## Deprecated Commands\n\nThe following commands have been removed as of v2.50.0.\n\n- [Set-ConsoleColor](docs/Set-ConsoleColor.md)\n- [Out-ConditionalColor](docs/Out-ConditionalColor.md)\n\n## Related Modules\n\nIf you find this module useful, you might also want to look at my PowerShell tools for:\n\n- [Keeping up to date with PowerShell 7 releases](https://github.com/jdhitsolutions/PSReleaseTools)\n- [Module and Project Status](https://github.com/jdhitsolutions/PSProjectStatus)\n- [Creating and managing customized type extensions](https://github.com/jdhitsolutions/PSTypeExtensionTools)\n- [Managing scheduled jobs](https://github.com/jdhitsolutions/ScheduledJobTools)\n- [Automating the PowerShell scripting process](https://github.com/jdhitsolutions/PSFunctionTools)\n- [A simple command-line task and to-do manager](https://github.com/jdhitsolutions/PSWorkItem)\n\n## Compatibility\n\nWhere possible, module commands have been tested with PowerShell 7, but not on every platform. If you encounter problems, have suggestions, or have other feedback, please post an [issue](https://github.com/jdhitsolutions/PSScriptTools/issues). It is assumed you will **not** be running these commands on any edition of PowerShell Core, i.e. PowerShell 6.\n","funding_links":["https://paypal.me/jdhitsolutions?locale.x=en_US"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdhitsolutions%2Fpsscripttools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdhitsolutions%2Fpsscripttools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdhitsolutions%2Fpsscripttools/lists"}