├── .github ├── FUNDING.yml └── workflows │ └── main.yml ├── .gitmodules ├── .hugo_build.lock ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── archetypes └── default.md ├── config.toml ├── config.yaml ├── content ├── _index.Rmarkdown ├── _index.markdown └── post │ ├── arrays.md │ ├── classes.md │ ├── constants.md │ ├── custom-object.md │ ├── error-actions.md │ ├── error-handling.md │ ├── for.md │ ├── foreach.md │ ├── functions.md │ ├── hashtables.md │ ├── hello-world.md │ ├── if-else.md │ ├── json.md │ ├── multidimensional-arrays.md │ ├── read-only-variables.md │ ├── reading-files.md │ ├── sorting.md │ ├── splatting.md │ ├── strings.md │ ├── switch.md │ ├── time-and-date.md │ ├── variable-scopes.md │ ├── variables.md │ ├── writing-files.md │ └── xml.md ├── layouts ├── _default │ ├── list.html │ └── single.html ├── _internal │ └── google_analytics.html ├── partials │ ├── foot_custom copy.html │ ├── foot_custom.html │ ├── head_custom.html │ └── header.html └── shortcodes │ └── error.html ├── resources ├── logo-32x32.pdn ├── logo.pdn └── raw_logo.png └── static ├── CNAME ├── css ├── fonts.css └── style.css ├── icons └── favicon-32x32.png └── twittercard.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: sanderstad 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: github pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main # Set a branch to deploy 7 | pull_request: 8 | 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | submodules: true # Fetch Hugo themes (true OR recursive) 16 | fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod 17 | 18 | - name: Setup Hugo 19 | uses: peaceiris/actions-hugo@v2 20 | with: 21 | hugo-version: "latest" 22 | extended: true 23 | 24 | - name: Build 25 | run: hugo --minify 26 | 27 | - name: Deploy 28 | uses: peaceiris/actions-gh-pages@v3 29 | if: github.ref == 'refs/heads/main' 30 | with: 31 | github_token: ${{ secrets.GITHUB_TOKEN }} 32 | publish_dir: ./public 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "themes/hugo-xmin"] 2 | path = themes/hugo-xmin 3 | url = https://github.com/yihui/hugo-xmin.git 4 | -------------------------------------------------------------------------------- /.hugo_build.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/.hugo_build.lock -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Thanks for your interest in contributing to PowerShell by Example! 4 | 5 | * To contribute to the project you need to have a GitHub account. You can then clone the repository and start working on the project. 6 | 7 | * We're open to adding more examples to the site. They should be on things used by many programmers and only require the standard library. If you're interested in adding an example, _please open an [Discussion](https://github.com/sanderstad/powershellbyexample/discussions) to discuss the topic first_. 8 | 9 | * If you have a question or want to discuss the project, please go to the [Discussion](https://github.com/sanderstad/powershellbyexample/discussions). 10 | 11 | * We're not going to change the navigation of the site, in particular adding a "previous section" link or an "index" link other than the one present on the page. 12 | 13 | ## Adding a new post 14 | 15 | To add an item you need to add a `.md` file to the `content/post` directory. 16 | Make the file name represent the part that you want to add like `arrays.md` or `functions.md`. 17 | 18 | A post should at least have this content at the top: 19 | 20 | ``` 21 | --- 22 | title: [title] 23 | author: [your name] 24 | date: 'yyy-MM-dd' 25 | categories: 26 | - Example 27 | weight: [weight] 28 | --- 29 | 30 | [description of the post] 31 | ``` 32 | 33 | * The title should be short and describe the content. 34 | * The author can be your full name. 35 | * The date should be in the format `yyy-MM-dd`, i.e. `2020-01-01`. 36 | * The weight should be a number higher than the weight in the latest post incremented by 10. If the weight of the last post is 120, your weight should be 130 if you want it to be the latest post. 37 | 38 | After you've added the post you can run `git add .` and `git commit -m "Add [title] post"` to commit the changes. 39 | 40 | After you've committed the changes to your clone you can then create a pull request (PR) from your clone to the main branch of this project. 41 | 42 | The PR will be assessed by the maintainers of the project and if it is approved your changes will be merged into the main branch. 43 | 44 | This step will automatically start the action to publish the content. 45 | 46 | ## Code 47 | 48 | PowerShell code should be wrapped in a markdown powershell code block "```powershell". 49 | 50 | ## Results 51 | 52 | If you want to display the results of your example code, you have to put the entire output into a "```" block 53 | 54 | ## Short codes 55 | 56 | Hugo works with short codes and in this project we created a couple of short codes to help out. 57 | 58 | ### Errors 59 | 60 | If you want to add an error message to your post you can use the `error` short code like so: 61 | 62 | ``` 63 | {{< error >}} 64 | THIS IS AN ERROR 65 | {{}} 66 | ``` 67 | 68 | A good example of using this short code is in the `variables.md` file. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Sander Stad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/README.md -------------------------------------------------------------------------------- /archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | baseURL = 'https://powershellbyexample.dev/' 2 | languageCode = 'en-us' 3 | title = 'PowerShell By Example' 4 | theme = 'hugo-xmin' 5 | googleAnalytics = "G-WRS58SRCQM" 6 | 7 | 8 | [services] 9 | [services.googleAnalytics] 10 | id = 'G-WRS58SRCQM' 11 | 12 | [privacy] 13 | [privacy.googleAnalytics] 14 | disable = false 15 | respectDoNotTrack = false -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | baseurl: "/" 2 | languageCode: "en-us" 3 | title: "A minimal Hugo website" 4 | theme: "hugo-xmin" 5 | googleAnalytics: "" 6 | disqusShortname: "" 7 | ignoreFiles: ["\\.Rmd$", "\\.Rmarkdown$", "_cache$", "\\.knit\\.md$", "\\.utf8\\.md$"] 8 | footnotereturnlinkcontents: "↩" 9 | 10 | permalinks: 11 | note: "/note/:year/:month/:day/:slug/" 12 | post: "/post/:year/:month/:day/:slug/" 13 | 14 | menu: 15 | main: 16 | - name: Home 17 | url: "" 18 | weight: 1 19 | - name: About 20 | url: "about/" 21 | weight: 2 22 | - name: Categories 23 | url: "categories/" 24 | weight: 3 25 | - name: Tags 26 | url: "tags/" 27 | weight: 4 28 | - name: Subscribe 29 | url: "index.xml" 30 | 31 | params: 32 | description: "A website built through Hugo and blogdown." 33 | footer: "© [Yihui Xie](https://yihui.org) 2017 -- {Year} | [Github](https://github.com/yihui) | [Twitter](https://twitter.com/xieyihui)" 34 | 35 | markup: 36 | highlight: 37 | codeFences: false 38 | goldmark: 39 | renderer: 40 | unsafe: true 41 | -------------------------------------------------------------------------------- /content/_index.Rmarkdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | --- 4 | 5 | [Github repo](https://github.com/yihui/hugo-xmin) 6 | 7 | # HUGO XMIN 8 | 9 | ## _Keep it simple, but not simpler_ 10 | 11 | **XMin** is a Hugo theme written by [Yihui Xie](https://yihui.org) in about four hours: half an hour was spent on the Hugo templates, and 3.5 hours were spent on styling. The main motivation for writing this theme was to provide a really minimal example to beginners of Hugo templates. This XMin theme contains about 130 lines of code in total, including the code in HTML templates and CSS (also counting empty lines). 12 | 13 | ```{bash, comment='', echo=3, eval=Sys.which('bash') != '', message=FALSE} 14 | cd ../..; 15 | if [ ! -f 'theme.toml' ]; then exit 0; fi # only run find below within the theme example site 16 | find . -not -path '*/exampleSite/*' \( -name '*.html' -o -name '*.css' \) | xargs wc -l 17 | ``` 18 | 19 | I can certainly further reduce the code, for example, by eliminating the CSS, but I believe a tiny bit of CSS can greatly improve readability. You cannot really find many CSS frameworks that only contain 50 lines of code. 20 | 21 | Although it is a minimal theme, it is actually fully functional. It supports pages (including the home page), blog posts, a navigation menu, categories, tags, and RSS. With [a little bit customization](https://github.com/yihui/hugo-xmin/blob/master/exampleSite/layouts/partials/foot_custom.html), it can easily support LaTeX math expressions, e.g., 22 | 23 | `$${\sqrt {n}}\left(\left({\frac {1}{n}}\sum _{i=1}^{n}X_{i}\right)-\mu \right)\ {\xrightarrow {d}}\ N\left(0,\sigma ^{2}\right)$$` 24 | 25 | All pages not under the root directory of the website are listed below. You can also visit the list page of a single section, e.g., [posts](/post/), or [notes](/note/). See the [About](/about/) page for the usage of this theme. 26 | -------------------------------------------------------------------------------- /content/_index.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | title: PowerShell by Example 3 | --- 4 | 5 | # PowerShell by Example 6 | 7 | **PowerShell** is an open source programming language designed for automation. 8 | 9 | PowerShell by Example, modeled after [Go by Example](https://gobyexample.com/), is a hands-on introduction to PowerShell using annotated example programs. Check out the first example or browse the full list below. 10 | 11 | To execute the scripts make sure you have at least PowerShell 5 installed. 12 | 13 | -------------------------------------------------------------------------------- /content/post/arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Arrays 3 | author: Sander Stad 4 | date: '2022-02-23' 5 | categories: 6 | - Example 7 | weight: 90 8 | --- 9 | 10 | An array is a data structure that is designed to store a collection of items. 11 | The items can be the same type or different types. 12 | 13 | ## Creating arrays 14 | 15 | Define an array using the `@()` 16 | 17 | ```powershell 18 | $values = @("One", "Two", "Three", "Four", "Five") 19 | $values 20 | $values.GetType() 21 | ``` 22 | 23 | Result: 24 | 25 | ``` 26 | One 27 | Two 28 | Three 29 | Four 30 | Five 31 | 32 | IsPublic IsSerial Name BaseType 33 | -------- -------- ---- -------- 34 | True True Object[] System.Array 35 | ``` 36 | 37 | Define an array by setting with comma separated values 38 | 39 | ```powershell 40 | $values = "Six", "Seven", "Eight", "Nine", "10" 41 | $values 42 | ``` 43 | 44 | Result: 45 | 46 | ``` 47 | Six 48 | Seven 49 | Eight 50 | Nine 51 | 10 52 | ``` 53 | 54 | Define an array with a specific type 55 | 56 | ```powershell 57 | [int[]]$values = 6, 7, 8, 9, 10 58 | $values 59 | ``` 60 | 61 | Result: 62 | 63 | ``` 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | ``` 70 | 71 | Define an array with the [array] type 72 | 73 | ```powershell 74 | [array]$values = 11, 12, 13, 14, 15 75 | $values 76 | ``` 77 | 78 | Result: 79 | 80 | ``` 81 | 11 82 | 12 83 | 13 84 | 14 85 | 15 86 | ``` 87 | 88 | ## Adding and changing values in arrays 89 | 90 | ```powershell 91 | $values = @("One", "Two", "Three") 92 | $values 93 | 94 | # Counting the items in the array using the Count property 95 | Write-Host "Items in array $($values.Count)" 96 | 97 | # Add a value to the array using the + operator 98 | $values += "Four" 99 | $values 100 | 101 | Write-Host "Items in array $($values.Count)" 102 | 103 | # Change a value in the array using the index 104 | $values[0] = "Five" 105 | $values 106 | ``` 107 | 108 | Result: 109 | 110 | ``` 111 | One 112 | Two 113 | Three 114 | Items in array 3 115 | One 116 | Two 117 | Three 118 | Four 119 | Items in array 4 120 | Five 121 | Two 122 | Three 123 | Four 124 | ``` 125 | 126 | ## Accessing arrays 127 | 128 | To access the items in the array, use the index. 129 | The index starts at 0. 130 | 131 | ```powershell 132 | [array]$values = 1, 2, 3, 4, 5 133 | 134 | # Access the third item in the array 135 | Write-Host "Item at index 2: $($values[2])" 136 | ``` 137 | 138 | Result: 139 | 140 | ``` 141 | Item at index 2: 3 142 | ``` 143 | 144 | ## Looping though arrays 145 | 146 | The same index method as the example before can be used with loops. 147 | 148 | ```powershell 149 | $nameArray = @("Erik", "Penny", "Randy", "Sandy", "Toby", "Uma", "Vicky", "Will", "Xavier", "Yvette", "Zach") 150 | for ($i = 0; $i -lt $nameArray.Length; $i++) { 151 | Write-Host $nameArray[$i] 152 | } 153 | ``` 154 | 155 | Result: 156 | 157 | ``` 158 | Erik 159 | Penny 160 | Randy 161 | Sandy 162 | Toby 163 | Uma 164 | Vicky 165 | Will 166 | Xavier 167 | Yvette 168 | Zach 169 | ``` 170 | 171 | -------------------------------------------------------------------------------- /content/post/classes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Classes 3 | author: Sander Stad 4 | date: '2022-04-11' 5 | categories: 6 | - Example 7 | weight: 230 8 | --- 9 | 10 | Since PowerShell 5 you are able to create your own classes in PowerShell. 11 | 12 | Although classes in other programming languages are a big advantage and sometimes even required, they are not required in PowerShell. 13 | 14 | In some cases you may want to use classes in PowerShell to create objects that can be used in PowerShell. One of those examples is when you use DSC (Desired State Configuration). 15 | Most of the time you will not need to use classes in PowerShell, and you will be fine using custom objects in your commands instead. 16 | 17 | # Create a class 18 | 19 | To create a class we need to use the `class` keyword. The example below shows an example of a class. 20 | It also shows how to use the `new` keyword to create an instance of the class. 21 | 22 | ```powershell 23 | class Tree { 24 | [int]$Height 25 | [int]$Age 26 | [string]$Color 27 | } 28 | 29 | $tree1 = new-object Tree 30 | $tree2 = [Tree]::new() 31 | 32 | $tree1.Height = 10 33 | $tree1.Age = 5 34 | $tree1.Color = "Red" 35 | 36 | $tree2.Height = 20 37 | $tree2.Age = 10 38 | $tree2.Color = "Green" 39 | 40 | $tree1 41 | $tree2 42 | ``` 43 | 44 | The result should look something like this: 45 | 46 | ``` 47 | ------ --- ----- 48 | 10 5 Red 49 | 20 10 Green 50 | ``` 51 | 52 | As you can see we can use the `New-Object` command or the `new()` keyword to create an instance of the class. 53 | 54 | # Constructors 55 | 56 | When creating a class you can also create a constructor. The constructor is a special method that is called when you create an instance of the class. 57 | This can be very useful when you want to initialize some properties of the class. 58 | 59 | The example below demonstrates how to create multiple constructors for the class. 60 | 61 | ```powershell 62 | class Tree { 63 | [int]$Height 64 | [int]$Age 65 | [string]$Color 66 | 67 | Tree() { 68 | $this.Height = 1 69 | $this.Age = 0 70 | $this.Color = "Green" 71 | } 72 | 73 | Tree([int]$Height, [int]$Age, [string]$Color) { 74 | $this.Height = $Height; 75 | $this.Age = $Age; 76 | $this.Color = $Color; 77 | } 78 | } 79 | 80 | $tree1 = [Tree]::New() 81 | $tree2 = New-Object Tree 5, 2, "Red" 82 | 83 | $tree1 84 | $tree2 85 | ``` 86 | The result should look something like this: 87 | 88 | ``` 89 | Height Age Color 90 | ------ --- ----- 91 | 1 0 Green 92 | 5 2 Red 93 | ``` 94 | 95 | In the example above you can see the first object is created with the default constructor and does not accept any parameters. This can be handy to initialize variables when the object is created. 96 | The second object is created using another constructor and accepts three parameters. 97 | 98 | # Creating methods 99 | 100 | We technically don't need to create methods to set values in the class because all the properties can be retrieved and set using the default methods. 101 | In some situations you may want to create methods to set values in the class. 102 | 103 | In the example below we create a method to let the tree grow by increasing the age and the height. 104 | 105 | ```powershell 106 | class Tree { 107 | [int]$Height 108 | [int]$Age 109 | [string]$Color 110 | 111 | # Initialize the tree by setting default values 112 | Tree() { 113 | $this.Height = 1 114 | $this.Age = 0 115 | $this.Color = "Green" 116 | } 117 | 118 | # Create a constructor with parameters a.k.a. constructor overloading 119 | Tree([int]$Height, [int]$Age, [string]$Color) { 120 | $this.Height = $Height 121 | $this.Age = $Age 122 | $this.Color = $Color 123 | } 124 | 125 | [void]Grow() { 126 | # Get a random height because plants and trees don't grow the same each year 127 | $heightIncrease = Get-Random -Min 1 -Max 5; 128 | $this.Height += $heightIncrease; 129 | $this.Age += 1 130 | } 131 | } 132 | 133 | $tree = [Tree]::New() 134 | 135 | # Let the tree grow for 10 years 136 | for ($i = 0; $i -lt 10; $i++) { 137 | $tree.Grow() 138 | $tree 139 | } 140 | ``` 141 | 142 | The result should look something like this: 143 | 144 | ``` 145 | Height Age Color 146 | ------ --- ----- 147 | 3 1 Green 148 | 7 2 Green 149 | 10 3 Green 150 | 11 4 Green 151 | 15 5 Green 152 | 16 6 Green 153 | 20 7 Green 154 | 24 8 Green 155 | 26 9 Green 156 | 28 10 Green 157 | ``` 158 | 159 | # Class inheritance 160 | 161 | The examples are all good to use with classes but can be done very easily without using classes. 162 | Where classes become useful is when you start to use inheritance. 163 | 164 | ```powershell 165 | class Tree { 166 | [int]$Height 167 | [int]$Age 168 | [string]$Color 169 | 170 | Tree() { 171 | $this.Height = 1; 172 | $this.Age = 0 173 | $this.Color = "Green" 174 | } 175 | 176 | Tree([int]$Height, [int]$Age, [string]$Color) { 177 | $this.Height = $Height; 178 | $this.Age = $Age; 179 | $this.Color = $Color; 180 | } 181 | 182 | [void]Grow() { 183 | # Get a random height because plants and trees don't grow the same each year 184 | $heightIncrease = Get-Random -Min 1 -Max 5; 185 | $this.Height += $heightIncrease; 186 | $this.Age += 1 187 | } 188 | } 189 | 190 | class AppleTree : Tree { 191 | [string]$Spieces = "Apple" 192 | } 193 | 194 | $tree = [AppleTree]::new() 195 | $tree 196 | ``` 197 | 198 | The result should look something like this: 199 | 200 | ``` 201 | Spieces Height Age Color 202 | ------- ------ --- ----- 203 | Apple 1 0 Green 204 | ``` 205 | 206 | For more information about classes in PowerShell see [Classes](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_classes?view=powershell-7.2). 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /content/post/constants.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Constants 3 | date: '2022-02-22' 4 | categories: 5 | - Example 6 | weight: 40 7 | --- 8 | 9 | PowerShell supports constants and read-only variables. 10 | Constants are variables that cannot be changed whatever you try. 11 | 12 | You create a constant variable with the `New-Variable` command with the parameter `-Option Constant`. 13 | 14 | ```powershell 15 | New-Variable -Name myConst -Value "This CANNOT be changed" -Option Constant 16 | $myConst 17 | ``` 18 | 19 | We can't change te value even with the `-Force` parameter 20 | 21 | ```powershell 22 | New-Variable -Name myConst -Value "I'm going to change it" -Option Constant -Force 23 | ``` 24 | 25 | {{< error >}} 26 | ``` 27 | New-Variable : Cannot overwrite variable myConst because it is read-only or constant. 28 | At line:1 char:1 29 | + New-Variable -Name myConst -Value "I'm going to change it" -Option Co ... 30 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 31 | + CategoryInfo : WriteError: (myConst:String) [New-Variable], SessionStateUnauthorizedAccessException 32 | + FullyQualifiedErrorId : VariableNotWritable,Microsoft.PowerShell.Commands.NewVariableCommand 33 | ``` 34 | {{< /error >}} 35 | 36 | -------------------------------------------------------------------------------- /content/post/custom-object.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Objects 3 | author: Sander Stad 4 | date: '2022-04-11' 5 | categories: 6 | - Example 7 | weight: 210 8 | --- 9 | 10 | Custom objects are a powerful feature of PowerShell and can be leveraged to make your function/commands even more suitable for advanced use cases. 11 | It is an easy way to create structured data without any fuzz. Importing and exporting data will also be muc easier. 12 | 13 | To create a custom object we can to use the `New-Object` command or use the [PSCustomObject] type. 14 | 15 | # Creating a custom object 16 | 17 | ```powershell 18 | # Old style of creating an object 19 | $object1 = New-Object PSObject 20 | 21 | Add-Member -InputObject $object1 -MemberType NoteProperty -Name prop1 -Value "value1" 22 | Add-Member -InputObject $object1 -MemberType NoteProperty -Name prop2 -Value "value2" 23 | 24 | $object1 25 | $object1.GetType() 26 | ``` 27 | 28 | The result should look something like this: 29 | 30 | ``` 31 | prop1 prop2 32 | ----- ----- 33 | value1 value2 34 | 35 | IsPublic IsSerial Name BaseType 36 | -------- -------- ---- -------- 37 | True False PSCustomObject System.Object 38 | ``` 39 | 40 | Of course we are going to use the new style of creating an object. 41 | 42 | ```powershell 43 | # New style of creating an object 44 | $object2 = [PSCustomObject]@{ 45 | prop1 = "value1" 46 | prop2 = "value2" 47 | } 48 | 49 | $object2 50 | ``` 51 | 52 | The result should look something like this: 53 | 54 | ``` 55 | prop1 prop2 56 | ----- ----- 57 | value1 value2 58 | 59 | IsPublic IsSerial Name BaseType 60 | -------- -------- ---- -------- 61 | True False PSCustomObject System.Object 62 | ``` 63 | 64 | As you can see the results are exactly the same but it is a lot easier to write it the new way. 65 | -------------------------------------------------------------------------------- /content/post/error-actions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Error Actions 3 | author: Sander Stad 4 | date: '2022-03-09' 5 | categories: 6 | - Example 7 | weight: 150 8 | --- 9 | 10 | In normal circumstances, because we want PowerShell to work even though sometimes we have errors. 11 | That is the reason why PowerShell errors in general are what we call non-terminating errors. 12 | 13 | ```powershell 14 | Clear-Host 15 | 16 | $items = @() 17 | 18 | # Generate more items 19 | $items += for ($i = 0; $i -le 3; $i++) { 20 | "$($env:TEMP)\$(Get-Process -Id $pid)-$($i).txt" 21 | } 22 | 23 | # Let's generate some errors 24 | $items | ForEach-Object { 25 | Get-Item -Path $_ 26 | } 27 | ``` 28 | 29 | Result: 30 | 31 | {{< error >}} 32 | ``` 33 | Get-Item : Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (powershell)-0.txt' because it does not exist. 34 | At line:2 char:5 35 | + Get-Item -Path $_ 36 | + ~~~~~~~~~~~~~~~~~ 37 | + CategoryInfo : ObjectNotFound: (C:\Users\Sander...wershell)-0.txt:String) [Get-Item], ItemNotFoundException 38 | + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand 39 | 40 | Get-Item : Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (powershell)-1.txt' because it does not exist. 41 | At line:2 char:5 42 | + Get-Item -Path $_ 43 | + ~~~~~~~~~~~~~~~~~ 44 | + CategoryInfo : ObjectNotFound: (C:\Users\Sander...wershell)-1.txt:String) [Get-Item], ItemNotFoundException 45 | + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand 46 | 47 | Get-Item : Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (powershell)-2.txt' because it does not exist. 48 | At line:2 char:5 49 | + Get-Item -Path $_ 50 | + ~~~~~~~~~~~~~~~~~ 51 | + CategoryInfo : ObjectNotFound: (C:\Users\Sander...wershell)-2.txt:String) [Get-Item], ItemNotFoundException 52 | + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand 53 | 54 | Get-Item : Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (powershell)-3.txt' because it does not exist. 55 | At line:2 char:5 56 | + Get-Item -Path $_ 57 | + ~~~~~~~~~~~~~~~~~ 58 | + CategoryInfo : ObjectNotFound: (C:\Users\Sander...wershell)-3.txt:String) [Get-Item], ItemNotFoundException 59 | + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand 60 | ``` 61 | {{< /error >}} 62 | 63 | Although we got a lot of errors, PowerShell still executes the script 64 | 65 | ## Error Actions 66 | 67 | There are six error actions in PowerShell 68 | * Stop 69 | * Continue 70 | * SilentlyContinue 71 | * Ignore 72 | * Inquire 73 | * Suspend (Only used for Windows PowerShell Workflow. Cannot be used with advanced functions) 74 | 75 | ### Stop 76 | 77 | Let's run the same script as before but now with an error action called `Stop`. 78 | 79 | ```powershell 80 | Clear-Host 81 | 82 | $items = @() 83 | 84 | # Generate more items 85 | $items += for ($i = 0; $i -le 3; $i++) { 86 | "$($env:TEMP)\$(Get-Process -Id $pid)-$($i).txt" 87 | } 88 | 89 | # Let's generate some errors 90 | $items | ForEach-Object { 91 | Get-Item -Path $_ -ErrorAction Stop 92 | } 93 | ``` 94 | 95 | Result: 96 | 97 | {{< error >}} 98 | ``` 99 | Get-Item : Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (powershell)-0.txt' because it does not exist. 100 | At line:2 char:5 101 | + Get-Item -Path $_ -ErrorAction Stop 102 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 103 | + CategoryInfo : ObjectNotFound: (C:\Users\Sander...wershell)-0.txt:String) [Get-Item], ItemNotFoundException 104 | + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand 105 | ``` 106 | {{< /error >}} 107 | 108 | Although in the previous example we could loop through the items, this time because we set an error action, the loop stops at the first error. 109 | 110 | ### Continue 111 | 112 | This is the default error action. The error will still be displayed but the script will continue. 113 | 114 | ```powershell 115 | Clear-Host 116 | 117 | $items = @() 118 | 119 | # Generate more items 120 | $items += for ($i = 0; $i -le 3; $i++) { 121 | "$($env:TEMP)\$(Get-Process -Id $pid)-$($i).txt" 122 | } 123 | 124 | # Let's generate some errors 125 | $items | ForEach-Object { 126 | Get-Item -Path $_ -ErrorAction Continue 127 | } 128 | ``` 129 | 130 | Result: 131 | 132 | {{< error >}} 133 | ``` 134 | Get-Item: 135 | Line | 136 | 2 | Get-Item -Path $_ -ErrorAction Continue 137 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 138 | | Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (pwsh)-0.txt' because it does not exist. 139 | Get-Item: 140 | Line | 141 | 2 | Get-Item -Path $_ -ErrorAction Continue 142 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 143 | | Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (pwsh)-1.txt' because it does not exist. 144 | Get-Item: 145 | Line | 146 | 2 | Get-Item -Path $_ -ErrorAction Continue 147 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 148 | | Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (pwsh)-2.txt' because it does not exist. 149 | Get-Item: 150 | Line | 151 | 2 | Get-Item -Path $_ -ErrorAction Continue 152 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 153 | | Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (pwsh)-3.txt' because it does not exist. 154 | ``` 155 | {{< /error >}} 156 | 157 | ### SilentlyContinue 158 | 159 | With SilentlyCOntinue the error message will not be displayed and the script executes the pipeline commands. 160 | 161 | ```powershell 162 | Clear-Host 163 | 164 | $items = @() 165 | 166 | # Generate more items 167 | $items += for ($i = 0; $i -le 3; $i++) { 168 | "$($env:TEMP)\$(Get-Process -Id $pid)-$($i).txt" 169 | } 170 | 171 | # Let's generate some errors 172 | $items | ForEach-Object { 173 | Get-Item -Path $_ -ErrorAction SilentlyContinue 174 | } 175 | 176 | $error[0] 177 | ``` 178 | 179 | No error should be displayed, but the error is still saved in the `$Error` variable. 180 | 181 | Result: 182 | 183 | ``` 184 | Get-Item: 185 | Line | 186 | 2 | Get-Item -Path $_ -ErrorAction SilentlyContinue 187 | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 188 | | Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (pwsh)-3.txt' because it does not exist. 189 | ``` 190 | 191 | ### Ignore 192 | 193 | The `Ignore` action is the same as the Silentlycontinue except the error output is *not* stored into `$Error` variable. 194 | 195 | ```powershell 196 | Clear-Host 197 | 198 | $items = @() 199 | 200 | # Generate more items 201 | $items += for ($i = 0; $i -le 3; $i++) { 202 | "$($env:TEMP)\$(Get-Process -Id $pid)-$($i).txt" 203 | } 204 | 205 | # Let's generate some errors 206 | $items | ForEach-Object { 207 | Get-Item -Path $_ -ErrorAction Ignore 208 | } 209 | 210 | $error[0] 211 | ``` 212 | 213 | The result should be that the script returns nothing at all. 214 | 215 | ### Inquire 216 | 217 | With `Inquire` PowerShell helps when an error occurred due to cmdlet. It will give the option to the user with choices and prompt for appropriate action. 218 | 219 | ```powershell 220 | Clear-Host 221 | 222 | $items = @() 223 | 224 | # Generate more items 225 | $items += for ($i = 0; $i -le 3; $i++) { 226 | "$($env:TEMP)\$(Get-Process -Id $pid)-$($i).txt" 227 | } 228 | 229 | # Let's generate some errors 230 | $items | ForEach-Object { 231 | Get-Item -Path $_ -ErrorAction Inquire 232 | } 233 | ``` 234 | 235 | Result: 236 | 237 | ``` 238 | Confirm 239 | Cannot find path 'C:\Users\Sander\AppData\Local\Temp\System.Diagnostics.Process (pwsh)-0.txt' because it does not exist. 240 | [Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help (default is "Y"): 241 | ``` -------------------------------------------------------------------------------- /content/post/error-handling.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Error Handling 3 | author: Sander Stad 4 | date: '2022-03-09' 5 | categories: 6 | - Example 7 | weight: 160 8 | --- 9 | 10 | The try/catch blocks in PowerShell are used to handle terminating error. With the try/catch block you also have a finally keyword that will be executed even when an error is found. 11 | 12 | ## General 13 | 14 | The example below is a standard way to do a try/catch block 15 | 16 | ```powershell 17 | try { 18 | # This will generate an error 19 | 1/0 20 | Write-Host "This is executed after the error" 21 | } catch { 22 | # Catch all errors 23 | Write-Host "Oh oh! Error occurred.`n$_" 24 | } 25 | ``` 26 | 27 | Result: 28 | 29 | ``` 30 | Oh oh! Error occurred. 31 | Attempted to divide by zero. 32 | ``` 33 | 34 | You can see that an error was caught and that the error was returned as well. 35 | 36 | ## Specific error catches 37 | 38 | ```powershell 39 | try { 40 | # This will generate an error 41 | 1/0 42 | Write-Host "This is executed after the error" 43 | } catch [System.DivideByZeroException] { 44 | # Catch all errors 45 | Write-Host "Divide by zero error occurred.`n$_" 46 | } catch { 47 | # Catch all errors 48 | Write-Host "Oh oh! Another error occurred.`n$_" 49 | } 50 | ``` 51 | 52 | Result: 53 | 54 | ``` 55 | Divide by zero error occurred. 56 | Attempted to divide by zero. 57 | ``` 58 | 59 | As you can see the specific error is returned instead of the general catch. 60 | 61 | ## Using finally 62 | 63 | ```powershell 64 | try { 65 | # This will generate an error 66 | 1/0 67 | Write-Host "This is executed after the error" 68 | } catch [System.DivideByZeroException] { 69 | # Catch all errors 70 | Write-Host "Divide by zero error occurred.`n$_" 71 | } catch { 72 | # Catch all errors 73 | Write-Host "Oh oh! Another error occurred.`n$_" 74 | } finally { 75 | Write-Host "Finally!" 76 | } 77 | ``` 78 | 79 | Result: 80 | 81 | ``` 82 | Divide by zero error occurred. 83 | Attempted to divide by zero. 84 | Finally! 85 | ``` 86 | 87 | As you can see the finally is always executed whether or not we have an error. 88 | -------------------------------------------------------------------------------- /content/post/for.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: For 3 | date: '2022-02-22' 4 | categories: 5 | - Example 6 | weight: 50 7 | --- 8 | 9 | Classic for loop 10 | 11 | ```powershell 12 | for ($i = 1; $i -le 5; $i++){ 13 | Write-Host $i 14 | } 15 | ``` 16 | 17 | Result: 18 | 19 | ``` 20 | 1 21 | 2 22 | 3 23 | 4 24 | 5 25 | ``` 26 | 27 | We can also use text in our for loop conditions 28 | 29 | ```powershell 30 | for ($i = '' ; $i.length -le 20; $i += '='){ 31 | Write-Host $i 32 | } 33 | ``` 34 | 35 | Result: 36 | 37 | ``` 38 | = 39 | == 40 | === 41 | ==== 42 | ===== 43 | ====== 44 | ======= 45 | ======== 46 | ========= 47 | ========== 48 | =========== 49 | ============ 50 | ... 51 | ... 52 | ==================== 53 | ``` -------------------------------------------------------------------------------- /content/post/foreach.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Foreach 3 | date: '2022-02-22' 4 | categories: 5 | - Example 6 | weight: 60 7 | --- 8 | 9 | Foreach is a loop that iterates over a collection. 10 | 11 | ```powershell 12 | $list = @('a', 'b', 'c', 'd'); 13 | 14 | foreach($item in $list){ 15 | Write-Host $item 16 | } 17 | ``` 18 | 19 | Result: 20 | 21 | ``` 22 | a 23 | b 24 | c 25 | d 26 | ``` 27 | 28 | The equivalent of the above is: 29 | 30 | ```powershell 31 | $list = @('a', 'b', 'c', 'd'); 32 | 33 | $list | ForEach-Object { Write-Host $_ } 34 | ``` 35 | 36 | Result: 37 | 38 | ``` 39 | a 40 | b 41 | c 42 | d 43 | ``` 44 | 45 | The `ForEach-Object` command has more options than the basic `foreach` loop. For more info about the `ForEach-Object` command run the `Get-Help` command. 46 | 47 | ```powershell 48 | Get-Help ForEach-Object 49 | ``` 50 | -------------------------------------------------------------------------------- /content/post/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Functions 3 | author: Sander Stad 4 | date: '2022-02-22' 5 | categories: 6 | - Example 7 | weight: 120 8 | --- 9 | 10 | Functions are not required in PowerShell, but when your code becomes repetitive you should consider using functions. 11 | Also when creating PowerShell modules you should really consider putting code into functions to make your code more readable. 12 | 13 | To create a function we use the `function` keyword: 14 | 15 | ```powershell 16 | function writeHelloWorld() { 17 | Write-Host "Hello World!" 18 | } 19 | 20 | writeHelloWorld 21 | ``` 22 | 23 | Result: 24 | 25 | ``` 26 | Hello World! 27 | ``` 28 | 29 | Obviously this function is not very useful, but it is a good example how easy it is to create a function. 30 | 31 | ## Parameters 32 | 33 | Parameters is where the magic happens. When you create a function you can pass parameters to it. 34 | 35 | ```powershell 36 | function writeMessage { 37 | param( 38 | [string]$Message 39 | ) 40 | 41 | Write-Host "Message: $Message" 42 | } 43 | 44 | writeMessage "Hello World!" 45 | writeMessage -message "Who is there?" 46 | ``` 47 | 48 | Result: 49 | 50 | ``` 51 | Message: Hello World! 52 | Message: Who is there? 53 | ``` 54 | 55 | Notice that we can pass parameters with and without specifying the parameter. 56 | 57 | ## Adding advanced functionality 58 | 59 | To make a function more advanced we can add `[CmdletBinding()]` to the function. 60 | This enabled you to support for: 61 | 62 | * Confirming for impact 63 | * Help URI 64 | * Support paging 65 | * Should process 66 | * Positional binding 67 | 68 | ```powershell 69 | function writeMessage { 70 | param( 71 | [Parameter(Mandatory = $true, Position = 1, HelpMessage = "The message to write")] 72 | [string]$Message 73 | ) 74 | 75 | process { 76 | Write-Host "Message: $message" 77 | } 78 | } 79 | 80 | writeMessage "Hello World!" 81 | writeMessage 82 | ``` 83 | 84 | Result: 85 | 86 | ``` 87 | Message: Hello World! 88 | cmdlet writeMessage at command pipeline position 1 89 | Supply values for the following parameters: 90 | Message: 91 | writeMessage: C:\temp\temp.ps1:14:1 92 | Line | 93 | 14 | writeMessage 94 | | ~~~~~~~~~~~~ 95 | | Cannot bind argument to parameter 'Message' because it is an empty string. 96 | ``` 97 | 98 | Notice that the function also includes the `process` keyword. 99 | 100 | ## Begin, process and End 101 | 102 | These blocks are not required but they are very useful when you want to execute code before or after the function. 103 | 104 | *Begin* is used for one-time processing before the rest of the function is executed. 105 | *Process* is used for processing the function. 106 | *End* is used for one-time processing after the rest of the function is executed. 107 | 108 | ```powershell 109 | function writeMessage { 110 | [CmdLetBinding()] 111 | param( 112 | [Parameter(Mandatory = $true, Position = 1, HelpMessage = "The message to write")] 113 | [string]$Message 114 | ) 115 | 116 | begin { 117 | Write-Verbose "Beginning of script" 118 | if (($null -eq $Message) -or ($Message -eq "")) { 119 | throw "Message cannot be empty"; 120 | } 121 | } 122 | 123 | process { 124 | Write-Host "Message: $message" 125 | } 126 | 127 | end { 128 | Write-Host "End of script" 129 | } 130 | } 131 | 132 | writeMessage "Hello World!" -Verbose 133 | ``` 134 | 135 | Result: 136 | 137 | ``` 138 | Beginning of script 139 | Message: Hello World! 140 | End of script 141 | ``` 142 | 143 | For more information about advanced function go to the Microsoft Docs website: 144 | 145 | - [Functions](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions?view=powershell-7.2) 146 | - [Advanced Functions](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced?view=powershell-7.2) 147 | - [Advanced Parameters](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.2) -------------------------------------------------------------------------------- /content/post/hashtables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hashtables 3 | author: Sander Stad 4 | date: '2022-02-23' 5 | categories: 6 | - Example 7 | weight: 110 8 | --- 9 | 10 | In the arrays example we saw how to create arrays. In this example we will see how to create hashtables. 11 | 12 | A hashtable is a data structure, similar like an array, but with a hashtable each value is stored with a key. You can compare it to a key/value store database structure. 13 | 14 | To declare a hastable we use the `@{}` syntax: 15 | 16 | ```powershell 17 | $employees = @{} 18 | ``` 19 | 20 | This is different from the arrays where the `@()` is used. 21 | 22 | ## Adding items to a hashtable 23 | 24 | To add an item to a hashtable we use the `Add` method: 25 | 26 | ```powershell 27 | $employees = @{} 28 | 29 | # Adding values using integers 30 | $employees.Add(1, "John") 31 | $employees.Add(2, "Mary") 32 | $employees.Add(3, "Bob") 33 | $employees.Add(4, "Sam") 34 | 35 | $address = @{} 36 | 37 | # Adding values using strings 38 | $address.Add("John", "123 Main Street") 39 | $address.Add("Mary", "456 North Street") 40 | $address.Add("Bob", "789 West Street") 41 | $address.Add("Sam", "321 South Street") 42 | 43 | # Creating the hashtable in one go with values 44 | $zipCodes = @{ 45 | "John" = "12345" 46 | "Mary" = "54321" 47 | "Bob" = "98765" 48 | "Sam" = "32145" 49 | } 50 | 51 | ``` 52 | 53 | ## Accessing items from a hashtable 54 | 55 | To access an item from a hashtable you use the `[key]` syntax: 56 | 57 | ```powershell 58 | $employees[4] 59 | $address["Mary"] 60 | $zipCodes.Sam 61 | ``` 62 | 63 | Result: 64 | 65 | ``` 66 | Sam 67 | 456 North Street 68 | 32145 69 | ``` 70 | 71 | Notice that this looks similar like an array, but the key is used instead of the index. 72 | The key can be an integer or a string if you like. 73 | The example above also directly used the key to get the value in the hashtable. 74 | 75 | ## Loop through a hashtable 76 | 77 | Accessing a hashtable in a loop is similar to the example you saw before. 78 | There are several ways we can loop through a hashtable. 79 | 80 | ```powershell 81 | $employees.keys | Sort-Object $_ | ForEach-Object { 82 | Write-Host "Employee ID $($_) : $($employees[$_])" 83 | } 84 | 85 | foreach ($key in $address.Keys) { 86 | Write-Host "$($key) lives at $($address[$key])" 87 | } 88 | ``` 89 | 90 | Result: 91 | 92 | ``` 93 | Employee ID 1 : John 94 | Employee ID 2 : Mary 95 | Employee ID 3 : Bob 96 | Employee ID 4 : Sam 97 | 98 | Bob lives at 789 West Street 99 | Mary lives at 456 North Street 100 | John lives at 123 Main Street 101 | Sam lives at 321 South Street 102 | ``` 103 | 104 | Notice that we can use the `keys` method to get the keys of the hashtable and then use that particular value in the loops to get the value. 105 | The script also uses the `Sort-Object` command to sort the keys. 106 | 107 | ## Hastable with different properties 108 | 109 | Within a hashtable you are not bound to the key/value pair. 110 | You can create a hashtable with different properties. 111 | 112 | ```powershell 113 | $employeeAddress = @{ 114 | Name = "Mary" 115 | Address = "456 North Street" 116 | Zipcode = "54321" 117 | } 118 | 119 | $employeeAddress 120 | ``` 121 | 122 | ``` 123 | Name Value 124 | ---- ----- 125 | Name Mary 126 | Zipcode 54321 127 | Address 456 North Street 128 | ``` 129 | 130 | ## Removing properties from a hashtable 131 | 132 | To remove a property from a hashtable you use the `Remove` method: 133 | 134 | ```powershell 135 | $employeeAddress = @{ 136 | Name = "Mary" 137 | Address = "456 North Street" 138 | Zipcode = "54321" 139 | } 140 | 141 | $employeeAddress.Remove("Zipcode") 142 | 143 | $employeeAddress 144 | ``` 145 | 146 | Result: 147 | 148 | ``` 149 | Name Value 150 | ---- ----- 151 | Name Mary 152 | Address 456 North Street 153 | ``` 154 | 155 | ## Sort a hashtable 156 | 157 | There are various ways we can sort a hashtable. 158 | 159 | The first thing we can do is create an ordered hashtable. 160 | 161 | ```powershell 162 | $addresses = @() 163 | 164 | $addresses += [ordered]@{Name = "John"; Address = "123 Main Street" } 165 | $addresses += [ordered]@{Name = "Sam"; Address = "321 South Street" } 166 | 167 | $addresses += @{Name = "Mary"; Address = "456 North Street" } 168 | $addresses += @{Name = "Bob"; Address = "789 West Street" } 169 | 170 | $addresses 171 | ``` 172 | 173 | Result: 174 | 175 | ``` 176 | Name Value 177 | ---- ----- 178 | Name John 179 | Address 123 Main Street 180 | Name Sam 181 | Address 321 South Street 182 | Name Mary 183 | Address 456 North Street 184 | Name Bob 185 | Address 789 West Street 186 | ``` 187 | 188 | What happens here is that the first and last item keys are ordered differently. In the first two rows the `Name` and `Address` keys are displayed and for the next two rows the `Address` and `Name` keys are displayed. 189 | That is because it is possible to set the order in which the items need to be iterated through. Once the `ordered` keyword is used the items will be displayed in that order. 190 | 191 | Another thing we can do is sort the hashtables by key: 192 | 193 | ```powershell 194 | $addresses = @() 195 | 196 | $addresses += @{Name = "John"; Address = "123 Main Street" } 197 | $addresses += @{ 198 | Name = "Sam" 199 | Address = "321 South Street" 200 | } 201 | $addresses += @{Name = "Mary"; Address = "456 North Street" } 202 | $addresses += @{Name = "Bob"; Address = "789 West Street" } 203 | 204 | $addresses | Sort-Object -Property @{e = { $_.Name } } 205 | ``` 206 | 207 | Result: 208 | 209 | ``` 210 | Name Value 211 | ---- ----- 212 | Address 789 West Street 213 | Name Bob 214 | Address 123 Main Street 215 | Name John 216 | Address 456 North Street 217 | Name Mary 218 | Address 321 South Street 219 | Name Sam 220 | ``` 221 | -------------------------------------------------------------------------------- /content/post/hello-world.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | date: '2022-02-22' 4 | categories: 5 | - Example 6 | weight: 10 7 | --- 8 | 9 | As with every first program we write, we will print the classic "hello world" message. Here’s the full source code. 10 | 11 | ```powershell 12 | Write-Host 'Hello, World!' 13 | 'Hello, World!' | Write-Host 14 | ``` 15 | 16 | Result: 17 | 18 | ``` 19 | Hello, World! 20 | Hello, World! 21 | ``` 22 | 23 | There is another method to print the output or the strings to screen and that is is `Write-Output`. 24 | 25 | ```powershell 26 | Write-Output 'Hello, World!' 27 | 'Hello, World!' | Write-Output 28 | ``` 29 | 30 | This will print the exact same thing as the previous snippet. 31 | 32 | Result: 33 | 34 | ``` 35 | Hello, World! 36 | Hello, World! 37 | ``` 38 | 39 | It all becomes different when the two commands are used to store the output. 40 | 41 | ```powershell 42 | $wh = 'Hello, World!' | Write-Host 43 | $wo = 'Hello, World!' | Write-Output 44 | 45 | Get-Variable wh 46 | 47 | Get-Variable wo 48 | ``` 49 | 50 | Result: 51 | 52 | ``` 53 | Name Value 54 | ---- ----- 55 | wh 56 | wo Hello, World! 57 | ``` 58 | 59 | As you can see the `Write-Host` outputs the value to the console while the `Write-Output` command stores the output in the variable. 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /content/post/if-else.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: If/Else 3 | author: Sander Stad 4 | date: '2022-02-23' 5 | categories: 6 | - Example 7 | weight: 70 8 | --- 9 | 10 | Using `if` and `else` statements in PowerShell is pretty straightforward. 11 | 12 | You can have an `if` statement without an `else` statement. 13 | 14 | ```powershell 15 | $value = 5 16 | 17 | if ($value -gt 1) { 18 | Write-Host "value is greater than 1" 19 | } 20 | ``` 21 | 22 | Result: 23 | 24 | ``` 25 | value is greater than 1 26 | ``` 27 | 28 | You can have an `if` statement with a single `else` statement, or an `if` statement with an `else if` statement. 29 | 30 | ```powershell 31 | $value = 5 32 | 33 | if ($value -gt 10) { 34 | Write-Host "value is greater than 10" 35 | } 36 | else { 37 | Write-Host "value is $value" 38 | } 39 | 40 | if ($value -gt 10) { 41 | Write-Host "value is greater than 10" 42 | } 43 | elseif ($value -lt 10) { 44 | Write-Host "value is less than 10" 45 | } 46 | else { 47 | Write-Host "value is 10" 48 | } 49 | ``` 50 | 51 | Result: 52 | 53 | ``` 54 | value is 5 55 | value is less than 10 56 | ``` -------------------------------------------------------------------------------- /content/post/json.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: JSON 3 | author: Sander Stad 4 | date: '2022-04-11' 5 | categories: 6 | - Example 7 | weight: 230 8 | --- 9 | 10 | If there is one thing that you want to do with PowerShell is handling JSON data. 11 | Because PowerShell is so flexible with custom objects, reading and writing JSON data becomes very easy and powerful. 12 | 13 | # Reading JSON data 14 | 15 | The parsing of JSON data is done using the `ConvertFrom-Json` command. 16 | 17 | ```powershell 18 | $url = "https://gist.githubusercontent.com/sanderstad/1c47c1add7476945857bff4d8dc2be59/raw/d12f30e4aaf9d2ee18e4539b394a12e63dea0c9c/SampleJSON1.json" 19 | $json = (New-Object System.Net.WebClient).DownloadString($url) 20 | 21 | $data = $json | ConvertFrom-Json 22 | 23 | $data.colors 24 | ``` 25 | 26 | The result should look like this: 27 | 28 | ``` 29 | color category type code 30 | ----- -------- ---- ---- 31 | black hue primary @{rgba=System.Object[]; hex=#000} 32 | white value @{rgba=System.Object[]; hex=#FFF} 33 | red hue primary @{rgba=System.Object[]; hex=#FF0} 34 | blue hue primary @{rgba=System.Object[]; hex=#00F} 35 | yellow hue primary @{rgba=System.Object[]; hex=#FF0} 36 | green hue secondary @{rgba=System.Object[]; hex=#0F0} 37 | ``` 38 | 39 | As you can see the data is transformed into a custom object. Any nested data deeper than one level is also transformed into a custom object and saved in the parent property. For example the `code` property is transformed into a custom object inside the parent custom object. 40 | 41 | # Writing JSON data 42 | 43 | Using the data as in the previous example, we can also convert it back to JSON and write the data to a file. 44 | To convert the custom object back to JSON, we use the `ConvertTo-Json` command. 45 | 46 | ```powershell 47 | # Make sure you run the previous example first before running this one 48 | 49 | $data | ConvertTo-Json | Out-File $env:temp\json.txt -Force 50 | Get-Content $env:temp\json.txt 51 | ``` 52 | 53 | The result should look like this: 54 | 55 | ``` 56 | { 57 | "colors": [ 58 | { 59 | "color": "black", 60 | "category": "hue", 61 | "type": "primary", 62 | "code": "@{rgba=System.Object[]; hex=#000}" 63 | }, 64 | { 65 | "color": "white", 66 | "category": "value", 67 | "code": "@{rgba=System.Object[]; hex=#FFF}" 68 | }, 69 | .... 70 | .... 71 | .... 72 | } 73 | ``` 74 | 75 | The data is converted to JSON and written to a file, but we have a problem. 76 | The color codes are not saved as strings but instead as the type it was imported as. 77 | 78 | ## Convert to a specific depth 79 | 80 | Whenever you want to convert the data to JSON, you can specify the depth of the data. 81 | By default the depth is set to 2 which may not be obvious in PowerShell 5 because no warning will be given that the data will be truncated. 82 | In PowerShell 7 you will get a warning that the data will be truncated. 83 | 84 | To convert the data to JSON with a specific depth, you can use the `-Depth` parameter. Using the same data we had before, we can convert it to JSON with the correct depth. 85 | The correct depth for this JSON data is 3. 86 | 87 | ```powershell 88 | $data | ConvertTo-Json -Depth 3 | Out-File $env:temp\json.txt -Force 89 | 90 | ``` 91 | 92 | The result should now look like this: 93 | 94 | ``` 95 | { 96 | "colors": [ 97 | { 98 | "color": "black", 99 | "category": "hue", 100 | "type": "primary", 101 | "code": { 102 | "rgba": "255 255 255 1", 103 | "hex": "#000" 104 | } 105 | }, 106 | { 107 | "color": "white", 108 | "category": "value", 109 | "code": { 110 | "rgba": "0 0 0 1", 111 | "hex": "#FFF" 112 | } 113 | }, 114 | .... 115 | .... 116 | .... 117 | } 118 | ``` 119 | 120 | As you can see the data on the deeper levels is now written in the correct way. 121 | 122 | -------------------------------------------------------------------------------- /content/post/multidimensional-arrays.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Multidimensional Arrays 3 | author: Sander Stad 4 | date: '2022-02-23' 5 | categories: 6 | - Example 7 | weight: 100 8 | --- 9 | 10 | There are two types of multidimensional arrays, jagged and true multidimensional arrays. 11 | 12 | ## Jagged arrays 13 | 14 | Jagged arrays are the arrays you will probably use the most. These types of arrays are very cost effective because the dimensions can be different in size. 15 | 16 | ```powershell 17 | $array = @(1, 2, (1, 2, 3), 3, 4, (10, 11, 12), 5) 18 | $array[0] 19 | $array[1] 20 | $array[2] 21 | $array[2][0] 22 | $array[2][1] 23 | $array[5] 24 | ``` 25 | 26 | Result: 27 | 28 | ``` 29 | 1 30 | 2 31 | 1 32 | 2 33 | 3 34 | 1 35 | 2 36 | 10 37 | 11 38 | 12 39 | ``` 40 | 41 | ## True multidimensional arrays 42 | 43 | With true multidimensional arrays can be compared to a matrix. You define the size of the array/matrix when you create it. 44 | 45 | ```powershell 46 | $array = New-Object 'object[,]' 5,8 47 | $array[2,5] = 'Hello' 48 | $array[3,7] = 'World!' 49 | $array 50 | ``` 51 | 52 | Result: 53 | 54 | ``` 55 | Hello 56 | World! 57 | ``` 58 | 59 | You can compare the above with the following: 60 | 61 | ``` 62 | [ ][ ][ ] [ ] [ ] 63 | [ ][ ][ ] [ ] [ ] 64 | [ ][ ][ ] [ ] [ ] 65 | [ ][ ][ ] [ ] [ ] 66 | [ ][ ][ ] [ ] [ ] 67 | [ ][ ][Hello][ ] [ ] 68 | [ ][ ][ ] [ ] [ ] 69 | [ ][ ][ ] [World][ ] 70 | ``` 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /content/post/read-only-variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Read-Only Variables 3 | date: '2022-02-22' 4 | categories: 5 | - Example 6 | weight: 30 7 | --- 8 | 9 | PowerShell supports constants and read-only variables. 10 | Read-only variables are variables that cannot be changed, in a regular way. 11 | 12 | You create a read-only variable with the `New-Variable` command with the parameter `-Option ReadOnly`. 13 | 14 | ```powershell 15 | New-Variable -Name myVar -Value 1337 -Option ReadOnly 16 | $myVar 17 | ``` 18 | 19 | Let's try and change it 20 | 21 | ``` 22 | $myVar = 31337 23 | ``` 24 | 25 | {{< error >}} 26 | ``` 27 | Cannot overwrite variable myVar because it is read-only or constant. 28 | At line:1 char:1 29 | + $myVar = 31337 30 | + ~~~~~~~~~~~~~~ 31 | + CategoryInfo : WriteError: (myVar:String) [], SessionStateUnauthorizedAccessException 32 | + FullyQualifiedErrorId : VariableNotWritable 33 | ``` 34 | {{< /error >}} 35 | 36 | To change the variable we need to use the `-Force` parameter: 37 | 38 | ```powershell 39 | $myvar # Should output 1337 40 | New-Variable -Name myVar -Value 31337 -Option ReadOnly -Force 41 | $myVar # Should output 31337 42 | ``` 43 | 44 | In this case the value can be changed 45 | -------------------------------------------------------------------------------- /content/post/reading-files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reading Files 3 | author: Sander Stad 4 | date: '2022-03-09' 5 | categories: 6 | - Example 7 | weight: 170 8 | --- 9 | 10 | To demonstrate reading files we need sample files first. 11 | 12 | ```powershell 13 | # Let's download a sample file just for the example 14 | $url = "https://gist.githubusercontent.com/sanderstad/7b9593f7f30abb9f17f9026c74ed9c68/raw/d4406c4cbbc427e15fc9d6d92f8bcf3c72a1e70a/samplefile1.txt" 15 | $filePath = Join-Path -Path $env:temp -ChildPath "samplefile1.txt" 16 | 17 | Invoke-WebRequest -Uri $url -OutFile $filePath 18 | 19 | $url = "https://gist.githubusercontent.com/sanderstad/f59996889fc3ec794d325ad2162648f8/raw/5353480009bd714f9764a093b52f0fabff1078fd/samplefile2.csv" 20 | $filePath = Join-Path -Path $env:temp -ChildPath "samplefile2.txt" 21 | 22 | Invoke-WebRequest -Uri $url -OutFile $filePath 23 | ``` 24 | 25 | ## Get-Content 26 | 27 | The easiest way to read files in PowerShell is by using the the `Get-Content` command. 28 | 29 | ```powershell 30 | # Get the content 31 | Get-Content -Path (Join-Path -Path $env:temp -ChildPath "samplefile1.txt") 32 | ``` 33 | 34 | Result: 35 | 36 | ``` 37 | Utilitatis causa amicitia est quaesita. 38 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Collatio igitur ista te nihil iuvat. Honesta oratio, Socratica, Platonis etiam. Primum in nostrane potestate est, quid meminerimus? Duo Reges: constructio interrete. Quid, si etiam iucunda memoria est praeteritorum malorum? Si quidem, inquit, tollerem, sed relinquo. An nisi populari fama? 39 | 40 | Quamquam id quidem licebit iis existimare, qui legerint. Summum a vobis bonum voluptas dicitur. At hoc in eo M. Refert tamen, quo modo. Quid sequatur, quid repugnet, vident. Iam id ipsum absurdum, maximum malum neglegi. 41 | ``` 42 | 43 | ```powershell 44 | $content = Get-Content -Path (Join-Path -Path $env:temp -ChildPath "samplefile1.txt") 45 | 46 | $content.GetType() 47 | $content.Count 48 | ``` 49 | 50 | Result: 51 | 52 | ``` 53 | IsPublic IsSerial Name BaseType 54 | -------- -------- ---- -------- 55 | True True Object[] System.Array 56 | 57 | 4 58 | ``` 59 | 60 | What PowerShell has done is get the content as an array and each row that end with a newline character will be a new entry. 61 | 62 | To get the first few rows we can do the following 63 | 64 | ```powershell 65 | $content = Get-Content -Path (Join-Path -Path $env:temp -ChildPath "samplefile1.txt") 66 | 67 | $content | Select-Object -First 2 68 | ``` 69 | 70 | Result: 71 | 72 | ``` 73 | Utilitatis causa amicitia est quaesita. 74 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Collatio igitur ista te nihil iuvat. Honesta oratio, Socratica, Platonis etiam. Primum in nostrane potestate est, quid meminerimus? Duo Reges: constructio interrete. Quid, si etiam iucunda memoria est praeteritorum malorum? Si quidem, inquit, tollerem, sed relinquo. An nisi populari fama? 75 | ``` 76 | 77 | ## Import-CSV 78 | 79 | When you have a specific CSV file, you can use the `Import-Csv` command to interpret the data as CSV. 80 | 81 | ```powershell 82 | Import-Csv -Path (Join-Path -Path $env:temp -ChildPath "samplefile2.txt") 83 | ``` 84 | 85 | Result: 86 | 87 | ``` 88 | Month : May 89 | Average : 0.1 90 | 2005 : 0 91 | 2006 : 0 92 | 2007 : 1 93 | 2008 : 1 94 | 2009 : 0 95 | 2010 : 0 96 | 2011 : 0 97 | 2012 : 2 98 | 2013 : 0 99 | 2014 : 0 100 | 2015 : 0 101 | 102 | Month : Jun 103 | Average : 0.5 104 | 2005 : 2 105 | 2006 : 1 106 | 2007 : 1 107 | 2008 : 0 108 | 2009 : 0 109 | ......... 110 | ``` 111 | 112 | As you can see it returns each and every row as a single object with the data. 113 | -------------------------------------------------------------------------------- /content/post/sorting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Sorting 3 | author: Sander Stad 4 | date: '2022-04-05' 5 | categories: 6 | - Example 7 | weight: 200 8 | --- 9 | 10 | Sorting values is important in any programming language. To do this in PowerShell you can use the `Sort-Object` command. By default the sort is done in ascending order and case insensitive. 11 | 12 | Here are some examples how to sort data in PowerShell. 13 | 14 | ## Sort by value 15 | 16 | ```powershell 17 | $names = @("Muffin","Romeo","Noodle","Zoe","Jack","Luna","Gracie","mittens","Phoebe","Peanut","Harley","Jake") 18 | 19 | $names | Sort-Object 20 | ``` 21 | 22 | The result: 23 | 24 | ``` 25 | Gracie 26 | Harley 27 | Jack 28 | Jake 29 | Luna 30 | mittens 31 | Muffin 32 | Noodle 33 | Peanut 34 | Phoebe 35 | Romeo 36 | Zoe 37 | ``` 38 | 39 | ## Sort by descending order 40 | 41 | By default any data is sorted in ascending order. To sort in descending order you can use the `-Descending` parameter. 42 | 43 | ```powershell 44 | $names = @("Muffin","Romeo","Noodle","Zoe","Jack","Luna","Gracie","mittens","Phoebe","Peanut","Harley","Jake") 45 | 46 | $names | Sort-Object -Descending 47 | ``` 48 | 49 | The result: 50 | 51 | ``` 52 | Zoe 53 | Romeo 54 | Phoebe 55 | Peanut 56 | Noodle 57 | Muffin 58 | mittens 59 | Luna 60 | Jake 61 | Jack 62 | Harley 63 | Gracie 64 | ``` 65 | 66 | The same can be done with a `-Ascending` parameter to sort in ascending order. 67 | 68 | ## Sort by case sensitivity 69 | 70 | By default the sort is done in case insensitive order, but you are able to change this with the `-CaseSensitive` parameter. 71 | 72 | ```powershell 73 | $names = @("Muffin","muffin","Noodle","Zoe","zoe","Luna","Gracie","peanut","Phoebe","Peanut","Harley","Jake") 74 | 75 | $names | Sort-Object -CaseSensitive 76 | ``` 77 | 78 | The result: 79 | 80 | ``` 81 | Gracie 82 | Harley 83 | Jake 84 | Luna 85 | muffin 86 | Muffin 87 | Noodle 88 | peanut 89 | Peanut 90 | Phoebe 91 | zoe 92 | Zoe 93 | ``` 94 | 95 | ## Sort by unique values 96 | 97 | You are able to sort the object in an array and remove all duplicates in the process using the `-Unique` parameter. 98 | 99 | ```powershell 100 | $names = @("Muffin","muffin","Noodle","Zoe","zoe","Luna","Gracie","peanut","Phoebe","Peanut","Harley","Jake") 101 | 102 | $names | Sort-Object -Unique 103 | ``` 104 | 105 | The result is: 106 | 107 | ``` 108 | Gracie 109 | Harley 110 | Jake 111 | Luna 112 | muffin 113 | Noodle 114 | Peanut 115 | Phoebe 116 | zoe 117 | ``` 118 | 119 | The values are sorted in an ascending order and case insensitive. 120 | 121 | ## Sort by property 122 | 123 | If an object in an array has any properties, you are able to sort by those properties using the `-Property` parameter. 124 | 125 | ```powershell 126 | $files = Get-ChildItem -Path $env:TEMP 127 | $files | Sort-Object -Property LastWriteTime | Where-Object{$_.PSIsContainer -eq $false} 128 | ``` 129 | 130 | The result would look something like this: 131 | 132 | ``` 133 | 134 | Directory: C:\Users\Sander\AppData\Local\Temp 135 | 136 | 137 | Mode LastWriteTime Length Name 138 | ---- ------------- ------ ---- 139 | -a---- 1/30/2020 1:30 PM 999  nsd8F8A.tmp 140 | -a---- 11/5/2020 9:52 AM 339816  Chipset.dll 141 | -a---- 1/13/2022 9:57 AM 15021  nscA6CC.tmp 142 | -a---- 3/25/2022 8:12 PM 942  wctBA18.tmp 143 | -a---- 3/25/2022 8:12 PM 942  wct5787.tmp 144 | -a---- 3/25/2022 8:12 PM 942  wctEF84.tmp 145 | -a---- 3/28/2022 9:21 AM 3192224  94e81122-594d-4910-b16b-3c9d9b28bff1.tmp 146 | -a---- 3/28/2022 7:49 PM 1825  wct3C2A.tmp 147 | -a---- 3/28/2022 7:49 PM 1825  wct9D9A.tmp 148 | -a---- 3/29/2022 10:15 AM 0 况 mat-debug-35588.log 149 | -a---- 3/29/2022 10:16 AM 0 况 mat-debug-26716.log 150 | -a---- 3/29/2022 10:22 AM 0 况 mat-debug-20228.log 151 | -a---- 3/29/2022 11:22 AM 0 况 mat-debug-15472.log 152 | -a---- 3/29/2022 12:22 PM 0 况 mat-debug-18972.log 153 | -a---- 3/29/2022 1:22 PM 0 况 mat-debug-7244.log 154 | -a---- 3/29/2022 1:22 PM 0 况 mat-debug-33388.log 155 | -a---- 3/29/2022 2:22 PM 0 况 mat-debug-28752.log 156 | -a---- 3/29/2022 2:25 PM 57833  wct2B1F.tmp 157 | ``` -------------------------------------------------------------------------------- /content/post/splatting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Splatting 3 | author: Sander Stad 4 | date: '2022-04-11' 5 | categories: 6 | - Example 7 | weight: 220 8 | --- 9 | 10 | In some situations we have so many parameters that we cannot fit it on a single line or have to use the "`" sign to separate lines. 11 | I'm not a fan of having very long lines or the backticks because it makes the code hard to read. 12 | Instead we can use variable splatting to pass multiple parameters to a function. 13 | 14 | A splatted variable is a collection of values that is passed to a function as a single parameter. 15 | This type of variable is in essence a hashtable. 16 | 17 | In the example below we will use the `Get-ChildItem` command to get a list of all the files in a directory. 18 | 19 | ```powershell 20 | Get-ChildItem -Path $env:TEMP -Include "*.txt" -Depth 2 -Recurse 21 | ``` 22 | 23 | This line is not to long yet but you can imagine that some functions/commands have a lot more parameters. 24 | 25 | We can rewrite the same command using variable splatting. 26 | 27 | ```powershell 28 | $params = @{ 29 | Path = $env:TEMP 30 | Include = "*.txt" 31 | Depth = 2 32 | Recurse = $true 33 | } 34 | Get-ChildItem @params 35 | ``` 36 | 37 | As you can see this is a lot more readable and easier to understand. -------------------------------------------------------------------------------- /content/post/strings.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Strings 3 | author: Sander Stad 4 | date: '2022-03-01' 5 | categories: 6 | - Example 7 | weight: 140 8 | --- 9 | 10 | 11 | # Defining strings 12 | 13 | There are various ways you define a string in PowerShell 14 | 15 | 16 | ```powershell 17 | $var = "Hello World!" 18 | 19 | "Lorem ipsum dolor sit amet..." 20 | $value1 = "Ut enim ad minim veniam... $var" 21 | $value2 = 'Duis aute irure dolor in... $var' 22 | [string]$value3 = "Excepteur sint occaecat cupidatat non proident..." 23 | 24 | $value1, $value2, $value3 25 | write-host $value1, $value2, $value3 26 | write-host $value1 $value2 $value3 27 | ``` 28 | 29 | Result: 30 | 31 | ``` 32 | Lorem ipsum dolor sit amet... 33 | Ut enim ad minim veniam... Hello World! 34 | Duis aute irure dolor in... $var 35 | Excepteur sint occaecat cupidatat non proident... 36 | Ut enim ad minim veniam... Hello World! Duis aute irure dolor in... $var Excepteur sint occaecat cupidatat non proident... 37 | Ut enim ad minim veniam... Hello World! Duis aute irure dolor in... $var Excepteur sint occaecat cupidatat non proident... 38 | ``` 39 | 40 | In the third line in the example above, the string is written to screen because we haven't given PowerShell anything to do with it. 41 | 42 | In the fourth line, we assign the string to a variable using double quotes. This is just a string. Although this is a string, using double quotes we are able to use variables in the string. 43 | 44 | In the fifth line, we assign the string to a variable using single quotes. Again this is just a string. Because we are using single quotes, the string in the variable is taken literally and no variables can be included like in the fourth line. 45 | 46 | In the sixth line, we assign the string to a variable using the PowerShell notation. This is also string. 47 | 48 | In the remaining lines we print out the variables in a couple different ways. 49 | 50 | # Concatenating Strings 51 | 52 | There are various ways you can concatenate strings in PowerShell. 53 | 54 | ```powershell 55 | $firstName = "John" 56 | $middleName = "Hubert" 57 | $lastName = "Doe" 58 | 59 | $fullName = $firstName + ' ' + $middleName + ' ' + $lastName 60 | $fullName 61 | 62 | $fullName = "$firstName $middleName $lastName" 63 | $fullName 64 | ``` 65 | 66 | Result: 67 | 68 | ``` 69 | John Hubert Doe 70 | John Hubert Doe 71 | ``` 72 | 73 | As you can see PowerShell is very flexible how you can concatenate strings. 74 | 75 | # Joining Strings 76 | 77 | We can use the `-join` operator to join multiple items together. We can assign a delimiter to the operator to define what separates the items. 78 | 79 | ```powershell 80 | # Join array 81 | $list = @('a', 'b', 'c', 'd', 'e') 82 | $list -join ',' 83 | 84 | # Join array without declaring variable 85 | 'f', 'g', 'h', 'i', 'j' -join '-' 86 | 87 | # Join array without separator 88 | -join ('k', 'l', 'm', 'n', 'o') 89 | 90 | # Using .Net string.Join 91 | [string]::Join('|', 'p', 'q', 'r', 's', 't') 92 | ``` 93 | 94 | Result: 95 | 96 | ``` 97 | a,b,c,d,e 98 | f-g-h-i-j 99 | klmno 100 | p|q|r|s|t 101 | ``` 102 | 103 | # Splitting Strings 104 | 105 | Instead of joining strings, we can use the `-split` operator to split a string into an array. 106 | 107 | ```powershell 108 | $string1 = "a,b,c,d,e" 109 | $string2 = "f-g-h-i-j" 110 | $string3 = 'monday,tuesday,wednesday,thursday,friday,saturday,sunday' 111 | $string4 = 'one1two2three3four4five5six6seven7' 112 | 113 | # Splitting based on comma with .Split() 114 | $result1 = $string1.split(",") 115 | Write-Host "Count of items split: " $result1.Count 116 | Write-Host $result1 117 | "" 118 | 119 | # Splitting based on hyphen with -split() 120 | $result2 = $string2 -split "-" 121 | Write-Host "Count of items split: " $result2.Count 122 | "" 123 | 124 | # Splitting based on a part of the string with -split 125 | $string3 -split "day" 126 | 127 | # Split the string based on a try/catch block 128 | # and limit the amount of items returned (3) 129 | $string4 -split { 130 | try { 131 | [int]$_ -gt 1 132 | } 133 | catch { 134 | # Just ignore it 135 | } 136 | }, 3 137 | ``` 138 | 139 | Result: 140 | 141 | ``` 142 | Count of items split: 5 143 | a b c d e 144 | 145 | Count of items split: 5 146 | 147 | mon 148 | ,tues 149 | ,wednes 150 | ,thurs 151 | ,fri 152 | ,satur 153 | ,sun 154 | 155 | one1two 156 | three 157 | four4five5six6seven7 158 | ``` 159 | 160 | In the first part the string is split based on the comma. The result is an array with 5 items. 161 | In the second part the string is split based on the hyphen with a different method. 162 | In the third part the string is split based on a part of a word. 163 | In the fourth part the string is split based on a try/catch block, but the amount of items returned is limited to 3. 164 | 165 | # Formatting Strings 166 | 167 | Formatting strings is something that can really make your code better readable. 168 | 169 | ```PowerShell 170 | $firstName = "John" 171 | $middleName = "Hubert" 172 | $lastName = "Doe" 173 | 174 | # Format the names 175 | "{0} {1} {2}" -f $firstName, $middleName, $lastName 176 | 177 | # Format the names but also do something else 178 | "{0}.{1}@awesomecorp.com" -f $firstName.Substring(0, 1), $lastName 179 | ``` 180 | 181 | Result: 182 | 183 | ``` 184 | John Hubert Doe 185 | J.Doe@awesomecorp.com 186 | ``` 187 | 188 | # Strings in Objects 189 | 190 | With PowerShell we can do a lot of things with custom objects and we may want to use the values within. 191 | Using these values is something that in some cases need to be done in a certain way. 192 | 193 | ```powershell 194 | # Create a simple object 195 | $person = @{ 196 | FirstName = 'John' 197 | LastName = 'Doe' 198 | } 199 | # Let's see what we have 200 | $person 201 | 202 | # Use the object by referencing a property 203 | Write-Host "`nHello, " $person.FirstName 204 | 205 | # Setup the full name of the person using the properties 206 | $fullName = $person.FirstName + ' ' + $person.LastName 207 | Write-Host "`nHello, " $fullName 208 | 209 | # Try to add the properties to a string 210 | $fullName = "$person.FirstName $person.LastName" 211 | Write-Host "`nHello, " $fullName # This will fail 212 | # Let's add them the proper way 213 | $fullName = "$($person.FirstName) $($person.LastName)" 214 | Write-Host "Hello, " $fullName # This will work 215 | ``` 216 | 217 | Result: 218 | 219 | ``` 220 | Name Value 221 | ---- ----- 222 | LastName Doe 223 | FirstName John 224 | 225 | Hello, John 226 | 227 | Hello, John Doe 228 | 229 | Hello, System.Collections.Hashtable.FirstName System.Collections.Hashtable.LastName 230 | Hello, John Doe 231 | ``` 232 | 233 | As you can see the first two examples work pretty well. We can retrieve the values using the properties of the object. 234 | 235 | In the third example we see we can't just add the properties to a string. We need to use the PowerShell notation to do this. 236 | 237 | In the fourth example we use the PowerShell notation to add the properties to a string. 238 | 239 | # Replacing Strings 240 | 241 | Replacing values in strings is something that is very handy in situation where you may use templates and want to replace certain values. 242 | Or maybe you have a CSV file and want to replace the delimiter from a comma to a semi-colon. 243 | 244 | You can either use the `.Replace()` method or the `-replace` operator. 245 | 246 | ```powershell 247 | # Setup the query 248 | $query = "SELECT * FROM [_SCHEMANAME_].[_TABLENAME_] WHERE id = _ID_"; 249 | 250 | # Replace the templated values using the .Replace() method 251 | $query = $query.Replace("_SCHEMANAME_", "dbo"); 252 | $query = $query.Replace("_TABLENAME_", "tbl_test"); 253 | $query = $query.Replace("_ID_", "1"); 254 | $query 255 | 256 | # Replace the delimiter for the CSV using the -replace operator 257 | $csv = "a,b,c,d,e,f,g,h,i" 258 | $csv -replace ",", ";" 259 | ``` 260 | 261 | Result: 262 | 263 | ``` 264 | SELECT * FROM [dbo].[tbl_test] WHERE id = 1 265 | a;b;c;d;e;f;g;h;i 266 | ``` 267 | 268 | 269 | 270 | -------------------------------------------------------------------------------- /content/post/switch.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Switch 3 | author: Sander Stad 4 | date: '2022-02-23' 5 | categories: 6 | - Example 7 | weight: 80 8 | --- 9 | 10 | `Switch` statements are a way to execute different code based on different conditions. 11 | This approach can be more efficient than using multiple if/elseif statements 12 | 13 | ```powershell 14 | $month = 3 15 | 16 | if ($month -eq 1) { Write-Host "January" } 17 | elseif ($month -eq 2) { Write-Host "February" } 18 | elseif ($month -eq 3) { Write-Host "March" } 19 | elseif ($month -eq 4) { Write-Host "April" } 20 | elseif ($month -eq 5) { Write-Host "May" } 21 | elseif ($month -eq 6) { Write-Host "June" } 22 | elseif ($month -eq 7) { Write-Host "July" } 23 | elseif ($month -eq 8) { Write-Host "August" } 24 | elseif ($month -eq 9) { Write-Host "September" } 25 | elseif ($month -eq 10) { Write-Host "October" } 26 | elseif ($month -eq 11) { Write-Host "November" } 27 | elseif ($month -eq 12) { Write-Host "December" } 28 | else { Write-Host "Invalid month" } 29 | 30 | # Instead we can write the above as 31 | switch ($month) { 32 | 1 { Write-Host "January" } 33 | 2 { Write-Host "February" } 34 | 3 { Write-Host "March" } 35 | 4 { Write-Host "April" } 36 | 5 { Write-Host "May" } 37 | 6 { Write-Host "June" } 38 | 7 { Write-Host "July" } 39 | 8 { Write-Host "August" } 40 | 9 { Write-Host "September" } 41 | 10 { Write-Host "October" } 42 | 11 { Write-Host "November" } 43 | 12 { Write-Host "December" } 44 | default { Write-Host "Invalid month" } 45 | } 46 | ``` 47 | 48 | Result: 49 | 50 | ``` 51 | March 52 | March 53 | ``` 54 | 55 | The result is the same but the code is much more readable. 56 | 57 | ## Wildcards 58 | 59 | You can use wildcards in the condition of the case: 60 | 61 | ```powershell 62 | # Using the -Wildcard parameter 63 | $msg = "Error, the action failed" 64 | switch -Wildcard ($msg) { 65 | "Error*" { "Action error" } 66 | "Warning*" { "Action warning" } 67 | "Successful*" { "Action succesfull" } 68 | } 69 | 70 | ## Or use it in the conditions 71 | $msg = "Error, the action failed" 72 | switch ($msg) { 73 | { $_ -like "Error*" } { "Action error" } 74 | { $_ -like "Warning*" } { "Action warning" } 75 | { $_ -like "Successful*" } { "Action succesfull" } 76 | } 77 | ``` 78 | 79 | Result: 80 | 81 | ``` 82 | Action error 83 | Action error 84 | ``` 85 | 86 | Both have the same result, but with the last example you are more flexible to the operators you want to use. 87 | 88 | ## Multiple conditions 89 | 90 | To use multiple expressions in a switch statement, you can use the `-and` and `-or` operators. 91 | 92 | ```powershell 93 | switch ((Get-Date).Day) { 94 | { $_ -le 10 } { "Day of the month is lower than 10" } 95 | { $_ -gt 10 -and $_ -le 25 } { "Day of the month is between 10 and 25" } 96 | { $_ -gt 25 } { "Day of the month is greater than 25" } 97 | } 98 | ``` 99 | 100 | Result: 101 | 102 | ``` 103 | Day of the month is between 10 and 25 104 | ``` 105 | 106 | -------------------------------------------------------------------------------- /content/post/time-and-date.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Time and Date 3 | author: Sander Stad 4 | date: '2022-03-14' 5 | categories: 6 | - Example 7 | weight: 190 8 | --- 9 | 10 | 11 | In many operations within PowerShell we need time and date information. 12 | When date and time values are being returned that is done with the `[datetime]` data type. 13 | The format that's being returned depends on the cultural settings of the computer. 14 | 15 | ## General 16 | 17 | To get the current date and time, use the ` Get-Date` command. 18 | 19 | ```powershell 20 | Get-Date 21 | ``` 22 | 23 | Result: 24 | 25 | ``` 26 | Monday, March 14, 2022 4:40:48 PM 27 | ``` 28 | 29 | ## Date and time parts 30 | 31 | To get specific values from the command we can use the properties in the `[datetime]` type. 32 | 33 | ```powershell 34 | $today = Get-Date 35 | Write-Host "Full Date: `t$today" 36 | Write-Host "Date: `t`t$($today.Date)" 37 | Write-Host "Year: `t`t$($today.Year)" 38 | Write-Host "Month: `t`t$($today.Month)" 39 | Write-Host "Day: `t`t$($today.Day)" 40 | Write-Host "Day of the Week: $($today.DayOfWeek)" 41 | Write-Host "Day of the Year: $($today.DayOfYear)" 42 | Write-Host "Hour: `t`t$($today.Hour)" 43 | Write-Host "Minute: `t$($today.Minute)" 44 | Write-Host "Second: `t$($today.Second)" 45 | Write-Host "Millisecond: $($today.Millisecond)" 46 | ``` 47 | 48 | Result: 49 | ``` 50 | Full Date: 03/14/2022 20:25:15 51 | Date: 03/14/2022 00:00:00 52 | Year: 2022 53 | Month: 3 54 | Day: 14 55 | Day of the Week: Monday 56 | Day of the Year: 73 57 | Hour: 20 58 | Minute: 25 59 | Second: 15 60 | Millisecond: 322 61 | ``` 62 | 63 | ## Formatting dates 64 | 65 | Sometimes we need to format the date. This can be done with the `-f` parameter. 66 | This parameter takes in a string and replaces the placeholders with the values from the `[datetime]` type. 67 | 68 | ```powershell 69 | $date = Get-Date 70 | $date 71 | $date -f "yyyyMMdd" 72 | ``` 73 | 74 | Result: 75 | 76 | ``` 77 | Monday, March 14, 2022 4:47:03 PM 78 | 03/14/2022 16:47:03 79 | ``` 80 | 81 | ## Adding and subtracting 82 | 83 | It is possible to add and subtract dates in PowerShell. The functions may seem confusing but you can add using positive numbers and subtract using negative numbers. 84 | 85 | ```powershell 86 | $today = Get-Date 87 | $yesterday = $today.AddDays(-1) 88 | $tomorrow = $today.AddDays(1) 89 | Write-Host "Today: `t`t$today" 90 | Write-Host "Yesterday: `t$yesterday" 91 | Write-Host "Tomorrow: `t$tomorrow" 92 | ``` 93 | 94 | Result: 95 | 96 | ``` 97 | Today: 03/14/2022 20:33:43 98 | Yesterday: 03/13/2022 20:33:43 99 | Tomorrow: 03/15/2022 20:33:43 100 | ``` 101 | 102 | The same actions can be done with the other add functions like: 103 | 104 | | Functions | Description | Type | 105 | | --------------- | ----------- | -------------------------------------- | 106 | | Add | Method | datetime Add(timespan value) | 107 | | AddDays | Method | datetime AddDays(double value) | 108 | | AddHours | Method | datetime AddHours(double value) | 109 | | AddMilliseconds | Method | datetime AddMilliseconds(double value) | 110 | | AddMinutes | Method | datetime AddMinutes(double value) | 111 | | AddMonths | Method | datetime AddMonths(int months) | 112 | | AddSeconds | Method | datetime AddSeconds(double value) | 113 | | AddTicks | Method | datetime AddTicks(long value) | 114 | | AddYears | Method | datetime AddYears(int value) | 115 | 116 | ## Set specific date and time 117 | 118 | To Set the date and time we can use the `Set-Date` command. 119 | 120 | ```powershell 121 | $date = Get-Date -Date "2022-01-02 03:04:05" 122 | $date 123 | ``` 124 | 125 | Result: 126 | 127 | ``` 128 | Sunday, January 2, 2022 3:04:05 AM 129 | ``` 130 | 131 | You can also set the current date but then change one part of it with for instance the month: 132 | 133 | ```powershell 134 | # Assume with this example that the current date is 2022-03-14 135 | $date = get-date -Month 5 136 | $date 137 | ``` 138 | 139 | Result: 140 | 141 | ``` 142 | Saturday, May 14, 2022 8:46:27 PM 143 | ``` -------------------------------------------------------------------------------- /content/post/variable-scopes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Scopes 3 | author: Sander Stad 4 | date: '2022-02-22' 5 | categories: 6 | - Example 7 | weight: 130 8 | --- 9 | 10 | When you create a variable, alias or a function in PowerShell, it is only available in the current scope where it was created. 11 | For example, when you create a variable in a function, it is only available in the function. 12 | When you create a variable in a script, it is available in the script and all functions in the script. 13 | 14 | There is a way to make these items available outside it's current scope. 15 | 16 | ## Local 17 | 18 | The local scope is relative to whatever context the code runs in at the time. 19 | 20 | To define an item local you use the *local:* modifier. By default the scope of a variable is the _Local_ scope. 21 | 22 | ```powershell 23 | $var = "bla" 24 | 25 | $var 26 | ``` 27 | 28 | Result: 29 | 30 | ``` 31 | bla 32 | ``` 33 | 34 | ## Global 35 | 36 | Items in the global scope are available everywhere. 37 | 38 | To define an item as global you use the *global:* modifier. 39 | 40 | ```powershell 41 | $global:varOne = "bla" # Assign a variable in the global scope 42 | 43 | Write-Host "Variable One:" $global:varOne # Print the variable 44 | 45 | # Function to demonstrate local and global scope 46 | function MyFunc() { 47 | $global:varOne = "bla bla" 48 | $varTwo = "boo" 49 | return $varTwo 50 | } 51 | 52 | Write-Host "Variable Two:" $varTwo # Print the variable 53 | 54 | $varTwo = MyFunc # Call the function and change the variable 55 | Write-Host "Variable One:" $varOne # Print the variable 56 | 57 | Write-Host "Variable Two:" $varTwo # Print the variable 58 | ``` 59 | 60 | Result: 61 | 62 | ``` 63 | Variable One: bla 64 | Variable Two: 65 | Variable One: bla bla 66 | Variable Two: boo 67 | ``` 68 | 69 | As you can see we defined a global variable called *varOne* and we changed the value of *varOne* in the function. 70 | We did not have access to variable *varTwo* because the scope of the variable was set to local in the function. 71 | 72 | ## Private 73 | 74 | Items that are defined as private are not available outside the scope where they are defined. 75 | 76 | To define an item private you use the *private:* modifier. 77 | 78 | ```powershell 79 | # Make sure that the variable is gone 80 | Remove-Variable -Name var1 -ErrorAction SilentlyContinue 81 | 82 | $var1 = "This is a variable" 83 | 84 | Write-Host "var1 = '$var1'" 85 | 86 | function test1 { 87 | Write-Host "Inside function, var1 = $var1" 88 | } 89 | 90 | test1 91 | 92 | # Now let's do it privately 93 | Remove-Variable -Name var1 -ErrorAction SilentlyContinue 94 | 95 | $Private:var1 = "This is a variable" 96 | 97 | function test2 { 98 | Write-Host "Inside function with private, var1 = $var1" 99 | } 100 | 101 | test2 102 | ``` 103 | 104 | Result 105 | 106 | ``` 107 | var1 = 'This is a variable' 108 | Inside function, var1 = This is a variable 109 | Inside function with private, var1 = 110 | ``` 111 | 112 | As you can see the function *test2* did not have access to the variable *var1* because it was defined as private. 113 | 114 | ## Script 115 | 116 | A script scope is automatically created every time a PowerShell script runs. 117 | 118 | To define an item script you use the *script:* modifier. 119 | 120 | ```powershell 121 | function myFunc { 122 | 123 | $Script:VarOne = "Script Scoped" 124 | $Var2 = "Function Scoped" 125 | } 126 | 127 | myFunc 128 | Write-Host "Var 1: $VarOne" 129 | Write-Host "Var 2: $Var2" 130 | ``` 131 | 132 | Result: 133 | 134 | ``` 135 | Var 1: Script Scoped 136 | Var 2: 137 | ``` 138 | 139 | As you can see the script is not able to access the variables `$Var2` but is able to access the variable `$VarOne`. 140 | 141 | 142 | -------------------------------------------------------------------------------- /content/post/variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Variables 3 | date: '2022-02-22' 4 | categories: 5 | - Example 6 | weight: 20 7 | --- 8 | 9 | In PowerShell we can store all types of values in PowerShell variables. It's possible to store the results of commands, and store elements that are used in commands and expressions, such as names, paths, settings, and values. 10 | 11 | PowerShell variables, unlike other languages are not case-sensitive, and can include spaces and special characters. Variable names with special characters and spaces are difficult to use and should be avoided. For more information, see [Variable names that include special characters](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_variables?view=powershell-7.2#variable-names-that-include-special-characters). 12 | 13 | PowerShell automatically detects the type of the variable and converts it to the appropriate type. It is also possible to declare variables with a specific type. 14 | 15 | ```powershell 16 | $a = 1337 # System.Int32 17 | $b = "Swifty" # System.String 18 | $c = 31337, "Swifty" # array of System.Int32, System.String 19 | $d = Get-ChildItem C:\Windows # FileInfo and DirectoryInfo types 20 | New-Variable -Name e -Value 1337 # System.Int32 21 | ``` 22 | 23 | PowerShell is even smart enough to detect when a variable is assigned a value that is not of the same type and convert it to the appropriate type. 24 | 25 | ```powershell 26 | $number = "1337" # The string is converted to an integer. 27 | $number.GetType() # Get the type of the variable. 28 | ``` 29 | 30 | As soon as the variable is assigned a value, it is considered to be of that data type. This means that it cannot be changed without converting it to a different type. 31 | 32 | ```powershell 33 | [int]$number = 1337 34 | $number = "One Thousand, Three Hundred and Thirty-Seven" #This will give an error 35 | ``` 36 | 37 | {{< error >}} 38 | ``` 39 | Cannot convert value "One Thousand, Three Hundred and Thirty-Seven" to type "System.Int32". Error: "Input string was not in a correct format." 40 | At line:1 char:1 41 | + $number = "One Thousand, Three Hundred and Thirty-Seven" #This will ... 42 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 | + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException 44 | + FullyQualifiedErrorId : RuntimeException 45 | ``` 46 | {{< /error >}} -------------------------------------------------------------------------------- /content/post/writing-files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Writing Files 3 | author: Sander Stad 4 | date: '2022-03-10' 5 | categories: 6 | - Example 7 | weight: 180 8 | --- 9 | 10 | There are several methods to write data to files 11 | 12 | ## Add-Content 13 | 14 | To add content to a file run the following script: 15 | 16 | ```powershell 17 | Add-Content -Path (Join-Path -Path $env:TEMP -ChildPath "test1.txt") -Value "This is just a test" 18 | Add-Content -Path (Join-Path -Path $env:TEMP -ChildPath "test1.txt") -Value "This is just another test" 19 | Get-Content (Join-Path -Path $env:TEMP -ChildPath "test1.txt") 20 | ``` 21 | 22 | Result: 23 | 24 | ``` 25 | This is just a test 26 | This is just another test 27 | ``` 28 | 29 | In this example you see that the command `Add-Content` automatically creates the file if it doesn't exist. 30 | It also adds the value to another line. 31 | 32 | What if you don't want to add a new line 33 | 34 | ```powershell 35 | Add-Content -Path (Join-Path -Path $env:TEMP -ChildPath "test2.txt") -Value "Test1" 36 | Add-Content -Path (Join-Path -Path $env:TEMP -ChildPath "test2.txt") -Value "Test2" -NoNewline 37 | Add-Content -Path (Join-Path -Path $env:TEMP -ChildPath "test2.txt") -Value "Test3" -NoNewline 38 | ``` 39 | 40 | Result: 41 | 42 | ``` 43 | Test1 44 | Test2Test3 45 | ``` 46 | 47 | ## Out-File 48 | 49 | The `Out-File` command is easiest used in combination with a pipe ("|"). 50 | 51 | ```powershell 52 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit" | Out-File -FilePath c:\temp\output1.txt 53 | Get-Content C:\temp\output1.txt 54 | ``` 55 | 56 | Result: 57 | 58 | ``` 59 | Lorem ipsum dolor sit amet, consectetur adipiscing elit 60 | ``` 61 | 62 | Without any other parameter `Out-File` will overwrite the file. We can use the `-Append` parameter to append text. 63 | 64 | ```powershell 65 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit" | Out-File -FilePath c:\temp\output2.txt 66 | "Ut enim ad minim veniam, quis nostrud" | Out-File -FilePath c:\temp\output2.txt -Append 67 | Get-Content C:\temp\output2.txt 68 | ``` 69 | 70 | Result: 71 | 72 | ``` 73 | Lorem ipsum dolor sit amet, consectetur adipiscing elit 74 | Ut enim ad minim veniam, quis nostrud 75 | ``` 76 | 77 | -------------------------------------------------------------------------------- /content/post/xml.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: XML 3 | author: Sander Stad 4 | date: '2023-12-12' 5 | categories: 6 | - Example 7 | weight: 240 8 | --- 9 | 10 | XML, or eXtensible Markup Language, is a versatile data format widely used for storing and exchanging structured information. In the realm of PowerShell, XML becomes a potent ally, offering a robust mechanism for handling and manipulating data in a hierarchical and human-readable way. In this article, we'll explore the integration of XML with PowerShell, unraveling the simplicity and efficacy it brings to scriptwriters. 11 | 12 | ## Creating XML with PowerShell 13 | 14 | PowerShell provides seamless ways to generate XML content, both manually and programmatically. 15 | 16 | Let's embark on a journey by creating a basic XML structure using PowerShell's intrinsic capabilities: 17 | 18 | ```powershell 19 | # Creating a simple XML document 20 | $xmlDocument = New-Object System.Xml.XmlDocument 21 | 22 | # Adding a root element 23 | $rootElement = $xmlDocument.CreateElement("Root") 24 | $xmlDocument.AppendChild($rootElement) 25 | 26 | # Adding child elements 27 | $childElement1 = $xmlDocument.CreateElement("Child1") 28 | $childElement1.InnerText = "Value1" 29 | $rootElement.AppendChild($childElement1) 30 | 31 | $childElement2 = $xmlDocument.CreateElement("Child2") 32 | $childElement2.InnerText = "Value2" 33 | $rootElement.AppendChild($childElement2) 34 | 35 | # Save the XML to a file 36 | $xmlDocument.Save("C:\Path\To\Your\File.xml") 37 | ``` 38 | 39 | Result: 40 | 41 | ```xml 42 | 43 | Value1 44 | Value2 45 | 46 | ``` 47 | 48 | In this example, we create an XML document, add a root element named "Root," and populate it with two child elements, each containing a distinct value. The resulting XML is then saved to a specified file path. 49 | 50 | ## Reading XML with PowerShell 51 | 52 | Reading XML in PowerShell is an intuitive process, allowing seamless navigation through the document's hierarchical structure. 53 | 54 | Let's explore how to extract information from an XML file: 55 | 56 | ```powershell 57 | # Load XML from a file 58 | $xmlFilePath = "C:\Path\To\Your\File.xml" 59 | $xmlContent = Get-Content -Path $xmlFilePath 60 | $xmlDocument = [xml]$xmlContent 61 | 62 | # Accessing elements 63 | $rootValue = $xmlDocument.Root.InnerText 64 | $child1Value = $xmlDocument.Root.Child1.InnerText 65 | $child2Value = $xmlDocument.Root.Child2.InnerText 66 | 67 | # Displaying values 68 | Write-Host "Root Value: $rootValue" 69 | Write-Host "Child1 Value: $child1Value" 70 | Write-Host "Child2 Value: $child2Value" 71 | ``` 72 | 73 | Result: 74 | 75 | ``` 76 | C:\> Write-Host "Root Value: $rootValue" 77 | Root Value: Value1Value2 78 | C:\> Write-Host "Child1 Value: $child1Value" 79 | Child1 Value: 80 | C:\> Write-Host "Child2 Value: $child2Value" 81 | Child2 Value: 82 | ``` 83 | 84 | In this snippet, we load an XML file, cast it to an XML type, and then access specific elements and their corresponding values. The result is a straightforward display of the extracted data. 85 | 86 | ## Modifying XML with PowerShell 87 | 88 | PowerShell empowers users to dynamically modify XML content, offering unparalleled flexibility in handling changing data requirements. 89 | 90 | Let's delve into an example where we update the value of a child element: 91 | 92 | ```powershell 93 | # Load XML from a file 94 | $xmlFilePath = "C:\Path\To\Your\File.xml" 95 | $xmlContent = Get-Content -Path $xmlFilePath 96 | $xmlDocument = [xml]$xmlContent 97 | 98 | # Modify a child element's value 99 | $xmlDocument.Root.Child1 = "New Value" 100 | 101 | # Save the modified XML 102 | $xmlDocument.Save($xmlFilePath) 103 | ``` 104 | 105 | Result: 106 | 107 | ```xml 108 | 109 | New Value 110 | Value2 111 | 112 | ``` 113 | 114 | In this scenario, we load the XML file, update the value of a specific child element (Child1), and then save the modified XML content back to the file. -------------------------------------------------------------------------------- /layouts/_default/list.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} {{if not .IsHome }} 2 |

