PowerShellTips.json

[
  {
    "CreatedDate": "2023-07-16T00:00:00",
    "Title": "PowerShell is open source",
    "TipText": "Did you know that PowerShell is open source? You can contribute to the project on GitHub.",
    "Example": "",
    "Urls": [
      "https://github.com/PowerShell/PowerShell"
    ],
    "Category": 0
  },
  {
    "CreatedDate": "2023-07-17T00:00:00",
    "Title": "Set Strict Mode on your scripts",
    "TipText": "Enforce coding rules and raise errors for common coding mistakes by declaring strict mode at the top of your scripts.",
    "Example": "Set-StrictMode -Version Latest",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-strictmode"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-08-28T00:00:00",
    "Title": "View your command line history",
    "TipText": "PowerShell lets you view your session history with `Get-History` and it's alias `h`.\r\n`Get-PSReadLineOption` used with `Get-Content` takes history reading further by allowing you to read your current users lifetime history.",
    "Example": "Get-Content (Get-PSReadLineOption).HistorySavePath",
    "Urls": [
      "https://learn.microsoft.com/powershell/module/psreadline/about/about_psreadline",
      "https://learn.microsoft.com/powershell/module/microsoft.powershell.core/get-history"
    ],
    "Category": 7
  },
  {
    "CreatedDate": "2023-09-05T00:00:00",
    "Title": "When checking for $null, put $null on the left",
    "TipText": "When checking if a variable or expression is null, put the $null on the left side of the comparison.\r\n\r\nIf the variable you are checking is an array that contains a null value, the comparison may not return the expected result if you put the $null on the right side of the comparison.\r\n\r\nDo this: if ($null -eq $variable)\r\nNot this: if ($variable -eq $null)",
    "Example": "if ($null -eq $variable) { \"The variable really is null.\" }",
    "Urls": [
      "https://powershellexplained.com/2018-12-23-Powershell-null-everything-you-wanted-to-know/",
      "https://stackoverflow.com/a/60996703/602585"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-06T00:00:00",
    "Title": "Use Ctrl+R to search your terminal history",
    "TipText": "When in your command prompt, press Ctrl+R to reverse search your terminal history. As you type, it will show the most recent matching command. This is a great way to find a command you ran previously, but can't remember the exact command or parameters.\r\n\r\nIf you press Ctrl+R again, it will show the next most recent matching command. You can keep pressing Ctrl+R to cycle through all matching commands. If you go past the command you wanted, press Ctrl+S and it will cycle through the matching commands in the opposite direction.\r\n\r\nNote: Requires the `PSReadLine` module, which is included in PowerShell 5.1 and newer.",
    "Example": "",
    "Urls": [
      "https://woshub.com/powershell-commands-history/"
    ],
    "Category": 7
  },
  {
    "CreatedDate": "2023-09-06T00:00:00",
    "Title": "Use Ctrl+Space to list all parameters, properties, and possibilities",
    "TipText": "In the terminal, when you are typing a command, parameter, or property, press Ctrl+Space to see a list of all the possible options. If there is only a single option, it will auto-complete the field for you. If there are many options, it will list them all for you to choose from and you can use the arrow keys to navigate the list and select one.\r\n\r\nCtrl+Space is similar to tab completion, except it will show you all of the options instead of just one option at a time and having to tab cycle through them.\r\n\r\nNote: Requires the `PSReadLine` module, which is included in PowerShell 5.1 and newer.",
    "Example": "- Type `Get-Process -` and press Ctrl+Space to list all the possible parameters you can use with the `Get-Process` command.\r\n- Type `$variableName.` and press Ctrl+Space to list all the properties and methods for the variable.\r\n- Type `Get-Pro` and press Ctrl+Space to list all the commands that start with `Get-Pro`, including their parameter sets.\r\n- Type part of a variable name (e.g. $var) and press Ctrl+Space to list all the variables that start with `$var`, including their type if available (e.g. [string], [int]).",
    "Urls": [
      "https://blog.danskingdom.com/PowerShell-intellisense-on-the-command-line/"
    ],
    "Category": 7
  },
  {
    "CreatedDate": "2023-09-11T00:00:00",
    "Title": "Ensure prerequisites are met by using #Requires",
    "TipText": "Use the #Requires statement to ensure that the environment meets the prerequisites for your script to run. You can use #Requires to check that:\r\n- A minimum PowerShell version is being used\r\n- PowerShell Desktop or PowerShell Core is being used\r\n- Specific modules or snap-ins are installed\r\n- The script is running as Administrator\r\n\r\nIf one of the required prerequisites are not met, PowerShell will throw an error and the script will not run.",
    "Example": "#Requires -Version 7.2\r\n#Requires -PSEdition Core\r\n#Requires -Modules @{ ModuleName=\"Az.KeyVault\"; ModuleVersion=\"4.0.0\" }\r\n#Requires -RunAsAdministrator",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-11T00:00:00",
    "Title": "Join the monthly PowerShell community call!",
    "TipText": "The PowerShell Community Call is held on the 3rd Thursday of every month at 9:30 AM US Pacific Time. Topics include PowerShell 7, Windows OpenSSH, PSEditorServices/VSCode-PowerShell, PSScriptAnalyzer, PowerShell Gallery, and any other projects owned by the PowerShell Team.\r\n\r\nYou can join the Teams live event at https://aka.ms/JoinPSCall. The call is recorded and posted on YouTube.",
    "Example": "",
    "Urls": [
      "https://github.com/PowerShell/PowerShell-RFC/blob/master/CommunityCall/README.md",
      "https://powershell.org/series/powershell-community-call/",
      "https://www.youtube.com/@powershellanddscteamchanne5739"
    ],
    "Category": 0
  },
  {
    "CreatedDate": "2023-09-11T00:00:00",
    "Title": "Read and write Excel spreadsheets with ImportExcel",
    "TipText": "Need to share large data sets with colleagues or your boss? Excel is still a popular way to do that. ImportExcel is a PowerShell module that makes it easy to read and write Excel spreadsheets. Use it to export your data to Excel, and even add charts and pivot tables. It's fast and doesn't require Excel to be installed on your computer. It's also cross-platform, so you can use it on Windows, macOS, and Linux.",
    "Example": "[PSCustomObject[]] $data = @(\r\n\t[PSCustomObject] @{\r\n\t\tFirstName = 'John'\r\n\t\tLastName = 'Doe'\r\n\t\tAge = 42\r\n\t}\r\n\t[PSCustomObject] @{\r\n\t\tFirstName = 'Jane'\r\n\t\tLastName = 'Doe'\r\n\t\tAge = 39\r\n\t}\r\n)\r\n$data | Export-Excel -Path 'C:\\Temp\\Results.xlsx' -WorksheetName 'People' -FreezeTopRow -AutoFilter -AutoSize",
    "Urls": [
      "https://www.powershellgallery.com/packages/ImportExcel",
      "https://github.com/dfinke/ImportExcel"
    ],
    "Category": 2
  },
  {
    "CreatedDate": "2023-09-12T00:00:00",
    "Title": "Get text file updates in realtime with Get-Content",
    "TipText": "Get-Content provides a `-Wait` switch that can be used to get updates to a text file in realtime. This is useful for monitoring log files from the terminal, or any other text file that is updated over time.\r\n\r\nIn addition, if you want to get the last N lines of a file, you can use the `-Tail` parameter. This is useful for getting only the last few lines of a very large text file.\r\n\r\nOnce you are done monitoring the file, you can press `Ctrl+C` to stop the command.",
    "Example": "Get-Content -Path $filePath -Wait -Tail 10",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content",
      "https://4sysops.com/archives/parse-log-files-with-powershell/"
    ],
    "Category": 3
  },
  {
    "CreatedDate": "2023-09-16T00:00:00",
    "Title": "Use Out-GridView to view and select tabular data",
    "TipText": "Instead of piping data to Out-Table, use Out-GridView. This opens a window with the data in a grid view, allowing you to interactively sort and filter the data. If you provide the -PassThru parameter, you can select one or more rows and the selected data will be returned to the pipeline, allowing you to save it to a variable or pipe it to other commands.\r\n\r\nNOTE: Out-GridView is only available on Windows.",
    "Example": "Get-Process | Out-GridView -PassThru -Title \"Select processes to return\" | Select-Object -Property ProcessName,Id",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/out-gridview",
      "https://woshub.com/using-out-gridview-table-powershell/"
    ],
    "Category": 3
  },
  {
    "CreatedDate": "2023-09-17T00:00:00",
    "Title": "Use F2 to toggle PSReadLine predictions to list view",
    "TipText": "PSReadLine v2.1.0 introduced history-based predictions. As you type, PSReadLine will show you a command that you previously typed, thinking that you may want to run the same command again. You can use the right-arrow to accept the suggestion.\r\n\r\nIf you want to see more predictions, you can press the F2 key to swap from Inline View (which only shows a single suggestion), to List View, which shows many. You can then use the up and down arrow keys to select a command from the list.\r\n\r\nUse 'Update-Module -Name PSReadLine' to update to the latest version of PSReadLine and use these features.",
    "Example": "Type \"Get-\" and then press F2 to see a list of commands that you have previously typed that start with \"Get-\"",
    "Urls": [
      "https://devblogs.microsoft.com/powershell/announcing-psreadline-2-1-with-predictive-intellisense/",
      "https://learn.microsoft.com/en-us/powershell/module/psreadline/"
    ],
    "Category": 7
  },
  {
    "CreatedDate": "2023-09-18T00:00:00",
    "Title": "Split long lines of code into multiple lines",
    "TipText": "Long lines of code can be difficult to read, especially when doing code reviews in a web browser and for users not using word-wrap in their editors. It is good practice to try and avoid long lines of code.\r\n\r\nPowerShell lines can naturally be split into multiple lines at many operators, such as =, +, -, |, {, -eq, etc.\r\n\r\nIf you need to split a line at an unnatural location, you can use the backtick character (`) at the end of each line. This is generally discouraged though as the backtick can be hard to see, easy to forget, and a space after the backtick breaks the line continuation. However, there are times when it may still be useful.",
    "Example": "# Split into multiple lines using natural operators.\r\n[bool] $arrayIsNullOrEmpty =\r\n $null -eq $myIntegerArray -or\r\n $myIntegerArray.Length -eq 0\r\n\r\n[int[]] $valuesGreaterThan10AndSorted =\r\n $myIntegerArray |\r\n Where-Object {\r\n $_ -gt 10\r\n } |\r\n Sort-Object\r\n\r\n[string] $myString =\r\n 'This is a very long string that is split into multiple lines ' +\r\n 'using the + operator.'\r\n\r\n# Split into multiple lines at an unnatural locations using the backtick.\r\nGet-ChildItem `\r\n -Path 'C:\\' `\r\n -Recurse `\r\n -File `\r\n -Filter '*.txt'",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing?view=powershell-7.3#line-continuation"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-19T00:00:00",
    "Title": "Use Splatting for nicer code and dynamic parameters",
    "TipText": "Splatting allows you to pass parameters to a function as a hashtable. This can make your code more readable when you have a lot of parameters to pass to a function. It also allows you to build the parameters dynamically.\r\n\r\nTo use splatting, create a hashtable with the parameter names as the keys and the parameter values as the values. Then, pass the hashtable to the function using the `@` operator.\r\n\r\nYou can also use splatting with arrays, where the array values are passed to the function as positional parameters.\r\n\r\nIn a function, you can use the $PSBoundParameters automatic variable to access the parameters that were passed to the function. This allows you to modify and extend the given parameters before passing them to another function.",
    "Example": "$hashtableParameters = @{\r\n Path = \"test.txt\"\r\n Destination = \"test2.txt\"\r\n WhatIf = $true\r\n}\r\nCopy-Item @hashtableParameters\r\n\r\n$arrayParameters = \"test.txt\", \"test2.txt\"\r\nCopy-Item @arrayParameters -WhatIf",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting",
      "https://adamtheautomator.com/powershell-splatting/",
      "https://4sysops.com/archives/use-splatting-and-psboundparameters-to-pass-parameters-in-powershell/"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-21T00:00:00",
    "Title": "Use Here-strings for hardcoded multiline strings",
    "TipText": "When you are defining multiline strings in code, you could create a string and use `r`n or [Environment]::NewLine to create new lines in it. If it is a long string, you may even choose to break it into multiple lines in code and concatenate them using the + operator. However, this can be cumbersome to both write and read. Instead, you can use a here-string to define a multiline string.\r\n\r\nA here-string is a string that is defined between two `@ symbols. The here-string can be defined with single or double quotes. If you use single quotes, the string will be a literal string and no variable expansion will occur. If you use double quotes, variable expansion will occur.\r\n\r\nHere-strings allow you to define and see a multiline string in your code exactly as it will appear when it is output.",
    "Example": "[string] $multilineString = @'\r\nThis is the first line of the string.\r\nThis is the second line of the string.\r\n\r\n There is a blank line above this line, and 2 spaces at the start of this line.\r\nThis $variable will not be expanded because we used single quotes.\r\n`'@\r\n\r\n[int] $johnDoeAge = 42\r\n[string] $jsonString = @\"\r\n{\r\n \"Name\": \"John Doe\",\r\n \"Age\": $johnDoeAge\r\n}",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules#here-strings",
      "https://devblogs.microsoft.com/scripting/maximizing-the-power-of-here-string-in-powershell-for-configuration-data"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-21T00:00:00",
    "Title": "Use PSBoundParameters to check if a parameter was provided",
    "TipText": "When writing a function you may want to check if a parameter was provided by the caller. With reference types (e.g. [string]) you can simply check if the parameter is null, but what is $null is a valid value for the parameter and you need to take different action if the parameter was not provided? Similarly, what if the parameter is a value type (e.g. [int]) and you need to take action if the caller provided the default value (e.g. zero), but not if they didn't provide the parameter?\r\n\r\nYou can check if a parameter was passed to a script/function by using the $PSBoundParameters automatic variable. This variable contains a hashtable of all parameters that were passed to the function, and you can use the ContainsKey function to check if a specific parameter was passed.",
    "Example": "function Test-ParameterWasPassed([string] $OptionalParameter = $null)\r\n{\r\n\tif ($PSBoundParameters.ContainsKey('OptionalParameter'))\r\n\t{\r\n\t\tWrite-Output 'OptionalParameter was passed.'\r\n\t}\r\n\telse\r\n\t{\r\n\t\tWrite-Output 'OptionalParameter was not passed.'\r\n\t}\r\n}",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables#psboundparameters",
      "https://devblogs.microsoft.com/powershell/checking-for-bound-parameters/",
      "https://www.reza-aghaei.com/how-to-determine-if-a-parameter-is-passed-to-a-powershell-cmdlet/"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-22T00:00:00",
    "Title": "Avoid Array addition",
    "TipText": "Array addition is an expensive and inefficient operation and can usually be replaced by PowerShell explicit loop assignment.\r\n\r\nUse a `List<T>` instead in those cases when adding to a collection while looping is required.",
    "Example": "# Array addition:\r\n$items = @()\r\nforeach ($i in 0..10) {\r\n $items += $i\r\n}\r\n\r\n# Can be easily replaced with explicit assignment:\r\n$items = foreach ($i in 0..10) {\r\n $i\r\n}\r\n\r\n# And, when not possible, a List<T> is recommended:\r\n$items = [System.Collections.Generic.List[int]]::new()\r\nforeach ($i in 0..10) {\r\n $items.Add($i)\r\n}",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/performance/script-authoring-considerations?view=powershell-7.3#array-addition"
    ],
    "Category": 4
  },
  {
    "CreatedDate": "2023-09-23T00:00:00",
    "Title": "Define hardcoded array items on new lines without commas",
    "TipText": "When defining hardcoded arrays with many values in PowerShell, you can define each item on a new line without commas; the commas are optional. This makes it easier to read and maintain the array items, and you don't have to worry about commas when adding or rearranging items.\r\n\r\nIf you choose to define multiple array values on a single line, then you will need a comma between each item on the line.",
    "Example": "[string[]] $stringArray = @(\r\n 'Notice that each item is on a new line without commas.'\r\n 'This is much easier to read and maintain.'\r\n 'And you can add comments to explain each item if needed.' # Like this.\r\n)\r\n\r\n[int[]] $intArray = @(1, 2, 3)",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-arrays?view=powershell-7.3#create-an-array"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-23T00:00:00",
    "Title": "Use $PSVersionTable to get PowerShell session info",
    "TipText": "The $PSVersionTable automatic variable contains information about the current PowerShell session, including the PowerShell version, operating system, and more.",
    "Example": "Write-Output \"The PowerShell version being used is $($PSVersionTable.PSVersion)\"\r\n\r\nWrite-Output \"Below is the full contents of the `$PSVersionTable variable:\"\r\n$PSVersionTable",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables#psversiontable"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-23T00:00:00",
    "Title": "Use Flags to allow multiple enum values",
    "TipText": "You can use the [Flags()] attribute to allow multiple enum values to be used at once. In addition to the attribute, you need to set the enum values to powers of 2 (1, 2, 4, 8, 16, etc.). This allows you to use the bitwise operators to combine enum values.\r\n\r\nWhen using a flags enum you must be careful to not use the -eq operator to check if a variable contains a specific enum value. This will only return true if the variable contains only that enum value. Instead, use the -band operator or the .HasFlag() method to check if the variable contains a specific enum value.",
    "Example": "[Flags()]\r\nenum FileAttributes {\r\n Archive = 1\r\n Compressed = 2\r\n Device = 4\r\n Directory = 8\r\n Encrypted = 16\r\n Hidden = 32\r\n}\r\n\r\n# Set a variable to multiple enum values.\r\n$attributes = [FileAttributes]::Archive + [FileAttributes]::Hidden\r\n$attributes += [FileAttributes]::Compressed\r\n\r\n# Check if the variable contains a specific enum value.\r\n$attributes -eq [FileAttributes]::Archive # False\r\n$attributes -band [FileAttributes]::Archive # True\r\n$attributes.HasFlag([FileAttributes]::Archive) # True",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_enum#enumerations-as-flags",
      "https://arcanecode.com/2021/12/06/fun-with-powershell-enum-flags/"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-09-29T00:00:00",
    "Title": "Use dynamic values in ValidateSet while maintaining tab completion",
    "TipText": "The ValidateSet attribute is a great way to limit the values that can be passed to a parameter, and it provides tab autocompletion for the parameter values. Typically if you wanted to use dynamic values you would use the ValidateScript attribute instead, but then you lose the tab autocompletion.\r\n\r\nA way to get the best of both worlds is to create a class that implements the System.Management.Automation.IValidateSetValuesGenerator interface. This interface has a single method, GetValidValues(), that returns an array of strings. You can put the logic to dynamically retrieve your allowed parameter values in the GetValidValues() method. You can then use the ValidateSet attribute with the type of your class, and the tab autocompletion will work as expected.",
    "Example": "class AllowedParameterValues : System.Management.Automation.IValidateSetValuesGenerator {\r\n [string[]] GetValidValues() {\r\n # Populate these values dynamically by querying a database, reading a file, calling an API, etc.\r\n $values = @('Value1', 'Value2', 'Value3')\r\n return $values\r\n }\r\n}\r\n\r\nfunction Test-ValidateSet {\r\n param (\r\n [ValidateSet([AllowedParameterValues])]\r\n [string] $Value\r\n )\r\n return $Value\r\n}\r\n\r\nTest-ValidateSet -Value # Tab complete here to see the dynamic values.",
    "Urls": [
      "https://www.linkedin.com/feed/update/urn:li:activity:7113300637735407618/"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-10-02T00:00:00",
    "Title": "Quickly create temporary file",
    "TipText": "Quickly create a temporary file by using the New-TemporaryFile command, or the GetTempFileName() .NET function.\r\n\r\nThis is handy when you want save data to a temporary log file and not worry about path/permissions/filename. The temporary file will be created in \"C:\\Users\\USER\\AppData\\Local\\Temp\\1\\some-tmp.tmp\".",
    "Example": "# Create temp file and get the path to it using the .NET class.\r\n[string] $tmpFile = [System.IO.Path]::GetTempFileName()\r\n\r\n# Or use the native PowerShell cmdlet instead, which returns a full FileInfo object.\r\n[System.IO.FileInfo] $tmpFile = New-TemporaryFile\r\n\r\n# Easily write/read/remove the temp file.\r\n\"Some data to be saved\" | Out-File $tmpFile\r\n\r\n# Cleanup when you no longer need it.\r\nRemove-Item $tmpFile",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/new-temporaryfile",
      "https://learn.microsoft.com/en-us/dotnet/api/system.io.path.gettempfilename#system-io-path-gettempfilename"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-10-02T00:00:00",
    "Title": "Use PowerShell classes for strongly-typed objects",
    "TipText": "PowerShell 5.0 introduced classes. Classes allow you to create strongly-typed objects, encapsulating properties and methods. This allows you to keep related data together and to define functions for manipulating the data, allowing for validation if necessary. Classes also allow for inheritance.\r\n\r\nThere are some caveats to working with classes in PowerShell though:\r\n- If you make changes to the class definition you must reload the PowerShell session for the changes to take effect.\r\n- PowerShell classes defined in modules are not exported when 'Import-Module' is used; Instead the 'using module' syntax must be used.",
    "Example": "class Employee\r\n{\r\n\t[string] $FirstName\r\n\t[string] $LastName\r\n\t[DateTime] $DateOfBirth\r\n\t[int] $Salary\r\n\r\n\t[string] GetFullName()\r\n\t{\r\n\t\treturn \"$this.FirstName $this.LastName\"\r\n\t}\r\n\r\n\t[void] IncreaseSalary([int] $amount)\r\n\t{\r\n\t\t$this.Salary += $amount\r\n\t}\r\n}\r\n\r\n$employee = [Employee]::new()\r\n$employee.FirstName = 'John'\r\n$employee.LastName = 'Doe'\r\n$employee.DateOfBirth = [DateTime]::Parse('1983-01-15')\r\n$employee.Salary = 50000\r\n$employee.GetFullName()\r\n$employee.IncreaseSalary(10000)",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_classes",
      "https://xainey.github.io/2016/powershell-classes-and-concepts/",
      "https://blog.danskingdom.com/PowerShell-class-definition-pros-cons-and-performance-comparison/"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-10-03T00:00:00",
    "Title": "PowerShell DevOps Global Summit 2024",
    "TipText": "The PowerShell DevOps Global Summit will be held in Bellevue, Washington, USA from April 8 - 11, 2024. The conference is a great place to learn about PowerShell and DevOps, and to meet and network with other people in the PowerShell community.\r\n\r\nWant to speak at the conference? The call for speakers is open from October 1 to November 15, 2023.",
    "Example": "",
    "Urls": [
      "https://www.powershellsummit.org/",
      "https://sessionize.com/pshsummit24/"
    ],
    "Category": 0
  },
  {
    "CreatedDate": "2023-10-03T00:00:00",
    "Title": "Process file lines with the switch statement",
    "TipText": "While the switch statement is typically used to evaluate a single value, it can also be used to evaluate arrays. By using the -File parameter with the switch statement, it will treat each line of the file as an array item, allowing you to process a text file line-by-line and take actions when a specific value is found. You can use the typical switch parameters to match on exact text, wildcards, or regular expressions.",
    "Example": "# Output the file contents to the console, converting error lines to errors, and warning lines to warnings.\r\nswitch -Wildcard -File $path\r\n{\r\n 'Error*'\r\n {\r\n Write-Error -Message $PSItem\r\n }\r\n 'Warning*'\r\n {\r\n Write-Warning -Message $PSItem\r\n }\r\n default\r\n {\r\n Write-Output $PSItem\r\n }\r\n}",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-switch#-file",
      "https://twitter.com/dfinke/status/1698733677285388581"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-10-07T00:00:00",
    "Title": "Store and retrieve secrets securely with SecretManagement",
    "TipText": "The Microsoft.PowerShell.SecretManagement module allows you to store secrets securely in a vault and retrieve them interactively, or in automated processes. This provides a secure alternative to storing secrets in plain text files, or continually being prompted for them.\r\n\r\nThe Microsoft.PowerShell.SecretStore module is a vault for storing secrets locally on your machine. There are other modules that provide integration with other vaults, such as Azure Key Vault, HashiCorp Vault, and LastPass. You can view them at https://aka.ms/SecretManagementVaults.",
    "Example": "# Install the SecretManagement and SecretStore modules.\r\nInstall-Module Microsoft.PowerShell.SecretManagement -Repository PSGallery\r\nInstall-Module Microsoft.PowerShell.SecretStore -Repository PSGallery\r\n\r\n# Register the SecretStore vault with the SecretManagement module.\r\nRegister-SecretVault -Name LocalFileSecretStore -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault\r\n\r\n# Store a secret in the vault (will be prompted for a vault password the 1st time).\r\nSet-Secret -Name MySecret -Secret 'MySecretValue'\r\n\r\n# Retrieve the secret from the vault.\r\nGet-Secret -Name MySecret",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.secretmanagement/?view=ps-modules",
      "https://devblogs.microsoft.com/powershell/secretmanagement-and-secretstore-are-generally-available/",
      "https://www.pdq.com/blog/how-to-manage-powershell-secrets-with-secretsmanagement/"
    ],
    "Category": 5
  },
  {
    "CreatedDate": "2023-10-08T00:00:00",
    "Title": "Prompt users for credentials and secrets securely",
    "TipText": "Sometimes we write scripts that prompt the user for their credentials, or for a secret like a password. We should avoid retrieving these values in plain text.\r\n\r\nTo securely prompt a user for their credentials use the Get-Credential cmdlet. This will prompt the user for their username and password, and return a PSCredential object with the password stored as a SecureString.\r\n\r\nThe securely prompt a user for a secret, use the Read-Host cmdlet with the -AsSecureString parameter. This will prompt the user for a secret and return a SecureString.\r\n\r\nMost cmdlets that require sensitive info will accept PSCredential or SecureString objects. In the rare case that you need the secret as plain text, you can convert the SecureString to plain text. This should be avoided if possible, as it exposes the secret in memory.",
    "Example": "# Prompt user for their username and password. The password will be stored as a SecureString.\r\n[PSCredential] $userCredentials = Get-Credential -Message 'Enter your credentials'\r\n\r\n# Some webhooks contain secrets, so treat them as sensitive.\r\n[SecureString] $secureWebhook = Read-Host -Prompt 'Enter the webhook URL' -AsSecureString\r\n\r\n# Convert a SecureString to plain text. AVOID THIS WHEN POSSIBLE.\r\n[string] $plainTextWebhook = [System.Net.NetworkCredential]::new('', $secureWebhook).Password",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.security/get-credential",
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/read-host",
      "https://www.pdq.com/blog/secure-password-with-powershell-encrypting-credentials-part-1/"
    ],
    "Category": 5
  },
  {
    "CreatedDate": "2023-10-09T00:00:00",
    "Title": "PowerShell Conference Europe 2024",
    "TipText": "PSConfEU 2024 will be held June 24 - 27, 2024. Save the date!\r\n\r\nMore details will be released at PSConfEU MiniCon on October 24, 2023.",
    "Example": "",
    "Urls": [
      "https://psconf.eu/"
    ],
    "Category": 0
  },
  {
    "CreatedDate": "2023-10-09T00:00:00",
    "Title": "PSConfEU 2023 MiniCon",
    "TipText": "The PSConfEU 2023 MiniCon will be held on October 24, 2023. Save the date!\r\n\r\nPSConfEU 2023 MiniCon is a free virtual event open to all of the PowerShell community. Wherever you are, join and say hi! There will be multiple sessions in several tracks, and many speakers and leaders of the community will be there to talk to you!",
    "Example": "",
    "Urls": [
      "https://psconf.eu/",
      "https://app.gather.town/events/It0l-Wx8TQmTI93yQvs-"
    ],
    "Category": 0
  },
  {
    "CreatedDate": "2023-10-11T00:00:00",
    "Title": "Create test files of arbitrary size",
    "TipText": "When doing performance testing it can be useful to have a file of a specific size to test with. Creating files of a specific size is fairly straightforward with the System.IO.FileStream class.",
    "Example": "[string] $fileName = [System.IO.Path]::GetRandomFileName()\r\n[string] $filePath = Join-Path -Path (Get-Location) -ChildPath $fileName\r\n[int64] $fileSize = 10MB\r\n\r\ntry {\r\n $tempFile = [System.IO.FileStream]::new($filePath, Create, ReadWrite)\r\n $tempFile.SetLength($fileSize)\r\n $tempFile.Close()\r\n\r\n Write-Output 'Created the following temp file:'\r\n Get-ChildItem $filePath | Select-Object FullName,DirectoryName,Name,Length,CreationTime\r\n} catch {\r\n Write-Error $_\r\n}",
    "Urls": [
      "https://learn.microsoft.com/en-us/dotnet/api/system.io.filestream",
      "https://claytonerrington.com/blog/creating-a-test-file"
    ],
    "Category": 8
  },
  {
    "CreatedDate": "2023-10-11T00:00:00",
    "Title": "Get file name from URL",
    "TipText": "If you have a URL that contains a path to a file, you can use the [URI] class to extract the file path and name.",
    "Example": "PS> [URI] $uri = 'https://some-server.com/Path/To/File.txt?someQueryParameter=123#Heading1'\r\n\r\nPS> $uri\r\nAbsolutePath : /Path/To/File.txt\r\nAbsoluteUri : https://some-server.com/Path/To/File.txt?someQueryParameter=123#Heading1\r\nPathAndQuery : /Path/To/File.txt?someQueryParameter=123\r\nSegments : {/, Path/, To/, File.txt}\r\nHost : some-server.com\r\nPort : 443\r\nQuery : ?someQueryParameter=123\r\nFragment : #Heading1\r\nScheme : https\r\n\r\nPS> Split-Path -Path $uri.AbsolutePath -Leaf\r\nFile.txt\r\n\r\nPS> Split-Path -Path $uri.AbsolutePath -LeafBase\r\nFile",
    "Urls": [
      "https://learn.microsoft.com/en-us/dotnet/api/system.uri",
      "https://twitter.com/devopsjeremy/status/1709773064563744888?s=46&t=-Ox1iPV67-4Vqb8wIZ275A"
    ],
    "Category": 8
  },
  {
    "CreatedDate": "2023-10-14T00:00:00",
    "Title": "Make convenience to objects by using calculated properties",
    "TipText": "PowerShell is a dynamic language, which means that you can add properties to objects on the fly. By using calculated properties, you can add properties to objects that are calculated from other properties on the object, or data from external sources.\r\n\r\nThe easiest way to add calculated properties is by using the `Select-Object` cmdlet to return a new object back with the additional properties. You provide a hashtable to the `-Property` parameter, with a `Name` key for the name of the new property and an `Expression` key for the value. You can add as many calculated properties as you want.",
    "Example": "# Get the first process and add a single calculated property to show how long it has been running.\r\n> Get-Process | Select-Object -First 1 -Property ProcessName,StartTime,@{ Name = \"RunningTime\"; Expression = { (Get-Date) - $_.StartTime } }\r\n\r\nProcessName StartTime RunningTime\r\n----------- --------- -----------\r\n1Password 10/14/2023 12:59:24 PM 00:32:59.1893342\r\n\r\n\r\n# Add multiple calculated properties (split into multiple lines for readability).\r\n> Get-Process | Select-Object -First 1 -Property ProcessName,`\r\n StartTime,@{ Name = \"RunningTime\"; Expression = { (Get-Date) - $_.StartTime } },`\r\n WorkingSet,@{ Name = \"WorkingSetMb\"; Expression = { $_.WorkingSet / 1MB }}\r\n\r\nProcessName : 1Password\r\nStartTime : 10/14/2023 12:59:24 PM\r\nRunningTime : 00:33:03.0717040\r\nWorkingSet : 73527296\r\nWorkingSetMb : 70.12109375",
    "Urls": [
      "https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_calculated_properties",
      "https://4sysops.com/archives/add-a-calculated-property-with-select-object-in-powershell/"
    ],
    "Category": 6
  },
  {
    "CreatedDate": "2023-10-20T00:00:00",
    "Title": "Use Out-ConsoleGridView for a cross-platform grid view",
    "TipText": "The Out-GridView cmdlet is very useful, but it only works on Windows. The Microsoft.PowerShell.ConsoleGuiTools module provides a cross-platform alternative called Out-ConsoleGridView. Rather than opening a new window, it displays the grid view in the current terminal window.\r\n\r\nYou can use Out-ConsoleGridView to display a table of data that the user is able to interactively navigate. The user can select rows from the list that can be saved to a variable or piped to another command, allowing you to perform actions on the selected rows.",
    "Example": "Install-Module Microsoft.PowerShell.ConsoleGuiTools\r\n\r\nGet-Process | Out-ConsoleGridView -Title \"Select processes to return\" | Select-Object -Property ProcessName,Id",
    "Urls": [
      "https://github.com/PowerShell/GraphicalTools/"
    ],
    "Category": 2
  },
  {
    "CreatedDate": "2023-10-21T00:00:00",
    "Title": "Learn about a random PowerShell cmdlet or topic",
    "TipText": "The tiPS module (which is bringing you these tips) is a great way to learn PowerShell every day. There are other ways to learn PowerShell every day too. Use the example code to learn about a random PowerShell cmdlet or topic. Try adding it to your daily routine, or even to your PowerShell profile.",
    "Example": "# Show the Help documentation for a random native cmdlet.\r\nGet-Command -Module Microsoft*,Cim*,PS* | Get-Random | Get-Help -ShowWindow\r\n\r\n# Show the Help documentation for a random PowerShell About topic.\r\nGet-Random -input (Get-Help about*) | Get-Help -ShowWindow\r\n\r\n# Open your PowerShell profile in VS Code so you can add the below code to it\r\n# to automatically see Help documentation each time you start a new PowerShell\r\n# session on Mondays before 10am.\r\ncode $Profile\r\n\r\n[DateTime] $now = Get-Date\r\nif ($now.DayOfWeek -eq 'Monday' -and $now.Hour -lt 10)\r\n{\r\n Get-Command -Module Microsoft*,Cim*,PS* | Get-Random | Get-Help -ShowWindow\r\n Get-Random -input (Get-Help about*) | Get-Help -ShowWindow\r\n}",
    "Urls": [
      "https://jdhitsolutions.com/blog/essential-powershell-resources/"
    ],
    "Category": 8
  }
]