&lt;?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Articles from 2022 on PowerShell.org - Welcome Automaters!</title><link>https://powershell.org/articles/2022/</link><description>Recent content in Articles from 2022 on PowerShell.org - Welcome Automaters!</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://powershell.org/articles/2022/index.xml" rel="self" type="application/rss+xml"/><item><title>PowerShell + DevOps Global Summit 2023</title><link>https://powershell.org/articles/2022-11-30-powershell-devops-global-summit-2023/</link><guid>https://powershell.org/articles/2022-11-30-powershell-devops-global-summit-2023/</guid><pubDate>Wed, 30 Nov 2022 14:38:05 +0000</pubDate><description>&lt;h2 id="summit-information" class="ps-heading"&gt;Summit Information&lt;a class="ps-heading-anchor" href="#summit-information" aria-label="Link to this section" title="Link to this section"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;What:&lt;/strong&gt; 2023 PowerShell + DevOps Global Summit&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where:&lt;/strong&gt; Marriott Downtown Bellevue WA&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;When:&lt;/strong&gt; April 24-27, 2023&lt;/p&gt;
&lt;h2 id="dates-to-remember" class="ps-heading"&gt;Dates to Remember&lt;a class="ps-heading-anchor" href="#dates-to-remember" aria-label="Link to this section" title="Link to this section"&gt;&lt;i class="fas fa-link" aria-hidden="true"&gt;&lt;/i&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1 - Jan&lt;/strong&gt; — Early Bird sales will end&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;15 - Dec&lt;/strong&gt; — The content committee will notify speakers no later than 15-December on if their sessions were selected.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2 - Jan&lt;/strong&gt; — Fill Schedule will go live 2-January&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is more information available at the event website &lt;a href="https://powershellsummit.org"&gt;https://powershellsummit.org&lt;/a&gt; including&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<h2 id="summit-information" class="ps-heading">Summit Information<a class="ps-heading-anchor" href="#summit-information" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h2><p><strong>What:</strong> 2023 PowerShell + DevOps Global Summit</p><p><strong>Where:</strong> Marriott Downtown Bellevue WA</p><p><strong>When:</strong> April 24-27, 2023</p><h2 id="dates-to-remember" class="ps-heading">Dates to Remember<a class="ps-heading-anchor" href="#dates-to-remember" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h2><ul><li><strong>1 - Jan</strong> — Early Bird sales will end</li><li><strong>15 - Dec</strong> — The content committee will notify speakers no later than 15-December on if their sessions were selected.</li><li><strong>2 - Jan</strong> — Fill Schedule will go live 2-January</li></ul><p>There is more information available at the event website<a href="https://powershellsummit.org">https://powershellsummit.org</a> including</p><p>Links to buy Tickets and our FAQ page</p>
]]></content:encoded></item><item><title>Learn Powershell in 5 Painless Steps – Decisions (If/Else, Switch, Function) – Step 5</title><link>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-decisions-if-else-switch-function-step-5/</link><guid>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-decisions-if-else-switch-function-step-5/</guid><pubDate>Thu, 28 Jul 2022 18:45:52 +0000</pubDate><description>&lt;p&gt;DevOps = Developers + Operations.  What if you&amp;rsquo;re in Operations and don&amp;rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, &lt;a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/"&gt;open sourced to the OSX and Linux communities&lt;/a&gt;.  It ships with a great minimalist development environment (Powershell ISE).&lt;/p&gt;
&lt;p&gt;The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&amp;rsquo;m hoping to enable you to automate your own workflows even if you&amp;rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<p>DevOps = Developers + Operations.  What if you&rsquo;re in Operations and don&rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, <a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/">open sourced to the OSX and Linux communities</a>.  It ships with a great minimalist development environment (Powershell ISE).</p><p>The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&rsquo;m hoping to enable you to automate your own workflows even if you&rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.</p><hr><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294981&amp;preview=true">Step 4: Loops(I can give you more)</a> &lt;&ndash; Step 5: Decisions(The time has arrived)</p><hr><p>We&rsquo;ve spent a month getting to this point. We&rsquo;re invested. Let&rsquo;s blow this party up! Sorry, I&rsquo;ve had too much coffee this morning. That was a bad decision. That&rsquo;s our topic for this last installment of the 5 steps: DECISIONS, not coffee.</p><p>We know how to get information from various sources, store them in fairly complex ways, and send it out to our users in different formats. According to the stated format of these blogs, there&rsquo;s only one piece left in this puzzle. When we stand up a virtual server, they&rsquo;re not provisioned the same across the board. An SQL server needs a far different configuration than an IIS server, a nano server, or a terminal services server.</p><p>If we talk through the process, an SQL server wants more RAM and disk space, whereas an IIS server is more focused on RAM and CPU, Whereas the Terminal Services server wants more of all three: RAM, CPU, and disk. Lastly, a nano server wants as little as possible.</p><p>I&rsquo;ve tricked you again. If you can talk through your decision making process again, you&rsquo;re already programming. Here&rsquo;s the pseudocode (fake code in comments to fill out afterwards):</p><blockquote/><p>`# SQL: RAM and DISK Heavy</p><h1 id="iis--ram-and-cpu-heavy" class="ps-heading">IIS: RAM and CPU Heavy<a class="ps-heading-anchor" href="#iis--ram-and-cpu-heavy" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="ts---ram-cpu-disk-heavy" class="ps-heading">TS: RAM, CPU, DISK Heavy<a class="ps-heading-anchor" href="#ts---ram-cpu-disk-heavy" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="nano-minimums" class="ps-heading">Nano: Minimums<a class="ps-heading-anchor" href="#nano-minimums" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>`I tricked you twice in the same paragraph. If we change the word whereas into else, we&rsquo;ve actually got the SYNTAX (syntax is using the right words in the right order with the right punctuation) for the first structure we&rsquo;re going to look into:</p><p><strong>IF / ELSE</strong></p><p>Let&rsquo;s start with the syntax statement for the IF / ELSE in Powershell:</p><blockquote/><p><code>if (condition) {statement 1} else {statement 2}</code>A real example of this can look like this:</p><blockquote/><p>`# Setup machine provisioning values
if ($machineType -eq &ldquo;SQL&rdquo;) {
# this is anything else, the DEFAULT for instance
$CPU = 2
$RAM = 8
$DISK = 150
} else {</p><h1 id="this-is-anything-else-the-default-for-instance" class="ps-heading">this is anything else, the DEFAULT for instance<a class="ps-heading-anchor" href="#this-is-anything-else-the-default-for-instance" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$CPU = 2
$RAM = 4
$DISK = 50
}</p><h1 id="removing-the-space-between-machinetype-and--will-confuse-powershell" class="ps-heading">Removing the space between $machineType and : will confuse Powershell<a class="ps-heading-anchor" href="#removing-the-space-between-machinetype-and--will-confuse-powershell" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Write-Output &ldquo;Building new $machineType server : NAME-$($ServerInfo_obj[0].name), RAM-$RAM, CPU-$CPU, DISK-$DISK&rdquo;</p><h1 id="build-the-server-with-the-given-requirements" class="ps-heading">Build the server with the given requirements<a class="ps-heading-anchor" href="#build-the-server-with-the-given-requirements" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="this-doesnt-actually-work" class="ps-heading">This doesn&rsquo;t actually work<a class="ps-heading-anchor" href="#this-doesnt-actually-work" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="note-the-line-continuation---added-for-readability" class="ps-heading">Note the line continuation ( `) added for readability<a class="ps-heading-anchor" href="#note-the-line-continuation---added-for-readability" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="note-everything-lined-up-in-nice-little-columns-to-feed-my-ocd" class="ps-heading">Note everything lined up in nice little columns to feed my OCD<a class="ps-heading-anchor" href="#note-everything-lined-up-in-nice-little-columns-to-feed-my-ocd" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>new-SCVirtualMachine<code>-ComputerName $serverInfo_obj[0].name</code>
-CPUCount $CPU<code>-DynamicMemoryMaximumMB $RAM * 1024</code>
-VirtualHardDisk &ldquo;\Path\To\New\Drive\Object$serverInfo_obj[0].name_$DISK&rdquo;<code>-OperatingSystem "Windows 3.1"</code>Picture if you will reading in a CSV or JSON file defining a thousand servers into an object array, then using Powershell to deploy them! Imagine driving this based on rising numbers of users logged on to a set of load balanced terminal servers. Imagine removing machines as well based on lowering numbers of users toward the end of the workday.</p><p>This is where we start to see the benefit of using scripting to drive performance vs. cost savings. As we moved from physical servers to virtual we, the industry, largely kept the manual workflow. As we&rsquo;re moving to Azure and being charged for resource use, this becomes a huge cost savings solution.</p><p>In our initial list of server types, we had 4 types of servers &ldquo;THERE WERE FOUR TYPES!&rdquo; Let&rsquo;s look at how we can make that work with what we know now. If we have our default settings as an else, but need more types, let&rsquo;s move the defaults to a declaration at the top, then alter them if they are not the &ldquo;nano&rdquo; type:</p><blockquote/><p>`# Change me to SQL, IIS, TS, or NANO
$machineType = &ldquo;NANO&rdquo;</p><h1 id="default-minimums-for-those-pesky-nano-servers" class="ps-heading">Default Minimums for those pesky nano servers<a class="ps-heading-anchor" href="#default-minimums-for-those-pesky-nano-servers" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$CPU = 2
$RAM = 4
$DISK = 50</p><h1 id="sql-ram-and-disk-heavy" class="ps-heading">SQL: RAM and DISK Heavy<a class="ps-heading-anchor" href="#sql-ram-and-disk-heavy" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>if ($machineType -eq &ldquo;SQL&rdquo;) {
$CPU = 2
$RAM = 8
$DISK = 150
}</p><h1 id="iis-ram-and-cpu-heavy" class="ps-heading">IIS: RAM and CPU Heavy<a class="ps-heading-anchor" href="#iis-ram-and-cpu-heavy" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>if ($machineType -eq &ldquo;IIS&rdquo;) {
$CPU = 4
$RAM = 8
$DISK = 50
}</p><h1 id="ts-ram-cpu-disk-heavy" class="ps-heading">TS: RAM, CPU, DISK Heavy<a class="ps-heading-anchor" href="#ts-ram-cpu-disk-heavy" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>if ($machineType -eq &ldquo;TS&rdquo;) {
$CPU = 4
$RAM = 8
$DISK = 150
}</p><p>Write-Output &ldquo;New $machineType : RAM-$RAM, CPU-$CPU, DISK-$DISK&rdquo;
`<strong>ELSEIF</strong></p><p>There&rsquo;s another mechanism for this type of thing that is cleaner to read as it groups the if / else decisions. We&rsquo;ll just flip the terms and remove the punctuation giving us elseif. Let&rsquo;s rewrite our decision to use this new term:</p><blockquote/><p>`# Change me to SQL, IIS, TS, or NANO
$machineType = &ldquo;SQL&rdquo;</p><p>if ($machineType -eq &ldquo;SQL&rdquo;) {
# SQL: RAM and DISK Heavy
$CPU = 2
$RAM = 8
$DISK = 150
} elseif ($machineType -eq &ldquo;IIS&rdquo;) {
# IIS: RAM and CPU Heavy
$CPU = 4
$RAM = 8
$DISK = 50
} elseif ($machineType -eq &ldquo;TS&rdquo;) {
# TS: RAM, CPU, DISK Heavy
$CPU = 4
$RAM = 8
$DISK = 150
} else {
# Default Minimums
$CPU = 2
$RAM = 4
$DISK = 50
}</p><p>Write-Output &ldquo;New $machineType : RAM-$RAM, CPU-$CPU, DISK-$DISK&rdquo;
`I&rsquo;d like you to note at this point that you&rsquo;ve just read a few slightly larger blocks of code and it didn&rsquo;t look as weird as it did when you started this tutorial (just over a month ago if you followed it in real time. If you&rsquo;re from the future&hellip; welcome back, we still wear shoes on our feet in our time!). Once we learn what the individual pieces look like, we can start to see the matrix unfold.</p><p>These can get wonderfully complex as we can NEST these statements, like decision inception (deception?), perhaps to differentiate the type of ERP software an SQL server is supporting:</p><blockquote/><p>`$machineType = &ldquo;GP&rdquo;</p><p>if ($serverInfo_obj[0].name -like &ldquo;<em>SQL</em>&rdquo;) {
if ($machineType -eq &ldquo;CRM&rdquo;) {
# SQL: RAM and DISK Heavy
$CPU = 2
$RAM = 8
$DISK = 150
} elseif ($machineType -eq &ldquo;VISUAL&rdquo;) {
# IIS: RAM and CPU Heavy
$CPU = 4
$RAM = 8
$DISK = 50
} elseif ($machineType -eq &ldquo;GP&rdquo;) {
# TS: RAM, CPU, DISK Heavy
$CPU = 4
$RAM = 8
$DISK = 150
} elseif ($machineType -eq &ldquo;Dynamics 365&rdquo;) {
# TS: RAM, CPU, DISK Heavy
$CPU = 4
$RAM = 16
$DISK = 100
}
} else {
# Default Minimums
$CPU = 2
$RAM = 4
$DISK = 50
}</p><p>Write-Output &ldquo;New $machineType : RAM-$RAM, CPU-$CPU, DISK-$DISK&rdquo;
`This allows for an amazing amount of gothic complexity once we start nesting more deeply. Since we&rsquo;re only using -eq on the internal IF statement, there&rsquo;s another structure that deals with these types of comparisons potentially more efficiently. We can think of it as taking an input variable and directing a specific output based on that. Like my Thom the Tanker (no relation) locomotive turntable track switch!</p><p><strong>SWITCH</strong></p><p>Let&rsquo;s check out the syntax statement for this one:</p><blockquote/><p><code>SWITCH (input) {condition1 {output}; condition2 {output}; default {output}}</code>That&rsquo;s uglier than previous ones&hellip; let&rsquo;s span a few lines with this one:</p><blockquote/><p><code>SWITCH (input) { condition1 {output} condition2 {output} default {output} }</code>If we apply that to our previous statement, it really cleans it up:</p><blockquote/><p>`$machineType = &ldquo;SQL&rdquo;</p><p>if ($serverInfo_obj[0].name -like &ldquo;<em>SQL</em>&rdquo;) {
switch ($machineType) {
&ldquo;CRM&rdquo; {
$CPU = 2
$RAM = 8
$DISK = 150
}
&ldquo;VISUAL&rdquo; {
$CPU = 4
$RAM = 8
$DISK = 50
}
&ldquo;GP&rdquo; {
$CPU = 4
$RAM = 8
$DISK = 150
}
&ldquo;Dynamics 365&rdquo; {
$CPU = 4
$RAM = 16
$DISK = 100
}
default {
$CPU = 2
$RAM = 4
$DISK = 50
}
}
} else {
# Default Minimums
$CPU = 2
$RAM = 4
$DISK = 50
}</p><p>Write-Output &ldquo;New $machineType : RAM-$RAM, CPU-$CPU, DISK-$DISK&rdquo;
`My challenge to you is to find something in your tech environment that you do every day and write the pseudo code for it. You&rsquo;ll find yourself equipped to build out a script from that series of comment lines. Make work easier for yourself starting today.</p><p>So&hellip; we&rsquo;re at the end. My sidebar in notepad++ tells me I&rsquo;m over 200 lines. I&rsquo;ve covered all of the points I&rsquo;d planned on covering. Should we do an encore? One last little tidbit to really help us with our code? Let&rsquo;s make a FUNCTION! Thank you !</p><p><strong>FUNCTION</strong></p><p>This is basically just a chunk of code that we&rsquo;re going to be using over and over again. For instance, we&rsquo;re reading in a thousand machines and we&rsquo;ll need to set the CPU, RAM, and DISK for it each time. Wouldn&rsquo;t it be nice if we could to it this way?</p><blockquote/><p><code>$servers = read-csv c:\serverList.csv foreach ($server in $servers) { $serverInfo_obj = make-serverObject $server new-scvirtualmachine $serverInfo_obj }</code>See that make-serverObject? I just made that up. That&rsquo;s not a real thing&hellip; yet.</p><p>although it can be done anywhere above the place we&rsquo;re calling it from, I like to group my functions at the top of my script. A function looks like this:</p><blockquote/><p><code>function verb-nounFunctionName { param ( [type]$firstInputVariableName = "default value" [type]$secondInputVariableName = "default value" ) # Stuff we're doing... return $whateverOutputVariableWeWant }</code>Breaking this down, the verb-noun structure is what we see in any of the cmdlets we&rsquo;ve been using so far: get-file, set-scvirtualmachine, clear-host, get-eventlog, etc&hellip; This makes the purpose of the function/cmdlet much easier to figure out. So much of our programming careers will be spent trying to figure out what the *#$%*&amp;$!@#% we were thinking when we wrote that chunk of code 4 months ago at 3:30 in the morning after a week of horrible sleep deprivation.</p><p>It functions, but we&rsquo;re not quite sure why. Variable names like $stupidUnicornsWontStopRunningThroughMyOffice and function names like make-itstop -orGoJump and need-morecoffee -now don&rsquo;t lend themselves to easy interpretation.</p><p>The param() structure houses the input for the function/cmdlet we&rsquo;re building. It&rsquo;s just a comma separated list of variable assignments. I&rsquo;ve added the [type] to the front of the variable to make it easier to figure out what it wants to have and make the error messages a little bit more informative when there is a TYPE MISMATCH error. This will be [string], [int], [int32], [switch]. Switch types are false by default, true when called:</p><blockquote/><p>`function get-switchTest {
param (
[switch]$flipTheSwitch
)
return $flipTheSwitch
}</p><h1 id="we-call-it-anywhere-now-and-it-gets-replaced-with-its-return-valueobject" class="ps-heading">We call it anywhere now and it gets replaced with its return value/object<a class="ps-heading-anchor" href="#we-call-it-anywhere-now-and-it-gets-replaced-with-its-return-valueobject" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>write-output $(get-switchTest).isPresent
write-output $(get-switchTest -flipTheSwitch).isPresent
`From this example, you can see that the return does just that. This can be a single variable or a whole custom object.</p><p>Between the param block and the return, we can do any chunk of processing code we want, even all the object building stuff we did at the beginning way back in the first lesson (note the order of operations from the parentheses during the .add() ):</p><blockquote/><p>`function make-serverObject {
param (
[string]$server = &ldquo;SERVER&rdquo;,
[string]$type = &ldquo;TS&rdquo;,
[int]$instance = 0,
[int]$RAM = 4,
[int]$CPU = 2,
[int]$DISK = 50
)
$newObject = new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;$type-$server-$instance&rdquo;;
&ldquo;type&rdquo; = $type;
&ldquo;totalC&rdquo; = $DISK;
&ldquo;cores&rdquo; = $CPU;
&ldquo;totalRAM&rdquo; = $RAM
}
return $newObject
}</p><h1 id="create-an-empty-array-with-the-class-arraylist" class="ps-heading">Create an empty array with the class arraylist<a class="ps-heading-anchor" href="#create-an-empty-array-with-the-class-arraylist" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>[System.Collections.arrayList]$serverInfo_obj = @()</p><h1 id="returns-all-the-defaults-and-adds-it-to-the-object-array" class="ps-heading">Returns all the defaults and adds it to the object array<a class="ps-heading-anchor" href="#returns-all-the-defaults-and-adds-it-to-the-object-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj.add( (make-serverObject) )</p><h1 id="returns-custom-values-and-adds-it-to-the-array" class="ps-heading">Returns custom values and adds it to the array<a class="ps-heading-anchor" href="#returns-custom-values-and-adds-it-to-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj.add(
(make-serverObject<code>-type "SQL"</code>
-server &ldquo;Custom&rdquo;<code>-instance 5</code>
-RAM 16<code>-CPU 8</code>
-DISK 1024
)
)
`I make functions out of anything I use more than 3 times. That way, I can just copy and paste them into the top of my script when I need them again&hellip; or did the brilliant developers at Microsoft think of a way to do that too? Note that I&rsquo;ve been refering to them as function/cmdlets? Time to dig in and avail yourself of some free training from Microsoft:</p><p><a href="https://mva.microsoft.com/en-US/training-courses/getting-started-with-microsoft-powershell-8276">https://mva.microsoft.com/en-US/training-courses/getting-started-with-microsoft-powershell-8276</a><br><a href="https://mva.microsoft.com/en-US/training-courses/advanced-tools-scripting-with-powershell-30-jump-start-8277">https://mva.microsoft.com/en-US/training-courses/advanced-tools-scripting-with-powershell-30-jump-start-8277</a></p><p>Thank you all for making this such a successful training series. I&rsquo;ve received amazing feedback and wonderful critique. Don&rsquo;t be afraid to reach out to the Powershell development community on Powershell.org (<a href="https://powershell.org/">https://powershell.org/</a> ), reddit (<a href="https://www.reddit.com/r/PowerShell/">https://www.reddit.com/r/PowerShell/</a> ), and technet (<a href="https://social.technet.microsoft.com/forums/en-us/home?forum=ITCG&amp;filter=alltypes&amp;sort=lastpostdesc">https://social.technet.microsoft.com/forums/en-us/home?forum=ITCG&amp;filter=alltypes&amp;sort=lastpostdesc</a> ).</p><p>For higher end powershell/devops work, Tao Yang is prolific in his script releases and deep knowledge of Microsoft&rsquo;s System Center (<a href="http://blog.tyang.org/">http://blog.tyang.org/</a> )</p><p>Now that we&rsquo;ve pulled back the curtain on the topic of scripting, development, devops, and powershell, keep digging into it. Share what you find with others. Always remember, someone else is asking exactly the same questions you are right now! Everything is possible through code.</p><p><strong>Ignore the box, define the curve.</strong></p><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294981&amp;preview=true">Step 4: Loops(I can give you more)</a> &lt;&ndash; Step 5: Decisions(The time has arrived)</p>
]]></content:encoded></item><item><title>Learn Powershell in 5 Painless Steps – Loops (Foreach, For, While) – Step 4</title><link>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-loops-foreach-for-while-step-4/</link><guid>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-loops-foreach-for-while-step-4/</guid><pubDate>Thu, 28 Jul 2022 18:45:44 +0000</pubDate><description>&lt;p&gt;DevOps = Developers + Operations.  What if you&amp;rsquo;re in Operations and don&amp;rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, &lt;a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/"&gt;open sourced to the OSX and Linux communities&lt;/a&gt;.  It ships with a great minimalist development environment (Powershell ISE).&lt;/p&gt;
&lt;p&gt;The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&amp;rsquo;m hoping to enable you to automate your own workflows even if you&amp;rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<p>DevOps = Developers + Operations.  What if you&rsquo;re in Operations and don&rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, <a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/">open sourced to the OSX and Linux communities</a>.  It ships with a great minimalist development environment (Powershell ISE).</p><p>The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&rsquo;m hoping to enable you to automate your own workflows even if you&rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.</p><hr><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294979&amp;preview=true">Step 3: Input (Just you and me)</a> &lt;&ndash; Step 4: Loops(I can give you more) &ndash;&gt;<a href="https://powershell.org/?p=294983&amp;preview=true">Step 5: Decisions(The time has arrived)</a></p><hr><p>We&rsquo;ve spent three weeks now learning to move data from point A to point B. Let&rsquo;s see how we scale this from a list of 3 servers to 30, 300, or 3 Million (Pinky to corner of mouth&hellip; yes I did, I assume you did as well). We&rsquo;ll start with our object code from before.</p><p>There is a matter of scale that happens here, and how we add to our object array matters. Using the += we&rsquo;ve been using isn&rsquo;t a big deal with 3 objects. When we start to ramp this up, we run into a problem. The problem is this:</p><blockquote/><p>`# Declare a test array $a
$a = @(&ldquo;thing 1&rdquo;, &ldquo;thing 2&rdquo;, &ldquo;thing 3&rdquo;)</p><h1 id="add-an-element-to-the-end" class="ps-heading">Add an element to the end<a class="ps-heading-anchor" href="#add-an-element-to-the-end" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$a += @(&ldquo;thing 4&rdquo;)</p><h1 id="this-is-what-its-actually-doing" class="ps-heading">This is what it&rsquo;s actually doing<a class="ps-heading-anchor" href="#this-is-what-its-actually-doing" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$a = $a + @(&ldquo;thing 5&rdquo;)
`We start on the right side of the equals sign (technical name: assignment operator). From left to right on that side, we (the computer) figure out what is in $a so we can find the end of it for the + then put the contents of the array @(&ldquo;Thing 5&rdquo;) into the existing array and return it across the assignment operator (equals sign).  When there are only 3 elements in $a, it&rsquo;s not a big deal.  When we get to thousands of them, it starts to take a long time.</p><p>It&rsquo;s as if our new object has to go to the front of the line in the deli and ask each customer in line if they&rsquo;re at the back of the line before getting into the back of that line.</p><p>The object knows how many elements it has.  It would be nice to take the new element, hand it the next index out of a virtual red counter number spindle and tell it to stand in that deli line.  This is a much better way to do this to make it faster at scale as it no longer needs to read through the whole array to find the end.</p><blockquote/><p>`# Create an empty array with the class arraylist
[System.Collections.arrayList]$serverInfo_obj = @()</p><h1 id="ive-changed-the-server-naming-conventions-slightly" class="ps-heading">I&rsquo;ve changed the server naming conventions slightly<a class="ps-heading-anchor" href="#ive-changed-the-server-naming-conventions-slightly" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="add-the-object-for-server-01-into-the-array" class="ps-heading">Add the object for server-01 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server-01-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$newObject = new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server-01&rdquo; ;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo; ;
&ldquo;totalD&rdquo; = &ldquo;200Gb&rdquo; ;
&ldquo;cores&rdquo; = &ldquo;2&rdquo; ;
&ldquo;totalRAM&rdquo; = &ldquo;8Gb&rdquo;
}
$serverInfo_obj.add($newObject)</p><h1 id="add-the-object-for-server-02-into-the-array" class="ps-heading">Add the object for server-02 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server-02-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$newObject = new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server-02&rdquo; ;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo; ;
&ldquo;totalD&rdquo; = &ldquo;50Gb&rdquo; ;
&ldquo;cores&rdquo; = &ldquo;4&rdquo; ;
&ldquo;totalRAM&rdquo; = &ldquo;16Gb&rdquo;
}
$serverInfo_obj.add($newObject)</p><h1 id="add-the-object-for-server-03-into-the-array" class="ps-heading">Add the object for server-03 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server-03-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$newObject = new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server-03&rdquo; ;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo; ;
&ldquo;totalD&rdquo; = &ldquo;50Gb&rdquo; ;
&ldquo;cores&rdquo; = &ldquo;4&rdquo; ;
&ldquo;totalRAM&rdquo; = &ldquo;16Gb&rdquo;
}
$serverInfo_obj.add($newObject)
`Now, we&rsquo;ll just enter another object for each of our 3 million servers we&rsquo;re managing.. I&rsquo;ll wait. No? Let&rsquo;s see how we can make our script LOOP through a large number of things. We&rsquo;ll start by noticing our naming convention has a simple format that would be suited well to just bumping the number a bunch of times and setting the name of the server to &ldquo;Server-$instance&rdquo;. This will be simple to perform using a RANGE. To see how a range works, enter this into your console:</p><blockquote><p>1..100</p></blockquote><p>Cool&hellip; we made a computer count to 100. I may have played with this dumb little piece of code far too much when I first learned it. We&rsquo;ll note that the numbers don&rsquo;t have the leading zeroes to make them the same number of digits. It&rsquo;s easier to read a list of them if they all line up. This looks a little bit like I sneezed while typing but I&rsquo;ll explain it once we&rsquo;ve run it:</p><blockquote><p>1..100 | %{ &ldquo;{0:000}&rdquo; -f $_ }</p></blockquote><ol><li>We know that the range generates all the numbers between 1 and 100.</li><li>We know that the PIPE character passes data from the left to the right.</li><li>We recognize that there is some sort of string in there "" and some CURLY BRACES {}</li></ol><p>We&rsquo;ll start with the curly braces. Anything inside a set of curly braces is a set of commands that get run and solved once we get to them. A very common structure you&rsquo;ll see frequently in scripts we get from online is this bit |%{}</p><p>| passes information across. Specifically, it passes objects. Those objects can be as simple as the number we&rsquo;re generating here, or as complicated as objects containing multiple properties and methods.</p><p>{} contains a set of commands, we just learned this.</p><p>% is a shorthand for a command called&hellip;</p><p><strong>FOREACH</strong></p><p>I just heard the dramatic hamster soundtrack in my head when I typed that. I need a hobby. The foreach command takes a set of 0 or more objects and runs the contents of the paired curly braces once for each of the objects being passed to it. In our case, we&rsquo;re passing it a bunch of numbers, one per object. Within the foreach structure, I&rsquo;d like to draw your attention to the $_ but. That is a shorthand for $PSItem, which is the current object coming across the PIPELINE. We can verify this thusly:</p><blockquote/><p>`# Shorthand
&ldquo;Ferdinand&rdquo; | % { Write-Output $_ }</p><h1 id="full-commands-i-prefer-these-for-readability" class="ps-heading">Full commands, I prefer these for readability<a class="ps-heading-anchor" href="#full-commands-i-prefer-these-for-readability" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>&ldquo;Imelda&rdquo; | Foreach { Write-Output $PSItem }</p><h1 id="passing-an-array-across" class="ps-heading">Passing an array across<a class="ps-heading-anchor" href="#passing-an-array-across" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>@(&ldquo;Ferdinand&rdquo;, &ldquo;Imelda&rdquo;) | Foreach { Write-Output $PSItem }
`All that&rsquo;s left is to PARSE (figure out) the &ldquo;{0:000}&rdquo; -f $_ part. It&rsquo;s a special structure that allows us to format strings. We now know that the $_ is the object coming across the pipeline&hellip; in our case, a number; let&rsquo;s say 42. The -f is called a format operator, the bits inside the string are the PLACEHOLDERS. To show you how they work, we&rsquo;ll do a simple demonstration.</p><blockquote/><p><code>"First {0}, Second {1}" -f "thing", "one"</code>You&rsquo;ll note that the stuff on the right is like an array with a part 0 and a part 1. Indices are difficult to talk about outside the code. I blame the binary numbering system for this problem. So &ldquo;thing&rdquo; is the zeroth item and &ldquo;one&rdquo; is the oneth item on the right side of the -f operator. They are represented by their index number in curly braces on the left, inside the string.</p><p>Now, as we look back at our initial piece of code we&rsquo;re working through, we&rsquo;ve got &ldquo;{0:000}&rdquo;. The 0 to the left of the : is our index. we know that the $PSItem is in our zeroth item in our single item array to the right of the -f operator, so that should show up there. To the right of the : we can only assume is the part that adds the zeroes to our number, making it 042, and we&rsquo;d be correct.</p><p>This is amazingly powerful for information display allowing left and right alignment, hexadecimal conversion, currency, number percision, etc. In our case, it&rsquo;s just setting aside digits that will be filled in with our 42. We could also use {0:D3} to do the same thing, I just like the {0:000} because it&rsquo;s a little easier to look at and tell what it&rsquo;s doing. To write that whole thing out without the short hand:</p><blockquote/><p><code>1..100 | Foreach { "{0:000}" -f $PSItem }</code>Here&rsquo;s a list of different formatting you can use with the -f operator:<a href="http://ss64.com/ps/syntax-f-operator.html">http://ss64.com/ps/syntax-f-operator.html</a></p><p>So, lets get back to naming our servers:</p><blockquote/><p><code>1..100 | foreach { "server-{0:000}" -f $PSItem }</code>I have another way to do this same type of thing. Instead of sending it things, this one generates them based on whatever you tell it to do. This structure exists in nearly every programming language out there. It is a little bit more programmer looking than the foreach loop.</p><p><strong>FOR</strong></p><p>We&rsquo;ll start by generating exactly the same thing as our last piece of code:</p><blockquote/><p><code>for ($i=1; $i -lt 101; $i++) { "server-{0:000}" -f $i }</code>Since it&rsquo;s more programmy, I&rsquo;m going to break it up into multiple lines. I&rsquo;m going to do this in a couple different ways to illustrate that it&rsquo;s really the same code, just formated differently. You can technically do this with most examples of code within curly braces {} or parentheses ():</p><blockquote/><p>`# More of a .NET / C# way of looking at this code</p><h1 id="one-thing-per-line" class="ps-heading">One thing per line<a class="ps-heading-anchor" href="#one-thing-per-line" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="blocks-open-and-close-on-their-own-line" class="ps-heading">Blocks open and close on their own line<a class="ps-heading-anchor" href="#blocks-open-and-close-on-their-own-line" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="lots-of-white-space" class="ps-heading">Lots of white space<a class="ps-heading-anchor" href="#lots-of-white-space" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>for
(
$i=1
$i -lt 101
$i++
)
{
&ldquo;server-{0:000}&rdquo; -f $i
}</p><h1 id="the-traditional-correct-powershell-way" class="ps-heading">The traditional &ldquo;correct&rdquo; Powershell way<a class="ps-heading-anchor" href="#the-traditional-correct-powershell-way" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="very-c-or-java-y" class="ps-heading">Very C++ or Java-y<a class="ps-heading-anchor" href="#very-c-or-java-y" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>for ($i=1; $i -lt 101; $i++)
{
&ldquo;server-{0:000}&rdquo; -f $i
}</p><h1 id="the-more-python-looking-way-if-youre-into-that" class="ps-heading">The more Python looking way, if you&rsquo;re into that<a class="ps-heading-anchor" href="#the-more-python-looking-way-if-youre-into-that" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="in-python-white-space-at-the-beginning-of-a-line-counts" class="ps-heading">In Python, White space at the beginning of a line counts<a class="ps-heading-anchor" href="#in-python-white-space-at-the-beginning-of-a-line-counts" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="the-curly-braces-wouldnt-even-be-necessary-there" class="ps-heading">The curly braces wouldn&rsquo;t even be necessary there<a class="ps-heading-anchor" href="#the-curly-braces-wouldnt-even-be-necessary-there" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>for ($i=1; $i -lt 101; $i++) {
&ldquo;server-{0:000}&rdquo; -f $i
}</p><h1 id="how-i-prefer-it" class="ps-heading">How I prefer it<a class="ps-heading-anchor" href="#how-i-prefer-it" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="--collapses-better-in-the-ise" class="ps-heading">- Collapses better in the ISE<a class="ps-heading-anchor" href="#--collapses-better-in-the-ise" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="--shows-me-the-block-start-and-finish-easier-when-nesting" class="ps-heading">- Shows me the block start and finish Easier when nesting<a class="ps-heading-anchor" href="#--shows-me-the-block-start-and-finish-easier-when-nesting" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="--has-the-brevity-of-the-python-without-the-open-ended-closing-bracket" class="ps-heading">- Has the brevity of the Python without the open ended closing bracket<a class="ps-heading-anchor" href="#--has-the-brevity-of-the-python-without-the-open-ended-closing-bracket" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>for ($i=1; $i -lt 101; $i++) {
&ldquo;server-{0:000}&rdquo; -f $i
}
`Use whatever makes the code easier for you to read. Feel free to reformat the scripts you download from others as well to make them easier for you to read. I use the latter format for the reasons I stated in the comments. Let&rsquo;s get back to the for statement:</p><blockquote/><p><code>for ($i=1; $i -lt 101; $i++) { "server-{0:000}" -f $i }</code>The command is FOR (initiate variable; condition; increment variable){code block}</p><p>We recognize the $i=1 We&rsquo;re setting the variable $i to the value 1 as a starting point. We can use the semi-colon ; to separate commands on the same line.</p><p>The second part is called an evaluation. The -lt stands for &ldquo;less than.&rdquo; So the middle statement reads: $i is less than 101. Our FOR LOOP will run as long as this is true (or as powershell sees it, $TRUE as opposed to $FALSE).</p><p>The third piece states what happens each time the loop comes back up to the top. In this case, we are incrementing our $i by 1. The ++ adds 1 to whatever integer based variable it&rsquo;s attached to. If we start at 0 instead of 1, we can loop through index numbers.</p><p>It&rsquo;s a little bit pointless as we can just pass through, but perhaps we want to loop through every other item in an array. We could do a $i=$i+2 for the third bit. Very useful on our search for the next prime number and that huge award! (2 is the only possible even prime)</p><p>I find the FOR loop a bit ugly for most of the processing I do. There are times it is exactly the thing needed, but I very much prefer having more control within the body of the loop. For this, I primarily use the WHILE loop instead.</p><p><strong>WHILE</strong></p><p>It is simple in concept, it loops WHILE the condition () is true (careful, this first example will loop forever - keep an eye on the stop button at the top of the editor):</p><blockquote/><p><code>While ( $TRUE ) { # Does a thing; Write-Output "Can't sleep" } While ( $FALSE ) { # Doesn't do a thing; Write-Output "Clowns will catch me" }</code>Let&rsquo;s talk TRUE and FALSE. There are special variables defined in almost every language for $TRUE and $FALSE. These are the two BOOLEAN conditions, the binary bread and butter of 1 and 0, so to speak. In fact, they are stored as a 1 and a 0 and can be used that way:</p><blockquote/><p><code>While ( 1 ) { # Does a thing; Write-Output "Can't Sleep" } While ( 0 ) { # Doesn't do a thing; Write-Output "Clowns will catch me" }</code>Let&rsquo;s talk BOOLEAN a little bit (get it&hellip; bit? Like a single 1/0 piece of storage in the computer? I slay me).</p><p>During the for loop discussion, we looked at the -lt operator, which I mentioned was a boolean operator. This one will take some explanation.</p><p>A boolean statement is any comparison that can be resolved to true or false. In our for loop, we had the statement $i -lt 101. As long as $i was less than 101, that statement resolved to $TRUE. As soon as it was equal (-eq) to 101, it was no longer less than it and therefore considered $FALSE. As seen in the simple statements above, $FALSE in the condition () part of the while loop &ldquo;# Doesn&rsquo;t do a thing.&rdquo; If we replace the $TRUE/$FALSE with a CONDITIONAL STATEMENT, we can build that same FOR loop using a WHILE loop.</p><blockquote/><p><code>$i = 1 While ( $i -lt 101 ) { "server-{0:000}" -f $i $i++ }</code>We&rsquo;ve got a bunch of different boolean operators we can use against numbers:</p><blockquote/><p><code>-eq Equal To -lt Less Than -le Less Than or Equal To -gt Greater Than -ge Greater Than or Equal To</code>A few for strings:</p><blockquote/><p><code>-like This takes wildcards: "server-1*" -notlike same as above, but excludes instead of includes</code>EXTRA CREDIT! There are a few more that will evaluate multiple boolean statements as well:</p><p>-and (both true)</p><blockquote/><p><code>$true -and $false = $false $true -and $true = $true $false -and $true = $false $false -and $false = $false</code>-or (at least one true)</p><blockquote/><p><code>$true -or $false = $true $true -or $true = $true $false -or $true = $false $false -or $false = $false</code>-xor (one true, not both)<br>
(&ldquo;exclusive or&rdquo;, not the bad guy from a low budget 80s sci-fi movie)</p><blockquote/><p><code>$true -xor $false = $true $true -xor $true = $false $false -xor $true = $true $false -xor $false = $false</code>-not (you&rsquo;re so negative, also known as !)</p><blockquote/><p><code>-not $false = $true !$false = $true -not $true = $false !$true = $false</code># Returns $TRUE when $i is 50 to 100
($i -gt 49) -and ($i -lt 101)</p><h1 id="makes-more-sense-as" class="ps-heading">Makes more sense as<a class="ps-heading-anchor" href="#makes-more-sense-as" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>($i -ge 50) -and ($i -le 100)
`You&rsquo;ll note the () I&rsquo;ve used. These are used in this case to indicate order of operations. The parentheticals are solved first. This turns them into a $TRUE or a $FALSE. Then those results are compared with the boolean operator. You can make these quite complex. Imagine you need to find all servers that have more than 8GB installed and smaller than 250GB disk, but not the ones named SQL-xxx</p><blockquote/><p><code>( ( $server.memory -gt 8 ) -and ( $server.diskC -lt 250 ) ) -and ( $server.name -notlike "SQL-*" )</code>This will evaluate the memory and disk space part first, then evaluate the server name, then check them against each other. This is great if all we&rsquo;re ever doing is checking whether to stop a loop. What if we want to adjust our dynamic memory settings on a VM based on its memory and disk configurations? We&rsquo;d need to be able to do this test, then have the results drive a DECISION! Have you guessed next week&rsquo;s topic yet?</p><p>Next week, we learn DECISIONS. Or as I like to call it, how SKYNET begins.</p><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294979&amp;preview=true">Step 3: Input (Just you and me)</a> &lt;&ndash; Step 4: Loops(I can give you more) &ndash;&gt;<a href="https://powershell.org/?p=294983&amp;preview=true">Step 5: Decisions(The time has arrived)</a></p>
]]></content:encoded></item><item><title>Learn Powershell in 5 Painless Steps – Input (Console, File, Applications) – Step 3</title><link>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-input-console-file-applications-step-3/</link><guid>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-input-console-file-applications-step-3/</guid><pubDate>Thu, 28 Jul 2022 18:45:31 +0000</pubDate><description>&lt;p&gt;DevOps = Developers + Operations.  What if you&amp;rsquo;re in Operations and don&amp;rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, &lt;a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/"&gt;open sourced to the OSX and Linux communities&lt;/a&gt;.  It ships with a great minimalist development environment (Powershell ISE).&lt;/p&gt;
&lt;p&gt;The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&amp;rsquo;m hoping to enable you to automate your own workflows even if you&amp;rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<p>DevOps = Developers + Operations.  What if you&rsquo;re in Operations and don&rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, <a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/">open sourced to the OSX and Linux communities</a>.  It ships with a great minimalist development environment (Powershell ISE).</p><p>The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&rsquo;m hoping to enable you to automate your own workflows even if you&rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.</p><hr><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294977&amp;preview=true">Step 2: Output (So much we can do)</a> &lt;&ndash; Step 3: Input (Just you and me)  &ndash;&gt;<a href="https://powershell.org/?p=294981&amp;preview=true">Step 4: Loops(I can give you more)</a></p><hr><p>We&rsquo;ve spent the last few weeks laying down the ground work to be able to deal with the one main thing that we as developers have to shuttle around our applications&rsquo; data. We&rsquo;re now able to store them, explore them, and send them somewhere useful. We&rsquo;re going to hit the third piece of this today and begin getting our data from somewhere else. Once we&rsquo;re done today, all that&rsquo;s left is to figure out what to do with the data we&rsquo;re collecting, storing, and distributing.</p><p>This one digs in a little bit deeper yet. After today, you get to get your programmer&rsquo;s card&hellip; that&rsquo;s not actually a thing. Sorry if I got you excited, perhaps you can make your own card. I&rsquo;d take one if you do.</p><p><strong>CONSOLE</strong></p><p>We&rsquo;re starting in the same place we always do, in our console. Do you still have it open or are you a console closing type of person? If you closed it, go ahead and open up the Powershell ISE again. We&rsquo;re going to start up top in the editor this time. Last time, we learned the &ldquo;correct&rdquo; way to write information out to the console:</p><blockquote/><p><code>$someVariable = "another string" WRITE-HOST "String to display on the screen" WRITE-HOST $someVariable WRITE-HOST "Another string and $someVariable"</code>Now, we&rsquo;ve got to figure out how to allow the user give us information. If we can trust that Microsoft is using logical naming for their CMDLETS, it should be about reading and writing information. Since output is WRITE-HOST, the input should be READ-HOST. If we start typing it, INTELLISENSE will start to show us possible things we want to enter as pop-up suggestions as we go. It shows me that they did indeed make the command READ-HOST.</p><p>We&rsquo;re going to go ahead and write a real live useful program that does a thing. It&rsquo;s not a particularly useful thing, but it will hit all 3 points: Input, Store, and Output. So that we&rsquo;re using the process of breaking down the task to smaller points, I&rsquo;m going to start with PSEUDO-CODE (It&rsquo;s just a step by step description of the task):</p><blockquote/><p>`# Ask the user for their name</p><h1 id="display-their-name-in-a-sentence" class="ps-heading">Display their name in a sentence<a class="ps-heading-anchor" href="#display-their-name-in-a-sentence" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>`Sounds pretty simple, but this could be anything we&rsquo;d want to store, like client information for recalling during a sales call; &ldquo;How&rsquo;s the kids? Bobby and Fran</p><blockquote/><p>`# Ask the user for their name
$firstName = Read-Host &ldquo;Enter your first name:&rdquo;
$lastName = Read-Host &ldquo;Enter your last name:&rdquo;</p><h1 id="display-their-name-in-a-sentence-1" class="ps-heading">Display their name in a sentence<a class="ps-heading-anchor" href="#display-their-name-in-a-sentence-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Write-Host &ldquo;Your full name is $firstName $lastName&rdquo;
Write-Host &ldquo;Your last,first is $lastName, $firstName&rdquo;
`Look! We made a thing. It does something almost useful. We should be able to store this type of information in an object as well once we collect it:</p><blockquote/><p><code>$userInfo = @{"first" = $firstName; "last" = $lastName}</code>This let&rsquo;s us store larger pieces of information so we can access it using our dot notation (we must use an AD-HOC STRING $() to make it solve before showing it to the string):</p><blockquote/><p><code>Write-Host "L,F is $($userInfo.last), $($userInfo.first)"</code>We could have the user&rsquo;s age, significant other&rsquo;s first name, last name, age, assigned server name, start date, last login date, etc. Store these in an array and we can catalog an entire company. This programming thing is starting to show some promise. For the record, this is the fundamental idea behind DSC (Desired State Configuration). All the information for a server is bundled in an XML object and delivered as an XML file to a program that knows how to read that XML to build a server based on that description.</p><p><strong>FILE</strong></p><p>Speaking of reading from files, wouldn&rsquo;t it be great if we could do that? Imagine being handed an excel file with systems and pertinent data in it that we want to process. We know we can export a CSV, we can also import one. Let&rsquo;s start with the most basic form of this. We want to get the content of a file. The command for that is &hellip; um &hellip; GET-CONTENT. They&rsquo;re smart, but I made no claims to their creativity in naming. The best thing about their naming conventions for the cmdlets is that we can start to see the pattern they&rsquo;re using and start to guess at the kind of command we want to use and allow Intellisense to guide our exploration. Let&rsquo;s try reading a file. Hop down to the console and try this:</p><blockquote/><p><code>get-content ~\Desktop\servers.csv</code>This should read the contents of the file we exported in the last lesson and write it directly to the console. Useless Cole! No, I retort. We can store that in a variable and manipulate it as a variable, trapped in its temporary digital prison, our plaything; MUHAHAHAHA! Too Dramatic? You started it. Let&rsquo;s try this. You can either enter these directly into the console or add them to the editor and run the whole thing or the selection as you see fit:</p><blockquote/><p><code>$serverInfo = Get-Content ~\Desktop\servers.csv Write-Host $serverInfo</code>Looks about the same, but we can now do this as well:</p><blockquote/><p>`$serverInfo = $serverInfo | ConvertFrom-Csv
Write-Host $serverInfo</p><h1 id="we-even-have-access-to-it-as-an-array-now" class="ps-heading">We even have access to it as an array now<a class="ps-heading-anchor" href="#we-even-have-access-to-it-as-an-array-now" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Write-Host $serverInfo[1]
`Now that&rsquo;s different. We assigned the variable to itself after sending it through CONVERTFROM-CSV. Remember from the first lesson when I mentioned it does all the stuff on the right of the = and stuffs that into the stuff on the left? This allows us to change the content of a variable on the fly. We were technically doing that to our $serverInfo_obj using the += OPERATOR. These two examples do the same thing:</p><blockquote/><p>`# Add the object for server02 into the array using +=
$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server01&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;27Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;76%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;10Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}
)</p><h1 id="add-the-object-for-server02-into-the-array" class="ps-heading">Add the object for server02 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server02-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj = $serverInfo_obj + @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server01&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;27Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;76%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;10Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}
)
`This method of adding items to an array or object is actually really slow. You won&rsquo;t notice it in these examples, but if you are dealing with thousands of items being added over and over again, each time you add a piece, it gets longer. So each time we want to add to the end of it, it gets to count the contents to find the end. This can really add up after a bit. There are much more efficient ways to do some of these exercises.</p><p>Know that, then put it out of your head, understanding that if you get to the point where that matters, the information about those methods are out there, and we&rsquo;re learning here. This method illustrates my points best. It is also a more approachable way to make quick and functional scripts for those of you who haven&rsquo;t ever programmed before and are being thrust kicking and screaming into this new and automated version of the future.<br>
*** (Shout out to user toregroneng on reddit for pointing out that I&rsquo;m not specifically using &ldquo;correct&rdquo; powershell style and practices)</p><p>All that said, we&rsquo;re starting to tie it all together. Let&rsquo;s see if there&rsquo;s a more efficient way to do the last CSV example.</p><blockquote/><p><code>$serverInfo = Get-Content ~\Desktop\servers.csv | ConvertFrom-Csv Write-Host $serverInfo[1]</code>Sweet, we made it a single line thing. If they built in a function for converting a CSV file into an object, I bet they added one for importing directly from a CSV file. Since we had EXPORT-CSV before, let&rsquo;s just go wild and try replacing EXPORT with IMPORT! Crazy programmers. Perhaps we can streamline it even more:</p><blockquote/><p><code>$serverInfo = Import-csv ~\Desktop\servers.csv Write-Host $serverInfo[1]</code>Look at that. These cmdlets don&rsquo;t yet exist for XML, HTML, and JSON, so we&rsquo;ll still have to convert those formats. Here&rsquo;s how that works:</p><blockquote/><p>`# First, we&rsquo;ll take our $serverInfo object and</p><h1 id="turn-it-into-an-json-file-using-the-cmdlets-were-familiar-with" class="ps-heading">turn it into an JSON file using the cmdlets we&rsquo;re familiar with<a class="ps-heading-anchor" href="#turn-it-into-an-json-file-using-the-cmdlets-were-familiar-with" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Get-Content ~\Desktop\server.csv | ConvertTo-Json | out-file ~\Desktop\servers.json</p><h1 id="then-read-it-back-in-as-the-point-of-our-exercise-here" class="ps-heading">Then read it back in as the point of our exercise here<a class="ps-heading-anchor" href="#then-read-it-back-in-as-the-point-of-our-exercise-here" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$JSON_obj = Get-Content ~\Desktop\servers.json | ConvertFrom-Json</p><h1 id="prove-to-ourselves-that-it-did-something-useful" class="ps-heading">Prove to ourselves that it did something useful<a class="ps-heading-anchor" href="#prove-to-ourselves-that-it-did-something-useful" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Write-Host $JSON_obj.name
`That first bit is a really common type of Powershell task structure. We&rsquo;re reading in a file, converting it from one format to another and then saving it out to a file. The task itself doesn&rsquo;t matter. The workflow and way of thinking of passing one thing into the next is a very common way of working that makes this an amazingly useful tool to learn, even if you don&rsquo;t use it as a programming platform.</p><p>Now, in our promise of automating absolutely everything so we never have to do anything again (we won&rsquo;t tell anyone that part), let&rsquo;s figure out how to ask VMM for some information. Even if your goal is just to never have to open extra applications on your server other than your Powershell ISE, this is the first step on that quest.</p><p><strong>APPLICATION</strong></p><p>In the last lesson, we imagined a story of darkness and woe whereby our hero (an anonymous everyman IT technician) was cornered by the opposing forces (Sales) and forced to do manual data entry under threat of eternal flogging and being forced to listen to zydeco standards as sung by a group of cats and dogs. Having actually had that job for a little while, our hero decided that s/he would never again perform those sorts of tasks for anyone, ever again. What did s/he do? Powershell. Powershell is always the answer. At least in a Powershell focused blog, it&rsquo;s a strong bet if you&rsquo;ve stopped paying attention and are asked a question.</p><p>We can assume that nearly everything an application displays in its interface is stored somewhere behind the scenes that we can get to. Many applications allow us to hook into them. Some by exposing their .NET guts like a tauntaun in winter, others through a package of cmdlets called a MODULE. Your installed modules are listed in the pulldown menu on the right side pane of the ISE interface. I tend to keep mine closed as I like to have as much blue space on the screen as possible without actually having a blue screen. Under the Module &ldquo;Storage&rdquo; I find the command get-volume.</p><p>Let&rsquo;s ask Windows for something&hellip; Like those bits from our $serverInfo_obj from the output lesson:</p><blockquote/><p><code>$driveCInfo = Get-Volume C</code>The output shows me the parts I am looking for, and other info as well.</p><p>$driveCInfo.Size would be great. As would SizeRemaining. They fit right into our existing object. If we pull up that code again, we can put in an object for our current host machine. In my case, it&rsquo;s a laptop.</p><blockquote/><p><code>$serverInfo_obj = $serverInfo_obj + @( new-object PSObject -Property @{ "name" = "server01"; "freeC" = $(Get-Volume C).SizeRemaining; "totalC" = $(Get-Volume C).Size; "CPU" = "76%"; "RAMUsed" = "10Gb"; "RAMTotal" = "16Gb" } )</code>This can be sped up slightly. Again, not that big a deal with one server, but with 1000 of them, we can cut our information grabs in half by assigning the results of Get-Volume to a variable first, then calling that instead of the cmdlet twice:</p><blockquote/><p>`# Query for our info
$volumeCInfo = Get-Volume C</p><h1 id="so-now-volumecinfosize-gets-the-size-for-us" class="ps-heading">So now $volumeCInfo.Size gets the size for us,<a class="ps-heading-anchor" href="#so-now-volumecinfosize-gets-the-size-for-us" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="but-its-not-in-gb-lets-math" class="ps-heading">but it&rsquo;s not in GB, let&rsquo;s math!<a class="ps-heading-anchor" href="#but-its-not-in-gb-lets-math" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$volumeCTotal = $volumeCInfo.size / 1GB
`1GB is a built in value that converts your Bytes to GB. But we&rsquo;d like to see it as a nice round number. Let&rsquo;s look at that. There&rsquo;s a bunch of math built into the system through .NET . I&rsquo;ll show it to you, then show you a cheat:</p><blockquote/><p>`# Using the math functions built into the system
$volumeCRoundedTotal1 = [system.math]::Round($volumeCInfo.Size / 1GB)
$volumeCRoundedRemaining1 = [system.math]::Round($volumeCInfo.SizeRemaining / 1GB)</p><h1 id="cheating-by-casting-it-into-integer" class="ps-heading">Cheating by casting it into integer<a class="ps-heading-anchor" href="#cheating-by-casting-it-into-integer" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>[int]$volumeCRoundedTotal2 = $volumeCInfo.Size / 1GB
[int]$volumeCRoundedRemaining2 = $volumeCInfo.SizeRemaining / 1GB</p><h1 id="add-it-to-the-object" class="ps-heading">Add it to the Object<a class="ps-heading-anchor" href="#add-it-to-the-object" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server01&rdquo;;
&ldquo;freeC&rdquo; = $$volumeCRoundedRemaining2;
&ldquo;totalC&rdquo; = $volumeCRoundedTotal2;
&ldquo;CPU&rdquo; = &ldquo;76%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;10Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}
)
`We can get ram using the WMI system built into windows. This returns the total ram in bytes.</p><blockquote/><p>`# Total
$(Get-WMIObject win32_PhysicalMemoryArray).MaxCapacity</p><h1 id="used" class="ps-heading">Used<a class="ps-heading-anchor" href="#used" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$(Get-WmiObject win32_OperatingSystem).freephysicalmemory</p><h1 id="computer-name" class="ps-heading">computer name<a class="ps-heading-anchor" href="#computer-name" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$(Get-WmiObject win32_OperatingSystem).csname</p><h1 id="cpu-usage" class="ps-heading">CPU Usage.<a class="ps-heading-anchor" href="#cpu-usage" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="this-we-have-to-force-to-calculate-using-measure-object" class="ps-heading">This we have to force to calculate using Measure-Object<a class="ps-heading-anchor" href="#this-we-have-to-force-to-calculate-using-measure-object" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Get-WmiObject win32_processor | Measure-Object -Property LoadPercentage -Average | select-object Average
`Like with sun screen, it is time to apply. Take a little bit of time to rewrite the rest of the object for the server with these new little chunks of code. If you need pieces of information from your systems, Google will find even more of the CLASSES of information you can grab using Get-WMIObject. I searched for these using:</p><blockquote/><p><code>Get-WMIObject class powershell</code>Go ahead and send that out to a CSV so that you can import it anywhere you&rsquo;d like. You can either use the | ConvertTo-CSV | Out-File combination, or the | Export-CSV technique.</p><p>Our business does quite a bit of work with PowerBI. Most of my reports that aren&rsquo;t for my own personal use, which end up as just text or in an excel table, get turned into dashboards for analyzing our clients&rsquo; environments to make them run more efficiently and allow stronger optimization based on actual use rather than &ldquo;one size fits all&rdquo; standards.</p><p>If you choose to get farther into this sort of thing, you&rsquo;ll start to notice that the older Visual Basic classes and the .NET classes are available to us using that ugly [class.name]::method(data) format.</p><p>For the purposes of this tutorial, I&rsquo;m only grabbing information that everyone has access to. The best thing about this technique is that we can grab information from any application that has cmdlets available to us. All of System Center grants us access. I happen to be a SCOM admin, so I use the information made available to me from Operations Manager for many of the tasks I need to complete.</p><p>To get to System Center Virtual Machine Manager, we&rsquo;ll need to get the cmdlets loaded by importing the module. Can you guess the cmdlet name for that?</p><blockquote/><p><code>import-module virtualmachinemanager</code>If this doesn&rsquo;t work on your computer you&rsquo;re using to learn powershell, you&rsquo;ll have to have either install the VMM Console, or be running the scripts from the VMM server.</p><p>What we&rsquo;re going to start running into is a matter of volume. Entering information about three servers by hand is a little bit annoying, but not too bad. Let&rsquo;s do that for 500 machines. How about 1000. Now we&rsquo;re talking some pretty serious RSI. The thought of it is enough to drive someone loopy. We should do that next. LOOPS. That will save us quite a bit of typing.  That should be a blog someone writes&hellip;</p><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294977&amp;preview=true">Step 2: Output (So much we can do)</a> &lt;&ndash; Step 3: Input (Just you and me)  &ndash;&gt;<a href="https://powershell.org/?p=294981&amp;preview=true">Step 4: Loops(I can give you more)</a></p>
]]></content:encoded></item><item><title>Learn Powershell in 5 Painless Steps – Output (Console, File, XML/CSV) – Step 2</title><link>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-output-console-file-xml-csv-step-2/</link><guid>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-output-console-file-xml-csv-step-2/</guid><pubDate>Thu, 28 Jul 2022 18:45:18 +0000</pubDate><description>&lt;p&gt;DevOps = Developers + Operations.  What if you&amp;rsquo;re in Operations and don&amp;rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, &lt;a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/"&gt;open sourced to the OSX and Linux communities&lt;/a&gt;.  It ships with a great minimalist development environment (Powershell ISE).&lt;/p&gt;
&lt;p&gt;The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&amp;rsquo;m hoping to enable you to automate your own workflows even if you&amp;rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<p>DevOps = Developers + Operations.  What if you&rsquo;re in Operations and don&rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, <a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/">open sourced to the OSX and Linux communities</a>.  It ships with a great minimalist development environment (Powershell ISE).</p><p>The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&rsquo;m hoping to enable you to automate your own workflows even if you&rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.</p><hr><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294975&amp;preview=true">Step 1: Storage (Lots of fun)</a> &lt;&ndash; Step 2: Output (So much we can do) &ndash;&gt;<a href="https://powershell.org/?p=294979&amp;preview=true"> Step 3: Input (Just you and me)</a></p><hr><p>This week it&rsquo;s all about OUTPUT. We&rsquo;ll be covering ways to use the stored data to get information to either the User (the most important part of the GUI) or to another part of our script for further processing. I do have a confession to make. I&rsquo;ve already tricked you into starting this lesson last week. If you haven&rsquo;t closed your ISE window yet, the next bit will show you exactly how to get information about our server objects we stored in the $serverInfo_obj array. If you did close it (I forgive you, it has been a week), open it back up and run the last chunk of code we wrote. It&rsquo;s the Object part from our last lesson. Any variable you put information into will be available in the console until you close the application.</p><p>Playing around with Variables is all well and good, although it would be better if we could do something useful with the values in there. I assume you&rsquo;re reading this because you want to do something with Powershell, not just learn Powershell for it&rsquo;s own sake. While writing scripts, we often find ourselves exploring objects that we didn&rsquo;t create in the console exactly the same way we were in the last exercise.</p><p><strong>CONSOLE</strong></p><p>If you recall from the previous lesson on Storage, the editor is the top part of our PowerShell ISE application and the console is the bottom part of the window.</p><p>Try typing this into the console followed by the enter key to EXECUTE this command:</p><blockquote/><p><code>$serverInfo_obj[0] | Get-Member</code>The VERTICAL PIPE character ( | ) takes the objects from the part to the left and hands them off to the part to the right. The process is called, simply enough, PIPING. I always envisioned it as a set of saloon doors from a western, though. In this case, we&rsquo;re sending our objects we created for our first server ( [0] ) across the pipe into GET-MEMBER. Get-Member is a function from Microsoft that shows you all of the elements of an object. We made a few PROPERTIES last time and you probably recognize them (name, totalRAM, etc&hellip;). It even tells you whether they&rsquo;re String or Int or some other data type.</p><p>When we&rsquo;re grabbing information from servers or software, it usually comes to us as an object. You will see other MEMBERS listed in those objects. Most specifically METHODS, which are little programs within the object itself but are a topic for another day. We used piping last week to send our object into a Format-Table with the autosize flag activated. In doing that task, I already had you output to the Console.</p><p>Let&rsquo;s imagine a scenario where we would use this. A client is coming to visit and the Powerpoint your marketing team is going to present gets that last minute slide added that needs information about a few of your servers. Name, number of cores, Installed RAM, Size of C: and D: &hellip; sound familiar? We can ask VMM or the servers themselves for all of that information. We&rsquo;ll cover some of that in our next lesson on input. Right now, we&rsquo;ve got a deadline to meet, the clients just pulled into the parking ramp. Boy, Cole (you might say), this sounds very specific &hellip; it may or may not have happened just the other day. Here&rsquo;s the procedure I may or may not have followed for this:</p><blockquote/><p>`# Create an empty array</p><h1 id="add-the-object-for-server01-into-the-array" class="ps-heading">Add the object for server01 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server01-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="add-the-object-for-server02-into-the-array" class="ps-heading">Add the object for server02 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server02-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="add-the-object-for-server03-into-the-array" class="ps-heading">Add the object for server03 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server03-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="pipe-the-object-through-format-table" class="ps-heading">Pipe the object through Format-Table<a class="ps-heading-anchor" href="#pipe-the-object-through-format-table" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="select-the-output-from-the-console-using-the-mouse" class="ps-heading">Select the output from the console using the mouse<a class="ps-heading-anchor" href="#select-the-output-from-the-console-using-the-mouse" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="control-c-to-copy-to-the-clipboard" class="ps-heading">Control-C to copy to the clipboard<a class="ps-heading-anchor" href="#control-c-to-copy-to-the-clipboard" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="open-the-ppt-deck" class="ps-heading">Open the PPT Deck<a class="ps-heading-anchor" href="#open-the-ppt-deck" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="navigate-to-the-slide-in-question" class="ps-heading">Navigate to the slide in question<a class="ps-heading-anchor" href="#navigate-to-the-slide-in-question" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="control-v-to-paste-the-text-into-the-block-theyve-assigned" class="ps-heading">Control-V to paste the text into the block they&rsquo;ve assigned<a class="ps-heading-anchor" href="#control-v-to-paste-the-text-into-the-block-theyve-assigned" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="control-s-to-save-the-document" class="ps-heading">Control-S to save the document<a class="ps-heading-anchor" href="#control-s-to-save-the-document" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="control-q-to-close-the-document-and-the-application" class="ps-heading">Control-Q to close the document and the application<a class="ps-heading-anchor" href="#control-q-to-close-the-document-and-the-application" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="lift-phone-handset" class="ps-heading">Lift Phone Handset<a class="ps-heading-anchor" href="#lift-phone-handset" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="dial-sales-department" class="ps-heading">Dial Sales department<a class="ps-heading-anchor" href="#dial-sales-department" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="let-them-know-youve-single-handedly-saved-their-presentation" class="ps-heading">Let them know you&rsquo;ve single-handedly saved their presentation<a class="ps-heading-anchor" href="#let-them-know-youve-single-handedly-saved-their-presentation" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="grow-a-mullet-youre-a-rockstar" class="ps-heading">Grow a mullet, you&rsquo;re a rockstar.<a class="ps-heading-anchor" href="#grow-a-mullet-youre-a-rockstar" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>`That seems like I may have gotten carried away. I actually have a reason for that. It&rsquo;s the kind of detail we&rsquo;ll be using going forward to start our scripts. Now we just have to fill in the actual script parts. I recommend you go for a haircut, the mullet was a horrible idea, although it worked for MacGyver.</p><p>Let&rsquo;s start by adjusting our object that we&rsquo;ve already created. They need specific pieces of information for their presentation:</p><blockquote/><p>`# Create an empty array
$serverInfo_obj = @()</p><h1 id="add-the-object-for-server01-into-the-array-1" class="ps-heading">Add the object for server01 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server01-into-the-array-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server01&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;totalD&rdquo; = &ldquo;200Gb&rdquo;;
&ldquo;cores&rdquo; = &ldquo;2&rdquo;;
&ldquo;totalRAM&rdquo; = &ldquo;8Gb&rdquo;
}
)</p><h1 id="add-the-object-for-server02-into-the-array-1" class="ps-heading">Add the object for server02 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server02-into-the-array-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server02&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;totalD&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;cores&rdquo; = &ldquo;4&rdquo;;
&ldquo;totalRAM&rdquo; = &ldquo;16Gb&rdquo;
}
)</p><h1 id="add-the-object-for-server03-into-the-array-1" class="ps-heading">Add the object for server03 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server03-into-the-array-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><pre><code>$serverInfo_obj += @(
new-object PSObject -Property @{
"name" = "server03";
"totalC" = "50Gb";
"totalD" = "50Gb";
"cores" = "4";
"totalRAM" = "16Gb"
}</code></pre><p>)</p><h1 id="pipe-the-object-through-format-table-1" class="ps-heading">Pipe the object through Format-Table<a class="ps-heading-anchor" href="#pipe-the-object-through-format-table-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj | Format-Table
`The rest is on you&hellip;</p><blockquote/><p>`# Select the output from the console using the mouse</p><h1 id="control-c-to-copy-to-the-clipboard-1" class="ps-heading">Control-C to copy to the clipboard<a class="ps-heading-anchor" href="#control-c-to-copy-to-the-clipboard-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>`Wouldn&rsquo;t the smart programmer folks at Microsoft, in their infinite wisdom, have thought of this? Indeed they have, so let&rsquo;s change that last line:</p><blockquote/><p><code>$serverInfo_obj | Format-Table | clip</code>Here&rsquo;s what ended up on my clipboard:</p><blockquote/><p>`totalC totalD totalRAM name cores</p><hr><p>50Gb 200Gb 8Gb server01 2
50Gb 50Gb 16Gb server02 4
50Gb 50Gb 16Gb server03 4
`I&rsquo;m not happy with the order it chose for the properties. I&rsquo;m going to force its hand using the SELECT-OBJECT command and a comma separated list of the properties I want it to show:</p><blockquote/><p><code>$serverInfo_obj | Select-Object name, cores, totalRAM, totalC, totalD | Format-Table | clip</code>name cores totalRAM totalC totalD</p><hr><p>server01 2 8Gb 50Gb 200Gb
server02 4 16Gb 50Gb 50Gb
server03 4 16Gb 50Gb 50Gb
`That&rsquo;s better. Now off to PPT and pasting. I&rsquo;m going to give you a freebie here! Are you down with OGV? It&rsquo;s a short name for Out-GridView and it&rsquo;s awesome! Imagine that instead of 3 servers, you&rsquo;ve got 1000 and they are from different clients and the sales presentation is for a single client and you can&rsquo;t let them see the other client&rsquo;s information?</p><p>You can pipe through Out-GridView to make a selection interface that allows dynamic filtering, shift-selecting rows of information, ctrl-clicking individual rows. I use OGV all the time! There are actually quite a few shortcuts for common commands: Format-Table is ft, Format-List is fl, Get-Member is gm).</p><p>The Out-GridView command takes an option called passthru. These are indicated by a dash ( - ) and can either be flags (True/False) like this one is or take data directly after them to send it down the PIPELINE:</p><blockquote/><p><code>$serverInfo_obj | Select-Object name, cores, totalRAM, totalC, totalD | ogv -passthru | ft | clip</code>I&rsquo;ve sometimes found it difficult to get sales to let me adjust their slide decks. A better option would be to send them a file. That will allow them to do the copying and pasting how they like so they are in control of their presentation.</p><p><strong>FILES</strong></p><p>The nice thing about Powershell is that piping from one small single purpose command to the next allows you to just change one piece to change part of your script. In this case, we can replace the clip command and change it to write to a file:</p><blockquote/><p><code>$serverInfo_obj | Format-Table | Out-File C:\Users\cole.mcdonald\Desktop\test.txt</code>This places a text file with that little table on my desktop so I can attach it to an e-mail. This file can go anywhere you have access to. If you need to write out to a folder that requires admin access, you can run Powershell ISE just like any other program: Right-Click and Run as Administrator.</p><p>!!!Caution. This is the one time I&rsquo;ll be serious during this entire series&hellip; you can wipe out your whole environment if you&rsquo;re not careful with elevating the ISE. Use it only if you absolutely must. Use it only for the task you need it for. Triple check your code!!!</p><p>For our next example, we&rsquo;re going to use a special kind of string. We know it&rsquo;s got quotes&hellip; but we want to keep line formating intact as well. This calls for a stringwich @""@. We can open the stringwich (splat-quote) anywhere we&rsquo;d like on the line, but the closing pair (quote-splat) has to be on its own line. Imagine that we&rsquo;re making a little bit of HTML to format that table we just made. The cool thing about strings is that we can access any of our variables inside them.</p><p>If we&rsquo;re using objects and looking to get at specific information in them, it gets a little bit fancy. We just have to hide what we&rsquo;re doing from the string using an AD HOC VARIABLE. It&rsquo;s just a fancy way to say we&rsquo;re solving what&rsquo;s in the parentheses first. For that we use this: $(). The dollar sign because it&rsquo;s a variable, and the parentheses means we&rsquo;re doing this first.</p><p>Getting to the name of server01, for example, we use this $($serverInfo_obj[0].name). We recognize all of the pieces of this from our objects lesson last time. It&rsquo;s the name property of element 0 of our $serverInfo_obj array. We&rsquo;ve stuffed it into the $() to hide the [0].name part from the string. Otherwise, it just treats it as the next few characters in the string. That&rsquo;s no good. Let&rsquo;s see what that looks like:</p><blockquote/><p>`$HTMLOutputFromTheObjectWeMadeEarlier = @"</p><pre><code> Server Configurations
name
cores
totalRAM
totalC
totalD
$($serverInfo_obj[0].name)
$($serverInfo_obj[0].cores)
$($serverInfo_obj[0].totalRAM)
$($serverInfo_obj[0].totalC)
$($serverInfo_obj[0].totalD)
$($serverInfo_obj[1].name)
$($serverInfo_obj[1].cores)
$($serverInfo_obj[1].totalRAM)
$($serverInfo_obj[1].totalC)
$($serverInfo_obj[1].totalD)
$($serverInfo_obj[2].name)
$($serverInfo_obj[2].cores)
$($serverInfo_obj[2].totalRAM)
$($serverInfo_obj[2].totalC)
$($serverInfo_obj[2].totalD)</code></pre><p>&ldquo;@
`Go ahead and look at that variable in the console. Should we be snooty about it and do it the &ldquo;proper&rdquo; powershell way?</p><blockquote/><p>`# This variable name is horrible, feel free to fix it by using</p><h1 id="a-better-one-when-you-enter-and-run-the-code-in-the-editor" class="ps-heading">a better one when you enter and run the code in the editor<a class="ps-heading-anchor" href="#a-better-one-when-you-enter-and-run-the-code-in-the-editor" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="write-host-outputs-strings-to-the-console" class="ps-heading">Write-Host outputs strings to the console<a class="ps-heading-anchor" href="#write-host-outputs-strings-to-the-console" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>Write-Host $HTMLOutputFromTheObjectWeMadeEarlier
`Note that all of the lines are separated and all of the tabs remain! If you&rsquo;d like to see the difference, try it without the @ @ (that&rsquo;s a Star Wars PUNctuation). I&rsquo;ve had inconsistent results keeping spacing without them. If the HTML code confuses you, feel free to just use the elements from our object array and build your own output, perhaps you can turn it into a comma separated text file (CSV). That would actually be really slick as it&rsquo;ll open directly in Excel or even insert as a table into the PPT deck. If only those super smart programmers at Microsoft had thought of that! Someone&rsquo;s talking to me in the background, hold on&hellip;</p><p><strong>XML/CSV/HTML</strong></p><p>So, I&rsquo;m back. I&rsquo;ve been told Microsoft&rsquo;s programmers did think of that. I was all geared up to get you writing some fancy chunk of code called a FUNCTION to turn objects into CSV files to export to files&hellip; not at all necessary. Apparently, that will have to be a later blog as well. Apparently, or so I&rsquo;m told, all we have to do is send it through another little command. Technically, in Powershell, these are called CMDLETS: pronounced command-lets. Powershell is still new enough they could afford full-blown commands. They are supposed to follow a specific format as well called verb-noun.</p><p>In the cases we&rsquo;ve seen so far, we&rsquo;ve used the verbs Get, Write, Format, and New. There are also Set (the dangerous one), Export, Read (which will be covered next week), and a few more. The nice thing about the ISE is that if you start typing a cmdlet, it&rsquo;ll suggest other ones for you. Microsoft calls this INTELLISENSE and it&rsquo;s a great way to explore what&rsquo;s available in the language. The right hand pane of the ISE window also contains a huge list of them and that&rsquo;s searchable as well. Explore there to find what all is available. You can even use Get-Help to find out more info about them:</p><blockquote/><p><code>Get-Help Write-Host -showwindow</code>This will make you a little window with information and examples for the command. If this didn&rsquo;t work, you may need to run the cmdlet Update-Help the first time out to get it to download all the help files to your computer. Let&rsquo;s look at our CSV option using this technique:</p><blockquote/><p><code>get-help convertto-csv -ShowWindow</code>This gives you a window that allows you to really dig into more information about the cmdlets. Let&rsquo;s try that using our out-file example and add the ability to select the elements to pass through using our GridView:</p><blockquote/><p><code>$serverInfo_obj | ogv -passthru | ConvertTo-CSV | Out-File ~\Desktop\servers.csv</code>The ~ character is brought over from the Linux world and refers to your current user directory. It makes it easier to get to your documents/desktop/downloads directories, etc. This can also take UNC paths to get to network resources.</p><p>So this example takes our objects, pipes them into OGV for us to select the ones to pass through to the conversion and then to the outfile command. The resulting file can now be double-click opened into Excel, inserted as a table in PPT, whatever you could normally do with this type of data&hellip; even stuffed into PowerBI or R for big data analysis. That previous HTML example can be done with a ConvertTo-HTML which I saw while I was looking up the CSV command earlier. Did you notice it too? It also does XML and JSON for using across the web or to build DSC files. Yes, Virginia, we can build DSC files from scratch using Powershell allowing us to automate server buildouts modelled after a single instance. This build out could even be scripted to provision IP addresses from a database you&rsquo;re using to keep track of such things and make DNS changes to your environment so you don&rsquo;t have to. There&rsquo;s a whole bunch of built-in cmdlets for dealing with your Azure deployment and System Center if you have it installed. It also allows for DSC configuration of VMs through VMM with a little bit of fiddling.</p><p>Now, if only we could have the program we&rsquo;re writing ask us for information to store in scripts&hellip; maybe if we can figure out the cmdlet name. Writing to the Console is Write-Host. I wonder what Reading from it would be? You can either explore that or wait until next week when we look at INPUT. We&rsquo;ll cover a few more options as well. At the end of next week, you&rsquo;ll be able to gather information, store it in variables and output it in various ways. Sounds as if we&rsquo;ll have you doing useful things by the end of next week. After that groundwork has been laid, we&rsquo;ll dig into building SkyNet.</p><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p><a href="https://powershell.org/?p=294975&amp;preview=true">Step 1: Storage (Lots of fun)</a> &lt;&ndash; Step 2: Output (So much we can do) &ndash;&gt;<a href="https://powershell.org/?p=294979&amp;preview=true"> Step 3: Input (Just you and me)</a></p>
]]></content:encoded></item><item><title>Learn Powershell in 5 Painless Steps – Storage (Variables, Arrays, Hashtables) – Step 1</title><link>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-storage-variables-arrays-hashtables-step-1/</link><guid>https://powershell.org/articles/2022-07-28-learn-powershell-in-5-painless-steps-storage-variables-arrays-hashtables-step-1/</guid><pubDate>Thu, 28 Jul 2022 18:45:08 +0000</pubDate><description>&lt;p&gt;DevOps = Developers + Operations.  What if you&amp;rsquo;re in Operations and don&amp;rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, &lt;a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/"&gt;open sourced to the OSX and Linux communities&lt;/a&gt;.  It ships with a great minimalist development environment (Powershell ISE).&lt;/p&gt;
&lt;p&gt;The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&amp;rsquo;m hoping to enable you to automate your own workflows even if you&amp;rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<p>DevOps = Developers + Operations.  What if you&rsquo;re in Operations and don&rsquo;t have a developer at your disposal?  That should never stop you from making your job easier and more efficient.  Powershell is a scripting language from Microsoft that is already on your Windows PC and Servers and more recently, <a href="https://azure.microsoft.com/en-us/blog/powershell-is-open-sourced-and-is-available-on-linux/">open sourced to the OSX and Linux communities</a>.  It ships with a great minimalist development environment (Powershell ISE).</p><p>The problem I had is that all of the tutorials out there either assume a background in scripting and programming, or act as nothing more than command references.  I&rsquo;m hoping to enable you to automate your own workflows even if you&rsquo;ve never programmed before.  You only need to learn 5 things: Storage, Input, Output, Decisions, Loops.  Everything you do manually is made up of these 5 things.  Every programming language is made up of these 5 things.</p><hr><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><pre><code>Step 1: Storage (Lots of fun) --&gt; [Step 2: Output (So much we can do)](https://powershell.org/?p=294977&amp;preview=true)</code></pre><hr><p>This is a slightly longer one, but I cover a lot of ground work we&rsquo;ll need in the next few weeks.</p><p>For our first week, I&rsquo;m covering storing information in your script. Without storage, none of the rest of what we&rsquo;re going to learn makes sense. The most basic type of storage is the VARIABLE, a collection of information can be stored as separate pieces of an ARRAY, and accessing the information over and over again in a script is made easier using a HASHTABLE, the last piece of storage we&rsquo;ll cover is the OBJECT&hellip; which will serve you later if you choose to get deeper into scripting or programming.</p><p><strong>VARIABLES</strong></p><p>When we&rsquo;re scripting, we&rsquo;re going to be grabbing information from various places, making decisions based on that information, doing stuff with that informaiton, and delivering it to various places. We need somewhere to store that information. Let&rsquo;s do this!</p><blockquote/><p><code>$ourFirstVariable = "Stuff Inside the Variable"</code>There&hellip; you&rsquo;re a programmer. There may be a little bit more to it, but this fundamental building block provides the basis for all fo the rest. I&rsquo;ll explain what the parts mean, then we&rsquo;ll get started in Powershell ISE to make it happen and to prove that something actually happened.</p><p>In Powershell, anything that begins with a Dollar Sign ($) is a variable. After that, the developer gives it a name. This name can be just about anything with letters and numbers as long as it starts with a letter:</p><blockquote/><p><code>$x $x1 $myThing $cellContents_1 $ServerName $Server_Name</code>&hellip; you get the picture. As a matter of style, I use what is called &ldquo;Camel Case&rdquo; for my variables. I always start with a lowercase letter and each word after that in the variable name is capitalized.</p><p>If you see a $ in a script, some piece of information is being stored or recalled at that point in the script. The equals sign (=) is what we refer to as an &ldquo;assignment operator.&rdquo; Basically, whatever is on the right side of it gets solved and assigned to what ever is on the left side. In the first case, the sentence (technical name: STRING) &ldquo;Stuff Inside the Variable&rdquo; is being assigned into the variable $ourFirstVariable. I liken it to writing down the sentence on a piece of paper and putting it in an empty coffee cup. When you need it later, you can just reach into the cup and pull the slip of paper back out to read. In the case of variables, you can label them&hellip; of course, in the coffee cup example, my variable would be $WithEnoughCoffeeNothingIsImpossible and the contents would be &ldquo;C8H10N4O2&rdquo;</p><p>Speaking of Strings, there are some different types of information we should be aware of. As I mentioned, the STRING has quotes around it and is any combination of letters, numbers, and most symbols on the keyboard. The different types of information (or DATA TYPES) can be indicated using the square brackets on your keyboard: []. And you thought you&rsquo;d never use those keys&hellip; we&rsquo;ll get to the squiggly ones later. In our first example, we can tell the computer exactly what data type we&rsquo;re assigning to the variable.</p><blockquote/><p><code>$ourFirstVariable = [string]"Stuff Inside the Variable"</code>It&rsquo;s not terribly useful in this case because Powershell can see that you&rsquo;ve got quotes and a bunch of letters and stuff in side it. It assumes it&rsquo;s a string. What if you were storing a number? You can&rsquo;t really do math with a string, so assigning a number to our variable stays a number. There are a few different kinds, but we&rsquo;ll stick to integers for now.</p><blockquote/><p><code>$storingANumber = [int]2 $storingAString = [string]2</code>These store the number 2 differently. The first stores it as a straight integer, whereas the second stores it as a string with only the character &ldquo;2&rdquo; in it. Being particular like this isn&rsquo;t neccessary all the time, but can help solve problems if you run into them. Powershell is pretty good at guessing what you&rsquo;re trying to do. The second example is called CASTING an integer to a string or CASTING to a string.</p><p>Enough talk&hellip; let&rsquo;s get the software running and play with some variables for real! Launch Powershell ISE (My Menu bar is on the left of my screen for &hellip; reasons):</p><p><img src="https://powershell.org/wp-content/uploads/2022/07/blogImage01-300x177.png" alt="Powershell ISE in the Windows Menu"/><p>If you&rsquo;ve done any work in the command prompt before, this is basically the same thing. A bunch of the commands even work in here the same way they used to. One of the biggest differences you&rsquo;ll see is the top part looks a bit like a text editor&hellip; with numbers down the left hand margin. The top half is the EDITOR, the bottom half is the CONSOLE.</p><p><img src="https://powershell.org/wp-content/uploads/2022/07/blogImage02-300x218.png" alt=""/><p>The stuff done in the console happens right away, whereas the stuff in editor won&rsquo;t do anything until we &ldquo;Run&rdquo; it. For simplicity&rsquo;s sake, we&rsquo;re going to start in the console.</p><p>When you first open the ISE (Integrated Scripting Environment), it will show you a PS \ &gt; prompt in the console. The \ part will be the path where the console is currently operating. If we type DIR here and hit enter, it&rsquo;ll give us a directory listing of that directory. As in the old CMD.exe prompt, it&rsquo;ll use CD to change directories. Let&rsquo;s enter our variable assignment from above:</p><blockquote/><p><code>$ourFirstVariable = "Stuff Inside the Variable"</code>Hit enter. Nothing happens. How can we tell what happened? Let&rsquo;s ask the console what it has in that variable.</p><blockquote/><p><code>$ourFirstVariable</code>Hit enter. Now we&rsquo;ve got the contents of our variable on the very next line!</p><p>I have a confession to make. Like in the matrix - &ldquo;There is no string!&rdquo; A string is actually a different storage type called an ARRAY. Let&rsquo;s look at those.</p><p><strong>ARRAYS</strong></p><p>At some point the string / integer may not be enough for you. Underneath, the string is just a series of characters, one after the other S, t, u, f, f. There&rsquo;s a special way to store that type of informaiton that becomes extremely useful for us. Much like the junk drawer, we can put anything we want in there and access it right away. The way to get at individual pieces of data in an array is fairly simple. Square brackets and an integer. Since we&rsquo;re programmers now, we start cointing at zero. There&rsquo;s a real reason for it&hellip; just go with it for now. [0] is the first ELEMENT in the array. We access it using the variable name and the INDEX of the element we&rsquo;re trying to get to. Let&rsquo;s prove that my statement about strings was true. In the console:</p><blockquote/><p><code>$ourFirstVariable[0]</code>Hit enter. It should return an S on the next line. Try other indexes in there. Each of our letters in turn is there. To have some real fun, let&rsquo;s put a RANGE in there:</p><blockquote/><p><code>$ourFirstVariable[0..24]</code>Did you hit enter already? good. This should be our entire string with each element of it per line&hellip; including the spaces, which are just another character to the computer.</p><p>What if we wanted to store a different collectio of things in an array? Perhaps a parts list or a DVD list of titles from your collection. Defining a string we used the double-quote character &ldquo;. To define an array, we&rsquo;re going to use what I like to call a Splat sandwich - or a Splatwich @(). Each of the elements are separated by a comma.</p><blockquote/><p><code>$ourFirstArray = @("thing1", "thing2")</code>Now we can access them using [0]and [1] after the variable. I&rsquo;m going to let you try that on your own, it&rsquo;ll speed up the rest of the tutorials. You may also notice that I have 2 strings inside an array&hellip; and a string is an array&hellip; array-ception? You would be absolutely correct. A MULTIDIMENSIONAL ARRAY makes for a very powerful data structure. Imagine this problem we need to solve:</p><p>Problem - We need a report of all of the servers on our network, their C: freespace, total C: size, CPU%Usage, RAM Used, and RAM Total.</p><p>Solution is to ask AD for all of the servers, Ask System Center VMM for the configurations of the servers. If they&rsquo;re physicals, you can use wmi to get performance counters. Now we have to store all that information in an array to make our report. Let&rsquo;s look at that array structure.</p><blockquote/><p><code>$server1 = @("server01", "27Gb", "50Gb", "76%", "10Gb", "16Gb") $server2 = @("server02", "20Gb", "50Gb", "53%", "12Gb", "16Gb") $server3 = @("server03", "14Gb", "50Gb", "14%", "3Gb", "16Gb") $serverInfo = @($server1, $server2, $server3)</code>You can either enter each of these lines in the console or try typing them into the editor and hitting the Run button on the ribbon (F5). Back in the console, let&rsquo;s explore this structure.</p><p>$serverInfo[0][0] will get you the name of the first item in the array (Server01). $serverInfo[2][3] will get you the CPU% for Server03. Good storage, horrible way to access it. I wish there were a way to access it something like $serverInfo[0][&ldquo;CPU%&rdquo;]&hellip; luckily, we can. Stick with this, we&rsquo;re nearly done and I&rsquo;m going to start making it look more programmy. We&rsquo;re going to split the assignment onto multiple lines.</p><p><strong>HASHTABLES</strong></p><p>Looking at the splatwich, you&rsquo;ll note that it opens and closes with parentheses. Powershell will allow anything to happen inside those.</p><blockquote/><p><code>$serverInfo = $(     $server1,     $server2,     $server3 )</code>This will work and allows you to look at this information in blocks. How you break the lines is a matter of style. I&rsquo;ve learned quite a few languages, and this style works for me. It&rsquo;s not the only way. Use what works for you once you get to that point.</p><p>To make this easier to get to the information inside our variable, we&rsquo;re going to name each of the pieces. The name of it is the KEY. The information inside is the VALUE. They are referred to as a KEY/VALUE pair. That looks like this:</p><blockquote/><p><code>$server1 = @{   "name"    = "server01";   "freeC"    = "27Gb";   "totalC"   = "50Gb";   "CPU"      = "76%";   "RAMUsed" = "10Gb";     "RAMTotal" = "16Gb" }</code>So, you&rsquo;ll note we&rsquo;ve siwtched the square brackets [] to curly brackets {} (one of my coworkers refers to them jokingly as curly fries). You&rsquo;ll also notice the commas have changed to semi-colons. I don&rsquo;t know why, but that&rsquo;s how it works. If you put the other 2 server&rsquo;s information together and add them at the end to the $serverInfo, it looks like this:</p><blockquote/><p>`# This is a comment line, anything that starts with a # is ignored by Powershell</p><h1 id="we-can-use-them-to-talk-to-our-future-selves-as-we-often-have-to-come-back-to-code" class="ps-heading">We can use them to talk to our future selves as we often have to come back to code<a class="ps-heading-anchor" href="#we-can-use-them-to-talk-to-our-future-selves-as-we-often-have-to-come-back-to-code" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="most-of-the-time-weve-forgotten-everything-weve-written-and-what-its-for" class="ps-heading">Most of the time, we&rsquo;ve forgotten everything we&rsquo;ve written and what it&rsquo;s for&hellip;<a class="ps-heading-anchor" href="#most-of-the-time-weve-forgotten-everything-weve-written-and-what-its-for" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="gather-data-for-server01-store-in-variable" class="ps-heading">Gather data for server01, store in variable<a class="ps-heading-anchor" href="#gather-data-for-server01-store-in-variable" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$server1 = @{
&ldquo;name&rdquo; = &ldquo;server01&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;27Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;76%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;10Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}</p><h1 id="gather-data-for-server02-store-in-variable" class="ps-heading">Gather data for server02, store in variable<a class="ps-heading-anchor" href="#gather-data-for-server02-store-in-variable" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$server2 = @{
&ldquo;name&rdquo; = &ldquo;server02&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;20Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;53%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;12Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}</p><h1 id="gather-data-for-server03-store-in-variable" class="ps-heading">Gather data for server03, store in variable<a class="ps-heading-anchor" href="#gather-data-for-server03-store-in-variable" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$server3 = @{
&ldquo;name&rdquo; = &ldquo;server03&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;14Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;14%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;3Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}</p><h1 id="collect-server-information-into-an-array-for-later-reference" class="ps-heading">Collect server information into an array for later reference<a class="ps-heading-anchor" href="#collect-server-information-into-an-array-for-later-reference" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo = $(
$server1,
$server2,
$server3
)
`My initial Script actually only consisted of this:</p><blockquote/><p>`# Gather data for server01, store in variable</p><h1 id="gather-data-for-server02-store-in-variable-1" class="ps-heading">Gather data for server02, store in variable<a class="ps-heading-anchor" href="#gather-data-for-server02-store-in-variable-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="gather-data-for-server03-store-in-variable-1" class="ps-heading">Gather data for server03, store in variable<a class="ps-heading-anchor" href="#gather-data-for-server03-store-in-variable-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="collect-server-information-into-an-array-for-later-reference-1" class="ps-heading">Collect server information into an array for later reference<a class="ps-heading-anchor" href="#collect-server-information-into-an-array-for-later-reference-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>`I started here so I could talk through the process I&rsquo;d be completing, then write the code after each of the comments to flesh out the code. Now we&rsquo;ve got a real program looking thing. Let&rsquo;s look at the data we&rsquo;ve got in $serverInfo now.</p><p>$serverInfo[1][&ldquo;totalC&rdquo;] will show us our total C drive allocation for server02. This is now useful. We can also use &ldquo;DOT NOTATION&rdquo; to reference these named pieces.</p><p>$serverInfo[1].totalC will reference exactly the same piece of information. The editor now also has some cool things going on it it. You&rsquo;ll note each of the lines that start a block have a little square next to it. You can click this to collapse the block. This makes it so if you have longer scripts, you can have most of it collapsed and view just the portions you&rsquo;re working on. It aids in the readability of the code.</p><p><strong>OBJECTS</strong></p><p>The last one is very similar to what we just did, but is dealt with differently internally. We&rsquo;re going to make an OBJECT. It&rsquo;s going to look very similar to what we&rsquo;ve just done&hellip; but later when we&rsquo;re passing our information to and from other parts of code, Powershell is made to deal with &ldquo;objects&rdquo; in a more robust fashion than passing variables like we&rsquo;ve been making. They look like this:</p><blockquote/><p>`# Clear the array
$serverInfo_obj = @()</p><h1 id="im-adding-_obj-to-the-variable-name-just-to-remind-my-future-self-what-is-in-this-variable" class="ps-heading">I&rsquo;m adding _obj to the variable name just to remind my future self what is in this variable<a class="ps-heading-anchor" href="#im-adding-_obj-to-the-variable-name-just-to-remind-my-future-self-what-is-in-this-variable" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="i-can-see-here-that-its-an-array--of-objects-_obj" class="ps-heading">I can see here that it&rsquo;s an array @() of objects _obj<a class="ps-heading-anchor" href="#i-can-see-here-that-its-an-array--of-objects-_obj" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="you-can-choose-not-to-add-the-_obj-if-you-dont-like-the-looks-of-it" class="ps-heading">You can choose not to add the _obj if you don&rsquo;t like the looks of it<a class="ps-heading-anchor" href="#you-can-choose-not-to-add-the-_obj-if-you-dont-like-the-looks-of-it" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="add-the-object-for-server02-into-the-array" class="ps-heading">Add the object for server02 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server02-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><h1 id="the--adds-the-contents-of-the--below-the-new-psobject-object-to-the-end-of-the-existing-array" class="ps-heading">The += adds the contents of the @() below (the new &ldquo;psobject&rdquo; object) to the end of the existing array<a class="ps-heading-anchor" href="#the--adds-the-contents-of-the--below-the-new-psobject-object-to-the-end-of-the-existing-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server01&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;27Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;76%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;10Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}
)</p><h1 id="add-the-object-for-server02-into-the-array-1" class="ps-heading">Add the object for server02 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server02-into-the-array-1" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server02&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;20Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;53%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;12Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}
)</p><h1 id="add-the-object-for-server03-into-the-array" class="ps-heading">Add the object for server03 into the array<a class="ps-heading-anchor" href="#add-the-object-for-server03-into-the-array" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h1><p>$serverInfo_obj += @(
new-object PSObject -Property @{
&ldquo;name&rdquo; = &ldquo;server03&rdquo;;
&ldquo;freeC&rdquo; = &ldquo;14Gb&rdquo;;
&ldquo;totalC&rdquo; = &ldquo;50Gb&rdquo;;
&ldquo;CPU&rdquo; = &ldquo;14%&rdquo;;
&ldquo;RAMUsed&rdquo; = &ldquo;3Gb&rdquo;;
&ldquo;RAMTotal&rdquo; = &ldquo;16Gb&rdquo;
}
)
`To refer to these now, we can still use index and dot notation $serverInfo_obj[0].name but you&rsquo;ll note as you type it, the property &ldquo;name&rdquo; shows up in the popup list! We made Powershell know about our data. This lets us do cool things with it. For instance:</p><blockquote/><p><code>$serverInfo_obj | Format-Table -autosize</code>Looks really useful. whereas:</p><blockquote/><p><code>$serverInfo | Format-Table -autosize</code>does not. The | character passes objects through to the next command for processing. In this case, we&rsquo;re formatting a table for OUTPUT. Which is, coincidentally, next week&rsquo;s topic.</p><h6 id="" class="ps-heading"><a class="ps-heading-anchor" href="#" aria-label="Link to this section" title="Link to this section"><i class="fas fa-link" aria-hidden="true"/></a></h6><p>Step 1: Storage (Lots of fun) &ndash;&gt; <a href="https://powershell.org/?p=294977&amp;preview=true">Step 2: Output (So much we can do)</a></p>
]]></content:encoded></item><item><title>On to the Future with Powershell</title><link>https://powershell.org/articles/2022-07-28-on-to-the-future-with-powershell/</link><guid>https://powershell.org/articles/2022-07-28-on-to-the-future-with-powershell/</guid><pubDate>Thu, 28 Jul 2022 18:44:45 +0000</pubDate><description>&lt;p&gt;When I started my 5 Painless Steps Powershell learning series. It was a smashing success. I was hoping a few dozen people would find it useful. It was viewed by over 2500 people in the first month. Yikes!&lt;/p&gt;
&lt;p&gt;The point of the series was specifically to bring more Ops to devops. Learning to program can be daunting and takes a dedication of time. The thing to realize, in my opinion, is that the 5 steps I presented can be applied and learned in any language. Most of the commands are just slight variations from one to the other as well. For instance, some languages use elseif, others else if. There are 2 trains of thought for the for loop, the (init, test, increment) model Powershell uses and the for/next model ($x = 1 to 100) used in basic.&lt;/p&gt;</description><content:encoded>&lt;![CDATA[<p>When I started my 5 Painless Steps Powershell learning series. It was a smashing success. I was hoping a few dozen people would find it useful. It was viewed by over 2500 people in the first month. Yikes!</p><p>The point of the series was specifically to bring more Ops to devops. Learning to program can be daunting and takes a dedication of time. The thing to realize, in my opinion, is that the 5 steps I presented can be applied and learned in any language. Most of the commands are just slight variations from one to the other as well. For instance, some languages use elseif, others else if. There are 2 trains of thought for the for loop, the (init, test, increment) model Powershell uses and the for/next model ($x = 1 to 100) used in basic.</p><p>Once the language has been abstracted and is fundamentally interchangeable with any other language, it becomes a framework for shuttling and mutating data. The sources of the data are the exciting pieces to me. We have all kinds of monolithic repositories of environmental information for each of our businesses. Knowing how to program allows us to answer the needs we identify in our worlds. I call them the &ldquo;wouldn&rsquo;t it be nice if I had&hellip;&rdquo; solutions.</p><p><strong>Wouldn&rsquo;t it be nice</strong><strong>if</strong> I could adjust the amount of hard drive space allocated to a backup server in azure based on time of day to allow for the extra space needed for compression while reducing cost over all by lowering classification of the server once the archival is completed.</p><p><strong>Wouldn&rsquo;t it be nice</strong><strong>if</strong> I could analyze the resource usage over time to figure out when I need to add cores to a server during the day and scale it dynamically.</p><p><strong>Wouldn&rsquo;t it be nice</strong><strong>if</strong> my environment would auto document itself. None of the off the shelf software accounts for this one odd thing we do.</p><p><strong>Wouldn&rsquo;t it be nice if</strong> &hellip; fill in your need here.</p><p>This is DevOps. As operations technicians, server admins, and/or customer support persons, we have a head full of processes and environmental states that inform the decisions we make day to day. Knowing how to code allows us to build those decision trees using that same data we&rsquo;d look at from disparate silos of information. Having those decision trees can then be turned into actions based on the outcomes. Those actions can move us toward &ldquo;click here&rdquo; administration to an environment which can react to usage and need dynamically.</p><p>If we start using historical data, we can even enter the &ldquo;big data&rdquo; realm and let our code perform our RCA discovery tasks for us&hellip; potentially even auto remediating found cases in the future. This is where we move into the realm of machine learning. It&rsquo;s not a large leap either. I just got there in 2 paragraphs. All we need to do is remember the simple phrase: EVERYTHING IS POSSIBLE THROUGH CODE.</p><p>Any &ldquo;Wouldn&rsquo;t it be nice&rdquo; moments we have are answered by that phrase. When asked if you can make something happen, yes can always be the answer. It&rsquo;ll be tempered by the time and effort required but there&rsquo;s always a solution to whatever specific task you&rsquo;re being asked to explore.</p><p>I have 5 posts that I&rsquo;ll be making shortly that are the &ldquo;Powershell in 5 Painless Steps&rdquo; series.  I&rsquo;ll add the links at the bottom here as I get them converted to this blogging platform.  I wrote them while I was working at Beyond Impact 2.0, LLC.  I&rsquo;m now with another MSP, Netgain Technologies, Inc. and still use Powershell every single day to make my job easier and more effective.</p><p><a href="https://powershell.org/?p=294975&amp;preview=true">Step 1: Storage</a><br><a href="https://powershell.org/?p=294977&amp;preview=true">Step 2: Output</a><br><a href="https://powershell.org/?p=294979&amp;preview=true">Step 3: Input</a><br><a href="https://powershell.org/?p=294981&amp;preview=true">Step 4: Loops</a><br><a href="https://powershell.org/?p=294983&amp;preview=true">Step 5: Decisions</a></p>
]]></content:encoded></item></channel></rss>