{{ .Title | markdownify }}

3 | {{ end }} {{ .Content }} 4 | 5 | 12 | 13 | {{ partial "footer.html" . }} -------------------------------------------------------------------------------- /layouts/_default/single.html: -------------------------------------------------------------------------------- 1 | {{ partial "header.html" . }} 2 |
3 |

{{ .Site.Title }}: {{ .Title | markdownify }}

4 |
5 | 6 |
7 | {{ .Content }} 8 |
9 | 10 | {{with .Site.RegularPages.Prev . }}

Home 3 |

4 | 5 |

6 | by Sander Stad | 7 | source | 8 | license 9 |

-------------------------------------------------------------------------------- /layouts/partials/head_custom.html: -------------------------------------------------------------------------------- 1 | PowerShell By Example 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /layouts/partials/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ .Title }} | {{ .Site.Title }} 9 | 10 | 11 | 12 | {{ template "_internal/google_analytics.html" . }} 13 | 14 | {{ partial "head_custom.html" . }} 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /layouts/shortcodes/error.html: -------------------------------------------------------------------------------- 1 |
2 | {{ .Inner | markdownify }} 3 |
-------------------------------------------------------------------------------- /resources/logo-32x32.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/resources/logo-32x32.pdn -------------------------------------------------------------------------------- /resources/logo.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/resources/logo.pdn -------------------------------------------------------------------------------- /resources/raw_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/resources/raw_logo.png -------------------------------------------------------------------------------- /static/CNAME: -------------------------------------------------------------------------------- 1 | powershellbyexample.dev -------------------------------------------------------------------------------- /static/css/fonts.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Optima, Candara, Calibri, Arial, sans-serif; 3 | } 4 | code { 5 | font-family: "Lucida Console", Monaco, monospace; 6 | font-size: 85%; 7 | } 8 | -------------------------------------------------------------------------------- /static/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 800px; 3 | margin: auto; 4 | padding: 1em; 5 | line-height: 1.5; 6 | } 7 | 8 | h1 a { 9 | color: #000; 10 | text-decoration: none; 11 | } 12 | 13 | a { 14 | color: #024391; 15 | } 16 | 17 | a:hover { 18 | color: #cf0000; 19 | } 20 | 21 | 22 | /*a:visited { 23 | color: #024391; 24 | }*/ 25 | 26 | 27 | /* header and footer areas */ 28 | 29 | .menu { 30 | padding: 0; 31 | } 32 | 33 | .menu li { 34 | display: inline-block; 35 | } 36 | 37 | .article-meta, 38 | .menu a { 39 | text-decoration: none; 40 | background: #eee; 41 | padding: 5px; 42 | border-radius: 5px; 43 | } 44 | 45 | .menu, 46 | .article-meta, 47 | footer { 48 | text-align: center; 49 | } 50 | 51 | .title { 52 | font-size: 1.1em; 53 | } 54 | 55 | .title a { 56 | color: #000000; 57 | } 58 | 59 | .title a:hover { 60 | color: #024391; 61 | } 62 | 63 | footer a { 64 | text-decoration: none; 65 | } 66 | 67 | hr { 68 | border-style: dashed; 69 | color: #ddd; 70 | } 71 | 72 | 73 | /* code */ 74 | 75 | .error { 76 | color: #f00; 77 | } 78 | 79 | pre { 80 | border: 1px solid #ddd; 81 | box-shadow: 5px 5px 5px #eee; 82 | padding: 1em; 83 | overflow-x: auto; 84 | } 85 | 86 | code { 87 | background: #f9f9f9; 88 | } 89 | 90 | pre code { 91 | background: none; 92 | } 93 | 94 | 95 | /* misc elements */ 96 | 97 | img, 98 | iframe, 99 | video { 100 | max-width: 100%; 101 | } 102 | 103 | main { 104 | hyphens: auto; 105 | } 106 | 107 | blockquote { 108 | background: #f9f9f9; 109 | border-left: 5px solid #ccc; 110 | padding: 3px 1em 3px; 111 | } 112 | 113 | table { 114 | margin: auto; 115 | border-top: 1px solid #666; 116 | border-bottom: 1px solid #666; 117 | } 118 | 119 | table thead th { 120 | border-bottom: 1px solid #ddd; 121 | } 122 | 123 | th, 124 | td { 125 | padding: 5px; 126 | } 127 | 128 | thead, 129 | tfoot, 130 | tr:nth-child(even) { 131 | background: #eee; 132 | } -------------------------------------------------------------------------------- /static/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/static/icons/favicon-32x32.png -------------------------------------------------------------------------------- /static/twittercard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanderstad/powershellbyexample/b70ad9ebfca83e32f0a92ad0bc3d239298084c87/static/twittercard.png --------------------------------------------------------------------------------