What you'll learn
- Use Get-Help, Update-Help, and Save-Help to interpret cmdlet syntax, parameter sets, and examples
- Build a correctly formatted command with Show-Command, such as creating a new service with New-Service
- Explain how cmdlets return objects with properties, methods, and events and pass them down the pipeline
- Choose between if, switch, do-while, for, and foreach constructs when controlling flow in a script
- Debug a script line by line, analyzing variables to troubleshoot your own code or a script someone else wrote
- Describe the DSC authoring, staging, and make-it-so phases, from generating a MOF file to applying it via the LCM
Free 477-minute video lesson with a full transcript and knowledge checks. No account needed to watch.
Overview
In this PowerShell course, trainer Garth Schulte will teach you about commands, pipelines, objects, automation, scripting, and more. Garth starts with a single machine to cover PowerShell basics and works his way up to real-world scripting against a full network of Windows machines, spanning many versions of Windows.
Supplemental File
Welcome to PowerShell 4 Foundations!
Garth presents a case for PowerShell and why this is a great time to get on board with the future of configuration, management, and automation of Windows environments. We also define what PowerShell is, what it's capable of, who this course is for (everyone!), what it contains, and get familiar with our learning playground, the Virtual NuggetLab. Let's rock!
Knowledge Check
PowerShell can be used to perform which of the following?
Knowledge Check
PowerShell can be defined as which of the following? (Choose three)
Select all that apply.
Knowledge Check
Native commands in PowerShell are referred to as which of the following?
Knowledge Check
Which of the following PowerShell versions will be covered in this course? (Choose two)
Select all that apply.
Installing PowerShell 4.0
Get up to speed on the installation process for PowerShell 4, including its requirements and supported operating systems. We also walk through the process of installing PowerShell 4 on a supported legacy operating system, discuss mass deployment across the enterprise, and even write a one-liner to check the version of PowerShell across all machines in a domain!
Knowledge Check
If you're running Windows Server 2008 R2 and newer, or Windows 7 and newer, PowerShell 4.0 is installed by default. True or false?
Knowledge Check
Which command will print the installed version of PowerShell?
Knowledge Check
PowerShell 4.0 can be installed from which of the following packages?
Getting Started
Take a tour of the PowerShell Console and the PowerShell ISE, the main tools for writing commands, scripts, and interacting with PowerShell. We also define the purpose of each tool and learn how to configure, customize, navigate, and execute the commands of each tool.
Knowledge Check
The cmdlet to get information about the current host environment is _____. (Hint: cmdlets are typically in the form Verb-Noun.)
This interactive assessment is available in the full learning experience.
Knowledge Check
Which of the following do the same thing? (Choose three)
Select all that apply.
Knowledge Check
The Powershell ISE (Integrated Scripting Environment) includes all features of the Console, plus additional UI elements for building and running scripts. True or false?
Knowledge Check
Which of the following PowerShell ISE features assist in writing scripts? (Choose three)
Select all that apply.
Getting Help
Learn to use the help system and help cmdlets in PowerShell! We look at how to keep help topics updated on your client machines, save help to a file share for disconnected clients, interpret help by understanding syntax and parameter types, and walk through a demonstration to show you the many common and not-so-common ways to use the Get-Help cmdlet!
Knowledge Check
You can download full help topics in Powershell with the Update-Help cmdlet. True or false?
Knowledge Check
When viewing the syntax of a cmdlet, what kind of parameter has NO brackets around it?
Knowledge Check
Which of the following are valid parameter sets for Get-Help? (choose three)
Select all that apply.
Knowledge Check
You can omit the name of a __________ parameter, entering only the argument as long as it's defined in relative order.
This interactive assessment is available in the full learning experience.
Commands
We cover the six PowerShell command types, including how to find them using Get-Command. We also look at the process for discovering and learning a "cmdlet a day," as well as creating and using aliases.
Knowledge Check
The following are types of commands: (choose three)
Select all that apply.
Knowledge Check
When using Get-Command, the -CommandType parameter is used to filter results by the command type. True or false?
Knowledge Check
You cannot run traditional DOS commands in a Powershell script. True or false?
Knowledge Check
Which cmdlet is used to load previously saved Aliases?
The Pipeline
Garth introduces you to the basics of constructing PowerShell pipelines! We look at the process for chaining commands together, and see just how easy PowerShell makes it with its object-oriented approach. We also run through a few fun demonstrations and finish with three pipeline challenges you can try on your own.
Knowledge Check
Powershell is object-based, NOT text-based. True or false?
Knowledge Check
Cmdlets that send output to a file, array of strings, or printer, for example, start with _____.
This interactive assessment is available in the full learning experience.
Knowledge Check
Which cmdlet can you use in the pipeline to select specific properties from objects?
Knowledge Check
There is a limit of five Pipe ( | ) commands in a single Powershell Command. True or false?
Objects
We define what an object is, where they come from, how they're used, and some of the common things we can do with them in the pipeline! We also learn about another crucial cmdlet for discovering what objects consist of, get-member.
Knowledge Check
An Object is described by a template or blueprint, which is known as a:
Knowledge Check
The items of an object that describe its state are known as _______.
This interactive assessment is available in the full learning experience.
Knowledge Check
The -whatif switch parameter is great for dry-runs and testing PowerShell commands or scripts. True or false?
Knowledge Check
Pipe into this Cmdlet in order to get specific properties of a object:
Knowledge Check
Match each option:
This interactive assessment is available in the full learning experience.
Extending the Shell
Garth provides an explanation and demonstration of what modules are used for in PowerShell! We cover the process for loading and unloading, automatically importing, and creating your own modules.
Knowledge Check
Modules are preferred for the following reasons (choose two):
Select all that apply.
Knowledge Check
Modules are supplied by Microsoft only and cannot be created by users. True or false?
Knowledge Check
Which of these are ways to load a module? (Choose three)
Select all that apply.
Extending Objects
Learn how to extend PowerShell by adding your own properties and methods to types and objects dynamically. We talk about PowerShell's Adapted Type System (ADT), Extended Type System (ETS), and cover member types and methods used to extend types and objects.
Knowledge Check
Which feature allows developers to expand the properties of a Powershell object?
Knowledge Check
Use this command to permanently add a member to an object in your script.
Knowledge Check
Use this command to create an object that you define yourself from "the ground up".
This interactive assessment is available in the full learning experience.
Knowledge Check
This command updates an object definition for all future instances of an object that are created in your script:
Formatting Output
Explore how PowerShell determines what properties and formats are used when outputting objects. We also cover popular formatting cmdlets, and many ways we can use them to control how objects are outputted to the console.
Knowledge Check
Powershell will lookup format files at the end of the pipeline for output display. True or false?
Knowledge Check
Powershell format files are in which format?
Knowledge Check
Match each command and option to it's output
This interactive assessment is available in the full learning experience.
Knowledge Check
Updating the Format files is the best way to change the default output for your objects. True or false?
The Pipeline Returns
Peer inside of the pipeline and cover parameter binding to observe how PowerShell wires up cmdlets together in the pipeline! Understanding these concepts, along with custom properties and parenthetical commands, gives you utmost control over the pipeline, ensuring there's nothing you can't do when stringing commands together.
Knowledge Check
Which of the following are ways a pipeline can accept a property? Select all that apply.
Select all that apply.
Knowledge Check
Cmdlets can accept almost any object if they allow pipeline input for a <PSObject>. True or false?
Knowledge Check
Which of the following cmdlets transforms a comma-separated file (.csv) to a PS object?
Knowledge Check
Get-Content will work to send data to a cmdlet that accepts pipeline input by property name. True or false?
Providers
We cover what providers are and how they abstract any underlying data store into a standardized view accessible from PowerShell. We also walk through a demonstration to get familiar with many of the core provider cmdlets.
Knowledge Check
Providers treat datastores such as Certificates or the Registry as:
Knowledge Check
You can CD (change directory) into a Provider entry point. True or false?
Knowledge Check
Cmdlets like Set-Item or Get-ChildItem are generic ways to work with providers. True or false?
WMI & CIM
We explore WMI and CIM, technologies that are for accessing management information on a machine. Along with demystifying each one, we talk about the need for utilizing low-level information, and the cmdlets for doing so. We also look at one of the best tools for exploring and discovering instances, classes, and properties in the repository.
Knowledge Check
WMI and CIM are interfaces for working with which of the following?
Knowledge Check
Powershell cmdlets are often just a quick way to work with the WMI/CIM repository. True or false?
Knowledge Check
You can pass an instance into Get-CimAssociatedInstance to learn about things like dependent services. True or false?
Knowledge Check
Invoke methods of a CIM class with this cmdlet:
This interactive assessment is available in the full learning experience.
Remoting
Journey through the wonderful world of Remoting, which is truly the best thing since sliced bread! Get up to speed on the WinRM service and see firsthand what we can accomplish with Remoting, from one-to-one and one-to-many sessions, to persistent sessions, and even implicit remoting. The future of multi-machine management begins here!
Knowledge Check
Which of the following protocols does WS-Man use?
Knowledge Check
You can use the command Enable-PSRemoting to turn on Powershell remoting on both Server and Client Windows. True or false?
Knowledge Check
Use this cmdlet to enter a 1-to-1 remoting session against another machine:
This interactive assessment is available in the full learning experience.
Knowledge Check
Which of the following can you use Invoke-Command for? (Choose two)
Select all that apply.
Jobs
Discover how to create the many kinds of jobs for asynchronous work in PowerShell, from background jobs to remote jobs to automation using scheduled jobs... you see them all!
Knowledge Check
Types of Powershell jobs include: (choose three)
Select all that apply.
Knowledge Check
Use this cmdlet to stop a running job:
This interactive assessment is available in the full learning experience.
Knowledge Check
When receiving data from a job with Receive-Job, use this switch to prevent the data from being cleared.
Knowledge Check
Get-Job will only return background jobs that are running in the current session. True or false?
Workflows
Discover what workflows are about and how to take advantage of them in PowerShell to control long-running processes, including how to coordinate and execute parallel tasks. We also walk through a demo of how to create a process that can survive failure and server restarts!
Knowledge Check
Functions and Workflows are fundamentally the same thing. True or false?
Knowledge Check
Which of the following keywords is used to define workflows?
Knowledge Check
Which of the following are ways that parallel workflows can be designed? (Choose two)
Select all that apply.
Knowledge Check
You can mix Sequential Workflows inside of Parallel script blocks. True or false?
Scripting - Getting Started
Get started in the world of PowerShell scripting by learning the anatomy of a basic script, executing scripts, dot-sourcing scripts, security features, and execution policies. Plus, learn how to digitally sign scripts to protect them yourself!
Knowledge Check
Powershell scripts are a block of one or more Powershell commands saved in a .ps1 file. True or false?
Knowledge Check
Built-in security policies for Powershell scripts include which of the following? Select all that apply.
Select all that apply.
Knowledge Check
Persisting your variables and functions after a script ends is done with:
Knowledge Check
Scripts signed with a self-signed certificate will run on remote machines whose Execution Policy is set to RemoteSigned. True or false?
Scripting - Essentials
Garth walks you through many of the core language concepts in PowerShell. We cover variables, conditional statements, looping, error handling, and functions before bringing it all together with a fun, real-world script!
Knowledge Check
Strongly typing variables forces the values assigned to that variable to convert to that type when possible. True or false?
Knowledge Check
Use this command instead of a large series of if..elseif statements for improved readability.
Knowledge Check
Which of the following are valid looping commands in Powershell scripts? Select all that apply.
Select all that apply.
Knowledge Check
Which common property dictates how a script proceeds after running into an error?
This interactive assessment is available in the full learning experience.
Knowledge Check
Use this syntax to escape a large block of text as literal text in a script.
Scripting - The Real World
Garth walks you through two fun and useful real-world scripts! We look at how to import users into Active Directory and monitor a network of servers. We'll also cover how to debug and walkthrough scripts, an invaluable asset every PowerShell administrator needs to write bulletproof scripts.
Knowledge Check
The Powershell operator to test if two values are equivalent is ___.
This interactive assessment is available in the full learning experience.
Knowledge Check
Use this statement to gracefully recover from any errors in your Powershell script:
Knowledge Check
A do {...} while loop is a valid alternative to creating a schedule job for a Powershell script. True or false?
Knowledge Check
Write the cmdlet to pause or sleep your script for a specified amount of time.
This interactive assessment is available in the full learning experience.
Knowledge Check
Use this feature of the ISE to pause code execution at a specific line of code.
Desired State Configuration - Getting Started
Garth gets you up to speed on the basics of Desired State Configuration! We talk about the need for this wonderful declarative management platform, get familiar with the components, and look at how to utilize it to ensure the state of a machine.
Knowledge Check
Powershell Desired State Configuration (DSC) is used to:
Knowledge Check
Match each operation with its step.
This interactive assessment is available in the full learning experience.
Knowledge Check
This deployment model is when a user actively tells a machine to apply a desired state.
Knowledge Check
Write the cmdlet to push a Desired State Configuration.
This interactive assessment is available in the full learning experience.
Desired State Configuration - Making it So!
Garth covers Desired State Configurations deployment models, push, and pull. We set up an HTTP pull server, download the DSC resource kit, and even utilize custom DSC resources!
Knowledge Check
Which deployment model routinely updates any changes in configuration on a refresh interval?
Knowledge Check
What are the steps required to setup the Pull deployment model include? Select all that apply.
Select all that apply.
Knowledge Check
The push and pull deployment models can both achieve the same configuration updates. True or false?
Knowledge Check
The Local Configuration Manager uses this part of the meta file to tie a configuration to the local machine.
Tips, Tools, and Resources
Garth shows you how to use profile scripts, points out some popular tools to improve your PowerShell experience, and gives you a list of great resources to help you in your journey to PowerShell mastery.
Knowledge Check
Shell customizations, drive setup, and other routine tasks you perform on every startup are good candidate for a profile script. True or false?
Knowledge Check
From where can you launch the Add-on website tools?
Knowledge Check
Which of the following are alternatives to Powershell ISE? (Choose two)
Select all that apply.
Conclusion
I hope this has been informative for you and I would like to thank you for consuming.
View Transcript
Welcome to PowerShell 4 Foundations!
0:00Hello, my friends, and welcome to PowerShell 4 Foundations. My name's Garth Schulte. I'll be your host throughout this course where we're going to learn all about the future of administration configuration and automation here in Microsoft environments. Now is as good a time as any to get some PowerShell skills in your toolbox. Maybe you've been avoiding PowerShell. Maybe you just haven't gotten to yet. Or maybe you clicked on that little blue button in the taskbar out of curiosity and said, you know what, this is just a glorified command dot exe with a blue background. No, thanks and you go back to your GUI ways.
0:31Well, I'm here to tell you and show you that PowerShell is a big deal. Microsoft is serious about it, an employers are starting to get serious about it. And once employers really understand what PowerShell is and what it can do, they see two things, right, they see time and they see money. In these are two areas that PowerShell can give back immensely. In fact, if I'm an employer right now looking to fill administrative position, and I've got some candidates, you know what I'm going to do? In fact, let's do this. Let's say we've got Bob over here, and we've got Joe over here. So Bob and Joe are vying for the same job. What I'm going to do is I'm going to give them a common everyday task.
1:04Maybe I've got 50 users in a department that all need their password reset or some attribute changed in Active Directory. Well, I'm going to give Bob and Joe that task and say, go do that. Come back when you're done. And let's say that Joe, Joe's like Bradley Cooper from Limitless. Anybody see Limitless where he takes the smart pill and he's like a ridiculous genius? Well, let's say Joe took the PowerShell pill. Joe writes a couple commands or turns it into a script, and does it, comes back in maybe a minute, and says, oh, by the way, it's done. And I made it repeatable. Here you go. Here's the script if you ever need to do that again, Boss.
1:36Where Bob is still over there waiting for Active Directory to launch. He's farting around in the GUIs. Come on, Bob, get with the show. PowerShell's the future. And you know, obviously, who'd get hired there is Mr. Joe. So together, you and I are going to learn to be like Joe. So if you're like Bob now, no worries, because it doesn't take much to learn and become effective and dangerous in PowerShell. Now let's get to this Nugget. This Nugget, I'm going to give you more reasons to learn PowerShell. If that wasn't reason enough, we'll take a look at many more. We'll also define what PowerShell is, and then we'll get a bird's eye view of the entire course to see all the things that we're going to cover.
2:11And we'll also get you familiar with our lab and demonstration environment, the Virtual Nugget Lab. We've got a five-machine network at our fingertips ready to go that span many versions of PowerShell and many versions of Windows. I'm excited to be your host. Thanks again for joining me. Let's jump in. Let's make the case for PowerShell and start with a simple question. How do you currently perform and automate tasks across some of these common areas such as Active Directory? We just saw an example of Bob and Joe. But let's say that you were tasked with creating a bunch of users or maybe had to move users around, or migrate users, or maybe you had to change some attributes of users, or join a computer to a domain.
2:47If you don't PowerShell, the answer to all those is probably the GUI. Here's another one, the file system. How do you currently create and manage those directory structures for things like reports and backups? How do you archive that stuff? If the answer is by hand, I'm sorry. But it's not going to be after you learn PowerShell. Also another one here is for personal use. I'll give you a good example. I've got a network-attached storage device here that has 15 years worth of photos and videos from the family, right? They all have iPods and iPads and phones and any time they upload anything, my only requirement was put it in the year directory for the year that it is.
3:20So I've got 15 directories that span 15 years over two and a half terabytes of data and everything has the default name, dsc9384.jpg or dot mpg or whatever. And I just let it go. I'm like, whatever, some day I'll get to that. Well, once I got some PowerShell skills, I'm like, you know what, this is going to be easy. It took me an hour to write a script to organize all that, appropriately name it, now anybody can find exactly what they're looking for. And that was a super fun one to build. What about server an operating system stuff? You know, those common everyday things that we do as administrators, like manage processes, services, event logs.
3:50Do you do that through the GUI? Probably. And you probably even do it on a machine by machine basis. PowerShell can help us out immensely in all those areas. What about-- and here's a really good one adding and removing features, roles and features. Let's say you've got three servers, and they're all going to be Hyper-V servers. How do you get Hyper-V on those? Would you log into each one individually, walk through the Add and Remove roles and Features Wizard? Probably. That sounds like half a day of work getting three Hyper-V servers up and running, right? With PowerShell you could do it in minutes. One command is literally a one-liner to do that. And you could send that command to all those machines and have them fully configured in no time.
4:23Pretty cool. Speaking of Hyper-V, virtualization is a big deal these days, right? But it's also a big time sink. If you don't know PowerShell, you're probably spinning up your environments by hand, and I can tell you from experience here being a trainer, I'm constantly spinning up virtual environments. And doing it by hand used to take forever. Doing it with PowerShell? Not only does it not take is long, but it's repeatable. So if I ever need to respin up that environment, I just run a script, boom, there it is. There's my network at the point exactly where I wanted it. And in fact, I did that for our Virtual Nugget Lab, spun up a network. Changed the computer names, brought up a domain controller, added all the machines to the domain, did a few configuration points, and now if I ever need to get us back to that starting point, I just run the script.
5:01What about server applications? How you manage and make configuration changes in things like Exchange, SQL, Systems, and our SharePoint? The list goes on and on there. The answer is probably the GUI. You're go into to the GUI, find what you're looking for, you make the change. But the problem with the GUI? It's not repeatable. What if you need to do it again, and again, and again? You're back inside of the GUIs. So PowerShell is great, because it lives outside of all these things. It's one tool to rule them all, and this is just a small example. Small small, small example of some of the things that we can do with PowerShell. How about a top 10 list? The top 10 reasons to learn PowerShell.
5:32Ready? Go. Number 10, it's easy to learn, really. It is incredibly easy to learn. Jeffrey Snover, the man and the myth, the legend behind PowerShell, somehow took the essence of the GUI and brought into PowerShell. And this is why GUIs are good, right? GUIs are good because it's what we're used to, number one, but they're also easy to learn. Once you learn something in one GUI, you can carry it over to the next. So the first time you learned how the X button to close the window, or the Minimize button or OK, Apply, Cancel, once you learn all those, you can carry it over to the next GUI. So it's efficient for learning how to learn.
6:03PowerShell is the same way. Not only will you be learning quickly, you'll be ripping off commands across your whole network in no time, but you learn how command-lines work, the structure, the syntax, the convention, you carry that information over to the next command-line. So whether you're working Windows, or SQL Server or SharePoint, it'll just be learning specifics about those command-lines. And we'll talk a little bit more about this, how it's discoverable and predictable, but just know that PowerShell is easy to learn. And CLIs get a bad rap, and that's kind of why PowerShell's a bad rap because who wants to work in a text-based environment?
6:35Nobody. But PowerShell's different as you'll see. Number nine, it can be the only way. Yeah, not every single feature is inside of the GUI. In fact, a lot of things in Active Directory and other products, you're only going to be able to access using PowerShell. Number eight, GUIs are slow and, of course, this incomplete kind of ties into number nine there. But the slow part is what I want to highlight here. No matter how good you are at doing something in the GUI, you'll never be able to do it as fast as you can do it in PowerShell. As an example, say you were tasked with creating 100 Active Directory Users.
7:06They give you a spreadsheet, here you go. What are you going to do? If you're going to do that in the GUI, at most, at the best, let's say it takes you a minute to create a user in Active Directory based on that spreadsheet. Enter all that data, you hit Create, and then you go to the next one, the next one, the next one. So if it takes you a minute, to do 100 users, that's a little over an hour and a half. In PowerShell, one line of code to import those users into Active Directory. I'm not kidding. One line, so it would take you seconds. Number seven, it's actually really fun to use. I'm not kidding. It's like you got to be careful with this stuff, because you could end up in PowerShell anonymous, right?
7:39PA. But really, once you get dangerous with this stuff, you're going to want to keep going more, and more, and more. And once you get familiar with a few commands, you get them under your belt, then you're going to want to start writing scripts and doing some incredibly neat stuff with very little effort. So it's fun to use as you'll see. It's like it's like Pringles, you know, once you start you can't stop. Once you pop, you can't stop. PowerShell and Pringles, one in the same. Number six, you can do so much with so little. These commandlets, which are native PowerShell commands that we'll get plenty into, have a lot of power in them.
8:10Combine that with something called the Pipeline, which we're going to look a lot at, which essentially allows us to connect commands together and pass data between commands, you'll be astounded. Half the time, again, you won't need a script to do something that you would normally need a script for. Number five Microsoft is baking it in to everything. Almost every GUI we use today on the server side is just executing PowerShell commands under the hood. And that trend is going to continue until eventually PowerShell is underneath everything. Number four, the time and cost savings are astronomical. We looked at this and an example of this earlier, but I mean this is the truth.
8:43Employers are going to be hiring people that have PowerShell skills over people that do not, because they're the ones that are going to help move the business forward by automating and making things repeatable. They'll never do things more than once, because they'll never half to. They do it once, they turn it in to a script or store that command somewhere. If they ever have to do it again, they just run it, so time wasted doing the same things over and over. Number three, it's enabling interactivity like never before. This is a big one. Here's why. Remember over here server apps? What if I had to create a process that did some kind of synchronization or coordination across some of these products, how would you do it now?
9:19Not easily. PowerShell makes it easy because, again, it sits outside in all of these products exposed commandlets that we can tap into from PowerShell. So now all of a sudden it becomes very easy to do cross product integration. Number two, it's the Microsoft standard for automation. Now, going forward, Microsoft's in it for the long haul here with PowerShell. So once you learn how to use PowerShell and how to automate something, you'll never need to, or even want to, do it any other way again. It's just that easy. And number one, your future is an IT professional depends on learning PowerShell.
9:51This is the skill that employers are going to be looking for in the future. So it's as good a time as any to learn PowerShell. In fact, now is the perfect time to get into PowerShell, because it's just starting to get interesting, really interesting. We're going to be focusing heavily on PowerShell Version 4. Version 4 brings a lot of stuff to the table. They've worked out a lot of kinks. They've added a lot more commandlets, which are going to give us a wider and deeper reach into Windows and beyond, and they've introduced a new feature called DSC, Desired State Configuration, which is going to, again, change the face of configuration management as we know it.
10:22So now that we know why we should be learning PowerShell, hopefully, let's talk about what PowerShell is. If I had to define PowerShell in one sentence, I would call it an object-oriented command line shell and scripting language based on the dot NET framework that gives us all those benefits, everything we need to do here from an administrative perspective. But here's the thing, this is an important keyword right here, object-oriented. Windows is an object-oriented operating system, but this term can scare a lot of people away, right? Because this is a developer term, object-oriented programming, things like classes, polymorphism, inheritance, instantiating objects.
10:53But here's the thing. We only need to know objects. Properties, methods, events, things we'll cover when we get into objects, but this is really the magic, the secret sauce behind PowerShell is it's an object-based shell. So we can create these really elegant pipelines, pass objects, and this is why we can do so much with so little. So again, the man and the mind behind PowerShell's name is Jeffrey Snover, brilliant guy. And his vision for PowerShell was outlined in something known as the Monad Manifesto, Monad, the name of PowerShell before it was actually renamed to PowerShell. But his vision was essentially to give anybody, power users, administrators, whoever could tap into PowerShell here, the power of dot NET framework and the power of a developer without actually having to do any coding or development work.
11:31The rest is history. So what is PowerShell? First up, it's a command-line shell. So it's just like command dot exe. In fact, we can run all those utilities that you're used to running, Ping, IP, config, [INAUDIBLE], all those things we can still do in PowerShell. So theoretically, you never have to open up command dot exe again. Just use PowerShell for that kind of stuff. We've got PowerShell specific things that we can do that replaces those to work with objects rather than text. And actually, that's going to be a big part of this course. We're going to learn a lot of commandlets. So think of commandlets like regular commands on steroids, because they're little dot NET utilities that send us back dot NET objects that we can work with passed down the pipeline to other commands or do all kinds of stuff with.
12:10Cool stuff that you will see. Secondly here, it is a scripting language. It's very simple scripting language once you get the hang of it. We have variables. We have control flows, so once we want to start doing more complex things, we're going to break out the scripts to do so. It's object-based rather than text-based, and this is really what sets PowerShell apart from a traditional Linux shell like Bash or even the Legacy command prompt that we were talking about here. So traditional shells output text this is the big difference right here. And that's going to make it difficult to do things like formatting and filtering.
12:40And there are tools to help us get the job done in those old school shells, like setting preferences, but it takes years to master things like regular expressions to do the heavy text parsing. So because PowerShell takes advantage of the underlying dot NET framework and uses objects to represent data, it's going to make life a lot more fun and efficient inside of the shell. PowerShell's also consistent with its syntax and conventions, and this is a big one because, again, with those Legacy shells, people build command line utilities all the time, and there's no standard. Again, some people may use dashes or slashes or whacks or whatever for their switches and there's no consistency across perimeters.
13:13Well, with PowerShell, you learn a commandlet, you learn a parameter, especially if it's a common parameter, that parameter's going to work the same across all the other commandlets. And that syntax is going to be the same across all of the commandlets, so it's is very learner friendly and user friendly. Now, this next bit is probably one of the coolest parts about PowerShell. This is a Microsoft term, are you ready? It's discoverable and predictable. Discoverable means we can easily find what we're looking for. So this happens a lot. The first time you fire up PowerShell, as most people do, they look at the screen and they go now what or what's next?
13:47Well, this is what's next. What's next is you need to find what you're looking for. So we've got a search engine on top of everything in PowerShell called Get Dash Comman. It's a commandlet. It's a very easy to use search engine to help us find what we're looking for. And PowerShell commandlets have a really consistent naming convention that goes in the form of verb, you know, get, add, remove, clear, that kind of thing, the action that you're taking. And then the noun, what research are you working with, service, event log, process, computer, so and so forth. So this is why it's predictable, because if a new set of commandlets come up for a product, you already know.
14:18You can essentially predict exactly what you're looking for based on that product. It's also flexible and extensible. So comes packaged with lots of core commandlets. But let's say we're in a Windows 8.1 machine, we have it installed, and we want to remotely manage Active Directory. Well, guess what? We can download the remote server administration tools which give us access to all those Active Directory commandlets. We import that, we work with them, and boom, now we can work with Active Directory from anywhere. And that goes for all the other server side products as well in many other areas. In fact, we can build our own modules. We can even build our own commandlets in the dot NET framework.
14:50It's literally five lines of code set up to skeleton to create your own commandlets. It's really, really neat stuff. It's dynamic and powerful as we'll see throughout the course. It's automatable and, as you'll see, it's now everywhere in Windows. So what are we going to be doing with PowerShell in this course? Well, I tell you, if you know nothing about PowerShell or if you know something about PowerShell, you've come to the right place. So we're going to start from the ground up, and then we're going to turn it up. So we'll start here immediately following this Nugget with installation. I'll show you how to install it on Legacy systems, how to install it across the Enterprise. And we'll talk about what versions of PowerShell installed by default, what's supported, and specifically, where PowerShell 4 is supported and what the requirements are.
15:28Then we'll get started. Here we're going to get familiar with our tools. We'll get familiar with the ISE, the Integrated Scripting Environment, as well as the shell itself, the old command-line shell. Those are the two screenshots we saw in the previous screen. And we'll get familiar with get command. So we're very familiar with how to use that search and define exactly what we're looking for. Then we'll get into the Help System, a very, very incredible and dynamic help system that will make it very easy to learn what all these commandlets do, everything from the syntax, to description, to examples. And we'll take a look at all different ways we can use that wonderful Help System.
15:59From there, we're going to get into commands. So here's where we're going to learn all the terminology in PowerShell. What's a command? What's a command level? What's a function? What's a script? What's an alias? So all those components that make a PowerShell, all those things we'll be working with we'll define there. We'll also get familiar with syntax, and we'll talk about some of the common commands that you'll be working with every day inside of PowerShell. From there, we'll get into objects. We'll define what an object is. We'll see why they're so critical to understanding how PowerShell functions. And we'll even look at something called get [INAUDIBLE], which allows us to interrogate an object to see everything there is to know about it. We'll get into pipelines.
16:29You've got to know objects before pipelines, because pipelines are how we're going to take data that's returned from a commandlet and pass it down the pipeline. And do some more with it, filter it, format it, sort it, transform it, or maybe just do something with it, right? So big look at the pipeline, and we've actually got a couple of Nuggets on the pipeline. One to get introduced to it, one to go deep down to understand how objects are passed around the pipeline. From there, we're going to get into providers. And providers essentially allow us to take an underlying data source and make it look like a file system. So everybody's familiar with the file system, right?
17:00You've got directories, subdirectories, subdirectories, and files. While providers abstract that underlying data source to make it look like this, so we can map a drive to things like the registry and make the registry look like a file system, which will make it very easy for us to work with. We'll also get into Windows Management Instrumentation and the Common Information Model, which will allow us to tap into the functionality of the operating system. We'll be using that quite heavily, too. It's a great way to get and extract information out from the operating system level. And, again, even tap into and utilize some of that functionality at the OS level.
17:32We'll get into remoting, which is how we're going to execute commands across the network. We've got other ways to do it, but this would be the best and most secure way of doing it. So if we want to execute, send commands, PowerShell commands, over to 100 machines, we can do that. And all those commands will get executed on those machines. And we'll get the results sent back to where we're running power, so on the client machine, really, really awesome stuff. We'll get into automation. We've got background jobs, which are way to run long running tasks in the background, as well as scheduled jobs for automation. We'll get into scripting. We've got a bunch of Nuggets on scripting to get familiar with how to write scripts.
18:04And at the end here, we're going to look at Desired State Configuration, which is that new feature in PowerShell 4 that is just absolutely incredible. Jeffrey Snover called this the "make it so feature." Essentially, this stops configuration drift. Configuration drift is one of those things that happens over time. People fight fires, they change settings, and they don't put them back. And eventually you have a system that is completely different from the state that you wish it to be in. So Desired State Configuation allows us to declaratively define what a machine should look like as far as configuration, settings, features, all that stuff.
18:36And then if those ever change, Desired State Configuration, after a set amount of time, will put it back to normal. Really powerful stuff, and it goes way beyond that, and that's what we'll dig into in those Nuggets. And we'll also, at the end here, throw some challenges your way, and along the way, we'll do some really neat real-world stuff. So here's the Virtual Nugget Lab. This is the network that we're going to be working with. And you can have access to this network as well. If you're a premium subscriber, you can fire it right up from the course page right through your browser and have access to this five machine network. And we're going to be doing a lot in here. So we're going to start small just working with one or two machines, and then by the end of this course, we'll be sending commands in automating things across the entire network.
19:13We're going to do some pretty cool things. So we've got DCNUGGET. This is our domain controller. FSNUGGETs are file server. APPNUGGET is going to be kind of our everything else. We'll eventually get IS on here. We'll write and automate some tasks to run across the whole network, gather some information, create a web page, put it on IS, and we'll use Desired State Configuration to make sure that all those features stay in place. Really cool stuff. We're going to, like I said, go from zero to hero here by the time we're done with this course. And then we've got some client machines here, a Windows 7 client and a Windows 8 client. Now let me introduce you to the network we're going to be working in.
19:44There it is. This is actually our domain controller here. In fact, let me bring this over. There we go, all right, cool. So here we go. Here's DCNUGGET, here's our File Server Nugget, Windows Server 2012 R2 on those. Here's our other server. So we have three servers here all with Windows Server 2012 R2. And we've got two client machines. Here's our Windows 7 client and here's our Windows 8 client. So right now, we've got all the default installations of PowerShell, which means we're fine on the server side and even the 8.1 side. In fact, we can see this. Let's just fire up PowerShell here and let's just run a quick PS version table. Don't worry about this if none of this make sense, we're going to get into it.
20:16So there we go. In fact, in our installation Nugget, it will get you very familiar with PS version table. We'll do some pretty cool things with it. So PowerShell version 4 right here, so we're good there. But if we head over to our Windows 7 client, and we try that out, you can see that we're running PowerShell Version 2. So this is something, an older Legacy machine, something you'll probably come across in the real world. If you have a lot of older clients out there, you'll need to get them up to PowerShell 4 if you want to take advantage of some of these cool features. So we'll look at how to do that in our Installation Nugget. In this CBT Nugget, I welcomed you to Power Shell 4 Foundtions, and hopefully made the case for why we all need PowerShell skills here going forward.
20:51It's going to make us more efficient. We're going to be able to do things that we ever thought possible before we're going to be able to easily manage, configure, and automate our environments. We also defined what PowerShell is. It's an object-oriented command-line shell and scripting language based on the dot NET framework. And then we went over what we're going to cover in this course, which is all the foundations and beyond of PowerShell 4. And at the end here, we got familiar with the virtual environment that we're going to be working with for all of our labs and demonstrations. I'm extremely excited that you're joining me for this course. So again, thank you. We're going to have a lot of fun.
21:22We're going to learn a lot, and you're going to be extremely effective with PowerShell by the time we're done with this course. I hope that this has been informative for you, and I'd like to thank you for viewing.
Installing PowerShell 4.0
0:00Installing PowerShell 4. So before we can start utilizing all these awesome features in PowerShell 4, we need to get it installed across the enterprise. And that can be a challenge, unless you're one of those lucky folks whose infrastructure's always on the latest version of Windows. So your servers are all up to date with Windows Server 2012 R2, your clients are all up to date with Windows 8.1. Well, number one, you're golden, because you already have PowerShell 4 installed. Number two, we envy you, because, generally, that's not going to be the case. Generally, we're going to have clients all over the place, XP, Vista, 7.
0:30We're going to have servers all over the place, 2003, 2008, 2008 R2, and that's going to equate to PowerShell versions all over the place. So in this Nugget we're going to talk about all things PowerShell 4 installation. We're going to cover its requirements, where you can find it, its availability. Can we even install PowerShell 4 in older versions of Windows? And we'll even talk about a couple of features that, in newer versions of Windows, are turned on rather than off. Which just goes to show that Microsoft is very serious about making PowerShell more accessible right out of the box. And finally, towards the end of this Nugget, we'll get into the Virtual Nugget Lab, and I'll give you a demonstration.
1:02We'll look at some neat commands that we can use to, again, interrogate our network to see what versions of PowerShell are out there. And then we've got a legacy Windows 7.1 client inside of our domain, that's running PowerShell 2, so we'll look at the process for getting them up to PowerShell 4. So without further ado, let's begin. All right, everything you need to know about installing PowerShell 4, here it is. So for down level installs, and I'm talking anything prior to 8.1 on the client side, and anything prior to Windows Server 2012 R2 on the server side, you'll need to first install the .NET Framework 4.5.
1:32Then we can install WMF, the Windows Management Framework 4.0, which is where we find PowerShell and all kinds of supporting technologies around it. Now here's the thing, WMF, when you try to install it, doesn't actually check for .NET 4.5. This is a known issue. So if you install WMF before .NET 4.5, it'll succeed, but it won't actually do anything. So if you run into troubles, you can then install .NET Framework 4.5, and then just run through the installation of WMF 4.0 again, and it'll succeed. Now here are the components of WMF. PowerShell 4, both the shell and the ISE, a couple of tools we'll be getting very familiar with.
2:06PowerShell Web Services, this is what allows administrators to expose commandlets via a restful endpoint. So developers can tap into these APIs and execute PowerShell commandlets remotely. It also comes packaged with WRM, Windows Remote Management. Now this is Microsoft's implementation of the WS-MAN protocol, which uses SOAP over HTTP and HTTPS for communication. And it's much more firewall friendly than, say, the computer name switch, which we're also going to talk about, how we can pass in a list of computers for a commandlet. That uses DCOM and RPC, which is not firewall friendly.
2:39So again, we're going to get heavily into this when we talk about remoting. We'll uncover the details here of the WinRM service and WS-MAN, and talk about how remoting works under the hood. And it's also going to be one your post-installation tasks if you want remoting to work across your enterprise, you're going to need to configure and enable Windows Remote Management, which is pretty easy to do here, through PowerShell. So again, more on that down the road, when we get into remoting. WMF is also going to upgrade WMI so it's compatible with PowerShell version 4. And then we get that sweet new feature here, called Desired State Configuration, it's going to install the components, so we can utilize that.
3:12And, again, we're going to take a big look at DSC down the road, as well. Now let's look at PowerShell 4's availability. Is it supported, and by what operating systems? Now, again, Windows Server 2012 R2 and Windows 8.1, it's installed by default, there's nothing you need to do. It's already got .NET 4.5, it's already got PowerShell 4, so you're ready to go. Windows Server 2012, you will need to install .NET 4.5, and then, again, you can install WMF 4.0. Windows 8, it is unsupported. So the only way, if you're on Windows 8, to get PowerShell 4, is to upgrade to Windows 8.1, and then you'll be ready to go.
3:43And again, that is a free upgrade. Windows Server 2008 R2, you will need to install SP1 and .NET 4.5, and then you can install WMF 4.0. And the same goes for Windows 7, install SP1, then .NET 4.5, then get WMF 4.0. For everything else, you guessed it, PowerShell 4 is unsupported. Now here's another view, this just kind of gives us the bigger picture here. And this is a great chart for reference, if you ever have any questions around PowerShell 4's availability. This will give us our default PowerShell version across all the relevant versions of Windows, and the supported versions of PowerShell across all these versions of Windows.
4:20It's also going to show us our default settings, for execution policy, and remoting. These are two very important areas, because they're going to determine whether or not you can execute scripts on the machine, and if you can execute PowerShell commands remotely across one or more machines. Again, these are your two big post-installation tasks right here, setting up an execution policy for scripts, and configuring enabling remoting. Both of these we'll look at down the road. We've got a couple Nuggets for scripting. The first thing we'll do is work with execution policy and get an understanding of what all these options are.
4:51And then first thing we'll do we get into remoting is learn how to configure and enable them. But notice one thing here, Windows Server 2012 R2, yeah, remote sign-in enabled. These are on by default, which is, again, just awesome, because it makes it more accessible and easier to work with. And also notice with Windows Server 2012, remoting was enabled. So that's a big deal. But also notice, Windows 8.1, remoting is disabled, Windows 7, remoting is disabled. So we've got two client machines in our network right now with remoting disabled. And that's going to come in the play here shortly when we get in and do a demonstration.
5:22So how do we figure out what version of PowerShell we currently have running on our system? Well, there's a bunch of ways to do it, as is the norm here, with PowerShell. But one common way to do it is to run what's known as an automatic variable here. Think of this like an environment variable for PowerShell. PS version table. We execute that, it's going to give us back a bunch of information, but the first item that it's going to return here is our PowerShell version. You can also run dollar sign host, which will give you a bunch of host information, including the version of PowerShell. But what we want to do now is head into the Virtual Nugget Lab, and let's take PS version table and turn it into a command that we can execute across the entire network, all the machines in our domain, using remoting.
6:00This is going to be really neat. And then we'll take a look at the installation process. And we'll even talk a little bit here about how to install it across the enterprise. All right, so we're in the Virtual Nugget Lab, we are on CL8 Nugget. This is our client machine for Windows 8.1. And what I want to do first is just show you where you can find all the files here, for this course. So on FS Nugget, our file server, I have a share there called PSV4. What we're going to do is build this out as we go. So right now we're in 0.2 installation. Every command inside of here, we will put inside of commands.ps1. Unless it's a script that does a specific thing, I'll store them all inside of this.
6:33So every command we do inside of this course will be accessible here inside of these files. So there will be a folder per Nugget, and then we'll even have kind of support folder here with all the installation files that you'll need. And if you don't have access to the Virtual Nugget Lab, don't worry, upon course completion I'll wrap this up and we'll make it available via our Nugget Lab files on the course page. All right, so let's fire up PowerShell here. You always want to run PowerShell as an administrator, otherwise it won't function as you expect it to. And let's go ahead and check out the version here on this machine. So again, we're on Windows 8.1 client right now.
7:04And you can see our PowerShell version, 4.0, so we're good to go on this machine. Now what if we wanted to check out all the other machines in our network? Does that mean we have to RDP into those machines and do the same thing? No, and that's what I want to show you here. But first, before I show you that, let's do a PS version table on our Windows 7 client here. We can see that we are on PowerShell version 2.0. So this is a machine that we're going to need to upgrade to get it to 4.0. But let's head back to our 8 machine here, and watch this. Now you're probably thinking to yourself, what the heck is that?
7:35We haven't even talked about commandlets or commands yet. And don't worry. We're going to get to that in Getting Started, we'll talk all about commandlets, their structure, get familiar with their syntax and such. I just wanted to show you something cool, to give you the idea of how powerful it is, and how we can do so much with so little. So here, we're using remoting via the invoke command commandlet. We're passing it a list of computer names that we want to send this command to, and then we're using the script block parameter and passing in the actual command that we want to execute. So it's going to send this command to all these machines, get all that data, bring it back, and give it to us right here on our local machine, which is really cool.
8:08Now the one thing I want to point out, though, is remember, Windows 7 and Windows 8, remoting is disabled by default. So this could bring back some errors, and it will bring back some errors, because we didn't configure remoting yet. But DCNUGGET, APPNUGGET, FSNUGGET, those are all 2012 R2, so we should get all their versions sent back to us. So I'm going to go ahead and hit Enter, and it's going to think about it for a second, send those commands over the wire, and they're going to come back. And look at that, CL8 Nugget failed with the following error message. And then it succeeded on these three, and it's still trying to hit CL7. We'll get that error message shortly.
8:38But how cool is that? That we could sit on one machine, send a command to all those machines, and get a response back from them. And there's our CL7. So CL7 Nugget and CL8 Nugget, because remoting is disabled by default, it didn't work on those. But it did work across all of our servers. Here's another really cool one. Can anybody guess what this is going to do? Notice we took that static list of computer names that we had up here out, and then we replaced it with another commandlet called Get ADComputer.
9:09Yeah, you guessed it. This is going to read all the computers in Active Directory. Pretty cool, right? And extremely powerful for something that we're doing in one line. And if I hit Enter, there you go. It's going to go ahead and read from Active Directory, and then we're going to get the same response here. So the three servers that are in Active Directory, great, but the two clients that are in Active Directory, because remoting isn't enabled, are going to come back with an error. All right, so we know that our three servers are good, they all PowerShell version 4. We know that our CL8 Nugget is good, because we ran a PS version table right on this machine here, we know that that's OK with 4.
9:40And we know that our CL7 Nugget, which is right here, is on PowerShell 2. So the first thing you want to do on your legacy operating systems is, make sure that you have the requirements. Since we're on Windows 7, those requirements are going to be .NET Framework 4.5, as well as Service Pack 1. Now, check this one out. Can you guess what this one's going to do? Yeah, it's going to query the operating system through WMI, to see the operating system version and the service pack version.
10:11Let's hit Enter. Look at that. So we're on Windows 7 Professional, Service Pack major version 1, so we're good to go there, we meet that requirement. Now we could also query the registry to find out if we have the .NET Framework 4.5 installed. In fact, let me show you this, only through the ISE. And we could fire up the ISE down here, we could run Windows PowerShell ISE, or we just type in ISE here in the command shell. And there it is. And what I'm going to do is just open up that command script I was telling you about here. So, all right, and we'll just hit up our file server here. There we go.
10:41There is the directory for this Nugget, and there is, commands.ps1. So let's open this up. Now, again, this is PowerShell 2's ISE. And don't worry, we're going to get a nice tour of all the tools, and we'll get very familiar with PowerShell 4's ISE, which is much nicer. But here are the commands that we were just running, there's your version check, here's your operating system and Service Pack check. And here, if you want to query the registry to see what version of .NET, you could do that. But we're just going to do a like on the end of this to see if we're running .NET 4.5. So if we execute our highlighted selection there, it's going to return false, meaning we do not have .NET 4.5 installed.
11:14All right, now our next step is to get the .NET Framework 4.5 installed. Here is the URL, I'll give you the short URLs for these as well, for the .NET Framework 4.5. This is for the offline installer. I also have the web installer inside of our installation directory here, but we'll talk about why you'd use one over the other here, shortly. And then here is WMF 4.0. I'm going to go ahead and run through installation here, so let me go ahead and just close out of this. Head into our directory, head into installs, and here's what we get. So here's the web installer. Here's the offline installer. These are both for .NET 4.5.
11:45And when you go to the WMF page, you'll have the option to download one of these. These are the 64 and 32-bit versions for client operating systems, and then there is the 64-bit version for server operating systems. So first things first, let's get .NET 4.5 up and running. I'm just going to use the web installer. And I'm not going to make you watch me run through all this, I'll run through it really quick here. And there we go, .NET 4.5 successfully installed. Now let's do the same thing for PowerShell here, and we are on Windows 7, 64 bits, so we're going to run this one right here.
12:15So let's go ahead and run this. WMF 4.0, we'll do the same thing here. I'm going to go ahead and choose Yes for the updates. And here it is. So, again, I'm not going to make you sit here and walk through this. So I'll fast forward through all this stuff, and when we're done, we should have WMF 4.0 installed, which will have PowerShell 4. We'll do a restart, and we'll be ready to rock. And there it is, WMF 4.0 installed. So all we need to do is restart, and we should be ready to go with PowerShell 4 here, on our Windows 7 machine. And we're back from our restart. Let's see if everything worked out. Let's run PowerShell as an administrator here.
12:46And we'll run our handy dandy automatic variable called PS version table. And it should say version 4. And look at that, we're on version 4. If we fire up the ISE, this should also be on version 4. You can already tell the splash screen looks a little more modern. And you can see when it opens up, it should look a lot different as well. And there it is. So here we go, we've got the latest version of the ISE on here, as well. Excellent. So everything worked out, and I should also mention that PowerShell can run side by side with other versions. But now, by default, everything is going to run through version 4. Now the last thing I want to mention here is installing PowerShell 4 across the enterprise.
13:21Let's head back to our share here, on FS Nugget, and let me show you a few things. There we go. Now here's the scenario. Let's say you've got 100 Windows 7 machines out there. You want to bring them all up to PowerShell 4 so you can manage them remotely. Are you going to go and log into every one and do it? Hopefully not. Here's what you'll do. First, you'll download your installers. Put them on a network share somewhere. And this is where you'll want the off-line installer for .NET 4.5, just in case you have machines out there that do not have internet access. So get the .NET Framework 4.5 offline installer on a network share.
13:52Then get your WMF 4.0 installers on a share as well, for whatever architectures and versions of Windows you want to support. Then, once you have that in place, it's just a matter of choosing your deployment method. There's a lot of ways to do it. You could use System Center Configuration Manager, or a nice cheap easy free way, assuming you've already paid for Windows to do this, is using group policy. In fact, I've got a batch script in here that will do just that. So the first thing you'll do is create a group, put all those machines inside of a group. Then create a GPO, and as a shutdown script, you'll specify a batch script like this.
14:24A very simple batch script. The first thing it's going to do is query the registry to see if we have .NET 4.5 installed. So you may have some machines that do, some machines that don't. If they don't, this will install it for them. Because it'll come back with an error level of one, and then it'll run down here and install .NET 4.5 from the offline installer that share in quiet mode with no restart. Because we're doing this in a shutdown script, no need to do any sort of restarting. Then we'll check for WMF 4. If that comes back false, then it will install WMF, and it'll check the processor architecture and install the right one for Windows 7.
14:56See, we're not incorporating any servers in here, because we're saying this for a Windows 7 scenario. But this will install the 32-bit one, if we're on x86. It'll install 64-bit if we're not. And that's it. That's a great way to do it. So PowerShell does not like to update itself yet. Hopefully we'll get better support that down the road, but for now we need to resort to archaic methods to pushing it across the enterprise in one fell swoop. But if you only need to install it across a couple of machines, very simple to do. Just remember, .NET Framework 4.5 first, WMF 4.0 second, and you're golden.
15:27So there you go, everything you need to know to get PowerShell 4 up and running in your environment. I hope that this has been informative for you, and I'd like to thank you for viewing.
Getting Started
0:00Getting started. In this Nugget we're going to begin getting familiar with the tools of the trade. So we'll look at the PowerShell console, as well as the PowerShell ISE, the Integrated Scripting Environment. We'll begin by clearly defining the purpose of each one of them, and then we'll jump in and get some hands-on experience. I'll show you how to configure them. Always the first thing we should do in these tools is configure and customize them to make them comfortable. Make them feel like home. And then from there we'll look at how to navigate around in these tools, and we'll even get familiar with executing commands. Let's begin. The first tool we'll be getting our hands on in here is the PowerShell console, pictured here.
0:32What I like to call the Blue Screen of Love. Because we already have a Blue Screen of Death, now we get a Blue Screen of Love. Which is kind of funny because the first thing I do whatever I get into PowerShell the first time is change the color scheme. I'll show you how you had to do that when we get into our demos. But this console is great because it's small. It loads quick, and it's really meant for quick work. Troubleshooting, diagnosing issues. You're going to eventually have a pocket full of go-to commandlets. And whenever something goes wrong, you're going to break out PowerShell, no matter where you are, and you're going to run those commandlets, get some information, diagnose the problem, and be on your way.
1:05Or maybe expand that to multiple commandlets all piped together. Stuff we'll get into. But this PowerShell console is great for just that. Quick work, troubleshooting, not for building big, complex scripts. And the reason is because it doesn't really give us a lot of assistance. This is not a good learning tool simply because it's a chore do anything. Copy and pasting, a chore. Navigating around, a chore. But we can make it a little better here with some key strokes. By learning how to become efficient here with the keyboard and the console, you'll become a wiz in no time.
1:38The other thing I want to mention is this may be your only option. Server Core, anyone? Yeah, there's no GUI in Server Core. So it's still going to be beneficial to learn how to get around the console, and really by having both of these tools in your pocket is the ideal way to go about PowerShell. The second tool you'll be getting familiar with here is the old ISE, the Integrated Scripting Environment. Now this is a great tool. You can use a lot more than what it's intended for. Its intended to be a tool for developing and debugging scripts, but you can also use it as a learning tool because it has so many cool features built in. Productivity features, things like IntelliSense, Tab Completion, Auto Complete.
2:11It's got everything in it. And by the way, Intellisense-- one the greatest features ever-- the fact that we get it in here is great because you can easily take out all the guesswork when you're doing things like finding commandlets, or finding parameters, or finding values for parameters, it helps out immensely. And of course, it's a modern tool. It's not the command line. So it feels like a real modern experience when you're working inside of it. So this will definitely be your preferred tool for doing anything that isn't quick. Essentially anything that you don't just need to get in and get done, you'll be using the ISE for.
2:42Now if you want to get very efficient in both of these tools, I'd advise getting familiar with the shortcuts. So here are the shortcuts for the console, here are the shortcuts for the ISE, and I'll be pointing these out as we go. With that, let's jump into the Virtual Nugget Lab and give familiar with these tools. We'll get them configured, show you how to navigate around, and we'll execute some commands. Here we are in the Virtual Nugget Lab. We are on our Windows 8 client machine. Now the first thing you need to do is launch PowerShell. How can you do that? Well, if you're lucky enough to have a shortcut in the Task Bar, that's all you need. You can right click on it even, and launch the PowerShell ISE from the regular console shortcut.
3:15Just keep in mind anytime you launch PowerShell, ISE, or console, run them as an Administrator or things won't work as you expect them to. Now if you don't have this down here-- in fact, let's just go ahead and unpin this-- what do you do? Well, just do a search for it. Here we go. And if you're on Client Operating System, chances are you'll have both 32 and 64-bit version. So choose the version appropriate for you. And then right click and pin it to the Task Bar. You can even pin both of them if you'd like to. So there we go. We've go them both pinned to the Task Bar and we're ready to rock. Let's launch PowerShell. Remember, give it a right click to run it as an administrator.
3:47And we're logged in as Domain Admin here, so we didn't actually have to do that, but you can verify other way by just checking if administrator is up there in the Title Bar. Now notice the font size, extremely small, we're going to want to fix that. Color scheme, that's all a matter of preference. But I'll show you how to change that. And then I never like where it puts the window. It always puts it at 0, 0, 0, left, 0, top. I like it kind of in the middle here. So it's nice and centered, and we can see the Desktop. But notice-- this is kind of neat. Once you do this kind of thing right here, change it around, move it around, now when we go into Options, it's actually going to pick up those settings and we can apply them.
4:20So to get into the settings for the shell, just click on the Control Menu, and go to Properties. Let's just highlight some of the important ones here on the Options Tab. Quick Edit Mode is important because that's going to make copying and pasting feel a lot less archaic. You know what I mean. Without this on, you're going to be stuck going through the Edit menus to mark and copy and paste, and it's a huge time sink. So make sure that's turned on, then you can highlight, right click to copy, right click to paste. Makes it very easy. Insert Mode, we want this turned on as well, because whenever we type, wherever our cursor is, it's going to insert those character rather than overwrite anything to the right of the cursor.
4:51So those are good. Let's add to font. Let's absolutely increase the font size. 16, 18, 20, whatever is comfortable for you. We'll put ours at 16 here. On the Layout Tab, the buffer size, this is how many characters are stored in memory. For the width, it's on a line. So it'll go this way until it runs out of memory, and then it'll push on to the next line. Height is going up and down. How many lines it stores in memory. Now the really important thing here comes with window size. Width and height, that's obviously just the window size that we have here. But if your widths are off, especially if your screen buffer size is larger than your window size, then you're going to get a horizontal scroll bar.
5:27And that's going to make working in here very difficult. So just make sure that your widths line up. And then all the rest of the stuff is pretty straightforward. And notice this was 0, 0, but I moved it before I came in to here. So it put our left at 211, and our top at 113. So that's good. So our window will show up right here. And finally, the Colors Tab. Here's where you can again, set up your color preferences for our background texture. If we want to make another, let's just change this to how about a 60, 60, 60. This will give us a nice, gray background here. And then for the text, let's make some orange text here. Let's go 255, 200, and let's go 110?
6:00110. Looks good. There we go. So we're good. Let's hit OK. There it is. Now if you don't like how that turned out-- like, ours a little off the screen here-- you can just go back in and change them. But watch this. I like how this is, it was just positioned a little funny there. So let's move it back. Now if we were to close out of this and watch it again, it remembers the settings. It doesn't remember that we moved it here, because we didn't go back in. So if we do this, go back into Properties, head over here to Layout. And just verify it looks good. Hit OK. Now if we close out of it and relaunch it, boom. We're good to go. Now all of those settings are stored in the shortcut.
6:31So if you want to give yourself a consistent experience across all of your PowerShell installs, what you can do is set up what's known as a Profile Script. And we're going to get into Profile Scripts down the road. We got a Tips and Tricks Nugget, which will go over all those random things that'll make your life easier in PowerShell. But what's really cool here is everything we just accessed in there is actually accessible through the automatic variable known as Host, which actually maps to the commandline Get Host. So this is great because this will allow us to programmatically do anything that you just saw on there, and then some. So we could do Host.UI.rawUI.
7:02Let's go to Window Title, for instance. Window Title-- I'm just going to use Tab Completion there to find Window Title equals super PowerShell ninja. Look at that. And we just changed the title. So what's great about this is now we can create a script. And we're going to get into scripting all that stuff, so we'll see how to do all this stuff. But we can create a script that contains all of our settings. Maybe when we create our own aliases, something else we'll get into, all kinds of things that we can do to pre-configure our environment. And then any time we launch it, it'll run that script. So again, profile scripts, down the road scripts, down the road, in general, we'll show you how you can do some neat things to make your life easier.
7:37And get a nice, consistent experience then across all of your PowerShell installs. Something you want to do, because if we were to close out of this-- ooh-- and then open it back up. Look at that. Our window title is gone. But all of our settings here in the local machine are fine because anything we did through here was stored inside of the shortcut. Let's do some PowerShelly stuff. We'll get some basics out of the way, and then we'll move into the ISE and we'll actually start doing stuff with Get Command. One of my favorite commandlets here in all of PowerShell. Now the first thing you're going to do, especially if you're a GUI person, when you get to this point right here, you're going to be like, uh now what?
8:09What's next? And that's where Get Command is going to come in handy. But for now, let's just go over some basics. Let's just type in a command here. Do something awesome. Hey, that's not a command. So this is what an error looks like. Get used to seeing the blood on the screen here, and trying to understand what it's telling you. But this is pretty much saying, do something awesome isn't anything that PowerShell can find. It's not a commandlet function script. It's nothing that I can do anything with. What about this one? Dir. Hey, we know that works. Dir. Everybody know what Dir is. Directory listing. So that got us a directory listing based on our current location here, which is our profile.
8:41Administrator dot in the Nugget Lab inside of the user's directory. Watch this. How about Dir with the recurse flag? What's that going to do? Or parameter? That's going to run through all the directories. Now here's the cool thing about PowerShell, Dir is actually what's known as an alias for something called Get Child Item, which is the same thing. If we run that, same thing as Dir. Here's the thing, a lot of these commands that we're used to are just aliases. They're just shortcuts on top of PowerShell. So a lot of things are just sitting on top of PowerShell commandlets. Here's the really neat thing-- and this is why the PowerShell team is so brilliant-- they made it comfortable for Windows users to pick up and do what they're used to doing, and they made it comfortable for Linux users.
9:18LS, right? That's a Linux command. Does the same thing. Those are both aliases on top of Get Child Item. And that's a command we'll look at down the road, because it is a very good one. Let's go over some of our characters here. Now the back to character is how we do multi-line entry. So if we hit Enter here, we're going to get the double command prompt there. This means it's waiting for more info. So we could do a recursor, we could Enter. We do add more parameters there. Keep hitting Enter. When you hit Enter twice or on a blank line, it's going to finish it and actually execute the command. We're going to get into all the other ones as well.
9:50Single quote, double quote, brackets are going to be important, parentheses are going to be important. All this stuff will be more important when we get into scripting. But for now, just know the back take there allows us to do multi-line entry. Let's clear our screen here. Let's do a little CLS. Or we could do a Clear, or we could do a Clear Host, which is the actual commandlet underneath both of those aliases. Now let's look at one of the greatest features here in the console, and that is Tab Completion. If I start typing something out-- let's say I'm looking for a commandlet that will help me out with services here. In fact, let's just do a get SC. I can hit Tab and one, it'll fly through all the available options.
10:23But two, if I get one that's right up to where I'm looking for, for instance, Get Serve, I'll hit Tab, and it'll complete it for me. That's the one I wanted. So that will save you a ton of typing. And this works at all levels. This actually works at the parameter level. So I can type in D and hit Tab to iterate through all the potential parameters here that start with D. Let's see, I was looking for Display Name, which I just passed. Now I can hit Shift Tab to go backwards. There it is. Display Name. And first, before we do that, let's just execute Get Service here. Boom. There's Get Service. So it shows all the services on the system sent back to us here in the console. Now I can hit Up to recall my Command History.
10:55This is going to become a vital when you are building pipelines. Because you execute your commands, see what you got. And then you can start adding onto it. So let's do Display Name here, and I hit Tab. It'll complete it for me. Let's say we wanted to see all the services in here that start with WIN. We do WIN, you use the wild card character, hit Enter, and there they are. Now let's recall that commandlet. Say that we want it to sort this, because it's kind of all over the place. It's sorted right now by system name, or the name-- not the display name, but the actual name of the system name of the service. And then we've got status over the place. So if we wanted to do that, we could do a pipe.
11:27And we're going to get all into piping. Pipelines are a critical part of PowerShell. But we're going to pipe these results over to the Sort Object. And we're going to say, yep. We want to sort by status. Boom, there it is. Now we're sorted by status. Pretty cool. Another critical one here for getting started is Control-C, which cancels the execution of a command. That's important, because how many times have you executed a command and you're just sitting there staring at blank screen? This will help you out at ton here. And especially if we did something like this. Let's say that we did this.
11:58And we forgot to put our filter in there for Display Name, so we just do a Get Service. But we're going to do it across the network. We're going to run Get Service across all the computers in our network. Let's just do two here. Get Nugget FS Nugget. This will probably still come back pretty quickly, but if it didn't, we get a Control-C. Boom. It bombs out right there. See that? Before it even got to the end. And let's let it get to the end. There you go. There's the end. So Control-C is a life saver because it can get you control of the Console Back. So there's a quick tour of the console. I think those are the really important points for getting started.
12:29Customize it, make it feel comfortable, get familiar with Tab Completion, and also some of the critical ones there as far as history goes. And by the way you can always hit F7 as well to view your history. All those keywords shortcuts I showed you in a previous slide, get familiar with all of those because they're a big, big, big help, and they'll save you a ton of time. Especially all the history ones, and then Control-C, obviously being a big one. And some of the navigation ones too. Like navigating around in here, you can go-- if you'll control down, it'll bounce back and forth between the words. See that? Those are super useful too when you have a big command you're trying to navigate around.
13:00A lot better than hitting left arrow a thousand times. So get some practice in. Just fire up PowerShell, type in a few commands. If you're don't not sure what commands to type in, we'll get a ton here at the end of this Nugget. Type those in, and just go through all of those keyboard shortcuts, just to start committing them to muscle memory. You'll thank yourself down the road because you'll be so much more efficient here in the console. Let's move on to the ISE. So again, the console is great here, especially for quick things for troubleshooting, when you just need to get something done. You're going to have a handful go to commandlets. And you're going to be able to write these long complex pipelines.
13:32The console is great for that. But the real power is in scripting. Especially when we're going to start automating lots of processes and integrating products together, and doing all that kind of stuff. You're going to want to work in the ISE. In fact, we're going to be spending most of our time in the ISE just because it's more modern, and there's a lot of great productivity features in it. So let's first launch it, right down here on the Task Bar. We'll launch this. Make sure you again, you run it as an administrator. And the first thing you want to do is customize the environment. You can do that in the Tools Menu here. Going into Options. So again, here's all your fonts here for the Script Pane and the Console Pane.
14:02We'll go over all these panes in here. But what you want to do first is just increase the font size. Let's again, put ours up to 12 so we don't have to strain when we're looking at this stuff. With that out of the way, let's go over all this. So this is your scripting pane. This is where we're going to be doing a lot of our work here. Like, Get Service. Here it is. Notice right off the bat, something amazing happened. It popped up with a list of all the valid values, based on what we typed in. This is IntelliSense. This is one of the greatest features that ever hit a development environment back in Visual Studio, and now we get it in PowerShells Integrated Scripting Environment, which is great.
14:34It's just going to save us a lot of time and guess work. And it'll save us on a lot of typing too. Because we can click these things, and it will type it up for us. You can still do Tab. It still supports Tab Completion and all that. But watch this. I hit a parameter-- a dash there for perimeter-- it's going to pop up all the parameters in here, and even give us the data type that perimeter expects. We're going over parameter sets, parameters, data types, all different kinds of parameters here when we get into the Nugget following this one, Getting Help. We'll go over all that stuff and syntax. But this is awesome that it pops up with all the potential parameters. So here it is. Here's Display Name.
15:05And then we can start typing, and it's going to give us a valid values, in this case, of all the display names of the services. How cool is that? If we didn't want Display Name, we wanted the System Name, we can do Name, and look at that. Here's all the System Names. How cool. So let's do Display Name again. Just type display. I'll hit Tab there. And let's do WIN with our wild card, and now I'm going to run this. And what I'm going to do is highlight this. And I'm going to hit this button right here, Runs Selection. We'll talk about the differences of those in a minute. But this is your Development Pane. This is where you'll be writing code, and this is your console. Just like the same exact console that we were just working.
15:37In fact, you can even come down here and type in whatever you want. And you still get IntelliSense and Tab Completion. We can hit Enter, and there's all the services again, on the local machine. Now the other pane we have open by default here is the Command-AddOn Pane. And this is really nice. It's just a browser for all the commandlets on the system. And it even breaks it up by module. Now watch this. Let's say we wanted to find all the commandlets on the system that have to do with the computer. They have computer in the name. We just type in computer, and they're there. Let's say we only care about Active Directory commandlets. We could drop down and choose the Active Directory module. Again, we'll talk about modules as well in a future Nugget. Once you find what you're looking for, click on it, here's all the parameters.
16:10You Can hold your mouse over these fields, get a tool tip of the type, and whether it's a mandatory or optional parameter. And then you can fill this out, you'll get an insert and it will actually write the code for you. Pretty cool. But what I like to do is close out of this because it takes up valuable screen real estate. And you can always get it back here with the last button on the Toolbar if you need it. Now the other button here next to it is called Show Command Window, and this is great if you like to use the GUI for executing commands. So you can highlight a command here, Get Service, and we can hit Show Command Window. And here it is. So here's all the parameter sets.
16:40We'll cover those in a future Nugget. And here's all the parameters then for each parameter sets. Here's Computer Name, we use that with Get Service. And here's the Name. Here's Display Name. So this is again, the system name down here. Here's the parameter set for Display Name. You can put in Computer Name to all these. But this is great for learning. Obviously, we're trying to get away from GUIs with all this. But this is absolutely great for learning parameter sets and what parameters are expected for each parameter set. And again, the types. And you can just enter the values in here. And you can get a copy, it'll write the whole thing out for you, or you can hit Run as well.
17:12So fantastic. We'll definitely get back into Show Command in the future, just because it's such a helpful learning tool. Now let's go over some these other buttons. See this here? These are how we can control our real estate here. The one that it's on by default here is stacked. So again, Development Pane up here. Console Pane down here. We can put them side by side, if you prefer that. But what I really like to do is this right here. That way we get the full real estate. We can focus on just our script and writing our commands in here. And then your best friend when you're in this view is going to be Control-R.
17:43See that? You can just flip back and forth between Control-R all day long. And any time you execute anything anyway, it's going to flip over to that. Then you can hit Control-R to get back. Retype. So this is good because it gives you a lot more real estate to work with. A couple other buttons up here. This will launch PowerShell dot exe. Now notice it didn't pick up our preferences, because this launched literally PowerShell dot exe, not the shortcut where our settings are stored down here. So that's that. This is for remoting. This is going to be super useful because you pop this open, specify a computer name, and it's just like you're sitting on that computer.
18:14So you can have lots of tabs with all your computers open, and you can fire off commands individually, or just use the power of remoting send one command to all of them. So I can't wait to get into remoting. As you can tell, I love it because it's one of most powerful features here in PowerShell. These next three are all for executing scripts. So the Run Button, which is F5, will execute the entire script. F8 is the Run Selection, which is what I was doing here. So if you have a lot of commands in here, you can just highlight a command, hit F8, and it will only run that command, not the entire script. Then you have all of your standard productivity things. Redo, undo, your squeegee here, which will clear the command line, same is executing CLS or Clear Host.
18:48Cut, copy, paste, the modern day way, much easier to do in here. And then all your standard ones. So there you go. Now let's move on here and get familiar with Get Command, because this is the first thing you're going to want to do when you get into PowerShell is play a little bit. And this is the best command for learning how to learn in PowerShell. So let's get some space here, and let's just start typing. Get c o m. It knows what we're looking for. So we can Tab Complete that, and let's just run that by itself. First I'll highlight that, I'll hit F8, and there we go. A list of all the commands and functions here in PowerShell.
19:22That does not bring back any legacy Windows commands. Anything non PowerShell. To do that, we can just pass in a wild card. And what this'll do is the same thing, except it's going to go out and it's going to get, not only PowerShell stuff, but anything that's in the path environment variable too, which by the way, is anything inside of here. We can do environment colon path. Boom. There it is. So anything in those paths, it looked into and it's going to pull out. And by the way, PowerShell, any of those legacy utilities, anything that isn't a command letter, and it isn't in PowerShell as a function or an alias, all things we'll cover, is known as an application.
19:57And that's why you see all these here are tagged as applications. Look at them all. Tons of them. But we can use Get Command to find anything. We can use it to find again, PowerShell specific things, we can use it to look for utilities, anything. In fact, say we did want to just look for commandlets. Well we've got a parameter for that. It's called Command Type. Here it is. It's base, and look at that. We can find anything here. We can find an alias, commandlets. So if you want to see all the aliases here in the system, we'll highlight it, hit F8. Look at that. There's all the aliases in here. Let's see if we can find Dir up here.
20:29And I see it. There it is. Dir. [INAUDIBLE] forget child item. Pretty cool. Delete for remove item. So that's a great way to do it. And then we could also say, we just want to see everything that's a commandlet. We can type in Commandlet here. C m d l e t. Hit F8, and here's all the commandlets in the system. Now let's say that we were looking for something specific. Like say, a service. Any commandlet that has to do with service. So let's do this. Let's type in Service with some wild card surrounding it. Highlight it, hit F8. And look at this. Every commandlet that has service in the name.
21:01Now notice something interesting there. We didn't actually type this right here. We didn't type in Name. Although this would give us the exact same result. That's because this is known as a positional parameter. Meaning it's a common parameter, as long as we put the value where it shows up in that parameter set, we don't have to specify the name. So it can save you on some typing there. Let's take this to another level. Let's say that we've got a lot of service stuff down here, but we really only care about services within Active Directory, because that's our ultimate goal here. We can type in module as a parameter, and type in Active Directory.
21:32Highlight it, hit F8, and look at that. Now we have everything that has to do with service that's a commandlet inside of Active Directory. Now let's do another one. Now commandlets as you see here, have a verb now naming convention, which is just awesome for so many reasons. Number one, it makes it predictable. Makes it easy to find things. But it also makes it easy to do a search. A Google or Bing search, because there's nothing else out there. If you search for specific command on Google or Bing, you're going to get that help just for that command. So a lot of brilliant design decisions, as you're going to see as we go through this course with PowerShell.
22:02And just makes PowerShell a pleasure to work with. But watch this. Let's do Get Command and say we want to find everything with the verb get. Highlight it, hit F8, and look at that. There's everything with get in it. We could also do everything then with a noun of let's say service. Hit F8, and there it is. We've got one Get Service. That's the one we were looking for, and that's the one we were using up top there. Let's say we wanted to find all commandlets that have the computer name parameter. We can say parameter, computer name. Highlight, hit F8, and look at that.
22:33Here's everything that supports the computer name parameter. So you can see this is a very versatile a little search engine inside of PowerShell. Get Command. It's your friend. And remember, one of the things you can do when you're first learning this is just highlight it, hit Show Command. And now we can see all the parameters. These are both the parameter sets here, one for searching for commandlets, one for searching for everything. Here's all the parameters that we can use. Pretty cool. So we used up parameter name right there. You can even go to parameter type. Earlier we used a module. We used noun, we used verb. So we used a good amount of all the parameters here inside of the commandlets set parameter set.
23:09So that's a good way to get you started here. Just jump in, start playing with Get Command. You can do it either here in the console, or do it in the ISE. But do it in the ISE because you'll just get a lot of help with IntelliSense, and it makes it just a lot easier to work with and learn. In this CBT Nugget, we showed you how to Get Started with PowerShell, where we covered the tools that we're going to be spending all of our time in here, the console, and the ISE. We saw how to configure them, navigate around, and even execute some commands. I hope this has been informative for you, and I'd like to thank you for viewing.
Getting Help
0:00Getting help-- this is another one of those incredible features in PowerShell. The help system is great from so many perspectives-- from installing it and keeping it updated to using it. It's comprehensive. It's simple. It's flexible. And if you're new to PowerShell, this Nugget is for you because this is how you're going to teach yourself how to learn everything there is to know in PowerShell. So in this Nugget, we're going to go over all of the things you need to know about the help system, and it's all wrapped in three commandlets-- Update-Help, Save-Help, and Get-Help. We'll even talk a little bit about syntax here, so we'll get familiar with parameter sets, different kind of parameters that commandlets support, and even talk a little bit about data types.
0:36And then we'll jump into the Virtual Nugget Lab, and we'll look at lots of demos to see the common ways to use help, and I'll even show you a couple of cool things you can do with the help system. Let's do it. The first commandlet we're going to look at here is Update-Help. Now, this is something that should be high in your post-installation checklist. In fact, the first thing you should do when you fire up PowerShell for the first time after installation is run Update-Help, and that's because PowerShell comes installed with minimal help information, just the bare bone information for all the topics, for all the modules here in PowerShell. And this is another brilliant design decision by the PowerShell team because by wrapping all of the operational side of help into a commandlet, they give us the power and flexibility to choose when and how we want to keep these help files updated.
1:13And it also obviously makes the download and installation much, much shorter. And because help is constantly changing, why wrap all that into the installation? So what Update-Help does is it will download all the latest information, all the latest help topics for all of the commandlets and the conceptual topics, which we'll talk about here shortly, in PowerShell. It's really cool how this works. This will actually do version checks for all the help topics and only download the differentials-- only the things that have changed since the last version for that help topic. Now, because Microsoft is hosting these help files, they do put some limitations in place, and that is, by default, Update-Help will only run once per 24-hour period on the machine that you run Update-Help on.
1:54So if you run it multiple times, any subsequent requests will be ignored. And there's also one-gigabyte limitation per uncompressed module. And, then of course, the other one is it does version checking. You can overwrite all three of those by using the force parameter in Update-Help. That will ignore version checking. It will ignore the one-gigabyte uncompressed content per module and the once-per-day limitation. Now, just to show you how easy this is, let me bring up a PowerShell command prompt. And I'm on my local production machine. This is not a machine that's in our virtual Nugget lab, so we'll do this again when we get into the virtual Nugget lab. But if we run a Update-Help, that's it.
2:25That's all you need to do. And I've already ran it on this machine-- today, in fact. So it's not actually downloading anything. It's doing version checking and moving on, and this will be very fast, see that? But if I were to run that with a force parameter, now it's going to go and actually download everything. So this would actually take a while to do because it's-- and these help topics are small for each commandlet, but it's still going to go out and download everything for every single module. So that's Update-Help. Now, the next we're going to look at here is Save-Help. So Save-Help is great because it allows us to save the help topics to the file system or to a file share somewhere.
2:57And this is going to be great for a couple of use cases, but the big one here is if we have client machines out there, say machine one and two here, that have restrictive internet access. Maybe they're behind a firewall or no internet access. We can still keep those machines' help topics updated. Actually, using the Save-Help commandlet is a breeze. We're going to call save-help. We can use the destination path parameter to specify exactly where these help files are going to get downloaded to, and then when we run Update-Help, well, they're going to use the source path parameter, pass in the share, and it will update that installation of PowerShell's help topics from the help in that share.
3:28Now, here's another great use case, and I would recommend setting up this process, because it's great for both connected and disconnected clients, and it centralizes all of your Update-Help operations. So let's say we've got a server out there that does have internet access. We could set up a PowerShell Java on that server to run Save-Help once a day, store it inside of a file share somewhere. Then, from our connected and disconnected clients, we could put an Update-Help pointing the, to that share inside of their profile script. So once a day, or any time when they launch PowerShell-- of course it will only happen once a day. But when they launch PowerShell, it'll go and get all the latest and greatest help, and that'll keep everything in sync across all the PowerShell clients in your network.
4:06We'll take a look at the script that does this from the server side, and we'll look at the profile script that does that from the client side once we get into, again, jobs and scripts later on in the course. On to the big one, Get-Help. So whether you're new or experienced with PowerShell, this is going to be your best friend, because this is how we're going to learn how to learn in PowerShell. Get-Help followed by the command will return the help topic for that command. We can also use help and man, which are aliases for Get-Help, but these pipe their other output, the help topic, to more, which will give us a paged view, rather than just spit out the entire topic and scroll us to the bottom.
4:38So when you're dealing with large help topics, it will help to use these, because we can go line by line through the topic Commandlet-? is the same as Get-Help for a specific commandlet, and it works the same as Get-Help. It just brings the whole topic, so it doesn't pipe it to more. You can also pipe Get-Help and commandlet to more, but help and man are great for that because they do it automatically. We also have about topics. These are great because it's essentially the documentation around all the core functionality and mechanics here in PowerShell. So I'll show you how you can find those and use them. And finally, you can use Get-Help as a search engine.
5:08So we just call Get-Help with a keyword, and it'll scan all of the full help topics and return us back things like commandlets and help files where that keyword shows up. Now, in order to become an effective learner PowerShell, we need to know how to interpret the help, and a lot of that's going to come down to understanding how to read syntax. The first thing you're going to do when you're learning a commandlet-- you want to know how to use it-- is you're going to look at the syntax to see what kind of parameters it supports. And understanding the different kinds of parameters and understanding perimeter sets will go a long way there. So let's start right there with parameter sets. Each commandlet has a number of ways that you can use it.
5:41Some of them have one or possibly more. Take Get-Help for instance; there's actually six or seven different parameter sets. I just included three in here. But a parameter set defines a specific way that we can use that commandlet. So here's how this works. Each parameter set has something unique about it. For instance, Examples has this example switch parameter. We'll talk about switch parameter shortly. But if we were to write a command that had the examples flag in it, for instance, get-help name of the help topic dash examples, we would be locked into this parameter set, and that's the functionality that we would get. If we were to write a very generic command, say get-help and followed by the name of the help topic, well, which one is PowerShell going to choose?
6:15These all have name in it. It would choose the first parameter set. And the All Users view for Get-Help, kind of think of it as the default parameter set. Because if we don't use anything specific in all the other parameter sets, then it's going to default here to the All Users view. It's also worth noting that you cannot mix and match these unique parameters across parameter sets because PowerShell won't know how to resolve the parameter set that you want to use. And just to give you an example of that, let's bring up PowerShell here. Let's say we wanted to get-help for say get-command. There's get-help for get-command, right? Let's say we wanted to see just the examples.
6:46I'm going to pipe this to more-- same as using Help rather than Get-Help. Now it's going to do it one line at a time, see that? So there's all the examples. I'm going to Control-C out of this. And let's say we wanted to add parameters in there. Now, we know this isn't going to work, right? Because we're mixing unique parameters across these parameter sets, so that should be parameter. And what parameter do we want to search for? Let's just put anything here. It doesn't matter because it's going to error out anyway and say the parameter set cannot be resolved using the parameters that we supplied. So those are parameter sets, and any time you launch Help, that's going to be the first area. Underneath Syntax, it's going to list all the parameter sets.
7:17In fact, let me just bring up PowerShell real quick once again. And let's do a help for Get-Help. Look at that. So since we did a Help, it's going to give us the paged approach starting from line one there. We can hit enter to go line by line through the help topic. But check this out; look at all these parameter sets in here-- lots of different ways to use Get-Help. And one thing I like about the online help-- notice back here I have these labeled with just one-word descriptions for these parameter sets. Well, let me Control-C out of this and add the online switch parameter to this command. It's going to launch a browser and take us right to the online documentation for Get-Help.
7:49And it's even going to launch us into the version that we launched it from. Look at that? It knew we were PowerShell Version 4, so it gave us the help topic for V4. If we were to launch this for Version 5, it would have taken us to this one. But here's what's cool about this. It actually adds the description for the parameter set. So we just used this one right here online. We used that unique parameter to this parameter set, so we were locked in to all these parameters, and that's what happened. Then it fired up the help topic here. We got that functionality. So this is great because it just allows you to quickly see what parameter set you'll need to use for whatever functionality you're looking for.
8:19Let's dig a little deeper into parameters. So parameters are how we pass data into a commandlet so it can perform its function. And when you're looking at syntax, you're going to see the name of the parameter, followed by the data type, the kind of data that you're going to pass into that parameter. And there's lots of data types out there-- strings, integers, dates, times, longs, Booleans, all these things that we'll see as we go throughout the course. But the most common one you're going to see by far here is the string parameter-- just passing in character data. But you may also see these open and closed brackets at the end of the data type. And that just tells us that this is accepts an array.
8:50It accepts multiple values. Take the computer name parameter, for instance, that we've used in previous Nuggets. We're going to specify the computer name parameter and specify computer name comma computer name comma computer name. That's specifying a list, a comma-separated list, that it's going to use to operate on all those machines. Now let's talk about the different kinds of parameters and all these brackets. Notice we have brackets over the place. We have brackets around just the parameter. Sometimes we have brackets around both the parameter and the data type. Sometimes we're missing brackets entirely. So let's start with positional parameters. You're going to see positional parameters are going to be the parameters that are going to be the most commonly used, and they're going to have brackets around just the name of the parameter-- not the entire parameter, but just the name of the parameter, like name, for instance, with Get-Help.
9:32This means we don't have to actually supply the name of the parameter, and we've already seen this. We used this quite a bit here in PowerShell by just doing a get-help get-command. Notice that we didn't specify the name parameter. That is equivalent to this right here. So there it is. We can use either one of these. This, we're using it positionally. This, we're using it as a named parameter. So it's not a positional parameter, it's a named parameter. Every parameter is going to be one of those. And again, you're going to see name parameters for the most common parameters, and it's good because it saves you time, especially when you're just writing commands inside of the shell.
10:06As a best practice though, always specify names of parameters inside of your scripts, especially if you're working with other people. It just makes it much easier to work with, and it's very clear. Also worth mentioning, position the parameters are relative. Meaning, we can do this right here. Let's go back to our positional parameter, and let's just throw the example switch right here. First, notice we're using that first and then we're doing get-command. Yeah, it's still going to work because get-command-- or name, I should say-- is positional.
10:36So it was the first positional parameter that we used, and that's why it was OK to use. If we had other positional parameters inside of here, they would need to go in that order. So we would need to ensure, no matter where we put it, that the name parameter. If we didn't specify a name, would have to be first, and then so on and so forth. And I'll show you, when we get into deeper into the help topics here, how you can identify the position of a positional parameters. So that's positional parameters. It just simply means we do not specify the parameter name. So just a little great time saving feature there, especially either when you're fighting fires or when you're doing things like this, getting help.
11:10Who wants to type the dash name help topic every time they want to get help? Wouldn't it be better if we could just to get-help commandlet name? There you go. All right, so the next one we have here are mandatory parameters, and these are parameters that do not have brackets around anything. So, examples, for instance, is a required parameter inside of this parameter set. Parameter is a required parameter inside of this parameter set. So that's all mandatory parameters are, are ones that do not have any brackets around them. We also have optional parameters. Those are ones where you have bracket around both the name of the parameter and the data type.
11:42So full brackets around the whole thing just simply means it's optional. And we also have switch parameters, and those are parameters without a data type. That just simply means on or off. If you specify that parameter, it's on. By default, all switch parameters are off. Let's make sure we have this down. I'm going to quiz you, ready? Say it with me now. What is this right here? This is what? It is an optional positional parameter. It's positional because we have brackets around the name of the parameter, but it's also optional because we have brackets around the whole thing. Now, what about category?
12:13What's that one? That is a named parameter. That also accepts an array as a data type, so we can pass in multiple categories. But remember, if it's not positional, it is named. What about, let's do this one right here. What's that? That is a mandatory named parameter. What about this one right up here? Right, that's an optional switch parameter, cool. Now, there's one more parameter types that I want to mention here, and that's called partial parameters. This is another one of those time-saving features. So again, best practice, don't do this, especially if you're in scripts-- type everything out.
12:45But if you're just troubleshooting, you want to get things done quickly, or you know commandlets really well, this will save you some time. Partial parameters mean that we only need to type the parameter name up to the point that it's unique and PowerShell will know which one we mean. Just to give an example here, let's get back into PowerShell. If we were to do a get-service and we want to specify the computer name, usually we do this, right? We type the whole thing out and then pass in our list of computer names. We don't need to do that because there's only one parameter that starts with C. So we can do that, and we'll get the same exact effect. And here, just to show you how you can find that, let's do a help on get-service, and let's do a P. Look at that.
13:19I'm already using partial parameters. If we look down here, there's a-- oh, no, there's two. That wouldn't work. Look at that. There's path and parameters. We'd actually have to do par. There we go. Par is for parameter. And then let's just do a C*. We're wild card searching the parameters here for get-service, and it's only going to return one-- just computer name. That's it. So those are partial parameters. So that's interpreting Help. Understanding the syntax in all these different parameter types will help you immensely in teaching yourself how to learn PowerShell. And kind of my workflow, whenever I see a new commandlet, is I'll go to the Help topic for it.
13:50I'll look at all the different parameter sets, and then I'll start digging into the parameters themselves to understand what they all do and then look at some examples. It's a great workflow for learning how to use all these commandlets. With that, let's jump into the virtual Nugget lab. I want to show you how to use Update-Help, Save-Help, and the many cool things that we can do here with Get-Help. Welcome back to the virtual Nugget lab. Let's bring up the ISE here and let's open up our PowerShell file containing all the commands for this Nugget here, 04, getting help. So we'll open that up. Here's all the commands we're going to be working with, and we're going to start with updating help. Now, before we even run Update-Help, let's run Get-Help against Update-Help to see what we've got here.
14:22We'll run that selection, and you can see we just get the basic help topic here, a nice quick synopsis. We get our parameter sets listed here and a description. So we look at the differences between these parameter sets. Once has source path. That's what's unique to this one. So this is how we will run Update-Help against a copy of help that's been locally downloaded or downloaded on a file share somewhere. And then our second one here, the difference is literal path. So that's the difference. So we could get more information on those parameters by adding the detailed switch here, and we'll go over what all these mean here shortly. But detailed will give us the parameter description.
14:54So if we scroll up here, as well as examples, here are all the parameters. So now we can see here's our literal path. So this is different than the source path parameters because the value of literal path parameter is used exactly as it is typed. Then you can come down here and see the source path parameter as well. So that's Update-Help. Let's go ahead and run it here on this local machine. We'll highlight that. I'll hit F8, and that's going to go ahead and run Update-Help. So this is going to get our help, update it to all the latest content here on this local machine. So that's how we can Update-Help from the internet. What if we wanted to save help locally and then update it based on that path?
15:27Here's how we can do it. If we open up the directory here-- I made a directory inside of our Nugget lab files called Help, and right now it's empty. So if we run Save-Help and specify a destination path pointing to that directory on our file server, it's going to download help locally. So I'm going to hit F8 to run that. It's going to do pretty much the same thing we just saw. The difference being it's loading up this directory with all of the help topics. So now we could go ahead and run Update-Help and specify the source path parameter pointing to that directory, and it will Update-Help on that machine based on those help topics save there on the file share.
16:00Now, I mentioned the common thing to do is to automate this process, and there's a number of ways to do it. But the examples for the Update-Help help file actually show you how to do this. It's really cool. So let's just type in the example switch on Get-Help, and this will show us just the examples for Update-Help. And I'll show you a better way to navigate around here. It's painful doing this in the shell. Because if you click anywhere, you'll go back to the bottom, and it's just painful to find things. But example number four up here will actually show you how to Update-Help automatically using a job. So here's a job that will Update-Help for this everyday at 3:00 AM.
16:30And example number five shows you how to do it from a file share-- Update-Help on multiple computers from a file share. So it does a Save-Help, specifying the destination path-- exactly what we just did there. And then it uses remoting invoke command, computer name, passing in a servers.txt, which is just a text file that has a list for every computer that you want to update, and then the script block Update-Help at the source path, like we just did as well. So turning all that into a job on one machine will take care of everything you need. It will download the help file to your file share and then send the Update-Help commands to all the machines that you want to keep updated-- really nice simple way to do it.
17:04Let's move on to Get-Help. Remember I said you could use Get-Help as a search engine? Yes, it's very easy to do-- Get-Help followed by your keyword. Wild cards are supported here. If it doesn't find any specific commandlet to display help for, it'll display anything with that keyword in it, because this is going to scan all of the help topics for that keyword. And if I just run this selection here, check it out. So here's all the commandlets with variable in it, all the help files. This is a great way to find those conceptual about topics. So say we wanted to learn what automatic variables are all about. We could just do a help about_auto, and this also, by the way, supports tab completion.
17:38There we go. And I can hit Enter, and here it is-- everything we need to know about automatic variables. And again, this is a huge topic, so scrolling will be quite painful. But if we get to the top here, you'll get a short description, and then the long description will list all of the automatic variables that PowerShell supports and what they do. So if we scroll down here, we can find host. We've used that one before, right? It contains an object that represents the current host application, and it allows us to control the properties of the host-- very, very cool. Now, here it is again, this time piped to more. The reason I wanted to show you this is because the more function is unsupported in the ISE.
18:10It'll always take you down to the bottom. But I'll show you how we can fix that when we get into functions. We'll write our own function that will paginate the output. What you can do in the meantime, though, and this is just great all around, is you show-window. Show-window is just fantastic because what it'll do is pop open the help topic in a separate window where we can find what we're looking for. So now we could easily find that host. Hit Next-- hey, there it is. There's host, and there's everything it does, and it'll highlight everything inside of here. So this is just awesome-- a great way, especially when you're learning, because this window will stay on top, so you can go over here and develop all day long, and you'll have the help topic right here to search through and find what you're looking for-- very, very, very handy feature there.
18:49Let's look at the many ways that we can use Get-Help. So let's say we want to learn all about the Get-Service commitment. We could run help get-service just by itself there, and this is going to give us very basic information-- just a synopsis, the syntax, a description, related links, commandlets, and remarks. If we wanted to get a little more detailed information, we could add the details switch, which is going to include parameters and examples-- just very basic parameter information. So let me scroll to the top here. We get, again, synopsis, syntax, description, but just basic information about each parameter, basically a description as well as the data type. And then if we scroll down, we get all the examples as well.
19:22So that's a great one. Let's see, what else do we got here? If we just want to see examples, as we saw, we can just run it with the example switch. And if we wanted full help, meaning detailed parameter descriptions, examples as well as notes and input/output types, we could use the full switch. And this is going to give us very, very detailed information here. And if I scroll down from parameters, you can see not only does it give us the description, but each parameter will have these five properties on it. This is a required parameter-- mandatory. Is it positional? If it's not positional, it'll be named. If it is positional, it'll have the number of position that it needs to show up relative to all of the other positional parameters.
19:58Default value-- see computer name here? If we don't type in anything, computer name will always default to the local machine. If it accepts pipeline input-- we'll talk about this more when we get into pipelining. And then if it accepts wild card characters-- so great information here around each parameter. Not only does it tell us what the parameter does, but it gives us those properties around that parameter. If we scroll down here, let's see if we can find one that's positional. There it is. Look at that. Name, it's a positional parameter in the first position. Another really useful one here is the parameter parameter. This is a great way to discover what parameters are supported by a commandlet, and you can use wild card searches against this.
20:31So let's say let's see all the parameters that start with D for the get-service commandlet. I'll hit F8, and you can see we have two of them-- dependent services. This will only give the dependent services for whatever service you're looking for, and then display name, and this is we can specify the display name, rather than the system name of the service. Let's finish this up with a real world look at how to use Get-Help. So here's kind of the flow I go through when learning a new commandlet. The first thing I'll do is pop open that commandlet in show window. So now we have a nice Help window over here to the right, everything we know about that commandlet, and we still have our scripting pane over here on the left that we can use to play.
21:02And what I want you to do next is reverse engineer this command for me. Can you tell me what parameter set this command is using for Get-Service? We've got three over here in our help topic. Which one is this using? Well, the first parameter we're passing in as a positional parameters, so that's kind of a dead giveaway. Because if you look at these three, there's only one that supports positional parameters, and that is the first one. So we're using this, passing in a system name using wild card characters, and we're going to say, give us all the services that start with BI across both of these machines. So let's do that, and there they are. We've got two. But here's the thing, and we're going to get a little ahead of ourselves here because I want to do a little pipelining, but this is really neat stuff to get you moving forward and thinking about the future.
21:39Here's the thing, which machine are these running on? They're both stopped. What if one is running and one was stopped? How would we identify what machine is stopped and which one's running? Well, this is where pipelining can become very, very powerful. So we're going to pipeline that to the select-object commandlet. Again, we'll talk a lot more about this in the future. But I want to extract the machine name, and here we're pulling out what are known as properties of the object. This get-service is going to return us two objects. We're going to pass those objects over to select-object, and we're going to say, we want to pull out extra information that isn't in the default view.
22:12And that's going to be machine name status and, let's say, display name, just like so. And let's hit F8 to run that, and there it is. Now we have machine name. It's formatted a little funky, and here's status and display name. But we could fix that as well. Watch this. Let's go ahead and add to the end of this. Let's pipe all of that to the format-list commandlet. And now we get what we're looking for-- cool. So we're going to get all into objects and all into pipelining here in future Nuggets. Let's take that one step further. Let's say we want to do something with those two stopped services, like, how about start them?
22:46Well, thankfully, because of PowerShell's awesome verb-noun naming convention, we know if there's a get-service, there's probably a start-service. So let's bring up the Help inside of our Help window. Here we'll just do a Show Window Help on Start Service. So I'm gong to go ahead and execute that, and there it is. It loads up our Help here with Start service-- perfect. Now, there's three different ways to use this. One, is to pass in an input object. Hmm, that's interesting. Input object as a service controller also a positional parameter. So this is the data type here-- service controller, and we can pass in multiple services, and it just so happens that get-service returns service controller objects.
23:20So that's what we're doing right here. We're just running a get-service to get those two services, just like we did above, and we're passing those over to the start-service commandlet. So we're using this parameter set, and that's going to start those services for us. If we run this, and then we can head back and let's just run our previous get-service command here. Look at that. Now they're both running, as opposed to being stopped previously. What about the second way we could have done this here? Right here, by using display name, that's our second parameter set here is display name. It accepts an array of strings. Meaning it probably supports wild card characters.
23:52If we looked at the details for display name, we could scroll down here, find display, or we could just search for it. It probably would be a lot easier to do, right? Display name-- there we go. And we can see right-- here it is. Right here, one of the first ones-- accepts wild card characters, true; position, named-- so everything we need to know about the parameter right there. And so we're just specifying the whole name, but this'll be the same thing. Also notice we're using a partial parameter for computer name because it is the only parameter that starts with C, but this would accomplish the same thing across those machines. It would start those based on their display name, rather than passing input objects.
24:23And the final one is pretty much how we've been using get-service, by just passing in the name, wild card character included, and that is, by the way, the default parameter set there. And if you were to do an online instead of show window, that would show us the exact same thing. It would show us these three parameter sets, only we'd get that nice name for each one. That's known as the default one when you work on the system name. Here's the input object parameter set that we were using, and here is the display name. So that's Help. Pretty cool, right? It can really help you learn how to use PowerShell. So my advice anytime you're learning anything in PowerShell, especially when you're learning commandlets, get into the Help, do a show window, and just start playing.
24:59Play with all the different kinds of parameter sets, get familiar with all the different kind of parameters, and definitely go through the examples because those can give you a nice head start on how to use commandlets. In this CBT Nugget, we saw how to get help in PowerShell. We covered the three help commandlets-- Update-Help, Save-Help, and Get-Help. We saw how to interpret the help by understanding syntax and parameter sets and different kinds of parameters out there. And we even did a demonstration in the virtual Nugget lab to show you how to use all three of those help commandlets. I hope this has been informative for you, and I'd like to thank you for viewing.
Commands
0:00Commands. In this Nugget, we're going to define what a command is. We're also going to go over the six different kinds of commands here in PowerShell, such as commandlets, applications, aliases, functions, scripts, workflows. So we'll define what all those are, and then we'll get into the Virtual Nugget Lab and we'll do some fun and useful things. I'll show you how to use Get-Command to search for commands of a specific type. We'll also get into aliases. Show you how you can use aliases, discover aliases, and even create your own aliases. At the end of this Nugget, I'm going to throw three challenges your way. Level 1, 2, and 3.
0:30Now that we're starting to build up that base of foundational PowerShell knowledge, I think it's a good time to start honing those problem solving skills. So at the end of Nuggets going forward, I'll give you some challenges. You can do them on your own. I'll also provide the solutions here in our Nugget Lab files, all right? So this will be a lot of fun, and it'll be a good way to get you involved, and start getting hands-on with PowerShell. Let's begin. Let's talk about commands. So in PowerShell we have six different kinds of commands. And command is really just a term used very loosely in PowerShell. Just think of it as an umbrella term that could be referring to any kind of command.
1:02Could be referring to a commandlet, an application, an alias, a function, a workflow, or script, and those are the six different kinds of commands that we have here in PowerShell. Let's start here with commandlets. Commandlets are the heart and soul of PowerShell. They are native PowerShell commands. They're internal, and specific, to PowerShell. Under the hood, commandlets are just simply compiled .NET framework binaries, such as .dll files. In fact, if you're a developer, or know a developer, they can easily write their own commandlets. So they'll use their favorite programming language, such as C# or Visual Basic, inside of their favorite development environment, such as Visual Studio.
1:36Build a commandlet compile it, give it to us. We can import it and then use it inside a PowerShell. The reason PowerShell is so awesome is because of commandlets, and the reason commandlets are so awesome is because of the .NET framework. And that's because everything is an object. Windows, it's an object oriented operating system. Visual Basic, C#, those are object oriented programming languages, and the .NET framework is an object oriented runtime of the deep type system. And if none of that makes sense, it will. We've got a Nugget dedicated to objects down the road. For now, just think of objects as these rich data structures that we can also do things with.
2:08And just to give you an example, I don't get too deep into this because we're going to get deep into it, but let's take Get-Service. We've actually used this commandlet many times. The Get-Service commandlet, if we were to call that and get back four service objects, we can then take those objects and pass them to another command. We can query those objects to get their state, those are known as properties. We can look at things like the name, the status, the machine name that they're running on. And then we could even do things with them right? We could start them, stop them, resume them, that kind of thing. So that's why commandlets are awesome, because they return objects that we can then do something with.
2:41So those are commandlets, and the more commandlets you know, the more you'll be able to accomplish in PowerShell. So my advice would be to try to learn at least one commandlet a day. Just read through the help file, get familiar with the syntax, the parameters. Go through a couple of examples and you'll be well on your way to mastering PowerShell in no time. The next command type we have here are applications. These are external commands. So all those utilities you were used to working with in the legacy command line, things like traceroute, ipconfig, ping, nslookup, those are all still accessible here inside of PowerShell. So there's very few, if any, reasons at all to go back to this old legacy command line Sure, we can still run ipconfig there, but guess what?
3:14We can come in to PowerShell and do the exact same thing. Very cool. In a lot of cases, some of these have better versions of commandlets. Ping is a good example. We now have Test-Connection, which gives us many more options. And of course it's object based, which means we can do a lot more with it. We also have aliases. Aliases are fantastic, right? These are named shortcuts to commands, and they serve a number of purposes. The obvious one is that they're going to save us on typing. The verb-noun naming convention is fantastic for so many reasons. But about the only reason they're not good for is typing, because they result in long names, even the short ones.
3:47Like Get-Content is still quite a bit of typing. So that's why we have aliases, number one, to reduce the amount of typing we have to do. But number two, this is how people could just jump into PowerShell and do what they did before. They were instantly comfortable because they could still do a dir. Or if they're from Linux, they could do an ls. These both map to the commandlet Get-ChildItem, a commandlet we'll be getting very familiar with. So aliases are great. I'll show you how we can use them, how we can discover them, how we can find them based on the command name, or how we can find commands based on alias names, and I'll even show you how we can create them here, later in this Nugget.
4:18We also have functions, which are a named grouping of commands, and they're extremely useful when you see yourself doing a lot of the same thing over and over across scripts. You can wrap that similar functionality into a function, and then call it by name, and that will give us code reuse. On top of that, it'll ensure that if we need to make a change we're only changing it in one spot, not in multiple scripts. Here's an example of a function, by the way, that I just threw together called Get-NewImages. Any idea what this does? Don't worry if not. We've got Nuggets down the road dedicated to writing scripts, and functions, and workflows, and all this code oriented stuff.
4:49But this is just going to get all the images, JPG images, in the user's profile for the last month. So it's going to take today's date, subtract a month from it, then store inside of a variable, called images, all of the images that live inside of, again, the user's profile directory, and all directories underneath that that have .JPG as a file extension. Then it's going to pipe that list into the Where-Object, which is going to pull out only the images that have a LastWriteTime that are greater than that start date, which is less than 30 days ago. And since I created that function, now I can use Get-Command with the command type of function, and it'll show up in the list.
5:25And then we can just call it by name. I created one image in there called lolcat, put it in there, and that's what it returns. If your head just exploded, no worries. We haven't even talked about half this stuff yet. Variables, pipelines, all this stuff we're going to get into. I just wanted to give you a quick idea of what a function looks like. Now we also have a command type known as workflows. Another very, very cool thing. So if you're familiar the Windows Workflow Foundation, think of it as kind of an execution engine here, that we can use to control processes. We can have them execute in sequence or in parallel across a number of machines.
5:56That's what-- kind of the power that we have brought into PowerShell here, natively. And it's absolutely incredible that we can now take commands and we can have them run all at the same time on a machine, or multiple machines, or we can sequence them across machines. It's going to make things very easy when you have an order of operation that you need explicitly defined inside of your scripts. And here's a really simple example here, actually. Workflow, called it parallelism, that's how we would call it then, as we do down here. And then we define a parallel group of commands. Meaning, these are going to execute at the exact same time.
6:29So if we execute it 10 times, chances are we're going to get different results. One's going to finish before the other one. Finally, we have scripts. This is really just a bunch of commands stored inside of a .ps1 file. But it's obviously a lot more than that, because this is where we're going to all the big stuff. Whenever we need to incorporate logistics, or control the flow of execution, we need variables to store data. We need to use lots of different commands. Maybe we need to do things across products. This is how we're going to get it done. Here's an example of when and how you would use a script. This one imports Active Directory Users from a CSV file. And it's not complete. We'll get in and clean this up down the road and make it actually work.
7:01But just to give you a general idea here, we've got a couple of variables here. One to store the domain name, one to import those users from a CSV file into a variable. Then we loop through each user for each record inside of that CSV file, and then we create an Active Directory User account. We set up some more variables inside of our loop, we call the New-ADUser command line, here, which will actually create the user. Then we set the password never expires to true on this user. Then finally, we enable the account. So it'll run this loop once for each user inside of that CSV file. We save this as a .ps1 file, and then we execute it through PowerShell.
7:34Pretty straightforward. Again, all stuff that we'll get into down the road, just want to give you an idea of what it looks like. Now that we're familiar with all the different command types in PowerShell, let's jump into the Virtual Nugget Lab and do a couple of demonstrations around commandlets, applications, and aliases. All right we're back in the Virtual Nugget Lab. Let's do some work. The first thing I want to do is show you how you can find commands of a specific type. So let's do a help on Get-Command here for the parameter of CommandType. So what this is going to do, is this parameter on Get-Command allows us to choose what we want to look for. Do we want to look for commandlets, aliases, scripts, workflows, functions, or all?
8:10So this all, by the way, is the same as doing Get-Command* which will give us everything. Just doing a Get-Command without specifying a command type, as you see, the default value down here will get commandlets, functions, workflows, and aliases. So what this means, here, is we could do something like this. If we wanted to find all commands that started, or let's say that had proc in it, for process, for the command type of say, commandlet. There we go. That's going to show us all just commandlets that have proc inside of the name. So here's all of our process commandlets.
8:41What about applications? Let's clear the screen here. So let's do something similar here. Let's do a Get-Command. Let's find everything starts with p that is of the command type, how about, application. Remember, applications are external commands, and there they are. Look at them all. Tons of them. And look at--there's ping in there. And by the way, this is going to search everything in the environment variable, inside of your path environment variable, which is right there. If you look inside of there, here are all the paths. You can add your own to it, as well. But that's going to search all of those for all the external commands that start with p. How about functions?
9:12Let's do the same thing here. And let's do a Get-Command. And let's search for all functions that start with cl that are of the CommandType function. There we go. All right, let's head back to commandlets. And what I want to do is just give you a nice, easy workflow for learning a commandlet a day. Here's how I do it. So the first thing we want to do is figure out what we want to learn about. Maybe today we're going to learn about all the different things we can do with services. But before we even go there, because of the whole verb-noun naming convention, verb dash noun is how commandlets are named, which makes it very easy for us to discover. Wouldn't it be helpful to get a list of those verbs?
9:44Well you can. Get-verb. Here's a new command that we haven't looked at yet. Check this out. All of the verbs that Microsoft uses across all the commandlets. So here's all your common ones-- add, clear, close, copy, enter, exit, find, format. So on and so forth. So just by looking at this, you could say, oh if I want to see everything that we can do formatting, we can just do a Get-Command -verb format. And that'll show us all the commandlets that have format as it's verb. Pretty cool, huh? Great. So that's that. Now the next step. Let's say that, again, we wanted to find all the things that we could do with services. Let's do a Get-Command. And this time, let's do a noun for service.
10:15Look at that. There's all of our service commandlets. We can do a Get-, New-, Restart-, Resume-, Set-, Start-, Stop-, Suspend-. Let's say that we wanted to create a new service. What are we going to do next? Probably look at the help topic, right, to get an understanding of what it does, its parameter sets, the parameters within those sets, and some examples. So we can do a help on new-service. And let's just do a -showwindow because it's always a good idea to get this help up here in a new window, so we can search for what we're looking for. And it's just a much easier way to learn about this specific topic. So we can see that there's one parameter set. We could dig into all the parameters in there.
10:46But let's say we-- now comes a time where we kind of understand what this does, we know what we want to do. Well what about actually writing the command? This is where show-command is extremely helpful. Let's do show-command new-service. It's going to pop up a GUI here that we can then use to have it write the command for us. This is so nice for learning how the parameters should be structured, and formatted, and how we could really structure the command, right? So let's type in a binary path here. What we're going to do is make Notepad run as a service. Silly, pointless, but it proves the point, here, inside of the demo.
11:18So let's do a c colon backslash system 32, I believe it is? It is. Notepad.exe, there it is. This is the system name. Let's just do np for the system name. For the display name, let's do Notepad, and let's give it a description, here. How about Notepad as a service. Awesome. Now, don't hit run. What you want to do is hit copy, close out of this, and then paste it in here. Remember Control-V won't work. Right-click is your copy with Quick Edit mode turned on. And there it is. It wrote the command for us. New service, there's the path to Notepad.
11:49There's the system name, there's the description, there's the display name. If we hit Enter, there it is. It's actually going to return back to us, and now we have Notepad running as a service. It stopped, but it's there as a service. In fact, if we just go into Services, here, just to show you in the GUI that it is, in fact, there. And we head down here to the Ns-- where are you? There it is. Look at that, everything we specified. There's the name, the display name, description, and if we go into it here, we can also see the system name, or the service name right there. Pretty cool, right? We just created our own service.
12:20Unfortunately, if we go back to Show-Command here, or Get-Command I should say, there's no remove service. There's nothing there. So we're not going to be able to use any built in commandlet for doing that. Probably a good thing there's no commandlet for Remove-Service, though. That sounds kind of dangerous if it was that easy, right? So I'm going to use WMI and an actual method on the object that it returns to do. So again, this may not make sense, but it will down the road.
12:54So we've got a PowerShell commandlet here that is going to go and get all the services filtered by the system name, or the service name of np. So this is going to return one object. It's going to return that object. So then we're going to directly call the Delete method of that object, and there it is. It's gone. Now if we do a Get-Service for anything that starts with np, we're not going to get anything because Notepad's gone. All right, let's move on to aliases. So how do you think we can find every alias in the system? There's actually a couple ways. We could run Get-Command with the command type of alias. That's one way.
13:24There they are. The other way would be, you guessed it, get-alias. There they are. Now let's say we're always using dir. We're always using ls. And we want to find out what commandlet these are actually executing. There we can run a get-alias, and just pass in dir. Or pass in ls. And we can see these are both mapped to get to Get-ChildItem. So what if we wanted to do the reverse of that? We wanted to find out all of the aliases associated with Get-ChildItem. Well here's where we could use the -definition parameter and pass in Get-ChildItem. There we are. Three of them. Dir, ls, as well as gci. You'll see all of the commandlets have built in aliases, as well.
13:58So get-process is gps. Get-Service is gsv. That kind of thing. Now let's say that we wanted to create our own aliases. How do you think we could go about doing that? You guessed it, New-Alias. So let's just look at the help file for this real quick. You can see we have one parameter set, two positional parameters in your name and value, those are going to be the most common ones. So New-Alias, your alias name, followed by the value. Which, if it's a commandlet, it's going to be the name of the commandlet. If it's an external application, it's going to be the path to that external application. So let's just do a New-Alias, and let's say, you know what? Let's say that we're sick of typing out right here, Notepad.
14:30Let's say we wanted to shorten that to np. We'll do a New-Alias, we'll call it np, and we'll say Notepad.exe. There you go. Now we can fire up Notepad just by doing that. Pretty cool. Now here's the thing with aliases. They're only going to last for as long as our session lasts. So if we close out of this and reopen it, np will no longer work. This is where Export-Alias comes into play. So let's just give us the path here, and let's just type in my-aliases.csv. And let's say we only wanted to export our np alias that we created, not all the system ones. We can do that.
15:01And now, it's safe and it's stored in there. And now if we close out and come back in, and type in np, you'll see that it no longer works. So what are we going to do? We're going to do an Import-Alias, and pass in the path to our file there. There it is. And now, Notepad will work. In fact, let's just Notepad my-aliases.csv just to check it out. And there it is. There is our alias for this machine. Cool. So that's aliases and that's how they work. Now last thing I want to do is show you some challenges, or give you some challenges, I should say.
15:31And also show you where you can find all these commands that we were just working with. In fact, here, if we just hit open, right inside of the directory for this Nugget in Nugget Lab Files, here is commands. So here's all the commands that we were just working with. So there's those for reference. And then if I open up challenges here, here are your challenges for this Nugget. Level one, display all services running on the local host to have a display name beginning with the letter B. We've done that one before. That should be relatively straightforward. Level two, display a list of commands that are commandlets in any module that starts with Microsoft. We've done that one before, too.
16:02That should be pretty straightforward. The third one here, we have not used this commandlet yet in this course. So I wanted to throw something out there so you could discover and use the help files to learn on your own. Copy the contents of a directory, including subdirectories, from one location to another. Follow these steps. It'll help you out along the way. It'll also get you familiar with some things we did in this Nugget, such as aliases. All right? Now the solutions, at least my version of the solution here, are underneath these regions. So you expand those, and it'll show you my solutions. To access this, again, all these Nugget Lab Files are available on the right hand side of the course page.
16:34You can download them. So just log in, head to the course page, download them, and you'll get access to all the commands that we've used throughout all these Nuggets, as well as the challenges. So good luck. In this CBT Nugget we defined what commands are in PowerShell. We covered the six different kinds of commands. We saw some of the neat things we could do with Get-Command. Went through some workflows for learning new commands. Learned all about how to use and create aliases. And at the end here, I gave you a couple of challenges. I hope this has been informative for you, and I'd like to thank you for viewing.
The Pipeline
0:00The PowerShell pipeline. So this is where things start to really get interesting, and this is where PowerShell begins to separate itself from the pack. Piping is how we can chain commands together. So we can take a command, get the results of that command, and pipe it as the input to another command. So this is what allows us to do so much with so little, without having to resort to things like scripting, because we can get a lot done by just stringing together commands in a pipeline. So in this Nugget, we're going to get all the basics of the pipeline down, we'll learn how to chain commands together, and by the end, we'll be doing some pretty cool things.
0:34Let's begin. So PowerShell allows us to chain commands together using the pipe symbol, which may look like this, or this, right? And what that allows us to do then is connect commands together, where the output of one command becomes the input for another command. Now, here's the big difference, and this is where PowerShell separates itself from the pack. It's very easy to construct PowerShell pipelines, because we don't have to worry about parsing text. Chain of commands is nothing new, in fact, it's been around for a very, very long time. But what is new is that PowerShell utilizes objects, not text. Anyone watching with experience in other shells will really appreciate this, because oftentimes, constructing pipelines in other cells meant that if you need to get something specific, you had to do string parsing.
1:14And it meant a lot more steps, and it equated to these extremely long and complex pipelines. So it takes hours and days to construct in older shells, it takes seconds and minutes here in PowerShell, due to these beautiful data structures, known as objects. Everything in PowerShell is an object, so commandlets return objects as output, and can accept objects as input. So here's how this works. Let's take a conceptual view of this first, and then we'll look at some real commands, and they'll actually get in do this stuff. So the first thing you're going to do here is you are going to run a getter, right?
1:45A getter, like get service, for instance. Here's the alias for get service, GSV. And let's say get service retrieves eight services, right? Maybe we put a filter on there to give us services that started with w or whatever. And these servers are going to come back and they're all going to be objects, right? Objects that describe that specific service. So we have a representation of that service here as an object. And let's say we've got three running services and a couple of stop services. Now, let's say we want to pipe this, here's where the pipe symbol comes into play. We want to take those objects and send them into the pipeline, because maybe we want to do something with. We want to transform them, maybe do some filtering, some sorting, some formatting.
2:19Whatever we want to do, we've got lots of commandlets here that we could send these objects to. So let's say we pipe them to something called Where-Object, and we're going to get into lots of this commandlets that allow us to operate and transform things in the pipeline. But Where allows us to put a filter, so let's say we want to filter out anything that isn't running, so we could do Where status equals running, and that would then give us just these three objects. It would throw anything that's stopped out of the pipeline. And these three objects then we could pipe to another command. And let's say we want to do something else, like use the Select-Object command, which allows us to pull out other properties.
2:53Whenever we've done GSV in the past, we only get those three default properties, which are name, status, and display name. Well, Select allows us to dig into the object to pull out all kinds of other properties. And once we get into objects, we'll actually see how to interrogate an object to discover what those properties are. Let's say we wanted to pull out not just the name and the status, but maybe the machine name, so we would do that. We would get those three objects, and we would pull out those specific properties, and then maybe want to pass it down the pipeline again. So we pass these three objects to, how about something like Sort, there's a Sort-Object.
3:25And let's say we want to sort it by their display name. This would actually line them up and just sort them by display name. Then we could take these and pass them further down the pipeline, to do even more with them. And once you get to the end of the pipeline, we could do something like send them to the stop service commandlet which would stop these three objects. Or we could send them to a format commandlet, which allow us to format the output. Maybe we want to format them as a table, or format them as a list, or maybe you want to send them to a file. So they're going to stay objects in the pipeline until the very end.
3:57And at very end, we're either going to do something with them like perform an action on those objects, again, something like self service. Or if we don't do anything, PowerShell is going to attach the out default commandlet to them, which will extract the default properties and display them on the screen. In fact, here's a list of a lot of the common commandlets you'll be using to operate on objects when you're in the pipeline, and we'll be going through many of these over the next few nuggets. So we've got some formatting commandlets, which allow us to control how the results of the pipeline are displayed. We've got some out commandlets, which allow us to send those results to things like files and printers.
4:29We've got a whole bunch of things that we'll be utilizing inside of the pipeline, so selecting, filtering, grouping, measuring to get counts in mins, and averages, and max. Tease, if we want to take the objects that are in the pipeline and send them to a variable or a file, while also leaving them in the pipeline. Sorting, comparing, and then for each, which allows us to loop or iterate over objects inside of pipeline. Again, we'll be getting familiar with many of these, especially when we get into our objects Nugget. And then we've got some commandlets here for converting to HTML, CSV. We've also got exporting and importing commandlets, so all kinds of things that we can do inside of the pipeline.
5:03Let's look at a couple of real examples, and then we'll get into the Virtual Nugget lab and see this stuff in action. So let's say we wanted to get a listing of files greater than a hundred megabytes, sorted by length, and then formatted in a nice list. Sounds like a lot of work doesn't it? Well thankfully in PowerShell, it's not. So the first thing we need to do is run our getter, to get a bunch of objects. And what could we do to get a listing of files? You guessed it, we can run Dir, which is an alias for get [INAUDIBLE]. We'll run it with the recurse switch and that's going to set us up by returning a lot of files as objects. Now, the next step is to set up a pipeline and send those objects down, but before we do that, let's fire up PowerShell.
5:38Actually follow along with me. If you've got PowerShell, just open it up and run Dir with the recurse switch, just like so, right? There it is. There's our big listing of files. Those are all objects. It's a collection of objects. I'm going to Control c out of that, because it would go on forever. But what happened there is we just ran a Dir with recurse switch. And what happened is, everything's a pipeline in PowerShell, so PowerShell actually appended a pipe to that, and sent it to out default, which is a commandlet that sets up the default formatting, which in this case was a table, and pulled out the default properties of that object, which in this case was the mode, the creation time, the length, and the name.
6:13That's going to be important once we get into objects and advanced pipelining. I'll show you how we can control all this stuff, but that's a good set up. Now, we only want to get files that are greater than 100 megabytes, so here's where we can pipe those objects to Where-Object's. Objects. So we'll set up a pipe here, which will send those objects down, and we're going to use Where-Object to filter out any objects that do not have a length greater than 100 megabytes. So this is going to take a lot of those objects that we just saw in the output, and kick them out of the pipeline. So let's do that.
6:43Let's head back here to PowerShell, and we already added the pipe. Now, we're going to do a Where-Object, and now we're going to specify the property that we want to filter on, let's say name-- or excuse me, length is what we want here. Length, and we're going to say greater than 100 megabytes, and let's hit Enter. And I should only have a few of them in here, and I do. There they are. So that was the next step in the pipeline. We took that down to just five objects. Now, the next step, let's add another pipe and let's say that we wanted to sort them by length, because right now, they're not sorted by length at all.
7:14So here, we're going to set up another pipe, and then we're going to use the Sort-Object commandlet, and say we want to sort them by length, and by default, it will sort them ascending. So let's recall our last command, which is just awesome by the way. That helps in constructing these pipelines, because you can run a command, see the results, set up your next command, see the results, so on and so forth. So let's add a pipe, let's do a Sort-Object, and we want to sort it by length, and let's hit enter. And now, we're going to get the same results, only now they're going to be sorted by length ascending. Check that out, pretty cool. Now, once again, it attached the out default commandlet to the end and gave us the default format and in default properties there.
7:49But let's finish this up by formatting it as a list. Let's just say we want to take those objects and we don't want the table format, we want to see them in a list, so let's do that same thing. Let's recall our last command, let's add another pipe, and let's just format that as a list. And now, instead of the table view, we get them all separated out in list format. Pretty cool. So that that's how powerful the pipeline is, and how easy it is to construct a pipeline. Let's do one more example. Let's say that we wanted to get all the services that were stopped. Pull out specific properties, sort it by the name descending, convert it to HTML, and then create an HTML file with all that data in it.
8:24Sounds again like a lot of work, but it's really not. We'll start with a Get-Service, which is going to get us, again, a bunch of Service-Object's, all of them, because we didn't put a filter. So this will get us all the services on the system. Then we can filter out anything that isn't stopped, so we'll do a Where-Object. The property we want to filter on here is status, word equals stop. So that's going to kick out anything that isn't stopped, and just give us a handful of services. Then we're going to use the Select-Object to pull out specific properties. Say we don't care about display name, we just care about the name and the status. Well, we could do Select-Object, name, and status, that will just get us those properties for those objects.
8:59Then we want to sort them by name, only this time descending, so we can use the descending switch on the Sort-Object commandlet, which will sort them in reverse order. And then we can convert the output to HTML, send that to the out-file command, which will then generate an HTML file with those results. Look at that, that's a nice little pipeline there using many commandlets to take the services that we want and a specific data we want, convert it to HTML, and store it inside of a file. All right. I think you get the idea, right? Pipelines are powerful. Let's jump into the virtual Nugget lab and see some of the neat things we can do with them.
9:30All right. Welcome back to the virtual Nugget lab. We are on our CL8 Nugget machine. Let's bring up the shell, and let's just do some work in here. Let's get service. What's the alias for Get-Service? GSV. And let's say we want to get all the services on the system, but we want to sort them, because the default output here, it is sorted, but it's sorted by the name, the system name. See that right here? It's sorted by the actual service name itself. So let's say we wanted to sort it by display name. You see that's not sorted by display name. We've got a, and then we got Windows here, and so on and so forth, it's all over the place.
10:00So let's sort this by piping this to Sort-Object. And by the way, sort is the alias for Sort-Object. And let's say we want to sort by display name, so we can do display name. There we go, now we're sorted by display name, pretty cool. Now, let's build on that. Let's say that we wanted to send the output to a tool that we could use interactively, and that is out-gridview. Out-gridview is awesome, because it opens up this tool that we can then filter and do all kinds of things inside of here. But there is same results, they're just inside of this nice great gridview inside of PowerShell.
10:32Cool. Now, what else could we do here? Let's say that we want to select all the properties, not just the default properties. Well, here's where we could add on to this a select. So let's add a select right inside of here, and let's do a select, which by the way is Select-Object, but select is the alias here. And let's say we wanted to select everything, we could put an asterisk in there. And this is actually to pull up all the properties of the object and put them here instead of a gridview. Check it out. Here's all the properties of our Service-Object right here. Pretty cool. So can pause and continue, can shut down, can stop, as well as all the required services that it depends on.
11:03And again, we still get the display name, the name, we get the status over here, and some other things as well. Machine name that it's running on and so forth. So there you go. All right. Let's take that to the next level. Let's say we wanted to run Get-Service against all the servers on our network and do some fancy things in the pipeline to pull out specific data. Well, on our share, on our ps4 share here on our file server, I created a directory called files. And in here, I've got servers.txt. Here's a list of all our servers, DCNUGGET, APPNUGGET, FSNUGGET. So we want to read those servers in as the computer name parameter for Get-Service, and then set up a pipeline to operate against those services.
11:37Let's do it. So here's what we're doing. We're going to run Get-Service. Let's just pull out the Bit-Service, rather than all the services. We're going to specify the computer name parameter, and then we're going to use Get-Content to pull all of those names, those servers, out of servers.txt stored on our file server. Then we're going to sort them by name, then we're going to do a Select-Object, name, status, machine name, and this is because machine name isn't in the default output for the object, so that's where we're going to pull out that specific property.
12:11And then, we're going to format it as a list. Let's see what we get here. So if we hit Enter, it's actually going right now across all those services to pull that Bit-Service back, and then it's going to pull out those specific properties, and give us a nice formatted list. And there it is. We've got a list, we get the service name, we get the status, and we get the machine that it's running on. Very cool. Let me show you something else neat we can do. So at the end of the pipeline this time, rather than displaying it to the screen here, let's output all that to a csv file and take a look. So let's run GSV here for Get-Service. Let's just grab all the services that start with win, and then let's pipe that to only get services that are currently running.
12:47So we'll do a Where-Object here, and we're going to do status, which is a field name, equals running. And we're going to pipe that to Export-Csv. Give it a name here, services dot csv, and there we go. Now, let's fire that up. Let's just do a notepad here on services dot csv, and there it is. So instead of putting those objects to the console, we exported them, all those objects and their properties, to a file. Let's do another one. Let's say that we wanted to create a web page of all these services. We'll see the same thing here, only this time let's export it to HTML.
13:18Now, there is no Export-HTML commandlet, so we first need to convert it. So we can do a convert to HTML, and then we're going to take the results of that, which will be HTML. And by the way, if we just did this, it's going to display the HTML on the screen. But we want to actually export it out to the files. We can do an Out-File, and let's call this one services dot HTML. Cool. Now, what we can do is Start-Services dot HTML, which will launch it in its default application, which should be Internet Explorer in this case, and there are all the services stored inside of a web page. So that you have a good taste of how to construct pipelines, and what piping is all about.
13:52Remember all of these commandlets return objects, and we could take those objects and pass them as input to other commandlets. And it makes it very easy to construct these elegant, easy to work, with pipelines. Let's finish this Nugget up with some challenges. So I'm going to fire up the ISC here, and remember, you can access the commands that we just worked with here inside of the directory in the Nugget Lab files for this Nugget, as well as challenges. So here are the commands we just worked with, and then over here, I opened up our challenges file. So here are the challenges for this Nugget, the PowerShell pipeline.
14:22Challenge number one, write a pipeline that returns only running services, and then sort the results in descending order by display name, something we did there. Challenge number two, write a pipeline that retrieves a list of files over one gigabyte on the system drive, and save the results to an HTML file. We did those across a couple of commands there. You should be able to figure that one out. And the big one, challenge number three, write a pipeline that retrieves the name, synopsis, and module name properties from Get-Help for all get commandlets in the Microsoft module, then output the results to a grid for interactive analysis. This is kind of a tricky one, so I gave you some help here.
14:54Number one, use Get-Command to retrieve all the get commandlets in the Microsoft modules. We've used this in previous Nuggets. Pipe those results to get help, and then you select to pull out the name synopsis and module name properties from those Help-Object's, and output the results through a gridview. The end result be a nice gridview containing all of the help that you need for all the get commandlets, right? It'll have the name, quick overview, and the module that they live in. Good luck. Remember, just expand these regions here in the challenges file to see the solution for these challenges. In this CBT Nugget, we started digging into the pipeline.
15:26We saw that the pipeline is really just a way that we can chain commands together using the pipe symbol. We can take the output from one command and use it as input for another command. And the beauty of PowerShell is that everything is object based, objects are flowing through the pipeline, which makes it very easy to work with, and this is how we get so much power out of just writing commands, rather than scripts. Until next time, I hope that this has been informative for you, and I'd like to thank you for viewing.
Objects
0:00Objects. This is it right here. This is what makes PowerShell PowerShell and what makes it stand out from all the other shells. In order to become an effective PowerShell IT pro, we need to understand what an object is and the role that it plays. And one of the great, great things about PowerShell is it's uniting sys admins and developers across the world because they need to speak each other's language. Developers need to understand how administrators perform their task so they can build commandlets that will help them automated. And administrators need to speak the language of developers.
0:30We need to understand what types are, what objects are, maybe even what classes are. In fact, that's all PowerShell really is. It's the .NET framework for administrators. So in this Nugget, we're going to dig into objects, see what they're all about and by the end of this Nugget, you will be able to your developer friends and say, hey, I know what you do all day. You create classes, you instantiate objects, and then you use them and pass them around all the layers of your application. Let's begin. So what is an object? To really answer that and to fully understand what an object is, it's going to help to take a step back and delve into the mind of a developer.
1:01So the first thing a developer will do when they're building a new application is take the real-world parts of that application, all those data points that we need to represent and transform it into its digital counterpart. Let me give you an example. Let's say that we wanted to build an application to track employees. How are we going to do that? How are we going to transform an employee-- a real person that works somewhere-- into an object that we can represent digitally? Well, they're going to do this through something known as a class. A class is just a template. It's just a blueprint. That's it.
1:31This is where we're going to make objects from. Classes are kind of like little factories. We're going to use them, it's going to return us an object that we can work with. Now, a class contains three main parts here. It contains properties, which are just data points that define the state of that object. So we'll have property for a first name, last name, maybe the address they live at, their position, their department, their salary, that kind of thing, all those data points we need to track that describe the employee. It also has things like methods. Methods are the actions that this employee can perform. What kind of actions can employees do?
2:03Well, we could promote them. There would be an action. They could call in sick. They could get paid. So those are all actions that we could take on the employee pass. The third one here is known as events. And events are things that can happen to our objects. So our employee object, for instance, employees, when they get fired, could trigger the onFired event or we could have an onHired event. We can have an onGotPaid and events just give developers a way to respond when certain things happen to their objects. So that's all a class is. It's just a definition of what objects should look like.
2:33It's where objects come from. So once we have a class in place, now we could start creating employee objects and these are going to have state. They're going to have all their properties fill in. If we were to call methods of these objects, they would apply to that specific employee and that's where objects come from. Now, when a developer is done modeling their classes, they'll have many of them in here. Some of them may have dependencies and relationships to other classes inside of here, but they'll wrap all of that and compile it into a DLL and that's one of the huge benefits of object oriented programming is now if a developer or other developers in the company want to build applications that are going to need to represent an employee, they can tap into that one DLL rather than creating their own version of it.
3:11And now I'm starting to go deep into the rabbit hole, so I'll stop. But if you want to continue on further and get a real good understanding of how object oriented programming works, I did a micro Nugget many, many years back called "What is Object Oriented Programming." I'll give you the link to that. Check that if you want to know more. So now we should know where objects come from. They come from these blueprints known as classes. Classes just contain the definition. Where we create objects, those definitions get filled in. Now, let's do a little exercise here because this will really help just to make sure they're all on the same page. Look around you right now and pick something out. Can you describe a couple of properties of that object?
3:42Maybe a couple of methods? I'm looking out my office window. I see a parking lot full of cars, so that's why I have a car here. And if I look at any one of these cars, I can list off the make, the model, the color, the height, the width the weight, that kind of thing. So all of those properties combined describe that specific object. What about methods, the actions that cars can perform? They can start, they can stop, they can go, they can brake, that kind of thing. So you get the idea. Everything in the role world is an object. Everything in PowerShell is an object. These commandlets, when we execute them, they return .NET objects and that's what gets passed down the pipeline.
4:17And they can also accept objects as input. Objects as we just saw, contain properties and methods and they are of a specific type. Think of a type as really just the name of the class, but it's a lot more than that. It actually forms part of the name space, which helps us uniquely identify that specific kind of object. So here's where Get-Member comes into play. Now, we know that objects are obviously important because they get passed down the pipeline and we can do things with them, but how do we know all of the properties that that object contains and all the methods, all the things that we can do with that object? Because by default, if we were just to run something like Get-Service, we would just get name, display name, and status back, but there's a lot more properties in there that we can work with and that's where Get-Member comes into play.
4:58This is really the final piece of the puzzle when it comes to the commandlets you should know first. We have Get-Commands, which helps us find commands, Get-Help, which allows us to get help, and then we Get-Member, which allows us to look at what that object exposes in terms of properties and methods. So Get-Member is going to display the members of an object. Member is just a fancy term for, you guessed it, properties, methods, and events. And it's going to be useful for discovering everything we can do with that object. From a method perspective, we can call methods directly on these objects and for extracting or working with properties that aren't necessarily exposed in the default output.
5:33And to it, we can just pipe objects to Get-Member just like we're doing here. We're doing a Get-Service and we're piping that to Get-Member and that's going to give us everything we need to know about that object. Let's jump over to the Virtual Nugget Lab see the kinds of things we can do with Get-Member and also some of the neat things we can do with objects. Welcome go back to the Virtual Nugget Lab. Let's fire up PowerShell here. So remember the whole point of objects and why they're so awesome is because they're this nice, simple-to-work-with data structure that we can easily pass around and work with the properties of these rather than text.
6:05Because if we were to go to command.exe and type in dir, that's not dirt. Yeah, that's pretty much what the old command line is now. It's dirt. But if we were to type in dir, this is all text. It's all text. So if we wanted to pipe this to another command, we would have to extract specific text out of here to pass over there. But with PowerShell, we don't have to do that. PowerShell, we run dir. All of these are properties of that object. So that's why we can easily pipe this to other command lists to work with objects and to work with and pull out specific properties.
6:35So now, we could easily do something like this, dir, and we're going to pipe that to select. I want to pull out specific properties of this object and let's say I wanted to pull out name, maybe full name, and maybe extension. Here we go. Now, there's no full name and extension in that default output. You didn't see it up here. But down here, look, name, full name, which is the full path, and the extension, which will show up if it's a file. So how did I know that this object had full name and extension? How did I knows those were even properties that we could work with? That is where Get-Member comes into play.
7:06So let's pipe this to Get-Member. Now, look at that. Now, this is actually going to return two types because dir, or Get-ChildItem, item, can return directories and files. So it's showing us here objects could be of directory type, directory info type, or they could be a file info type and both of them have a different set of operations and a different set of properties on them. So there we are. There's extension and there's full name. These are properties of the file info class, which are the objects that we're going to get returned to us. So we can also see the definition otherwise known as the signature here, which is how these properties are defined inside of that file info class.
7:43So we can see the data type that these returned. These are both strings that get returned back to us. Now, watch this. Let's clear the screen here. So let's run Get-Service-- remember GSV is the alias there-- and let's pipe this to Get-Member. GM, by the way, is the alias for Get-Member. And look at all this juicy information. We get the type name. It's a service controller and then we get all of its methods and all of its properties. Remember when we run Get-Service, we only get the status, the name, and the display name. And also notice name is actually an alias on top of service name.
8:13Required service is an the alias property on top of service service is dependent on. Now we're going to get more into all the different kinds, but note that .NET classes are really just properties, methods, and events. PowerShell is extremely extensible and so there's a way to extend that and add properties on top of properties and there's also the same thing with script methods. We can add our own methods on top of this. And we'll get more into this. We've got a Nugget on extending PowerShell. We'll get into extending objects as well as importing modules and things of that nature.
8:44But for now, just know this is how we look inside of an object. Use Get-Member because it will show us all the things that we can do and all the data points that we can pull out. Let's check out the help topic for Get-Member. There it is, pretty straightforward. It's gets the properties and methods of an object. There's two ways we can use it. We can just pipe an object to Get-Member or we could use the input object parameter to get. But here's the thing. See this static switch here? This is really interesting. So classes. can also contain what are known as static members, meaning, you don't actually have to create an object in order to use it.
9:16It actually says it right here, to return information about static members, members of the class, not of the instance. So whenever we create an object from a class, it's known is instantiation. You instantiate the object. And that just means creating the object from a class. Well, watch this. Let's take the math class, for instance, and let's just pipe this to Get-Member. Check out this math class. Lots of things we can do with the math class and let's say we wanted to get just the static properties. Here we go. These are all the static properties and methods, meaning, we don't actually need an object. So we can do something like this. Let's look at the math class and lets look at pi.
9:47See that right down here? And if I hit Enter, I didn't type in math all the way. There we go. Check it out. There's pi right there. And see all these static methods? Yeah, we can use these as well. In fact, let's take a look at the Min method. If you just type it in without actually calling with the names of its parameters, it's going to show us all of the different overloaded definitions, all the different ways that we can call it, and there is lots of different ways that we can call it using data types, but you're going to pass in two values. So we're going to do this. We're going to pass in value 1, how about 100, and value 2, 10,000. What's the min of those two?
10:17100. Right? So that's it. We're calling these methods directly on the class. We're not using any sort of commandlet to do it. So I just wanted to show you that because that can actually be very powerful as you'll see when we get into scripting. There's some pretty cool things you can do to take advantage of things like this. If you need to do any mathematical operations, you could just go right against the static members of a math class to do so. Let's see how we can work with properties and methods directly on these objects and then we'll look at some common things we'll be doing with objects in the pipeline. So let's do this. Let's do a dir with the directory switch here and let's pipe that to Get-Member.
10:49We know this is only going to return this time the directory info type. And if we look inside of here and look at some of the properties, we can pull out full name. We looked at it before but watch this. Now, we can do something like this. Let's just wrap this in parentheses. This means execute this first and we're going to need that because we need objects before we can start working with their properties. But if we do this, look at this. It's just going to pull back the full name. We worked right against that object directly to pull that property out. We do the same thing with methods here and there's a method actually up here-- let's take a look-- called CreateSubdirectory.
11:21Look at that. There's a method right there. All right. Let's take a look at that. We can do that one by doing the same thing only we're going to say .CreateSubdirectory. There we go. And then we're going to pass in the name of the directory, but if I were to run this right now, we would have to create whatever directory we decided to name it in each one of these directories. So let's just do one for the desktop here. We'll just type in desk asterisk and that will just create the subdirectory name. How about Test? Here we go. Hit Enter and now we created it. If we look on the desktop when we minimize this, there it is. There's that directory we created.
11:52So that's how we call a method directly on that object. How about another one? Now, I'm going to introduce you to one of my favorite commandlets because it's just so extremely useful and in so many things you'll be doing. Its Get-Date. If we run Get-Date, it's going to return back the default property for Get-Date, which is today. Now, let's do something crazy here and we're going to get into all kinds of this stuff later. But I'm going to create a variable and I'm going to store inside of that variable a Get-Date object. So now we've got an object inside of that variable. In fact, now we could pipe that variable today to Get-Member and what's it going to do?
12:24It's going to return back our date here. system.datetime is the type and look at all the juicy information we can do here. We can do all kinds of awesome things, add days, hours milliseconds, minutes, months. And on the property side, we can extract the day, the year, the month, the minute, the millisecond, just all kinds of great information. In fact, now we could do something like this. Today dot-- let's get the day of the year that it is. Boom. It's day number 286 out of the year. Let's call a method. Let's say we want to know what six months from now is going to be.
12:56We could do add months, pass in six. There you go. There's six months from right now is April 13, 2016. Let me show you one more useful thing when it comes to types and then we'll jump into the ISE here and I'll show you some neat things we can do with objects and give you your three challenges for this Nugget. So Get-Service. If we just run Get-Service, what's that? It's all the services on the system. What type are those? Let's find out. Let's pipe that to Get-Member. All of those, each one of those was a service controller object. So every service that came back was a service controller object and all those services together are known as a collection of service controller objects.
13:32Now, here's something really interesting. Watch this. Let's pipe all that to Stop-Service. Now, I don't actually want to run this because it will probably run to the system, completely useless. So I'm going to add the switch WhatIf, which is just an awesome parameter that means it's going to give us the result as if it did it without actually doing it. So if I hit Enter, Stop-Service would have worked. How did that work? Well, if we look at the help her for Stop-Service, we're going to see in that first parameter set, look at this, we've got a positional parameter here called InputObject that accepts service controller objects, in fact, an array of service controller objects.
14:02So that's how this was able to work because GSV, Get-Service, returns a list of service controller objects and we just pipe those directly into, in this case, Stop-Service or any other commandlet that has us perform actions on services. And what does this do under the hood? Yeah, it calls the Stop method on all of these objects when they get to that commandlet. Isn't that neat? So that will hopefully give you a little insight into how this stuff works under the hood. All right. Let's fire up the ISE here. I'm just going to type in ISE right there. Boom.
14:32Another way to fire it up. Let's open up our Commands file here for this Nugget07 objects. And the top half here is what we were just working with. They're in the console. What we're going to do is just get you quickly familiar with a couple of the more common object commandlets that you'll be using. A lot of these are very powerful and any time you construct a pipeline, you'll probably be using one of these to some degree. But just a Get-List of all the object commandlets, we can run a Get-Command with the noun of object and here they are. So some of the ones that we're going to be here ForEach, Select, Sort, and Where, by far the most popular ones.
15:05So Where object is first and this is what allows us to filter out objects from the pipeline so we can toss them on out of there. In fact, here's an example. We're going to run Get-Service, which is going to give us all the service objects. So we'll pass that collection over here to Where object and we're going to say, you know what, we're going to filter out anything that isn't running. So we'll say, only keep the objects in the pipeline where the status is equal to running. And this syntax here is property comparison operator value. And by the way, check out the About topic for comparison operators. You can get a list of all the different operators out there.
15:36There's a lot of neat things you can do. But in this case, it's equal. So if we run this, just highlight it all and hit F8 on the keyboard. There it is. There are all of services that have a running state. So all the ones that were stopped got booted out of the pipeline. Now, the second one is interesting because this is actually functionally equivalent to the first one. It's the same exact thing, just how we use it is a little different. So this is known as comparison statement syntax up here. It's a little more natural and human readable. The second one is known as script block syntax and this one is a little more programmary, but it's also more powerful.
16:09You can do more with it. So you'll use this comparison statement syntax for simple stuff. But we need to start adding in multiple conditions, for instance, say we wanted to do an And in here, and this is another beautiful thing about IntelliSense is that we can see that And isn't even an option in the list, so we know it's unsupported. If we go to the script block and do an And, look at that. It's there. And now we can add more onto it just like we have down where we're adding the Boolean property, can stop only, meaning, true or false. The other major part of this I want to point when it comes to script block syntax and you're used to this especially when you get into looping and such, is this dollar sign underscore.
16:46This is a special variable. It's really just a placeholder that means this and this in programming languages means the current object. So this is really just a reference to those service objects and in fact, if we use the dot after that, we're going to get IntelliSense here to give us a list of all the properties and all the methods, just like Get-Member. So here's where we can just come down to the property and start typing and it will scale it down for us and that's what we want. So we can click on it. There it is. Very cool. So that's Where object. It allows us to create filters and conditions and there's a couple of different ways to do it.
17:16Now, Select object is how we're going to pull out specific properties and here's a neat little trick here. If you pipe any of your objects to Select object and run an asterisk or a star, then it will actually give us back all of the properties and their values. Look at that. So that's useful to use with Get-Member because Get-Member will show us all the properties and their data types. Running this will actually show us the data inside of there, so that's extremely useful for troubleshooting and even developing. But what we'll really be using Select objects for is to pull out specific properties of the object.
17:49So here we're pulling out machine name and service type, for instance, which is in the default output, so that will allow us to do things with those properties here in the pipeline. We also got some interesting switches here, parameters. We have the first and last parameters, so we can pull back x number of objects. And this can be useful too for creating those top 10 lists especially combined with Sort. We can sort something descending by a numeric value and pull back the first 10 and that will give us our top 10 list. There's also unique parameter if you only want to work with unique objects, so running this will give us the top five objects.
18:20Now, we didn't do any sort, so it's just going to give us the top five objects from A on downwards. Now, this next one is really interesting. We're going to step it up a notch here. So we're going to run Get-ChildItem against our Installs directory on our PS4 share on our FS Nugget file server and then we're going to use Select to pull out name and length. Now, up to this point, pretty standard stuff, right? If I run this, it's going to give us the name and the length, which is in bytes. But this last bit here is known as a calculated property. We're adding our own property into the pipeline on the fly and it's a calculation.
18:52So here's how this works. This is actually called a hash table. A hash table is really just a bunch of key value pairs. So we're defining our hash table at the ampersand and inside of the script block here, the name, key, is going to be the name of the property and then that's the value then is megabytes. And then the expression is going back to the value for this property. So our expression here, we're utilizing an existing property on the object length and we're dividing it by 1 megabyte. And it's very cool that PowerShell supports the megabytes, and the gigabytes, and the kilobytes, and so on and so forth. That way we don't have to do all of this manual calculation on this stuff.
19:24But what this will do then, if we run this, is that our own custom properties to the end, that's calculated. It's dividing this by a megabyte and that gives us the megabytes rather than the bytes. We also have Sort object and this is obviously going to be useful because we can sort the objects in the pipeline by their properties. We've got some good switches here. If you want to sort descending, you can add the switch parameter to descending. If you want your sort to be case sensitive, you can add the case sensitive switch, so this will just simply then sort it by length. There it is. Everything is sort of now by a length. See that?
19:54And we specify descending so it's going highest number down. The last one I want to get your familiar with here is looping. The ForEach object allows us to integrate over the objects in the collection one by one so we can do something to that object. And this is really powerful stuff that we can do this in a command. We don't have to resort to scripting to do this although we can do this in scripting as well, which we'll look at down the road. But here's a very simple example. We're going to take 1, 2, 3, and 4. Here's four objects, which are just integers and they're just numeric values and we're going to pipe this to ForEach and then inside of this script block here, it's going to process those one by one.
20:28And again, we're referencing the current object. So the first object that's going to go in is 1. It's going to get multiplied by 100, then 2, then 3, then 4, and watch the results of this. There it is, 100, 200, 300, 400. So that should give you a good idea of how ForEach works. It just iterates over each object in the collection and we do something with it inside of our script block. Now, let's take that to the next level. Let's say that we wanted to get a list of all the exe's on a machine that were created this year and log them to a file. That's what we're going to do here with this command.
21:00So we're just going to run a dir against the system drive for all the exe files and we'll recurse it. Then we're going to pipe all of those objects, there will be a ton of them, to our Where object and Where is obviously, the [INAUDIBLE] there for Where object. Then we are going to say, only give us objects, only exe's, that were created this year. And this is really cool because what we're doing is, we're doing this based on the creation time of that file, but because it's a date time object, as we saw earlier with Get-Date, we have access to a lot of underlying properties on that object such as year, month, day, second, minute, millisecond, so on and so forth.
21:38So we're just going to extract the year property of that and do an equality comparison against the current year. So this is going to kick anything out of the pipeline where the creation year is not this year. Then we're going to use the percent sign here. This is the alias ForEach object. And then we're going to have a begin, a Process, and an end. So we BeginOnly happens once before the loop occurs. EndOnly happens once after the loop is done. Process is this right here and that is the positional parameters here. This is why we didn't have to specify Process.
22:10But Process is what is actually going to get run for each object inside of the pipeline. And in this case, what we're going to do is, we're going to send each object to the Outfile commandlet, we're going to store it inside of exe-log.txt, we're going to append to it because if we don't do that, we'll only get one object, the very last one on the pipeline since it will just keep overriding, and then we're going pass as the input object here the full name of the file, which will just give us the path. So the end result will be this huge log file full of paths to exe's that were created this year.
22:42And by the way, these begins and ends are great for pre processing, post processing, and in this case, we're just going to mark the time so we'll know exactly how long it took to run this command. All right. Here we go. Let's highlight this whole command and let's just run that selection. And you can see it started there right now. So here was our Begin parameter, just spit out the current date. And now it's running. We've got a couple of errors in here. I'll show you how to deal with errors in the future. We've got a couple of access denied errors here on specific paths. But notice one thing. It's running right now in the background because we didn't hit that end yet.
23:14And we'll know it's done when we get a time stamp down here at the bottom. All right. Now, it's done. So it took about 34 seconds to run. So now we can start the name of our log file here and that was exe-log.txt. And there it is. Look at that. All of the files, all the exe's that were created on this machine in this year. Now, while we're on the topic of pipelines, I wanted to show you a very, very useful parameter here called passthrough. A lot of the times when you do something to an object and you don't actually output it like we did here where we actually sent that information to a log file, it didn't output anything except the beginning and the end.
23:50Well, the same thing is going to happen here. What's going to happen is, we're going to get a listing of all read-only text files and I made two of them here, by the way. I got one inside of documents called SomeData and I made one in the Test directory we made called TestData. These are bookmarked as read-only files. So if we just run this, it should just return those two files. So then what we're going to do is, we're going to pipe those files to RenameItem because we're going to rename all the read-only files on our system tag them with -ro. So RenameItem, we're going to specify new name and the new name is going to be whatever the current name is plus add ro.txt on the end of it.
24:22Now, if we run this without passthrough, what's going to happen is it is going to run. It's going to rename those files, but look, we don't get any results back, so we don't know which files were changed and that's where passthrough is incredibly useful. Because if we do that same thing, it's going to do it again. It's just going to append another ro. In fact, let's just see if that worked. Yeah, it did. There we go. There's a -ro on it. But if we do this again only this time specify passthrough, we're going to actually get to see those results because it kept those objects in the pipeline. So once they hit the end of the pipeline, the default out formatter brought them to the screen here. So that's where passthrough is useful.
24:53When you're troubleshooting and developing pipelines and you still want to see the objects that went through the pipeline, add passthrough to it. You'll be able to see it. All right. Let's move on and take a look at our challenges for this Nugget. Number 1, examine the object members returned from Get-Process. That should be pretty straightforward. Number 2, write a pipeline to get processes where CPU utilization is greater than 0. Return properties not shown in the default view and sort the results by CPU descending. That one shouldn't be too bad either. Number 3 though, this one's a little tricky. So write a pipeline to find all GPG and PNG files created on a drive in the last 24 hours.
25:28Copy them to another directory named Backup. A lot of steps involved here. That's why I give you a little help with these steps. But you'll be using Get-ChildItem as well as Where, as well as ForEach to loop through. So good luck. The answers are, again, underneath the regions and you can find all these files and challenges inside of the Nugget Lab files, downloadable on the right-hand side of the course page. In this CBT Nugget, we covered objects. We saw that objects are really just a live representation of something. They contain properties, which describe the object, that's the data stored for that object.
25:59They have methods, which are operations the object can perform and they have events, which are things that can happen to that object. We also saw that commandlets return objects as output and can accept objects as input and it's how PowerShell passes data across the pipeline. I hope this has been informative for you and I'd like to thank you for viewing.
Extending the Shell
0:00Extending the Shell. In this Nugget, we're going to take a look at how to get more functionality in the PowerShell. So how do we get access to more commandlets, providers, functions, all these components in PowerShell? The answer is modules. So we're going to take a big look at modules, what they are, the different module types, how we can even create and import modules into our PowerShell sessions. Let's begin. So we know PowerShell is pretty good out of the box. We have a lot of core commandlets that we can do quite a bit with. But what if we wanted to manage a specific product? Say, maybe, SQL Server. Maybe we wanted to manage our hyper-v environment, or maybe exchange, or maybe Active Directory.
0:33None of those commandlets come with PowerShell by default. And how we're going to get them is by working with modules and snapins. Modules are really just a package of PowerShell commands. Commands being everything. Right? Commandlets, functions, variables, providers, all that stuff. So Microsoft and third-party vendors can package up all this functionality into a module, usually targeting a specific product or functionality. Microsoft, for instance, will look at, again, how to do hyper-v and Active Directory. But VMware has modules to manage their products. And we can even build our own modules.
1:05And then a couple of good use cases there is if you find yourself writing the same code over and over. Maybe you're managing all the disks across all the machines in your network, and you're constantly writing the same WMI and SIM commands. Why not package that up in a module? That will also give you the added benefit of being able to share your code with others, so they can then import your modules and work with that as well. So in this course, in going forward, our focus is going to be on modules. There's also the concept of snapins. These are essentially what we had before modules, still just a package of commandlets and other things. But there's a lot more manual intervention involved in order to get these into PowerShell.
1:39They needed to be installed and registered with the system. So they weren't as easy to distribute as modules are. Modules are self-contained. You can literally just get them and copy and paste them into a directory, and you're done. No installation, no tie-ins with the system. So that's why modules are preferred. And that's why snapins have been going away. In fact, modules are so easy to distribute and work with, once we acquire them, we can just copy and paste them into one of the directories referenced here in the PSModulePath environment variable. We'll go over these directories here shortly. And then, as long as they're in there, whenever we do one of these three things, they will get automatically loaded.
2:11Get command against one of the commandlets inside of that module. Get help against one of the commandlets inside of that module. Or we can use a commandlet that's in that module. And PowerShell will automatically load it. And by the way, that automatic loading is done through an environment variable called PS module auto-loading preference. And there's really very few situations where you'd want to turn that off. Here are those directories referenced inside of the PSModulePath by default. And yes, you can add your own to this environment variable as well. But here we go. We've got two of them here. These are considered user directories.
2:42So you've got home, Documents, Windows PowerShell, Modules. Pop them in there. Run a commandlet, or get help, or get command of that commandlet inside of that module, and boom. It will automatically load it for you. And by the way, the first path here is for PowerShell version 3 and before. The second one is for PowerShell version 4. So Program, Files, Windows PowerShell, and Modules. They moved the module directory for version 4 for a desire to take configuration purposes. And by the way, that was put in place so the Local Configuration Manager component inside of DSC can access the resources in modules here on the system, which it may not have access there if it's stored inside of the user's profile.
3:18The system directory, as we call this one, is stored in pshome, Modules. And I'll show you where that translates to here when we get into a demonstration. So pop your modules. Copy and paste them into either of those areas. And PowerShell will automatically load them when we do one of these three things above. The other scenario here is, what if we download our modules, put them on a file share, put them inside of some directory that isn't stored in PSModulePath? In that case, we would need to use the import module commandlet to bring that module into memory, in which case that module will be available for that PowerShell session, or unless somebody explicitly removes it from memory using remove module.
3:56So we've got a handful of commandlets here to work with in PowerShell. We've got Get-Module. Get-Module by itself will show us all of the current modules loaded in your session. You can also use the list available switch parameter here, which will give you all the available parameters, loaded or not, in your session. We can also use Import-Module, as we see. That's what we'll use to load modules up manually. We can create our own New-Module. This is going to create a dynamic module, which only exists in [INAUDIBLE]. And we'll talk about that one shortly. And then we also have Remove-Module, which is going to unload it from the current session.
4:28Now, there are different kinds of modules out there. Let's go over the ones that you're going to come across out there in the wild. So we've got the script module. This is actually a PSM1 file extension. And this is just a module built using PowerShell code. So it's going to be great for, again, code reuse and code sharing. And I'll show you how we can create our own module using PowerShell code, import it into our session, and work with it. The second one we have here is a binary module. And again, this is what developers are going to build using the dot net framework. So they'll compile all that code into what we call an assembly, which is, more often than not, going to take the shape of a DLL file, that we can then put into one of these directories, and load up, and use those commandlets inside of PowerShell.
5:04We also have something known as a manifest module. Now, this is a PSD1 file. And that stands for PowerShell Data File. It's literally just a text file with a hash table of keys and values. And what this is going to allow us to do is describe the contents of the module and give us a little control over how that module is processed. And just to give you a few examples, we can describe it by specifying an author, a company, copyright description, all those fun things. But we can also set up system requirements and dependencies. So we can specify the minimum version of PowerShell, the minimum version of the dot net framework.
5:35And we can also customize users' environment. There's actually a key in there called scripts to process, where we can pass in a bunch of scripts that will get processed prior to importing the module. And there's a bunch of other things you can do in here as well. But I also want to mention, in order to get specific features, you will need to define a manifest module. So if you want to support updatable help, for instance, then you'll have to have a manifest module associated with your module. And by the way, you can generate these using the New hyphen Module Manifest commandlet. There's also a Test hyphen Module Manifest commandlet that you can use to test them out. The last type of module we have here is a dynamic module.
6:07And this is a module that is, again, created entirely in memory. So there's nothing persistent it is, no physical file to manage. And it's, again, created from the New-Module commandlet. Now, these will be good if you still want some kind of code reuse, but you don't necessarily need to share that code with others. We can wrap some of those utility functions inside of a module, load it up in our session, and call it from multiple places. With that, why don't we jump into the Virtual Nugget Lab? And you can get some hands-on experience working with modules. Welcome back to the Virtual Nugget Lab. Now, the first thing I want to do is just get you familiar with some module basics here in the Shell.
6:38And then I'll show you how to install new modules, where you can find new modules. And we'll even create our own module. So we have ourselves a fresh PowerShell session here. And what I want to do is just start by running Get-Module. Again, this shows all the currently loaded modules in the system. There's only one right now. And it contains all those core commandlets. You can see this is actually a manifest module. Now, let's do something like run Get-Service. Hey, that worked. So we know that it's loaded. But you want to know something interesting? If we still run Get-Module, we can see we have the same exact module loaded. And now, if we run a Get-Command on Get-Service, watch this.
7:11Look at the module name, Microsoft dot PowerShell dot Management. Name, Microsoft dot PowerShell dot Management. And so we know that Get-Service lives inside of that module. All right. Let's clear to screen here. Let's run Get-Module. Only this time, let's use the list available switch. So what this will do is show us all the modules available in the system that PowerShell can see inside of those directories that we were talking about. And look. It's got access to all kinds of modules in here. In fact, look at that, Active Directory. Now, this wouldn't be in a standard installation, because I actually added Active Directory myself.
7:41And I'll show you a couple of ways to do that. But as we scroll down here, we can see we've got a lot of modules available to us on the system. Where do they live? This is where the environment variable PSModulePath comes into play. So if we look at this, here are those paths I was talking about. So here is my profile, Documents. Here is the Program Files, Windows PowerShell, Modules. So this is the version 4 directory. This is the version 3 directory. And then here is the system directory, Windows System 32, Windows PowerShell, v1.0, Modules. Pay no attention to v1.0.
8:12It's always been like that. All right. Let's pick one out of this list that's available and watch the auto-loading magic work. So let's take-- SmbShare, here we go. Let's do a get-smbshare to see all the shares on this machine. There they are. Now, let's run a Get-Module. Hey, hey. Look at that. SmbShare is now loaded. Pretty cool. Right? Now, what if we wanted to unload modules? Let's do a Get-Module. Remember, that's all the currently loaded modules. And let's just pipe that to Remove-Module. Boom. And now, if we do a Get-Module, we've got absolutely nothing loaded.
8:44But what if we do something like this? Run it again. It's loaded now. How come? Because the last time we ran Get-Module it loaded this module up in order to display all the currently running modules. Cool. All right. I think you get the point. Now, one more thing. Just a little quiz for you. What are the three ways that a module will get auto-loaded? Remember, that PS module auto-loading preference must be on, which it is by default. So no worries there. But the three ways, again, were to run help against any commandlet in module. So we could do help get-adcomputer, for the Active Directory module.
9:18That's one way. The other way was Get-Command. Right? So get-command, again, get-adcomputer. We'll do the same thing. And then the third way was to just use the commandlet. So get-adcomputer. Now, just because we already did a couple of those, we can do a Get-Module. And guess what's loaded. There it is, Active Directory. So the big question, how did I get those Active Directory commandlets inside of my PowerShell session? And the answer is for things that are built into the operating system, like hyper-v and Active Directory, on the server side, you generally just go to the Roles and Features Wizard.
9:50On the client side, you can just go to the Windows features on and off area and enable them. And just to give you an example here, we're in Windows 8.1. So let's just do a search here for Windows features. Here we go to Turn Windows Features On and Off. And we'll head down through here. Actually, here we go. Hyper-v, right there. If we expand this, expand management tools, there it is, the hyper-v module for Windows PowerShell. So if we check this and hit OK, what would happen is it would plant and install that module right into PowerShell's home directory, the system directory there that we were looking at, which means we wouldn't have to do anything but do this, and then just do a Get-Command to find some hyper-v commandlets and run a help on one of those commandlets.
10:25And that module will be automatically loaded and available. And if we scroll down here to Remote Server Administration Tools on a client OS, there it is. And you can see here under Role Administration AD DS and AD LDS, there it is, Active Directory module for Windows PowerShell. It's already installed. So that's what I did. That's all I did to get that Active Directory functionality here in PowerShell is installed this. And I should mention, if you're on Windows 7, you will need to explicitly download RSAT for Windows 7. Just do a Google search for that. Download, and install that. Then go into Windows Features, turn it on, and you will have the Active Directory module available to you on your Windows 7 PowerShell installs.
11:01Now, on the server operating system, let me show you where that is. Let's go over to FS Nugget. This is our file server. Pop open Server Manager. Drop down Manage here. Add Roles and Features. And let's just rip through this wizard real quick. But if we head down to Features here, let's go ahead and find Remote Server Administration Tools. They're somewhere in here. Here they are. There they are. There's AD DS. And there is the Active Directory module for PowerShell. So this is how you can do it on server OSs. So that's good for things that are built into Windows. Right? But what about things that are outside of Windows?
11:31Now, for the most part, just executing a simple Google or Bing search for whatever you're looking for will get you in the right direction. But just to give you a couple of places to get started, here are some common resources for finding modules. gallery.technet.microsoft.com is a great place. If you scroll down on the left here to Tags, just hit PowerShell. Look at that, 2,700. There's also lots of PowerShell scripts. But if you hit this there's tons of modules and scripts and code snippets and everything. So here's a Windows Update PowerShell module, for instance. And you can see there's lots of good ones in here.
12:02Another one is poshcode.org, a user-driven repository. You can even upload your own stuff here and get the same results. In fact, they actually give you a PoshCode module here. So if you right-click on this, save the link as, you'll get your PSM1 file. In fact, let me just click on this and open it up. And this will give you a couple of commandlets here for upgrading, for getting PoshCode, search for and download code snippets, new PoshCodes, so you can upload your own, and then Get-Webfile to download specific ones. So those are some good ones there to get you started. Now, what about creating and importing our own modules?
12:34Let's go over it. It's pretty straightforward. Just a couple of gotchas here that I want to walk you through. So let's minimize the console here. And let's head into the ISC. I've got our commands.ps1 file opened up, all the commands we're using here in this Nugget. So we just went through all this stuff here. Now, we're going to go through some of the bottom ones here. And let me just show you where these are in our NuggetLab files. So let's head over to our file server here, psv4. Here is the directory containing all of our code here for this Nugget, 08 extending shell. And we've got commands. We've got our challenges. And then we've got our module. So the big trick here with creating your own modules is they must exist in a directory that has the same name without the dot PSM1 file extension.
13:12So we've got our car directory here ready to go. And I've got our cars.psm1 file open. So I saved this as a dot PSM1 file. And that is telling PowerShell that this is a module. And here we just have a couple of simple functions with no implementation in them. We've got new car with some parameters here-- Get-Car, Set-Car, and Remove-Car. And we're also exporting the module members. These are all functions. So we use the function switch here and specify which ones we want to export. So this is going to make them visible-- in other words, usable-- from the module.
13:42When we import this module and try to work with these, and we run a Get-Command, it's not going to show these other car commands-- New and Remove. We'll consider these private functions. So only we'll be able to use these inside of the modules. These we're exposing to the outside via export module members, the gets and sets here. All right. So we've got our module. And we've got it sitting in our file server. So how could we automatically import this module? You guessed it. We would need to copy this directory here to one of the locations in PSModulePath.
14:14So let's head to our commands file here. And the first thing I want to do is just show you how to do it automatically. And then I'll show you how to do it manually using Import-Module. So what we're going to do first is copy item, which is going to copy this directory from our file server, our car directory that contains our car.psm1 module, over to our user directory, Program Files, Windows PowerShell, Modules. So let's just copy it over. Just hit F8 to run that. And let me just go into that directory here just to show you and double-check that it did, in fact, go in there. So Program Files, PowerShell, Modules.
14:46There's our directory, car.psm1. Now, what if we run a Get-Command? We know that module's in there, so automatic loading should happen, because our preference, by default, is on. So let's execute this line. And look at that. It found it. And now it should also be loaded, because if we do a Get-Module here, look at that. There It is, our car module loaded up and ready to go. We can also do a Get-Command. And we can pass in the noun of car. And we should get both of them. Let's do that the manual way.
15:17So what we're going to do here is remove the module. It's unloaded from memory here. So now if we do a Get-Module, it's not in there. No more car. And then let's just remove that item completely with the recurse parameter. That way, it'll remove the directory as well as our module. It's gone. Now, let's say that we wanted a module directory living in our file server where all our modules are. And we wanted that to stay there. A couple things we could do. Number one, we could add this path to our PSModulePath. So it would get auto loaded. Or we could run an import module and do it manually.
15:49Now, if we're going to do any sort of importing of modules, you need to set your execution policy to a value that will allow you to do so. We'll get more into this when we talk about getting started with scripts. But essentially, this is going to get treated as a script. And we won't be able to do it unless we set our execution policy. So I'm going to do that. And I'm going to hit Yes here. And now, we should be able-- well, just to prove the point that car isn't here, if we run a Get-Command, it's going to say, nope, sorry. We can't find it anywhere, because we didn't add this path into our module path, nor did we copy this over, like we did before. So now, we're just going to run an Import-Module, specify that in directory.
16:21And now, it should be manually imported. And now, we should just be able to run a help or any of those other two methods to load them up. And if we run it, check it out. There's help for Get-Car. And I should mention you can write your own help files for your modules. And I'll give you the link. It's very simple. We don't really need to go into it, because it's not very complex at all. But I will give you the link so you can check that out on your own. All right. So there's a good look at how modules work here in PowerShell. Let's finish this Nugget up with a look at your three challenges for extending the shell.
16:51Challenge number one-- and a lot of this stuff we've done here. So it should be pretty straightforward. Challenge number one, view a list of loaded modules and then a list of available modules. Use the autoloading feature to load a module that is currently unloaded. Challenge number two, create a simple script module-- psm1 file-- save it outside of the PSModulePath, then import and load it into a session. So you'll be using Import-Module to do that. And challenge number three, download a module from the internet. Add it to a PSModulePath directory. Get help on a commandlet in the module, and view the loaded modules.
17:23And here, again, are some of those resources that we looked at. So find something on there that you would find useful. Download it. Add it to the PSModulePath, and then use it. And again, you can find the answers here underneath these regions. Just expand those, and you'll find the challenges dot ps1 file in the directory for this Nugget in the Virtual Nugget Lab files. And as always, good luck. In this CBT Nugget, we saw how to extend the shell. We saw that a module is a deployable unit in PowerShell. We can download other people's modules. We can create our own modules. But they're really just packages that contain all of the components in PowerShell that we can use.
17:57So commandlets, functions, providers, variable scripts, all that stuff we can package up into a module. So it's PowerShell's deployable unit. And what makes them so awesome is that there's no installation or registration. It's just a simple copy-paste somewhere. And then we can either automatically load it or, as we saw, use Import-Module to manually load. We also saw here how to create our own modules. I hope this has been informative for you. And I'd like to thank you for viewing.
Extending Objects
0:00Extending Objects. So we've seen that PowerShell is extensible from the outside, and that is we can bring in more functionality in the form of commandlets and such through modules. We can import and load them into our session and start working with them. Well, PowerShell's also extremely extensible from the inside, meaning we can add our own members, properties, and methods to types and objects here within PowerShell. Now this is a great productivity feature that's going to allow us to create our own shortcuts and reduce the amount of typing when writing commands, especially if you see yourself writing a lot of the same stuff within your commands. Just to give an example of that, let's say that we are always working with files here in PowerShell, so we're running dir or get ChildItem to pull back a list of files which are, by the way, FileInfo objects.
0:41And these FileInfo objects expose a length property. But guess what, that length property, it's in bytes. So if we want to work with megabytes or gigabytes or whatever bytes, we would then need to pipe these objects to maybe a select or aware if we're doing filtering, and then write our own customer expression to convert that to gigabytes, or megabytes, or whatever have you. Wouldn't it be great if we could just wrap all of this inside of our own custom property called length megabytes or length gigabytes, and going forward, we only need to work with that property rather than write all that extra code to convert it.
1:15So extending objects is a great way to get PowerShell to work for you, and that's just one of the many benefits. So let's jump in and we'll dig in to see how PowerShell makes this possible. We'll also get familiar with all the different types of members that we can add, and then we'll get into demonstration to show you how to do. Let's begin. So in a previous Nugget I said that PowerShell is really just dot Net framework for administrators. And while that isn't entirely false, it's also not entirely true, because PowerShell can work with many, many, many underlying object frameworks. And this is all due to something known as the Adapted Type System. So while dot Net gets all the glory because that is where most of the awesome is, other object frameworks such as COM, ADO, WMI, CIM as well as XML have been mapped into PowerShell as well.
1:55And it's all done through this common layer known as PS Object. So developers can write adapters that map these underlying frameworks into a PS Object, which is really the base for all objects here in PowerShell. PowerShell also has an Extended Type System, and this is what's going to allow us to dynamically add our own members, properties, and methods to PowerShell types and objects. For example, let's say that we ran the get AD Computer commandlet from the Active Directory module, and we got back a bunch of computer objects representing Active Directory computers.
2:25We could extend that object, add maybe an IP address property, and maybe a ping method. That way, we wouldn't have to pipe this to other things to do that they would just be built in right onto that object. And I'll show you how to do that here when we get into our demonstration. So the big takeaway here, just remember that type adaptation is what allows developers to map other object frameworks into PowerShell. Type extension is what we're going to use to add our own members onto existing PowerShell objects. Let's take that a step further and look at the kinds of ways that we can extend our objects.
2:57So we have what are known as member types, and we've seen these when we ran Get Member in previous Nuggets. Let's go over them now. Let's start here with Alias Property. So this is very simply just a new property with another name on top of an existing property. In fact, let me bring up PowerShell and give you a good example of this one. So if we do a Get Service and pipe it to Get Member, and we head up to the top here, here's two alias properties, so name is an alias for service name, a little less typing there. And required services is an alias for services depended on, a little more readable and understandable, required services than services depended on.
3:29So that's generally what we use alias properties for make it a little easier to read it a little easier to type. No Property is just a property with a static value. Script Property is a property with PowerShell code behind it, and a Script Method is the same thing, a method with PowerShell code behind it. And then Code Properties are really just properties and methods that sit on top of statis.net methods or static.net properties. Most of the time you'll be using Script Properties and Script Method, so we'll be writing PowerShell code to extend our PowerShell objects. And we'll take a good look at how to create these here shortly in our demo.
4:01Now there are many ways to extend an object with these member types and, again, we'll go over all these different methods here in a demonstration. But the first one here we've done in previous Nuggets. Pass a hash table to select-object. We give it a name. We give it an expression and essentially it's a way to create a calculated property on the fly. But do note that this is really only good for display purposes, because it will convert that original object to a PS custom object, so if you try to pass it further down the pipe to something that expects a specific object, you could run into problems there.
4:31Using add member against anything is a great way to add a property or method to an existing object. Take a look at how to do that. Using new object to extend the PS object. This is how we create our own PS custom object. So for example, if you wanted to create your own computer object, and you didn't want to use the AD Computer object, then you create your own from scratch, fill it up with properties and methods and utilize it. Show you how to do that. And then not extend types using Update Typedata. This is great, because while Add Member is good for a single instance or are single variable containing a collection of your objects, Update Typedata will actually update the types or adding it to the actual type itself, meaning that any objects we spawn off that type will automatically have those extended properties and methods in them.
5:16With that, why don't we jump into the Virtual Nugget Lab and take a look at how to utilize PowerShell's Extended Type System. Hey, welcome back to the Virtual Nugget Lab. So one thing I wanted to do real quick before we jump into the ISE and I show you how to extend objects is just show you one little neat thing here with Get Members. I'm just going to pipe Get Service to Get Member, and I wanted to show you this view parameter. This is useful because it allows you to see things like adapted members, base members, that that's how the dot.Net framework sees the members. Adapted is how the Adapted Type System sees the members. Extended is another good one, because it allows us just to see the extended members to the ETS, the Extended Type System here.
5:52This is where all of your Alias Properties, Note Properties, Script Properties, Code Properties, Script Method, and Code Methods would show up. So that's useful for seeing how these numbers look from different perspectives. All right, let's jump in to the ISE. So let's look at the many ways we can extend an object and work with those member types. We're going to be utilizing Get WMI Object, and we haven't gotten into WMI or CIM yet. We will down the road. But by passing in Win132 operating system, it's going to give us a bunch of great information about our local machines operating system and beyond. So I'm just going to highlight this code just to show you what we get here first, and then we'll put it into a variable and see some of the things we can do with it.
6:27So look at this, a lot of great information here such as the operating system, which is known as caption in here, which would probably be a great idea for an Alias Property because caption is kind of silly. Why not call it operating system? But there's a lot of other information in here, but let's say that we're missing something. Maybe we wanted this to also have the IP address of the local machine. Well, we could do something like this. We could do a select and pass in an expression here by giving it our hash table with name of the property and the expression being a commandlet to extract the IPv4 address of this machine.
6:59So that's one way to do it. And by doing that, check it out. There's a computer name, there's caption, and there is the IP address is here of this local machine. So that's one way to do it using select object. Now next up we're going to work with Add Member and, again, Add Member's going to be the preferred method of doing so, because we're going to be able to work with these methods and properties, these members, later on down in our script, where Select Object is good for just adding them on the fly to create calculated properties. So the first thing we're going to do is add a Script Property just as we did above, only we're going to break it out here. So if we pipe our variable to Add Member passing the member type being a Script Property, passing the name just as we did above in our hash table here, it's going to be the name of the property.
7:35And then the value of the property just as we had in our expression up here is going to be the same. It's going to be the Get New IP address commandlet, pass in the parameter of our address family of IPv4. So if we run that, we have now just added this member physically to the object, if we run a Get Member, we should see it down here at the bottom. Check it out. There's our Script Property. There's the definition, and there is the name. And now we can work with it like it was a real property on the object because it is a real property on the object. So that's a Script Property just PowerShell code inside of your value. What about an Alias Property and Note Property?
8:07Again, Alias Property is a great way to rename something just as we're going to do here with Caption. We're going to add an Alias Property using Add Member, so the member type is going to be Alias Property. Give it a name operating system, and the value is going to be caption. So that's the field that we're referencing. So it'll make it a little easier to understand. And then the second one will do for service packs. So we'll rename service pack major version to just service pack, which will reduce the amount of typing we have. And then the third one we're going to add here is a Note Property called department, which again, for static value. We'll just add the static value there PSOps.
8:38So by adding these three members to it, now if we pipe this to Get Member, we should see all of them. And these are in alphabetical order by member type. So up top here we'll have our two Alias Properties. There's operating system, there's service back. Here's our Note Property here in department. And then down at the bottom, we should have our Script Property that we just previously created in our IPv4. So we've got all of our properties in here that we made so far. And now we can just pipe all this to select to pull out these specific properties, all of them that we've created thus far, and they're there.
9:08What about a Script Method? Let's say, again, that we wanted to add some ping functionality to our object here. We're going to pipe, again, our variable to Add Member. This time we're going to specify Script Method. We're going to give it the name ping, and then our value's going to be connection. Our computer name is going to be this, dotPScomputername, which is referencing the property on this current object. Now the only caveat here that you need to be aware of, is when you're defining Script Methods, you cannot use the dollar sign underscore placeholder you need to use this for the placeholder rather than that.
9:41All right, so for anything Script Method or Script Property-related, keep that one in mind. So let's go ahead and highlight all this. And by the way, the ForceOne will override it if it's always there. Just want to throw that in there, because if you're doing this and your testing, and your testing, and your testing, and you run this without Force, you'll get an error that that property already exists. So use Force to overwrite any existing property or method member as we call it. So let's run this one. Let's hit Execute, and now we should be able to just doing an OS ping, and that will ping this machine. There it is.
10:11And again, if we pipe our variable here to Get Member, we will now see we should have a pink Script Method right here. There it is. Cool. So that's how we use Add Member. Now let's take a look at another one here. This is a cool one. How about New Objects? Say you wanted to create your own custom objects from scratch. Let's do that. Let's create our own PC object here. So we're going to create a variable called PC. We're going to use the New Object commandlet. We're going to pass in the type that we want to work with. We're going to create a brand new PS object, which is going to give us a PS custom object from scratch. Then as the property parameter, we're going to pass in a hash table defining all of our initial properties.
10:44So we'll have a user in there, which is going to pull the username is currently logged in, and we'll send that to lower. The machine's going to grab the computer name that I'm currently on and send that to upper. We'll get IPv4 in here again, which we're going to call that commandlet. We're going to get the operating system you're using CIM rather than WMI this time. We'll pull the caption off of that. And then we'll get the service pack, which will pull the service pack major version again off of there as well. So by doing this, we're going to have our own object, our own brand new object. In fact, if we just pipe this all to Get Member, let's do that. We can see the kind of object that we're working with.
11:15Check it out. There it is. PS custom objects. We get all those base members, and then we get the ones that we added in here. Right now, those are all added in as Note Properties. Now let's make things a little more interesting here. Now the first one isn't very interesting. We've done this. We're just adding another Note Property here called department, put a static value in there. But these next couple of lines are very interesting. So we're going to create a service variable, and we're going to store in there to the currently running services. So Get Service where the status is equal to running. And then we'll create another log variable, and we'll say Get Event Log, all the system event logs, the newest 10 entries.
11:46And then we're going to add a Script Method. We'll call it Get Running Services, and we'll pass in that variable. And we'll do the same thing here for our log. And then, we'll also add another one that I haven't mentioned yet, just to throw in here, called a Property Set, and we'll call it Stuff. And we'll get the value of machine OS and SP, the ones that we recruited above here initially. A property set is just a way to create a group of properties, and then you can call that one property, and you'll get all of the properties associated with the back. Again, a nice great productivity feature there if you find yourself working with common properties, wrap it into a property set.
12:17Then you can just call that one property instead of multiple properties in one shot. All right so let's add all of these into here. And now, if we come down here and run a Get Member once again, look at them all. So we've got our property set, we've got our Script Method, we've got all our Note Properties that we were working with there before. And now just to show you here, we could pipe this to select stuff and it's going to give us those three properties that we set up in that property set. And if we call a Get Running Services, it's going to run that method and get all of the running services as they were at that point in time.
12:47We can also do the same thing here and run a Get System Logs, and it would give us the same result, all the logs that we stored inside of that log variable that we associated with that Script Method. So New Object, another really great way to create your own objects and start building it up with your own properties and methods. Now the last method I want to show you here is extremely useful, because this is how we extend types rather than objects. Again, objects live in memory, so as soon as they go out of memory, we lose them. We lose all these members that we dynamically added, and we need to reconstruct them any time we run the script, which may or may not be a big deal.
13:20But this could be a huge time saver, especially if you're doing something like we're going to do here. Let's say that you're always working with daytime objects, and you have a big need to work with quarters, maybe for reporting purposes or whatnot. Well, guess what? Quarter is not a property on Get Date. In fact, if we run Get Date and pipe it to Get Member, you can see that there's no quarter on here, so no daytime objects have quarter on them. So this would be something that if we dynamically added in anytime we're in daytime objects, it would equate to a lot of code, right? But by running Update Typedata, passing in our type name, and then adding our own Script Property or Script Method to it, which is what we're going to do here.
13:57Member type, we're going to give the name quarter, and then our value is just a big if statement to figure out where the current month is, and then outputting whatever quarter that month is as the value. So by doing this we're updating the raw type information, meaning any object that gets spawned off of this, no matter where it comes from, will automatically have quarter on it. So let's run this, and now no matter what we do Get Date or otherwise, anything that has system.datetime as a return object will have quarter on it. In fact, we can see this if we just pipe Get Member here, we should now see quarter down here as a Script Property.
14:32Cool. And now we can grab the quarter, and we can see that we are currently in Q4 of this year, but this is great. Now the only other thing I want to mention here is that this is also session-based, so it's going to live in memory from the time you run this to the time you close out your session, so this is another great candidate for profile scripts, something else we'll cover later on in the course. But by putting this inside of your profile script, you'll never have to worry about it again. Any time you fire up PowerShell, quarter will automatically be added to your daytime types. So that's how we can take advantage of PowerShell's extended type system to add our own members to both types and objects.
15:08Let's finish this Nugget up with a look at your challenges. Challenge number one, view only the extended members of a System.IO.File Info object. So here we're going to do is first we need to get a bunch of FileInfo objects. How will you do that? Right, run Dir or Get ChildItem, pass in the file, switch parameters, so you just get a bunch of FileInfo objects. Then pipe all of those to Get Member and use that view parameter that we were just looking at earlier in this Nugget. Challenge number two, extend the System.IO.FileInfo type to add a custom Script Property for LengthMB.
15:38So this, pay attention to the wording here, type. What does that mean? Well how are you going to extend the type? You guessed it. Using the commandlet we were just looking at, Update Typedata. So again, this is just a great real-world one, especially if you find yourself writing the same expressions over and over to generate the same properties. Why not just add it to the type so it's always there. Now this last challenge is probably the trickiest one I've given you yet. Let's go over it. You're going to extend the objects returned from Get ChildItem using Add Member to include a last written to Script Property that contains the difference between the current date and the last write time in the format of days and hours, colon minutes, colon seconds.
16:11And you're probably like, huh, what? Here's the idea. So we've got a last write time on objects, right? In fact, let me fire up PowerShell here and just show you. If we do a Dir against sequel backslash, myDir, we've got this last write time here. And we know what the current date is. So what I want is a property on the end of here that says the last time this file was written to in the form of four days, three hours, 15 minutes, and five seconds ago, that kind of format. So that that's the whole idea here. Now this will obviously be very tricky if you've never worked with format strings, but I'll tell you, it's really not that bad.
16:45It's a lot easier than it seems. And if you do feel like doing this one on your own, just do some Google searching for format strings with the two-string method. And then if you want to try it on your own, pause me or close me right now, because I do want to walk through the solution now, because I think this is extremely valuable. It's a great thing to learn, because it will certainly be something that you come across in PowerShell someday. So three, two, one, here we go. Here's the solution. So what we're going to do is run a Get ChildItem against a directory. That's going to give us a bunch of FileInfo and directory info objects that are going to get stored inside of our variable.
17:17Then we're going to pipe those objects to Add Member adding a Script Property with the name last written to. Here's the value. Here's all the tricky part right here. Here's all the magic. So we're going to take Get Date, and we're going to subtract it from the last write time, and that's going to give us a timespan, right, the amount of time from this moment to the last time the file was written to. So all we need to do is format that into something friendly. How do you want to format it? Days, hours, minutes, seconds? We're going to do all of those and inside of the two-string method, you can pass in a format string. You can format currency, numerics, decimals, dates, times, everything using these format strings, extremely, extremely powerful.
17:50So how we're going to format this time span is by doing a date, so we'll do first day, dd, and so that's going to give us the length of two there, so 01, 02, so it's going to zero pad it for us. Then the backslash means the next character is a literal. So that's where the period comes into play. So it's going to be date date dot, then our hour, backslash, colon, minute, backslash, colon, seconds. And that's it. Pretty straightforward. So let's do this. Let's highlight all this, hit Execute. And now, if we run this, and I just created a file in there not long ago, so if we run all of this and hit Execute, we should get those three files inside of this directory that I created here called myDir.
18:30Here are those three files. If we look, we've got the last write time here, and then we've got the last written to in the format that we specified there. So the first one here, 34 days, three hours, 50 minutes, 40 seconds. Here's what I just created four minutes and 20 seconds ago, and here's our other one, test, that was created 25 days ago. Pretty cool. But see, it's not as bad is it seems, just a little tricky there with the formatting. In this CBT Nugget, we saw how to extend the PowerShell objects. We got familiar with the adapted and extended type system. We got familiar with the many different member types that we can use to extend objects with, such as Script Method, Script Properties, Code Method, Code Properties, Alias and Note Properties.
19:05And we also got familiar with the many different ways that we can extend objects using Select Object, using Add Member, using New Object, as well as using Update Typedata. I hope this has been informative for you, and I'd like to thank you for viewing.
Formatting Output
0:00Formatting output-- wouldn't it be great if you had full control over how the PowerShell displayed objects once you hit the end of the pipeline? Well, I'm here to tell you that you do. And that's what we're going to look at in this Nugget. We're going to familiar with the major format commandlets. I'm going to get you familiar with the process that PowerShell goes through for determining how to display our objects once you hit the end of the pipeline. I'll even show you how to control those defaults. And we'll look at how formatting in the format commandlets differ from the select commandlets. Because they feel very similar and you can do a lot of similar things between them. All right, let's begin.
0:30So, PowerShell does a pretty decent job of displaying our objects in a format that's easy to comprehend. But sometimes it doesn't. And that's why it helps to understand how PowerShell does these things and, of course, understand the format commandlets. Because that will give us total control over our output. Here's how this works. Now let's say that we were just going to execute a command and let PowerShell take over from the formatting perspective. In fact, let's just do a get-process here. And let's get all processes that start with W. Right, now how did PowerShell know to grab these properties and format this as a table?
1:05Notice this is a table. We have column headers here. We have rows inside of here with all the data. And also note. That these column headers are not the property names that live inside of those process objects. In fact, if we just piped us to get member, look-- there is no VM, meaning virtual memory in megabytes or page memory in kilobytes or working set in kilobytes. None of these columns, so to speak, are inside of the actual object, right? So how did PowerShell know to do that? That is the formatting system taking over here.
1:37And that's what I want to get you familiar with first is how PowerShell decides to format. So it's going to do this no matter what at the end of the pipeline, right? We're going to create a pipeline. We're going to go get some objects. Maybe we'll filter out a few objects. And right when it gets to the end of the pipeline, PowerShell's going to look at a bunch of these format files to determine what properties are going to get outputed by default and what format they're going to get outputted in-- so format being a list view or a table view as we just saw. So before all of this data gets to the host, PowerShell needs to figure out how it's going to display them.
2:08And it's going to go through some processing rules here. Rule number one is it's going to loop through these files for a predefined view for that type. Let me give you an example. Let's bring PowerShell back up here. Let's get some space to work with. And by the way, all these format files live inside of pshome. So let's just do a cd, which is an alias for a set location, on pshome. And now let's just do an ls and find anything with format in the name. Look at them up. There they are-- tons of them. So what I want to do here is, first, let's head to the top and let's see what type we're working with here.
2:39We know, because we did a get-number, that the type is System.Diagnostics.Process. Let me just grab this. And then we'll copy it. And then we'll head down to where I was here. And let's just start. I'm going to do DotnetTypes because I know that's where this specific type's view definitions live. So I'm going to start this up. All right, now let's go ahead and do a Control-F and let's find anything with that type. And now the first one it's going to find here is actually Process Modules. Let's do it again. There it is. So what it's doing first is it's looking for this view right here.
3:10See that? See that view? This is a view, which is going to pretty much determine the kind of format it's going to use to output these objects. And this is a table control, which actually lines up with what we saw here because, guess what? That is a table, right? Rows and columns. And if we look further into this, we can see all of these column definitions-- the label, the width, the alignment. If we come down, you're going to see there's our working set. There's our virtual memory in megabytes. And so this is what's going to override the property names. And then we head down here, here are the actual mappings.
3:42So we have a script block in here that defines exactly what it is. So here's our working set divided by 1024. It will give us the kilobytes. And then virtual memory divided by that will give us the megabytes. So that's the first thing it's going to do. It finds it. Great, it's done. It outputs it using those defaults. And that's exactly what we have here with getProcess. Let's do another one here. Let's take the file info object here. If we do a dir file, let's just pipe this to get member here and head up. We know that this is going to be a System.IO.FileInfo type. We've used this one before. I'm just going to copy that to the clipboard.
4:13And if we head back to our Dotnet types here, let's just go to the top and let's search for this. It's not in there. How come? Well, that's because there are many format files and they all get loaded into memory. In fact, again, if we do an ls here for format, we'll be able to see that file info is probably in the file system doc format file. So if we do-- let's see. Let's go ahead and just start this up here. There we go. And we can see right up here is the definition for directory info and file info. And if we scroll down, here is the view definition. It's also going to be a table, Mode, LastWriteTime, Length, so on, and so forth.
4:46And that matches up with what we have here-- Mode, LastWriteTime, Length, so on, and so forth. All right, so that's step number one. It's going to look for those predefined views for that type in all those formats files. And yes, you can create your own format files and have total control over the formatting and the output here. You can create your own format files, put them in a directory that'll get loaded into memory. And it will then look for your specific views as well. And by the way, just think of a view as really just another layer on top of your objects for formatting. So you can define those column headings. You can define the widths of those columns, the alignment and things I'll show you here once we get into all the different format commandlets.
5:20Now, what if there is no view for that type? This is where it's going to take the second step and it's going to look at the raw type definition inside of the types.ps1xml file to determine which properties to output by default. And to give you an example here, let's just go ahead and do a Get-wmiObject. And let's do this for the win32 operating system. So this is one that has no predefined view. In other words, there is nothing for this type inside of the format files. And what type am I talking about here? Let's pipe this to get-member and let's grab this right here.
5:55Copy it to the clipboard. And I know we can go through all the formatting files and you won't find it. So what we can do is let's just open up here types.ps1xml. Again, this is where all the type definitions live for all the types here in PowerShell. So if we open this up, and I'm just going to search for that, we will find this. And so the second step it's going to do, then, is look for anything that has a default display property set, which everything does. And it's going to use this, then, to determine the default properties to display-- so system directory all the way down to version, which lines up with what we have here in PowerShell when we ran that command.
6:31There it is-- system directory all the way down to version. So that's how it determines the default properties. But how does it determine the default format? List, or a table? Well that's step number three here is since, again, we don't have a view defined, it's going to look at the number of properties and it's going to say, all right, if it's five or more, then it's going to put them inside of a list. If it's less than five, it's going to display them in a table. And those are the internal rules that it uses to do so. And just to prove that here, let's head back to PowerShell and let's just run GetwmiObject again here.
7:03Only let's just select, how about, system directory and version. See that? Now we get a table rather than a list because it's less than five properties being returned. So that's how PowerShell determines internally how to display our objects once you hit the end of the pipeline. Now let's get familiar with these formatting commands. These are extremely useful to know because it'll help you customize your output. So Format-Table, we were just looking at this, just gives us rows and columns to work with. Format-List gives us kind of key value pairs up and down, a property kind of view where we have the name of the property, colon, and then the value of the property-- extremely useful when you're troubleshooting as well here.
7:40I'll show you some neat tricks with that. Format-Wide is really just used to work with one property. So if you're working with one property, it'll list them all in a row. And we have control over the columns here as well. I'll give you that. And then Format-Custom is one of the advanced format commandlets that allows you to define your own customized views. So you can output things any way you can think of. All right, let's jump into the virtual Nugget lab here and take a look at how to work with these format commandlets. Now, the first thing I want to do is get familiar with Format-Wide. But before we do that, let's just do a get-service and let's pipe this to select and pull out just a single property.
8:11Now, what did that do? That give us a table with one property. And that is going to result in a lot of scrolling. Wouldn't it be better if we could just format this as a wide here? So we'll do a format wide which, by the way, has a property switch on it. And that's positional. So we don't technically need to type that out. And then let's say name. What's that going to do? Results in a lot less scrolling because now we have two columns with that single property inside of it. In fact, we can even control this with the column parameter here. We can say column, give me five columns. And look at that-- they all are in one nice view with a lot less scrolling.
8:43So use Format-Wide when you're dealing with a single property because it makes it a little easier to work with there on screen. Now, the next one I want to get you familiar with you here for Format-List. So let's do a get-service and let's do a Format-List here. Put in the property parameter just so you can see it. Let's do name, display name, and how about status? All right, there you go. Look at that. So there's Format-List, right? And we didn't actually need to do that because we were under four properties there. So we could have just did this in a select object and we would got them back here as a list anyway.
9:17But one thing I want to show you here is kind of a neat little parameter to get used to because this is extremely useful. And that is group by. Let's say we wanted to group by status. And the nice little gotcha here is that didn't work so well. And that's because it grouped them as those objects were coming at the end of the pipeline. They were just getting pushed out one at a time. So this is why whenever you use group by, just make sure that you do some sorting here. So let me head back here-- right here. And let's throw a sort in here. Sort by status first and then format it.
9:50And now it's grouped accordingly. So now I'll get some column headers here. And there's running. See that? And here's all the stopped ones. So we get some column headers and then all the stopped services underneath that, all of the running services underneath that. So that's group by. Now, what Format-List is really good for is when you want to do some troubleshooting and you want to see all the properties. Because we could do something like this. I'm just going to do a get-service here, format list. And instead of typing out property-- it's positional, we'll use it-- we can do an asterisk there, which means it's going to pull out every single property.
10:21And in fact, here-- that was a lot going on there. In fact, we could probably do something like this here. We could do a select. Let's just do, how about first five? There we go. And then we'll pipe that there to format list. And there we go. Now we get the first five. But what's great about this is that it's just an awesome way to do some troubleshooting against your objects because it shows you absolutely every property on the object that's getting sent here to Format-List. So that's Format-List. The next one we'll look at here, probably one of the more useful ones and more powerful ones-- we can do quite a bit with this-- is Format-Table.
10:56So let's do a get-service here. And let's pass that over to Format-Table. Again, the alias there is ft. And let's just say property here. And let's pull out name, display name, and status. Now, here's the thing. Look at that. See what it tries to do by default is it tries to fill up the entire screen. Here's where the auto size parameter is extremely useful. Because what it'll do is it'll just make sure that every column is as wide as it needs to be for, of course, the widest value within that column.
11:28Let's do another one here. Let's do GSV, pipe that to Format-Table. We'll do an asterisk so we get everything. And let's see what this returns. Woah, look at that. That's a lot going on there in that table. Now, any time you see dot, dot, dot, that just simply means that there is more to be had. It couldn't fit it all inside of that column. So this is where wrap comes in handy here. There we go. We could add the wrap switch for Format-Table, which will actually wrap it then inside that column so it's all typed out downwards.
11:58And then we could also combine then with an auto size-- oop, auto size-- to clean that up a little bit. And there it is, even though it's still a little more difficult to use. But at least it auto sized it and wrapped it. So it's a little easier to read than before. So those are going to be the most popular switches here with all these formats commandlets-- group by, auto size, and wrap. Get familiar with those. Play around them because they can go a long ways and help you control the output of your object. Now, another neat thing I want to show you here with format table that's also going to highlight one of the differences between this and select object is customizing your output, right?
12:35Creating your own columns, aligning them, formatting them-- that kind of thing. So let's jump in the ISE here because there's a lot of typing involved here. I don't want to make you watch me type all this out. And I opened up our commands file for this Nugget. Now, this is all the stuff we just did up to this point right here-- get-eventlog. So here, what we're going to do is we're going to get the system event log, get us the first 10 entries or the most recent 10 entries, and then we're going to format the table. Now, let me show you what this looks like without our custom column. Because we're going to add our own custom formatted column here on the end of all this.
13:06Here's what it looks like. So you can see we've got some issues here with the formatting. But we're getting the most recent 10 entries here. We're pulling back these columns. So we're going to add our own column onto the end of this called when. And what we're going to do is format this in the form of days, hours, minutes, seconds so we know exactly how long ago this happened relative to now. So we're going to take the date. We're going to subtract time generated, the time this interview was generated from it, and we're going to align this column to the right and then format it here using this format string. This should look familiar.
13:37We did this in a previous Nugget, all right? So it's very easy to do. We pass a hash table in. We specify the name. You can also use label. You could spell out a name or you can just use n, which will result to name. So that will give us our column header. Then our expression here is going to be the actual value. And here, we're just doing get date minus the time generated, which will give us, again, the relative time that this happened in the form of days, hours, minutes, and seconds. But here's the special part of this expression inside a format table. We can control the alignment-- right, left, center-- and we can control the format of that string.
14:13Pretty cool-- now let's take a look at this by running it. And there it is. Now, we still have some formatting issues, but we've got our column here and it looks great. All those formatting issues can be fixed with our magical switch here, auto size. So let's just add auto size into that. And look at that. It looks great. So there's one of the big differences between format and select. Think of select as you're in the pipeline, doing things with your objects in the pipeline. But we can still pull out specific properties if you have no need for formatting. Formatting is really good for you're at the end of the pipeline.
14:44Your objects are about to get displayed. Do you want to do anything else to them? Make them pretty, line them up, do that kind of things. And I should also mention second big difference here is that Format-Table or any of the format commandlets, once they hit, your objects are done. They're toast. They actually get fully replaced. Because if we do something like this here, if we do a get member after a select, they're still objects, right? Look at that. We get our objects. And here, we're going to get a listing for every type of entry in there. But they're still objects. Where if we were to do a get-member here after our format, they're going to be format objects.
15:19Look at that. See that? So those objects are gone. They've been formatted. They're out of the pipeline. So that's why it's very important that whenever you do formatting, make sure that it is the last thing you do. Now, the last thing we want to show you how you can control the default output for properties on objects. Now, of course, you could go into your format files and edit those or your type files and edit goes. But that's definitely not the recommend way to do it. Leave those files alone. If you're going to create your own formats, create your own format files. And if you want to control default property output, use our trusty commandlet that we've looked at in a previous nugget called Update-Typedata.
15:53We can also use this to determine or I should say define the default display outputs. So here, we're going to take the System.DateTime type. And we're going to say, you know what? We don't want the defaults. In fact, just to show you the defaults here, if we do a get-date and send it to format-list, here's what it looks like. There are all of those properties that are outputted there by default. So if we wanted to control that-- to say maybe we only wanted a couple-- then we could use Update-TypeData, specify your type name, and specify default display property set and pass in your properties. PropertySet is used for Format-List.
16:24Property without the set here, just default display property, is how you control outputting for Format-Wide. So here, we're going to say date, time, day of year, and quarter. Let's go ahead and run this. And remember, this will only work inside of this session. So if you're going to do this stuff you want a permanent, this will be another thing that you add to your profile. So we do that. And now if we run this, we should just get those properties. But guess what? We don't have quarter defined in here because this is a different session from when we were working with our extending objects where we actually ran this block of code to add our own member type, our own script property here, to the date time type.
16:59So let's run this block of code, same block of code we ran in a previous Nugget. So we're going to add our own script property called quarter with a value here that'll figure out the quarter based on the current month. So I'm going to execute that. And now if we run Get-Date with Format-List, we should have quarter filled out. There it is-- awesome. So there are all of your formatting commandlets, how to use them, and also how to control the default output. Let's take a look at your challenges for this Nugget. Challenge number one-- pretty straightforward. We did this in our demo here just a little bit ago. Return a list of all processes. Use Format-Wide to output the name property using six columns.
17:32Challenge number two-- return a table of the 25 most recent system event log entries sorted by entry type. Than output source time generated and message using Format-Table. Then group by entry type and wrap the results-- again, something else that we've done here in our demo. And challenge number three-- return a table of processes. Use Format-Table to return the ID name VM, and define a custom property named VM megabytes. Remember, VM by default returns bytes. So you're going to add your own custom column here, which is going to be VM, Virtual Memory, in megabytes.
18:04So you're going to use an expression that converts that to megabytes, use right alignment with the numeric stream format for two decimals, and auto size the results-- a little more involved, but again, really not that difficult to do. Just remember, you're going to use a hash table to define that custom property using the property switch on your Format-Table to add your own column into the results. Remember, you can find the solutions underneath these regions. Just expand them and you can find all of these files inside of the Nugget lab files, which are downloadable on the right hand side of the course page.
18:35Good luck! In this CBT Nugget, we covered formatting output in PowerShell. We saw how PowerShell determines what format to use and what properties to pull out of our objects once they hit the end of the pipeline. And we got familiar with those big formatting commandlets-- Format-List, Format-Wide, and Format-Table. I hope this has been informative for you and I'd like to thank you for viewing.
The Pipeline Returns
0:00The pipeline returns. So PowerShell rocks because we can do so much with so little. What used to take complex VBScripts can now be done with a one-liner in PowerShell. But how does it do it? How do objects traverse the pipe line and commandlets transfer data to the next commandlet? That's what we're going to cover in this Nugget. Understanding the internals of the pipeline, and how objects are transferred between commandlets can go a long way in giving you the power to control that pipeline. Let's begin. So how does the pipeline really work? Up to this point, we've been stringing commands together, and we just kind of assume that it's all going to work.
0:34So we were to do something like a get-service, and we were to pipe to this over to say, a stop-service, we just know it's going to work. Now up to this point, we've talked about objects. So we know that get-service is going to return objects, and it's going to send those objects over to stop-service. But we just take this pipe for granted. It's a magic symbol that does all the work for us. We don't have to know how it works. But again, understanding how it works will help us really have a lot more control over the pipeline, as you'll see here. So here's how it works, right here. Commandlets accept input on a parameter.
1:07So this is also why it helps to dig into the Help files to look at the details of each parameter, because we've got a really nice property underneath each one of these parameters called Accept Pipeline Input. And that's what we're going to dig into. Now, how PowerShell determines what parameter to hook up to is a process known as Pipeline Parameter Binding. And it's going to do this in one of two ways. It's either going to do it ByValue or ByPropertyName, which is one thing that you're going to see on the Accept Pipeline Input.
1:37If that's true, it's going to either say ByValue, ByProperty, or it's going to be both ByValue or ByProperty. Let's look at ByValue. This is the first thing PowerShell is going to try to do. It's going to try to take those objects and see if there's any parameter that matches that object type and can accept pipeline input ByValue. So PowerShell is going to first evaluate the objects coming in. If there any parameters that can accept this object type as pipeline input, then it's going to say awesome, great, I'm going to pass all those objects through that parameter to the next commandlet.
2:12If it can't do that, then it's going to move on to step two. But let's just pause for moment and just kind of digest what just happened there with step one. Let's take get-service, for example. So if we were to run get-service, get a bunch of objects back, and then we pass this [INAUDIBLE] stop-service, again, the PowerShell is going to look at the types of those objects. It's going to say, OK, these are service controller objects. And then it's going to look at this commandlet that we're passing it to, and it's going to say, all right, does this commandlet have any parameters that accept a service controller object as pipeline input ByValue?
2:47And it does, and in which case it would use that, pass those objects into that parameter, and stop-service would then be able to do its thing. So what if by value fails. In other words, we're passing data through a commandlet that doesn't accept objects of this type for any parameters that accepts pipeline input. If it doesn't, it's going to move over to step number two and try to match them up ByPropertyName. Now, what this means is it's going to take a look at the objects coming in, and it's going to look at the actual property names of those objects, and try to match them up to the perimeter names of the commandlet that's accepting these objects that also accept pipeline input ByPropertyName name, and literally just match them up.
3:28It's going to take the data from that object property, and pass them over to the parameter with the same name. And it will hook them up. Now there are, of course, a couple of pitfalls with this, because it's not guaranteed that that's the right data going back and forth. And I'll give you a good example of that. And that's what it really helps to understand this internal process, because you'll be aware of that fact. And if things go wrong or you get unexpected results, you'll know why. So that's all it is. It's just literally going to match up the name. It's going to evaluate the objects, match the name of the property of the object with the name of the parameter that accepts pipeline input ByPropertyName.
4:04And it will match multiple property names. So if you have an object that has a name property, and maybe a title property, and then you have a commandlet that has both of those parameters that accept by pipeline input ByPropertyName, it's going to send both of them over the commandlet at the same time. Now let's step into the Virtual Nugget Lab so I can show you how this process works in both ByValue and ByPropertyName. And then I also want to show you how you can control this by using custom properties. So we can manipulate the objects in the pipeline so we can ensure that they're getting transferred over to commandlets accurately.
4:39And I also want to show you something about parenthetical commands, which is a great way to get around certain limitations within specific commandlets. All right. We're in the Virtual Nugget Lab. Now, the best way to show how this works is to get a couple of Windows side by side here, so we get some Help files, as well as XEU commands here in the same screen. So the first thing we want to do is just show you how this works ByValue. So if we were to do a get-service, and we were to pipe this to stop-service, and I'm going to throw a what if on here, so we don't actually do it and crash our machine, that would've worked. It would've stopped all the services on the system.
5:10But how? How did that work? Now let's get help here on stop-service. And let's go full mode here. We need full. That way, we get all the perimeter descriptions and such. And I'm just going to scroll up here. And what we're going to do is look at these parameters. So the one that you're looking for is right here-- accept pipeline input. So Display Name, nope, Exclude, nope, Force, nope, Include, nope. Oh, but look at this one, Input Object. It accepts ServiceController, and more importantly, or it accepts pipeline input ByValue, meaning if we were to pass ServiceController objects over to this top service commandlet, this is how it's going to accept them, and it'll work.
5:48And that's exactly what we did over here, because we know that get-service-- in fact, if we do a get-service here and just pipe it over get-member, we know that these are ServiceController objects. So that's why that succeeds. And that's always going to work when you have nouns here that are the same. So get-service piped over to stop-service, and start-service. Those are pretty much going to work all the time. All right. Let's take another example here. Let's just clear our screens. And let's do a get-service. And let's pipe this over to sort-object.
6:19And let's sort say, by a display name. All right. Cool. Hey, how did that work? Well, let's get a help here on sort-object. And let's get full. This one's very interesting, because you can pretty much pass any object over to sort-object, and it'll work. But how? How will it do it? Well, let's look at the properties here, and let's see here. Look at this. Oh, we've got a PSObject. Oh, look at that. It accepts it True ByValue. We also have a more generic object here on Property, but guess what? It doesn't accept pipeline input, so we know that it won't work.
6:51But this one will work. So PSObject is what? Yeah, the base of all objects in PowerShell. So what that tells us is we could pretty much pass anything into sort-object here, and it'll work. So keep an eye out for that. So that's just another good example there of ByValue. And it's a much more generic example, because sort-object accepts virtually any kind of object here in PowerShell. Let's do another one, and let's do ByPropertyName now. So what I'm going to do here is I'm going to just do a get-help on, let's say, stop-process instead of services here.
7:23Mix it up a little bit. And let's just get the full help here. Let's take a look at these parameters. So how can we pass data here to stop-process. Well, if we scroll down here-- oh, there's one. ID. And it's ByPropertyName. So if we have an object with ID in it, we can pass it over here and stop it. What about here? Oh, InputObject, of course, process. So we can use get-process to get process objects. And of course, if we do that, then that's what it will use. But if we don't do that, then we have a couple of options here ByPropertyName that's going to be ID as well as name as a string.
7:55So let's see. Let's do something here. Let's fire up some Notepad instances here. How about just one? Let's do a get-process for Notepad. All right. So we've got one process in there. And now how about this? The name of it is Notepad, even though it went off the screen there. Let's format that as a list. There we go. Notepad. See, formatting commandlets are great, because we can do things like that. So here it is. Notepad is the name. And what was I looking for there? Yeah, that's pretty much what I was looking for. So can we do this? Can we do Notepad and pass it over to stop-process.
8:28Will this work? Should this work? Because look at that. It can accept a string, ByPropertyName if we hit Enter. You can say, no, sorry. Anybody know why that didn't work? Right. Because this isn't an object. We just passed a string. I'm sorry, it's not an object that contains a property with name in it. So this won't work, because we're just passing a string over. In fact, if we do this, Notepad, and we pipe that to get-member, we're just passing over a System.String. So it works from the data type perspective, but parameter binding isn't working ByPropertyName because this isn't an object with the property of name.
9:08That's what we really need here. So watch this. Let's do this. Now, let me get a little more screen space for this one here. Properties. Layout. Let's just change this back to 120 here. 120. All right. Good deal. So let me paste some code in here. Now, here's what's happening. We're going to create a brand new object here. Just a base PSObject. So our own custom object. And then we're going to add the member name. Just a note property here with a value of Notepad. And we'll just add one more in here just to get another property in here called Time. It's just going to be a time stamp. Now if we execute, or pass I should say, this object over to stop-process, is it going to work?
9:42Watch this Notepad down here when I hit Enter. Oh, it's gone. It worked. And why did that work? Because if we look at this object here, we just send our variable over to get-member, we can see that this is an actual object that has a property of Name. And if we head back over to our Help here for stop-process, we can see that there it is, Name. ByPropertyName. And it failed on ByValue because we're passing over a PSCustomObject, and the ByValue here accepts ProcessObjects. So step one failed. Step two succeeded, because we have a property name accepted on Name.
10:15And we've got another property name up here for ID, but we don't have ID. If we did have ID, it would also pass that data over as well. But this is how it succeeded right down, and how Notepad was killed. Because we created an object with the Name property, and it matched up to the Name parameter, because it accepts pipeline input on that parameter. Make sense? All right. Cool. Now, let's head into the ISE here. Now this is why we need to be aware of how this stuff works. Because there is a potential, when you're not passing objects ByValue that objects property names and parameters names from commandlets could line up, but it could be different data.
10:52Here's an example. Get-service. What if we piped this to stop-process? Look at that. Two totally different commandlets. We're dealing with services. We're dealing with processes. But services, of course, underneath the hood still expose generally a long running process. But here's the thing. Service names, because get-service returns objects-- in fact, just to show here-- returns objects with a Name parameter. There's that Name parameter. And yeah. Stop-process, as we just saw, accepts parameter or pipeline input on the name parameters.
11:24So this would actually work. But it may not line up. In fact, I'm just going to do a what if on this, just in case. But if we hit F8 there, it worked. The commandlet actually accepted parameters. The reason we're getting these errors here is because it can't find processes with the same name and service names. But there are a couple of things. I could scroll up here a ways. But there are a couple that will work, because some services' name are the same as their executable. So that would work. So this is why you just need to be careful when working with ByPropertyName, because object properties likely could have a name or two that match a parameter that you're passing it to.
12:03But thankfully, we can control this. We have full control over everything in the pipeline. So let's take an example of that. Let's say that we've got a couple of departments coming on board, and we need to create a bunch of Active Directory Users. So we get a CSV, or spreadsheet, or whatever data, and whatever format here from HR, and they give us the CSV file that contains the name, the user name, the title, and the company, and maybe lots of other fields inside of here. And this CSV file, we can import and turn into a bunch of objects.
12:33And the Import-Csv commandlet is just an awesome commandlet for this. So I actually created this file called Users.Csv with this exact data inside of it. And if we were to just run this by itself, you'll see that it brings it in, and it transforms those column headers into object properties. And then we have an object for each one. So we've got three objects inside of here. And actually just to prove that here, if we have pipe this to get-member, watch this. This is pretty neat. So we get a PSCustomObject. And we get Company Name, Title, and Username as properties of those objects. So that would give us three objects representing those individuals.
13:08Now, here is where things get interesting. So let's say that we wanted to pipe this to the commandlet New-ADUser which creates an Active Directory user. Now, we know we're passing over PSCustomObject. So if we looked at the Help for a New-ADUser-- in fact, let's do that. Let's look at the Help here for get-help new-aduser. I'm going to do full Help here. If we check this out, and we scroll up here, look at all these ByPropertyNames. Look at them all. There's lots of them. So we know that in order to create Active Directory Users ByValue, we would need to actually get ADUser Objects But this coming from a CSV.
13:46We've got a PSCustomObject. So our only option here is going to be ByPropertyName. But pretty much everything in here accepts ByPropertyName. So that means we could map all of this stuff from the spreadsheet from those property names, but we need to make sure that the property names of those objects line up with the parameter names inside of New-ADUser. And how can we do that? Because name will line up, but username will not line up. It's actually same account name. Title and company will also line up. So we need to do something about this username. And maybe we have another one on here. Maybe we have D-E-P-T instead of something spelled out department.
14:19How can we do that? This is where custom properties are awesome, because we can throw a select object in between our import and our New-ADUser command to transform that pipeline, to add our own new properties on top of these existing properties with names that won't work with New-ADUswer. And what New-ADUswer will do then is to just ignore anything that doesn't map. So username, we don't have to do anything special with it. We can just ignore it, because that commandlet will ignore it, and we'll create our own called samaccountname on top of it.
14:50And if we did have department, we could spell out department, and then create a custom property that maps to the D-E-P-T. We don't have that in here. I just wanted to show you that for completeness there. But let me get that out of there. There we go. And now if we execute this, it's going to actually create these three users, because we now have Sam account name, which is required. So let's do that. And there it is. It should have created that. How do we know? We can run a Ge-ADUser, and we should get all three of those individuals in here. There it is. There I am. There's starlord, and there's Jeffrey Snover.
15:20Cool. And just to show you in the GUI here, if we do Active Directory Users and Computers, and we head down to Users, hey, there I am. And if we head over to Organization, hey, look at that. There's my title. It got mapped over. Company got mapped over. And even our account here, if we look there, got pushed over here to the username, was mapped to the samaccountname. Pretty cool, isn't it? So that is how we can control the pipeline. So if you're to working with ByPropertyName, just make sure that what you're passing over lines up with the parameter that you're expecting.
15:54And if you do need to transform properties, just create your own custom properties here using select object. Really powerful stuff. Now, the last thing I want to show you here is parenthetical commands. This is another really powerful trick that you can use to get commandlets to work for you, especially if they do not accept pipeline input on a specific parameter. So I've got two files, servers.txt. This is just a file with literally just our servers in it. There's no heading. It's not a CSV, So it's just literally strings inside of there. And I've got another file called servers.csv, which is the same data, only we've got some columns inside of here.
16:29So this will be an object with the computer name property on it. Now get-service, we know just from the Help here, if we do a get-help on get-service-- we've got to do full. There we go. And if we look at the Computer Name parameter here, somewhere in here, here we go, that this does accept pipeline input ByPropertyName. So we know the first one won't work, because it's just a bunch of strings getting passed over, right? Not going to work. But this one will work because it's an object with the Computer Name property and Computer Name except ByPropertyName.
16:59So that would work in that case. Now, let's take a look at a commandlet that has the Computer Name parameter, but it doesn't accept pipeline input. So get-wmiobject has a computer name perimeter. But look at this. It does not accept pipeline input. It accepts a string of computer names. So how do we get around that? Because if we were to do something like this, import our CSV, get our object with Computer Name, and try to pass it, nope, not going to work, because the input object cannot be bound to any parameters for the command.
17:29All right. So this is how we can use parenthetical commands to get around this. We can wrap in parentheses another commandlet, get-content. This'll get all those server names, and we will pass them over to the Computer Name property. And this will work. If we do get-wmiobject to get all the OS info across all the computer names in our networks, this will work. So there it is. Look at that. There's all of the OS properties for all of our machines there. Pretty cool. So that's a great way to get around some limitations of parameter binding.
18:00And here's another way to do this. We could run Get-ADComputer. And then, I wanted to show you this Expand property, because this is a great one. But what this will do is this will get all the Active Directory computers inside of Active Directory as ADS computer objects. So if we didn't do this right here, this won't work, right? Because we're getting computers, and we're trying to pass this through the computer name parameter, which accepts an array of strings. So what we can do there is we can pull out a specific property, and use the Expand Property switch here parameter on select-object, which will actually go and get the data.
18:33In fact, if we just do this right here-- actually, let's do this. The full thing. There we go. You can see it's going to pull out those names as we saw them, just like we saw them inside of our servers on a txt file, only it's pulling it from Active Directory. So it's pulling everything. But this one will, in fact, work as well, because we're just extracting the raw string out of that computer object that's returned from Get-ADComputer. And this will give us the exact same result, except across all of our servers and clients that are in Active Directory. So those are some very powerful techniques that you will absolutely be using when you get deeper into PowerShell.
19:07Because having the ability to add our own custom properties to ensure that they map correctly to commandlets as we're passing them down the pipeline and having this little trick here with parenthetical commands will ensure that there is nothing that is stopping us from controlling that pipeline. All right. Let's go look at our challenges here for this Nugget. Challenge number one, review the full help topic for Get-EventLog. Does this commandlet accept pipeline input? And number two here for challenge number one, review the full help topic for Get-Hotfix. So which parameters accept pipeline input? So here, just getting you accustomed to looking into the full help topics, analyzing those parameters seeing what accepts pipeline input, and how it accepts pipeline input.
19:46And that way, again, there won't be any surprises when you're connecting commands together. Challenge number two, retrieve the most recent system event log entry from multiple machines using parenthetical binding. Would you have accomplished using parameter binding, and why not? So here, what you're going to do is use the Get-EventLog commandlet. Take a look at the parameters for that commandlet, and see how you could pass multiple computers into it, why you'll need parenthetical binding to do so. And then challenge number three, use parameter binding to pass a list of computers from Get-ADComputer to the Get-HotFix commandlet to view installed hotfixes across servers in the network.
20:22And I'll give you a hint with this one here. Get-ADComptuter, the property name that's returned for the Computer Name is actually called Name. Get-Hot for Computer Name, it tries to map it ByPropertyName on computer name. So you'll need to use a custom property to transform the Name property from Get-ADComputer to the Computer Name property on Get-Hotfix. That way, you can line them up, and it'll work. Good luck. Just remember, you can see the solution in the Nugget lab files, downloadable from the right-hand side of the course page.
20:52Look underneath these region files to see the solution. In this CBT Nugget, we dug deeper into the pipeline to get an understanding of how commandlets connect by passing objects back and forth. We took a big look here at ByValue and ByPropertyName. We saw that the first thing PowerShell will do will try to connect commandlets and their object data ByValue, meaning it will actually try to connect the objects to a parameter that accepts that object type and can accept pipeline input. And we saw that if that fails, it will use ByPropertyName, which will literally just line up the name of properties in the object with the name of parameters in the commandlet.
21:29So understanding how this process works will give you the ultimate control over your pipelines. I hope this has been informative for you, and I'd like to thank you for viewing.
Providers
0:00Providers. Wouldn't it be great if we can see any information store through PowerShell as if it were the file system, this nice familiar hierarchical structure? Well, that's what providers bring to the table. We have a single set of common commandlets that we can use to access things like the file system, the registry, SQL Server, ISS, access any of those as if it were this very familiar hierarchical structure. So that's what we're going to look at in this Nugget. Let's get to it. So again, what is a provider? It's really just a model for treating data storage hierarchically.
0:31PowerShell has these things called PS providers. And they're really just adapters that transform that underlying datastore into what we're all familiar with, the file system. So no matter what that underlying data structure looks like-- be it the file system with drives and directories, subdirectories, files, or the registry with hives, and root keys and keys and values-- or really anything-- like SQL Server, right, you've got instances, databases, and a whole smattering of objects underneath databases-- no matter what it looks like at the source, PowerShell transforms it into this common hierarchy that we can access through a common set of commandlets.
1:06And believe it or not, it's actually pretty simple to write to your own provider. So if you have a custom data store out there that you want to access through PowerShell using these generic commandlets, then, now, if you have some [INAUDIBLE] skills or know a developer that you can talk into writing one for you, you just simply need to map their data store to these generic commandlets here that we're going to be looking at through the rest of this Nugget. And it's really, it's pretty straightforward. So how this works-- just to give you an idea here. Let me break out a screenshot. Here we go. So how it works here is we've got providers at the very top level. And when you define a provider, you have your capabilities, what this provider could do.
1:39We'll talk about these capabilities here shortly when we get into our demonstration. And then we have drives. Everybody's familiar with drives, right, that nice entry point into what we all know and love, the file system. And now, this is where people can get tripped up because they're like, wait a minute, drive, you're dealing with the file system. Well, think of a drive really as just an entry point. So yes, if you're dealing with the file system, it's literally going to be the drives that are the drive letters on that file system. But if you're dealing with the registry, a drive is going to be your entry point-- such as HKLM, local machine, that would be a drive. HKCU, current user, that would be a drive.
2:09So think of it as the entry point for whatever data store you're hooking into. Underneath drives, we have items. And in items, we're dealing with the file system. Could be a directory. Could be a file. If it's a directory, it's container, so it can contain other items. If we're dealing with something like SQL Server, it could be a database. That's an item. But a database is also a container that can contain other items like tables and stored procedures and indexes. If we're dealing with something like a registry, we've got keys. If we're dealing with say, ISS, we could have virtual directories and items underneath that. So a item is just a generic placeholder for whatever we're working with.
2:42And you want to know something funny about this-- we've actually been using these generic item commandlets quite a bit up to this point. Here's one for you-- DIR. Frankly, we've been doing DIR all over. If we switch to a drive that's on top of the registry or SQL Server, we can use DIR to get a listing of everything underneath that because what's DIR mapped to? You guessed it. Get child item, GCI. And there's also one called GI for get item. There's so ton of item commandlets for working with specific items underneath the drive. And items, of course, have item properties.
3:12So if we're dealing with a directory or a file, we can set attributes like read only, write only, that kind of stuff, so attributes in metadata about that item. There's also location commandlets that allow us to navigate the hierarchy. And we've used one quite a bit up to this point as well, CD, which is an alias for set location, which allows us to move to a specific item in the hierarchy. So that's the whole idea behind providers, just giving us a nice, consistent way to access any information store through a common set of item commandlets. Let's jump into the Virtual Nugget Lab.
3:43We'll get familiar with how to work with providers, drives, and many of the item commandlets. Welcome back to the Virtual Nugget Lab. Let's get to it. So let's start by running a get PSProvider. So this is going to get us all the current loaded providers. Here are the defaults. And another provider I didn't mention-- Active Directory. So if we do something like get AD computer-- and let's just add a filter on here for everything. Watch this. It's going to load that module. Now, if we run get PSProvider, check it out. We have Active Directory down here as well. And here is the drive that we can then CD or set location into and start running DIRs or Get-Item, Get-ChildItems, all over.
4:17Now, this capabilities thing is interesting. So should process is telling us that this accepts the what if parameters. So we could use the what if parameters as well as the confirm parameter. I don't know if I mentioned the confirm parameter before, but essentially, that just means any time you run something with the confirm switch parameter on it, it will ask you, are you sure you want to do this, yes or no or cancel, that kind of thing. So other capabilities here are credentials. So we can supply credentials to this provider and run it under that security context. Transactions-- the registry supports transactions, so we can do all or nothing propositions.
4:51Let's see. We got filter. We just saw that one with Get-ADComputer. It allows us to run queries against that data store. We also have include and exclude, so we can include specific ones, ensure they're in the results, or exclude, so on and so forth. So these are just the capabilities, specific parameters and switches that those providers support. Now, we can also run a get PS drive, which will give us a listing of all the current drives on the system. So before, we had providers and we had a drive property for the provider object that showed us all of them inside of an array. This shows us all the drives actually listed out.
5:24So now we can set location or change directory to any one of these. For instance, here's a really cool one. Let's do a change directory to, how about environment variables? See this one? Any time you do it, you need to add a colon to the end of it. So here's environment. Look at this. Now we are in the environment variables drive. And now if we do a DIR, or get child item, we'll get all the items underneath that. And look at that. Here's all the environment variables on the system. We can also go into PowerShell variables here, which is CD into variable.
5:54And this is extremely useful, by the way. We'll do an ls, same as DIR, same as get child item. And look at that. All of these variables here in PowerShell, as well as their values. What about the registry? CD HK. Let's go current user here, colon, and do a DIR. Look at that. There's at that. There's the top level items of the out Pretty neat, huh. How about the file system? Let's go back to the file system here. We'll switch to the C drive, which will get us right into our profile. Now, just to take a step back for a moment. You can also create your own drive. It's just like mapping a drive in Windows. The only differences is, you're mapping it to anywhere, any provider drive, and it's only accessible through PowerShell.
6:29But just to give you an idea here, let's do a PS drive, new PS drive. And let's give it a name here. Let's say we wanted to map this to our Nugget Lab files over on our file share somewhere. So we'll call it Nugget Lab here. We'll give it the PS provider property. It's going to be a file system. And then we'll set the root up here to be about, what is that, FS Nugget. That's the name of our file server, PSv4. And now, we have ourselves in drive. And we can see that, obviously, right there it gives us the result. But we could also then do a get PS drive, and boom, there it is.
6:59Another lab. And so now we could do a CD Nugget Lab. And look at that. We're there. And now we can do a DIR and we're right into all of the files there on our file server. Let's create a file over there. Let's do a new item. We'll call this myfile.txt It's going to go into the root of our Nugget Lab directory there, by the way. And then let's call this the item type, it's going to be a file. There it is. We just created a new file. Now, we can also set content. Here's another-- all the content commandlets as well you can use to work with any item inside of a provider data store.
7:32So get item here or set content will do a path. And let's just path write to myfile.txt there. And let's set the value equal to hello. Perfect. And now we could do a item property. Let's set this as read only now. So what we'll do is set item property. And let's just go ahead and specify the path here, myfile.txt. And the name here of the property is read only. There's a property right there. And then the value, let's set this to true, meaning we're setting the read only property to true there.
8:03And there it is. Now, if you would get item property, we could also do a get content on the file there, passing the path, myfile.txt. And there it is, hello. We could also just run get trial item, otherwise known again, as DIR here. And there it is. Look at the mode property. A stands for archived. R stands for read only. Let's do the same thing in the registry. Let's switch over here to HK local machine. And let's just go right into the software hive here. And once we're inside of here, now we can do a new item, new item. We'll call this Nuggets. And the item type here is going to be directory.
8:36All right. There it is. Now we have a new node underneath the software in HK local machine. Now, we can do new item property and let's just set the path here to be Nuggets. We'll give this the name. How about the key of win. And the property type is going to be a string. And let's give the value here. How about just my reg data? Perfect. There it is. And now let's go take a peek at that in the registry. We can also just do a DIR. Just to show you from a graphical perspective here, let's go to reg edit 32.
9:09And let's head down here into local machine, software. We should now have-- look at that. There it is, Nuggets. And there's our key of win with my reg data. Pretty cool, huh? And we can do all of this stuff through a common set of commandlets through PowerShell. And we also then run set item or set item property to change the value of this key, if we wanted to. But all the commandlets-- there's a lot of them. Let me just give you an idea of how to find some of them here. So let's bust out our favorite-- one of our favorite commandlets here-- get command, GCM, for short. We're going to use the non-parameter.
9:40This is actually a parameter that accepts a string array, so we can pass a comma delimited list of strings here. Let's do item, item property, child item, location, and path. There it is. There are your provider commandlets. So we can use these commandlets. We will be using these commandlets, no matter what provider you hook into. And then the only two that then show up in here are PS drive and PS provider, which we looked at. But all of these live inside of the PowerShell.management module. So no matter if you're working with the file system, the registry, the certificate store, IIS, SQL Server, Active Directory, these are the commandlets you'll be using to work with all of the items inside of those data stores.
10:19All right. Let's bring up the Integrated Scripting environment here. Here's a list of all the commands that we were just working with. There's one more thing I want to show you in here and then and I'll give you your challenges here for this Nugget. And that is, whenever you're working with providers, you're going to be a lot of navigating and finding things. And so path versus literal path is important to understand the difference. And to just to give you an idea here, let's head back here just for a second here and let's just do a help on GCM, or GCI, sorry, get child item. So here it is. And if we look up here, we've got two different ways to use this.
10:49One is path. One is a literal path. Where is it? There it is. Right here. And this is a required parameter down here. So if you use literal path, you're not going to be able to use path. They're mutually exclusive here. Now, the big difference is that some data stores work differently than others. And a good example of that is the file system. You can't use colons and question marks and things that act as special characters. You can't use those when you name a file or directory. But certain data stores, you can. Like the registry, you can use a question mark to name a node inside of the registry.
11:20So path is the default and will use those special characters as things like wild card characters. And a good example of this over in the ISE here is if we were to create a bunch of files here-- let's create File.txt-- File 1 with brackets, File 2 with brackets. Now, these brackets, we can create in Windows. We can use these brackets to name the file. And there you go. We just created those three files. In fact, if we do a DIR here just to show you, there they are. They're in here right here. Here's those three files. So if we try to just do a get child item using path, which is the default, guess what, it's not going to work.
11:53It didn't come back. And that's because these are special characters with path that it is actually using the range wild card. So we'd use this to define a range of characters amd values within the file name. But literal path, it will work because it's treating those as literals. So that's the big difference. That's just something that you certainly need to be aware of because path, which is the default, uses special characters as wild cards. Literal path will use them as actual characters inside of the path. So keep that in mind.
12:23That will be extremely important. And it's definitely something that we need to know when working in PowerShell because you will come across it when you're navigating providers, file systems, all that kind of stuff. I'm going to remove those items using a wild card character because that's what path does. And there we go. Now they're all done. If we do a DIR, they're all gone out of there. All right. Let's at your challenges for this Nugget. Pretty simple here. Challenge number one. Display a list of PowerShell providers. Switch to the environment drive. Create a new environment variable and then list all environment variables. Couple of hints here.
12:54How do you get a list of PowerShell providers? We saw that one. It was one of the first things we did, get PSProvider. Switch the environment drive. Just remember, once you look at your providers, you will see the drives listed in there. You can also do a get PS drive to view all the drives and just add that colon at the end of the drive name. So you'll do a CD or a set location to env colon to switch. Then create a new environment variable, which we ultimately use for that, yeah, new item, right, new items which we'll use. And then obviously, you'll know how to list all environment variables. We've been doin that quite a bit with get child item and DIR.
13:25Challenge number two-- use PowerShell to navigate to the H key local, or excuse me, current user, software Microsoft Windows current version hype and perform a wildcard search for anything within that contains the word internet. That's an interesting one. And number three, use PowerShell to create a new file on a network share, or really anywhere, add some test data, set it to read only, and read the data back into the shell. Certainly something that we did here. I'll give you a demo of that. But just to give you some hints here. You're going to be working with navigation commandlets. You're going to be with some item commandlet here, item property commandlets, and then content commandlets for getting set content.
13:59So those are your challenges. Good luck. And again, you can find the solutions underneath these region properties inside of the Nugget Lab files downloadable on the right hand side of the course page. In this CBT Nugget, we took a big look at providers. We saw that providers in PowerShell are really just a layer of abstraction that allows us to work with any underlying data store using a common set of commandlets. So we learn these commandlets once and we can use them no matter what provider we're working with. I hope this has been informative for you and I'd like to thank you for viewing.
WMI & CIM
0:00WMI & CIM, or as I like to call it the "Wimmy and Cim Show." We're talking about Windows Management Instrumentation, and the Common Information Model. This is really one thing, this is an underlying standard used to access the hardware and software layers of a system. So in this Nugget we're going to talk about the differences between these two, why we have two things for really one underlying technology. And how we can utilize them from PowerShell to get access to virtually any management information on a system. Let's begin. So way back in the early days of computing the DMFT, the Distributed Management Task Force, which Microsoft is a member of, said we need to create a set of standards for exposing and accessing management information at the hardware and software layer.
0:41So they came up with something known as CIM, the Common Information Model. Now those were the early days so these standards weren't fully developed, but Microsoft still wanted to get on board. So they said, we're going to create our own layer on top of that, and that's where Windows Management Instrumentation, WMI, came from. WMI is really just Microsoft's implementation of CIMS, known as a CIM server. So when PowerShell came out we had a whole set of WMI commandlets to tap into that wealth, vast, vast wealth of information there at the hardware and software layers.
1:13So these WMI commandlets were great. But again because these standards were loose, there was no standard for communicating with WMI, and DCOM was very popular back then, Microsoft decided to use DCOM and RPC to communicate with the WMI repository. Fast forward to modern day times, and we know that Microsoft has all but abandoned DCOM and RPC because it's not very firewall friendly, uses dynamic port allocation, and some other things that just make it difficult as a communication layer to CIM, the underlying repository that contains all this information.
1:44So that's why we now have a whole new layer, a whole new set of commandlets from PowerShell 3.0 and beyond, which are CIM commandlets. So we get WMI commandlets which are old school, and we've got CIM commandlets which are new school. And they communicate using the WS-MAN Protocol, which we'll talk more about when we get into remoting, which is delivered over HTTP. So the bottom line here is that these WMI commandlets are still around, they're going to be around for a while for backwards compatibility purposes. But for new development they're legacy. So only use them if you have to, meaning if you're on PS version 1 or 2 Use the new CIM commandlets going forward for PowerShell 3.0 and beyond.
2:21So here's how this works. Every machine has a repository on it, right? That contains all that juicy management information exposed via these CIM interfaces. So every single machine has its own repository. And no matter if we use the WMI commandlets or the CIM commandlets that information is going to be the same. It's just one repository. It's just the communication layer to access that information is really what's changed between these two different sets of commandlets. So if we were to dig inside the repository here, at the top level we have something known as a NameSpace.
2:52And NameSpaces are really just a way to group and organize all of that information. Think it as a directory inside of the repository. But underneath NameSpaces we have Classes. And we talked about Classes pretty extensively on our Objects Nugget. We know the a Class is just a way to represent a live Object, or to represent something. So we've got Properties, which describe the data points of the state. And we've got Methods, which describe the actions we can perform against that. Then we have Instances. And an Instance is a live version of that Class. So for instance, we have a Class known as Win32_logicaldisk.
3:23And then we have an Instance for each one of the actual disks inside of the operating system. So we have one for the C drive, the D drive, the E drive, so and so forth. So the big to take away from this, is again, when you're inside the repository it doesn't matter if you're using WMI or CIM. Because that repository contains the same information no matter what. What really matters is from the outside. Because WMI uses is DCOM and RPC, CIM uses WS-MAN and HTTP or HTTPS. Now because this communication layer is so different across these sets of commandlets, it means that we need to work with them a little bit differently.
4:00For example WMI we always have a live connection to the repository, meaning when we request these Instances we are going get live Objects back to work within PowerShell. That means we can call Methods here on these Objects inside of the pipeline and from the client side. So it's a really tightly coupled set of commandlets. CIM on the other hand, it's more modern day, it's more like working with a web server, it's stateless. We request these Objects from the repository, they get serialized into XML and sent across as data, and deserialized back into Objects at the client side.
4:33Meaning all the Methods are getting stripped off the Objects, we're not going to be able to work with these Objects because they're not live Objects. But this also means it's much more lightweight, and it's much better on performance. Because we don't have this tightly coupled connection to the repository, it's very loosely coupled as most things are in today's stateless world. So again the bottom line here is going forward use the CIM commandlets. It's what Microsoft is pushing us toward, they're really providing the WMI commandlets here for backwards compatibility. All right let's jump into the Virtual Nugget Lab and get some experience here working with WMI and CIM.
5:06All right, welcome back to the Virtual Nugget Lab. Now the first thing I want to do is give you this tool for exploring the repository. It's an excellent tool, I'll give you the URL where you can download it. I'll also include it here in the Nugget lab files, it'll be in the directory for this Nugget 13WMI-CIM. So it's called WMI explorer. And this is just a fantastic tool because it allows you to literally explore the repository from top to bottom. Everything that's in it, all the Classes, Instances, Properties, Methods, it's a really, really great tool. So what I'm going to do here is just connect to the local machine, we can also connect to any server in our environment here.
5:39And what that'll do is first give us a list of NameSpaces underneath this machine, so here they are. And by the way, this is going to be the most popular NameSpace, it is also the default NameSpace here. Which I'll talk about here when get into some these commandlets. But here it is, Root, whack, CIMV2. So inside of here when you double click on a NameSpace it'll actually give us all of the Classes in that NameSpace. Again this will be by far the most popular one. And look at this, we have all of these Win32 Classes in here, which are going to be the majority of the Classes that we're working with it.
6:11And by the way why is this even important? I should have mentioned that early, but why do we need to access to this repository, when we have lots of commandlets that get this information anyway? Well, the answer to that is there is so, so much more information. Like I said it's extremely vast. And while we are getting commandlets on top of all of this-- in fact, let's find one here, Win32_service, something that we've been working with quite a while here in PowerShell our Services. It's in here somewhere, this is why we have a filter up here. Right here, Service, there we go, WIN32_service.
6:42That's all the GetService commandlets do, by the way. What most commandlets that get information, they're just hitting up this repository, that's all they're doing. So yes we do have commandlets, thankfully. So we don't have to rely on purely hitting the WMI repository here. But there are lots of things out in here, I should say, not out here-- in here that we can't get through commandlets. So as time goes on we're going to get more and more commandlets that access, and make it easier to hit this information. But this why it's crucial to know this stuff, because there will be things in your PowerShell career that you can't do through commandlets, that you will only be able to do here using this repository.
7:18All right, so once we find something in here, we find a Class, we can double click on it. And that's going to go and get all the Instances of that Class. So when we're dealing with Services we're going to have an Instance for every Service. We can click on it here and it's going to give us a list of all the Property and Property values for that Instance. And by the way these tabs are great up here as well because if you hit Properties you can get nice descriptions on all of the Properties for this Instance in this case. Pretty cool. And any time you click on them it will take you right to that Property and give you a nice description of it.
7:49And we also have all of our Methods here. We can click on it to see what our parameters are, the input parameters, and output parameters are for these Methods, as well as descriptions of them. So this is a great, great, great tool. Because it allows us to explore and discover, as well as get some great information on what data these Classes expose, and descriptions. It's just a fantastic, fantastic tool all around. And the search by the way, is also fantastic. Because you can search Classes, Methods, or even Properties. Say for instance, that we wanted to find everything with memory in it.
8:19We can type that in and it's going to search that name space. So this is why we have a little recursive take over here, because it'll search all the other NameSpaces underneath that NameSpace that you're in. But we won't do that because that'll take a very long time. So I'm just going to hit search, which is going to search all of the Class and Properties inside of the Root CIMV2 NameSpace here. And look at that, there's quite a bit and it gives us the Property name, as well as the Class they live in. And then we get the other NameSpaces with their descriptions here. So all kinds of stuff here for memory. We could go to Methods, we could say what are all the things we could create here for everything inside of-- here, give us the create Methods.
8:53Look at that we create processes, we can create Services, we can create shares, and all kinds of other things in here. And of course you can also search for Classes. So, say, I want to do something that's going to involve BIOS, I can search for BIOS and look at that, there we go. We've got some Classes here that work with BIOS. So get familiar with this tool and always have it handy because it will be your go-to tool, again when it comes to working with anything inside the repository. Now let's jump into PowerShell and get familiar with some of these commandlets. And really I want to focus on the CIM commandlets, but I will give you just a taste of the WMI commandlets as well.
9:26The first thing I want to do is show you where you can find all these CIM commandlets. So we can do a get-command here. And let's just go ahead and say Module, CIM, commandlets. This is the module that they all live in, and here are all of the CIM commandlets. The important ones here are the ones we're going to be working with, CIM Class, CIM Instance, CIM Associated Instance. I'll even give you a little taste working with sessions. More of that when we get into remoting, but it's still pretty cool to be able to create a session, and some of the neat things we can do with working with remote repositories. And also invoking CIM Methods, so we'll look at some of the more popular ones.
9:59The first thing I want to show you is how to find Classes, even though it's hard to compete with this tool when it comes to finding what you're looking for. So generally, I would say any time you're looking for things just use this tool. But you can certainly still use PowerShell, in fact you can use Get-CimClass to find anything. And they have a NameSpace parameter, so you can look for a specific NameSpace. Again the default is that Root CIMV2 NameSpace, which is where a majority of things you're going to be looking for live. So you can generally just omit the NameSpace parameter.
10:30But if we just do a Get-CimClass it's going to give us all of the Classes inside of the Root NameSpace that we were looking at. That's equivalent to just double clicking our route CIMV2, same exact list right here. We can also do something like this, Get-CimClass where, let's say the ClassName has disk in it. Here we go, there's all the Classes that have disk in it. We can do the same thing with Methods. Let's say we want to see anything that has a Method, as we did there in the UI, of create. Here we go, this will give us all the Classes that have a create Method. So while it is great that we can use PowerShell to find this information, just use the WMI explorer.
11:04It's so much easier to find things. How about the important stuff, getting data from the repository? Let's start with the same commandlets. If we do a Get-Command and let's just do for the module a cim-commandlets, that's where they all live. There it is. Cim-- oops forgot the commandlets part-- commandlets there we go. Cim-commandlets, here they all are. So we just look at you Get-CimClass Get-CimInstance is the one that we'll be using to retrieve data from the repository. Also I'll show you a little bit about the session stuff at the study, and also how to invoke Methods using the Invoke-CimMethod So Get-CimInstance we're going to provide it with a Class, so here we go, Get-CimInstance What's our ClassName going to be?
11:41Well, again we can jump over to the handy-dandy WMI explorer, let's go to Classes. Let's say we wanted to find all the disks on the system. Let's just do a search for disk in here. And look at that here we go, Win32_logicaldisk. There's our Class, here's our Instances, we need to double click on this and that'll give us our Instances. So here we go, we got three Logical Disk here on the system. So if we head back into PowerShell and provide that as a Class name Win32_logical-- and now here's another really nice thing about the CIM commandlets is they support Tab completion.
12:12Looks at that, I'm Tabing through all of the Classes that is completing for me typing in Win32_logical. 32 This will not work with any of WMI commandlets. So no Tab completion, no IntelliSense support, anything like that, only with the CIM commandlets. So a great reason to use the CIM commandlets. So let's go back to Logical Disk, somewhere-- where did I go-- there we go, Logical Disk. So let's just start with this. I'm going to hit Enter. Here we go, we just queried the repository and there are those three Logical Disks.
12:42Now we can also do the same thing with WMI, just to prove that it's the same exact repository. And by the way for WMI it's Get-WmiObject And we can pass in the same thing here for the Class. So instead of a ClassName it's actually just Class. And both of those, by the way, are positional parameters so you'll actually need to provide them. But let's just do the same thing, Win32_logical. And now I'm hitting Tab, notice that, it's not working. So no Tab completion we need to type if all out. Logical Disk, and there it is. The same exact information, it's just giving it to us in a List format rather than a Table format, but the same exact results because it's coming from the same spot.
13:15What about Filtering? Let's do this, let's do that same command here Get-CimInstance, ClassName Win32_LogicalDisk only as a Filter parameter. See this? So this Filter parameter we can use by passing in let's say, let's look up here, DriveType is your Property. DriveType = 3. What is that? Well, once again we can jump over here into WMI explorer, we can go over to Properties, and let's look for Device Type, or Drive Type. There it is. Drive Type contains a numerical value corresponding to the Type of this Drive this Logical Disk represents.
13:47And here are those values, 0, 1, 2-- or no, actually, possible enumeration values is not a value. So this one's 0, 1, 2, 3. So these are Local Disks. So for the Network Drive 5 will be Compact Disks. So we know that so that these are all Local Disks that we're going to be querying for. And so if we hit Enter we should get just one of them. We only have one disk on this machine, and that is the C Drive here. Now the downside of using this filter parameter is it's not what we're used to with PowerShell. Look at this, we have an equal sign. With PowerShell we're used to doing -EQ.
14:19In fact, we could still do something like this here. Let me just go recall our last command here. We do something like this, we could say we don't need to filter, we want to use PowerShell from this point, that we keep this side more using the underlying technology, being the repository WMI/CIM. And then we can use PowerShell for everything else right. We could do a Where here, and then we could do a $_. and then say DriveType, here it is, DriveType- = 3.
14:50We could do this, we'll get the same results. But the big difference there, this is server-side filtering. This is client-site filtering. So once we start getting into doing this, and we start adding the ComputerName parameter to it, and decide we want to do is for DCNUGGET and maybe FSNUGGET. Doing this is actually doing all of that processing on those individual servers. So this is server side, that's a good-- that's the positive side of using this filter parameter.
15:20And this is actually WQL, the WMI query language. So it's nonstandard but you're doing it on the server side, as opposed to using PowerShell, the syntax we're familiar with and bringing all those Objects on to the client and then filtering them down. So if you want to reduce network traffic, especially if you're bringing back large volumes with data, which can certainly happen when querying the repository. Then you may want to think about how you structure your filters. So keep that one in the back of your mind, Filter, server side, PowerShell, WhereObject, client side. Another word for you here. Let's recall our previous command, let's do this one right here.
15:53And let's just add this into some variables, let's grab some variables. I want to show you associations, it's what the point is. So Disk1 and Disk2, even though there's only one disk, so actually, we could probably just get away with just one. But if we had multiple disks, we could pop them into their own variable. So we'll do this one equals, Get-CimInstance, thing is going to pipe it into that variable. So now we've got it inside of the variable. Now can call Get-Associate, or Get-CimAssociatedInstance here it is. Get-CimAssociatedInstance, we can pass in that variable, and now what it's going to do is it's going to go get all of the Classes that are associated with this Instance.
16:29We've got quite a few of them back here. So I know this one is the System_Directory, Win32_Directory. We've got one for partitions, we've got one for the computer. We've got some other ones. How do we find this, out jeez. Well, what we can do is pipe it, let's just pipe Disk1 here to GetMember. And let's see everything that came back. So, well, in this case we've got our logical disk back here. Oh, that's all that came-- There we go, Get-AssociatedInstance. Obviously, this one just contains a logical one because that's what we put inside of it.
17:01But if we do a Get-CimAssociatedInstance and pipe to GetMember, now we're going to get all of those Associations. So Win32 Group was one of them. We've got Quota Setting was one of them. We've got-- this one should be Computer System, there it is Win32_ComputerSystem. And then we got a disk partition in there, oh, we got another one up here as well. Yeah, Win32_Directory. So these are all of the associated Classes for that Instance. So all the associated data around what we originally passed in here which was the logical disk.
17:32Now you could also get something specific. So we could do something like this Get-AssociatedInstance for Disk1, and we can pass in the ResultClassName here. And let's say we only really cared about the disk partition, we can do Win32_DiskPartition, use a little Tab completion there since we're dealing with the CIM commandlets. And there we go, we just get back that specific Instance. Let's do one more example of Associations here. Just a little bit different of an example but same idea. Let's say that we wanted to get all of the dependent Services from a Service. Let's create a Service Variable. And let's put inside of the Service Variable the Result of Get-CimInstance.
18:06And how about for the Win32_Service is going to be our Class there. And let's just add a Filter on here. Let's say our Filter is going to be again Name. So Name, Like, and then double quotes here, and we'll end it with a single quote, the Name's going to be Like how about WinRM, the WinRM Service. Now notice a couple of things. Number one, whenever we're dealing with a query inside of a query, our query inside of here we start with our single quotes, then we have double quotes around the string. Also use percentages for wild cards because again we're dealing with the WMI query language here.
18:36So we're going to put that inside of a Service, let's just make sure that we have that, we just look at Service here, boom, there is. So there's our Service for WinRM. And now let's say that we wanted to get the Associated Instances with this. Let's do a Get-CimAssociatedInstance. And we're going to pass in as an InputObject Service. And our Association is going to be Win32_DependentService. We Enter and there it is. So the WinRM Service depends on the HTTP service.
19:07Cool. Now what about Methods? How do we call Methods on these CIM Instances? Well, first let's get a list of Methods. I'm just going to create a Variable called P. And inside of here we'll do a Get-CimClass. And let's get the Class here for the Wind32 Process. All right, that looks good. And all we need to do is a P dot-- and look here, we can get Methods, Properties, and all kinds of other information. Let's say we wanted to see a list of all the Methods. Here they are. Here's all the things we can do with a Process, Create, Terminate, Get-Owner. Let's say we wanted to get the owner of a specific Process.
19:39Take our PowerShell Instance here that we're working with. So let's create another Variable. We'll call this one A, we'll say Get-CimInstance. The Instance we're going to get here is a Win32 Process. Let's add the Filter on here, and let's just do a Name like, how about PoweShell, or we'll just do Power. So, Power. Here we go, that should do it. So do we have anything in there? We do, there it is, the PowerShell IC what we have right here. So now all we need to do is pipe this to a little Method known as Invoke-CimMethod.
20:12There it is, Invoke-CimMethod. What Method we would like to invoke? Here's our MethodName, let's say GetOwner, and there it is. So remember, we have this Invoke-CimMethod because we're dealing with a stateless environment. So we need to take the Objects that have been de-serialized at our local machine and pass them to this CimMethod in order to get them over to the machine to invoke the Method on these Objects. Let's finish this up with a couple of random things. The first random thing is Credentials. Now Get-WmiObject, in the WMI commandlet support the Credential parameter.
20:42Which is nice because you can prompt users for credentials, or you can supply your own credentials whenever you need to. Especially if it's something remote that requires maybe specific credentials. But the Get-Instances, in the CIM commandlets do not have that parameter. So imagine this is still because the CIM commandlets are relatively new, I'm sure eventually we'll get them. But that doesn't mean we can't use credentials. In fact this is where Sessions come into play. Now, before we even get into Sessions let's do something interesting here. Let's do a Get-CimInstance, and let's say we wanted to get all the Win32_Environment variables across multiple machines.
21:18So let's just pass in here, how about our DCNUGGET, our domain controller, and our file server. Cool, you know what that did? That just used remoting over HTTP to go to these machines-- because, by the way remoting is enabled by default on Windows Server 2012 and that's what both of these machines are, so we didn't have to do anything special there. And remoting automatically adds this last column to anything. Which is awesome because now we can tell where these environment variables came from. These came from FSNUGGET, these came from DCNUGGET. And we're getting heavily into remoting and sessions, and all that stuff, in a future Nugget.
21:50In fact, it's actually the Nugget immediately following this one called Remoting. But that's great, but what if we wanted to supply a credential? This is where Sessions come into play. So if we can do a New-CimSession-- we could pass in a computer name, let's do the same thing. Let's do ComputerName, let's do DCNUGGET, maybe we'll do APPNUGGET this time. And then let's also give the session name, we'll call it Servers. And here is where we can pass any credential parameters. So if you need to, passing credential there, and then give it a username here, let's do NUGGETLAB, backslash Administrator.
22:22And now if we hit Enter, it's going to prompt us. Cool. So that's really nice-- in fact let me just Escape there, and I didn't even have to supply the password because I'm already logged in under this. But what that did is it created two sessions, one for each one of the servers. Now this is where this really gets powerful is if you wanted to maybe hit a down level server, and you wanted control over the protocol. Because by default here we're using WS-MAN and HTTP. But what if we've got, again, a bunch of old servers out there that we want to manage?
22:54Well, we could create a SessionOption here, you can do this right here. A SessionOption, so can do a New-CimSessionOption, there we go. And now we could pass in the protocol, and we could say DCOM, look at that. So now, let's just hit Enter there, we create another Session. Let's create this, let's call this New-CimSession, pass in the computer name here, we can just call this old server. And let's hit up our APPNUGGET here, we're going to hit our APPNUGGET using DCOM. And then we can pass in the session parameter here, SessionOption parameter, and pass in our SessionOptions.
23:28There it is. I totally messed up my screen here, so I fixed it and I got us back to where we were. So let's say that we wanted to use these Sessions. We've got our two Sessions here with the name servers. So if we want to use those we could do a Get-CimSession, Get-CimSession. And we could get them by ID, by name, by computer name, let's say we wanted to get them by name here. We can do Name, pass in servers, and we can pipe these sessions over to Get-CimInstance. And let's say the same thing Win32_Environment, cool, and there it is, same results.
23:59Now if we want to use our-- we'll called this our DcomSession, we could do the same thing, only let's pipe in the Name, I believe it was CimSession three, CimSession three. And here it is, same result. And it was CimSession three, we can actually verify that right here, CimSession three. So that actually used DCOM there to hit up our APPNUGGET server with that previous command. So CIM Sessions are very cool, and they stay out there so we can continue to reuse and again. We'll get more into that when we talk about remoting. That's about it for this Nugget my friends. One thing I want to point out before I give you the challenges, is that, again, the commands .Ps1 file inside of the directory for each respective Nugget here in the NUGGETLAB files, contains all the commands that we've worked with throughout that video.
24:41And I just want to point out for this one I also added Help for each major commandlet. So here's GetHelp for CimClass, GetHelp for Get-CimInstance, for AssociatedInstance, as well as New-CimSession. So definitely dig into the help files get familiar with the syntax and some of the parameters in there. Because it would be impossible for us to cover them all, there's just so many. All right, your challenges for this Nugget. Challenge number one, less of a challenge more of a task. Use WMI Explorer to explore Classes, Instances, and Properties. So just get familiar with that fantastic tool, it'll go a long way in your future with PowerShell.
25:14Challenge number two, use WMI Explorer to find the Class for working with BIOS. Then use the CIM commandlets in PowerShell to retrieve all of the Instances properties. And challenge number three, this is a good one. Use the PowerShell CIM commandlets to query for a physical drive and change the label the volume. Now the reason this is cool, and a little bit tricky, is because we didn't cover Set-CimInstance to change the value of a property. So do a little discovery and exploration, get help on this to see how to do it. But essentially what you're going to do is create a drive variable, store the results of Get-CimInstance for the Class that contains a physical drive.
25:51Then pope that variable-- yeah I'm sure the Pope would love variables. Pipe that variable to Set-CimInstance and set the VolumeName property. And also, optionally here, you can use the pass through switch so you can see the results of the operation. Or you can just go into Windows, look at the file system and see if that drive label was changed. So this also just shows some of the power of working-- having access to the WMI repository is a big deal. Because if you can't do it using the regular commandlets you can certainly do it using the repository. And not only is it a place to see all this information, but you can see we've got Methods on many of these Classes.
26:25So we can actually do things. We can create new ones, we can modify existing ones, or even remove things, Really, really powerful stuff. All right, good luck. In this CBT Nugget we covered WMI & CIM, otherwise known as Windows Management Instrumentation and the Common Information Model. We saw that WMI is really just Microsoft's own layer on top of CIM standards. And that's all we had in PowerShell 1 and 2 so that's what we used. But now with PowerShell 3, 4, 5, and going forward we've got CIM commandlets. Which are based on HTTP, as well as WS-MAN, firewall friendly protocols.
27:00Where WMI was based on DCOM and RPC, not very firewall friendly, definitely legacy. And they're really only there for backwards compatibility. So we saw how CIM works. We took a good look at all the major CIM commandlets, and we saw that awesome tool, WMI Explorer. I hope this has been informative for you and I'd like to thank you for viewing.
Remoting
0:00Remoting. Now we're starting to get into the cool stuff. And remoting is the coolest of the cool. This is the reason that people are going to be moving to PowerShell right here. Because remoting is what enables us to write a command and send it to many, many machines. So the productivity gains alone from this are astronomical, and you certainly don't need to be a PowerShell ninja to take advantage of this stuff right now. So let me ask you a question. How do you manage a bunch of machines? Let's say, for instance, that we've got a cluster of IIS servers out there, or maybe database servers, or SharePoint servers, or whatever. And something happened, you need to make a configuration change, or maybe you need to patch all these machines.
0:34How would you do that right now without PowerShell? Let me guess, you probably have an RDP connection manager out there with all of your RDP sessions, and you would log into each one of those machines individually to do that, right? Definitely, probably, what most people do without PowerShell skills. Or maybe they fire up an MMC snap-in and connect to all those machines individually. Definitely not the way we want to do that going forward. The way going forward is using PowerShell. One command, hit all of those machines without ever having to physically log in and do anything to them.
1:06Very, very cool stuff. Let's see how it all works. So what is remoting? We know that it's the super tech that allows us to execute PowerShell commands remotely. But really, what it is, it's just simply the WinRM service the Windows Remote Management Service. This is based on the WS-Man protocol, the Web Services Management Protocol, which is another open standard defined by the DMFT for communication across the wire. It's based on SOAP, which is what web services are based on, the Simple Object Access Protocol, which just basically means that our objects are serialized into XML.
1:36XML is the only thing that's transmitted across the wire, and then that XML is deserialized back into an object at the source. And the real key thing here is that it uses HTTP or HTTPS for communication, which is great, because as we know, HTTP is firewall friendly. As opposed to that computer name parameter we've seen on some command lines in the past, which use DCOM and RPC. So here's how this works inside of WinRM. When we enable remoting, which I'll show you how to do, even though it's enabled automatically on Windows Server 2012 and above machines. But when you do enable it, the first thing it's going to do is set this service, services start mode to automatic.
2:10Then it's going to create four end points. And end points are also known here in remoting as session configurations. And it really just defines the application, and there's some other options in there. And we can actually set some options too. We can control who or who cannot connect to it, what commands and scripts they can run, the security context. It must run under that kind of thing. So it's going to create these end points. Then it's going to create a couple of listeners. It's going to create one for HTTP, one for HTTPS, and it's going to bind them to the IP addresses on your machine. So when the requests come in, say a request goes over the HTTP line, that listener is going to accept that request and forward it to whatever end point or session configuration is set up for that application.
2:48Then it's going to run the command on the machine, take those objects, serialize them into XML, and send them back to the client machine where it will deserialize them into objects, and we'll have our results. So that's really the basics behind remoting. It's just simply the WinRM service, which handles all of the communication and transporting of our commands and objects across these machines. So what can we do with it? Well, we can do a number of things. We've got one-to-one remoting, which is just basically, for all you Linux folks out there, it's SSH in Windows.
3:18That's all it is. So in PowerShell, we can enter a PS session, which will literally put us right on that machine in our PowerShell console. And all the commands we execute are actually getting executed on that machine. There's also one-to-many remote management. And this is the really powerful stuff, because this is what's going to allow us to write one command, send them to all those machines, and then those machines will do all the work and send the results back to the client. Let's get familiar with many of the commands that you'll be working with here when working with remote commands.
3:48And then we'll get into Virtual Nugget Lab and play with many of these. So Enable and Disable remoting is how we turn remoting on and off. And you're essentially enabling or disabling the WinRM service. Then, we've also that enter EnterPSSession and ExitPSSession. This is for one-to-one remoting, otherwise known as interactive sessions. So we Enter PSSession, pass in a computer name, and we are literally on that machine just like we were SSH'ed into it. We exit it, boom, it's gone. That session is destroyed. We also have InvokeCommand. This is your one-to-many here. And this is how we're going to send a command to many, many machines.
4:21And we can do so by just sending a script block. So we just pass in a command. Or we can even pass in a files, so we can send whole scripts over to remote machines. We also have the ability to create our own sessions, which is extremely useful when you want to maintain state across calls. Because if we were just run an InvokeCommand and pass a command over, it'll spin a PowerShell in the remote machine, execute that command, then spin down PowerShell and send us the results. Meaning, if we were to declare a variable, and then come back that machine again, that variable would be gone. Or if we were to import modules, those modules would be gone, because everything is session based, right?
4:52So this allows us to save our session, and then we can just disconnect from it, and then reconnect to it later, maybe from another machine, and our state will be there. Our PowerShell session will be intact with everything that we did inside of it. Kind of like RDP. If you were to RDP into a machine, you log in, you open some tools, and then you disconnect, rather than log off, that allows you to come back later. And your machine will be in that exact same state. You'll be logged in, all your tools will be there. So you won't have to go through that process all over again. That's what sessions bring to the table here in PowerShell. All right, I'm sure you're ready to see this stuff in action.
5:23Let's do it. Let's jump over to the Virtual Nugget Lab and look at all the cool things we can do with remoting. And we're back. So the first thing we need to do is enable remoting. And remember remoting is enabled on Windows Server 2012 and above automatically. So here's our App Nugget server already enabled, DC Nugget already enabled, FS Nugget already enabled. But our client machine here, it's not enabled. And you can actually easily figure that out by just running a get PSSessionConfiguration. And if you hit Enter there and it's not, it's going to say hey, WinRM service is not started, and running this command will start the service. So we're actually going to say no there.
5:55You can also just look at the service. It gets service. Let's look at WinRM here. There it is. We can see that it is stopped. If we go to our other machines, let's go to our server machine here, and do the same thing-- let's just do a get PSSessionConfiguration. It's going to send back end points if it's enabled, and it is, cool. Or we could do the same thing here, get service winrm. And look at that. There it is. It is running. So it's enabled there, not enabled on our client machine. Not that we would need to enable it on our client machine, but just to show you how the process works and what it does, let's do it anyway. So we're going to enable PSRemoting.
6:26There it is. Hit Enter. It's going to walk us through a couple things here. So the first thing it's going to do is run this set WSManQuickConfig command list. Don't run this one by yourself. Always enable this through the enable PSRemoting command, because there's some other things that it does. But this is going to start or restart the WinRM set the startup type to automatic, create some listeners on all of our network cards for all the IP addresses, and then enable a Windows Firewall rule exception for WS-Man HTTP traffic. So we're going to say yes to that. And now, it's going to create those four end points.
6:56So it's going to run set PSSessionConfiguration to create the PowerShell end point. This is for the 64-bit version, the one we're in. So we're definitely going to need this. And then it's going to as us to do one for workflow, ask us to do one for PowerShell 32-bit, and then ask us to do one for Server Manager workflows. So we're going to say yes to all those. That will create all those end points. And now if we run get PSSessionConfiguration, it should come back with all those end points. Perfect. Not too bad, right? Pretty painless. Now the only caveat I want to point out there, if you're on an older operating system and you have a network card that's location is set to public, then it'll fail.
7:29But there is a way around that. And it is called SkipNetworkProfileCheck. So that's a workaround. Obviously, a better way to do that would be to change the network location out of public, but this will certainly get you there. All right, let's get into a one-to-one remoting here first. So this is really easy to do. Ready, enter PSSession, and give it the name. Let's create a session over to our file server. That's it. Now, look at that. We are on our file server as you can see, because our prompt now is prepended with this FS Nugget. Pretty cool. So now we can change directories.
7:59Let's just change right over to the files. And you know what this is, right? Yeah, we have our share set up on top of this that we've been hitting here for our Nugget Lab files. So we can just do a DIR there, right in that psv4. Check it out. There's all our files. We are on our file server right now, even though we are technically on our client machine here, CL8 Nugget. But that's as easy as it gets. Enter PSSession, give it the computer name, and this is called an interactive session, one-to-one. It's just like SSH'ing into the machine. If we want to leave, we do an exit PSSession, and we're gone.
8:32We're back to where we were. Now, what about one-to-many remoting. If you're not already familiar with this command line, you will be getting very familiar with it. In fact, this will be your favorite command line, I guarantee it, going forward. So invoke Command. We're going to pass in a script block. We could also pass in a file path. I'll show you that one in a second, but let's do a script block here. And in the script block, what remote command do we want to send over here? Let's do something a little different? How about get windowsFeature. This is a good one. And let's say we want to see if the web server role is installed on multiple machines. Now we're going to use that computer name switch parameter and pass in some computer names.
9:06Let's see, let's look at DC Nugget, App Nugget. Let's do all of our servers here. And what's our last one, oh yeah, FS Nugget, our file server. So what we're seeing here is we want to send this command to these machines. And this is a remoting command line. So this is not using RPC and DCOM. This is all using HTTP. All right, we hit Enter. And now it's going to go all of those commands ran on those servers. How cool is that? They all did their own processing and sent us back the results. Pretty crazy. But here's the results. None of those have IIS installed on them.
9:37We'll change that later on in this Nugget. How about another one? Let's do an invoke Command here. And this time, let's just pass in a file path. So this will be great when you want to pass in scripts. And I actually have one here. It's not a full blown script, but we'll start to create scripts very soon, once we get into scripting. But just to show you, let me open this with Notepad here. It's just simply a one-liner that'll create a directory called /logs on the C drive. So let me copy this location here. And I'll just paste that into here, and let's do this, it's called create-logdirs.ps1. Oh, there it is.
10:07I can just auto complete there. Perfect. Now we just need to specify the computers we're going to run them on. Let's run them on everything, DC Nugget, App Nugget, and FS Nugget. Hit Enter, and there it is. Look at that. How ridiculously powerful is that? I feel like we should be in Windows version 2050 or something, because it was way too easy to create a directory across all these machines in one go. Absolutely incredible. In fact, we can just verify that. Let's go over to App Nugget here. Let's go into the C drive. Look at that, logs directory. Here's our domain controller, C drive.
10:40Oh, it's a little slow, there we go. Logs directory. And then, obviously FS Nugget would have the same result. But really, really neat stuff, and very simple to do. And a really great thing about this Invoke-Command commandlet is it automatically adds the property to the end of whatever objects are coming back, PSComputerName, so you know exactly what computer that data is referencing. Now, here's the thing though with the way we've been using it, is it literally just spins up a PowerShell session on the remote machines, executes a command, and tears it down. So if we wanted to do something across commands, we would lose our state.
11:14And this is where sessions come into play. But just to prove that, well let's run an invoke Command. And let's just do a script block here. And inside of here let's store instead of a variable here called w. We'll set this equal to get service. Let's get all the Win services here. Perfect. And let's just execute this across a couple of machines. How about App Nugget and FS Nugget. Perfect. So that executed. Now, let's do another one, only let's just get the result here of w, see if anything is in it. What do you think? What's going to happen? Nothing. There's nothing in it. How come?
11:44Because that's how invoke Command works. It literally spins up PowerShell, executes it, spins it down, send us the result. So that's why we have no persistence across these. And this is where sessions come into play. So let's create a session here, a new session, and store this inside of a variable called DC. We'll do this for our domain controller. So new PSSession, and we're going to connect right up to DC Nugget. All right, there we go. So now if we do a DC here, we can see that's a session. In fact, if we do a get session, we've got a session out there ready to go. So now let's enter the session. Enter PSSession, only this time we're going to pass in that variable.
12:17Oop not DV, DC. There we go. And look at that, we are now connected to that session. So now let's create a variable, just like we did before, logs in, let's just do get EventLogs here. And let's do this for the system. Let's get the newest 10. Perfect. So now it's in there. We can verify that if we look at the logs. Variable, there they are. Perfect. So now, let's exit this session, exit PSSession. We're out of it, and now let's disconnect from it, disconnect PSSession. And we're going to pass in our DC variable there.
12:48And now, it's in a disconnected state. So now, we could-- maybe we had to go somewhere, but we still want to maintain our state there for later. Or maybe we're even switching machines and we're going to a different part of the building. But we still want to connect to that. Well, what we could do is lets mimic that by firing up a brand new PowerShell session. If we do a get PSSession here, it's not going to see it. See that? We actually need to specify the computer name that it's on. So let's see all the sessions on our DC Nugget machine. Hey, there it is. All right, let's do the same thing, only let's put that into a variable called newdc, and boom, now we've got a session.
13:19We've got that session stored inside of a variable. Now we can do something like this. Let's do an invoke Command, and we'll just do a script block here. And let's see if we get that logs variable in here. We called that logs, right, log or logs. Hopefully it's logs. But we're going to set that over there, and we're going to use the session parameter here to pass in our new DC session. Oh, and it didn't like that because, anybody, anybody? Know why it didn't like that? Read the error message. The session state is disconnected. We need to, first, connect it. So let's just recall a couple of commands here.
13:51And let's just pass this all into connect PSSession. That'll get it back up and running and store that in there. Now this'll work. Invoke Command script block. Let's see if we can get that logs variable here. We're going to pass in the session of newdc, and hey it worked. So cool. That's what sessions are all about. They allow us to maintain state across calls. They allow us to move around, fire up new sessions, go to another machine, go to another part of the world, and still connect and again, maintain all that state. Now, one really cool thing that I want to show you, this is really powerful stuff here, is implicit remoting.
14:26This is the future of remote management right here. The whole idea of implicit remoting is that I don't ever need to install tools on a client machine I don't need. To give you an example of that, take Active Directory. I don't need to install RSAT on this CL8 Nugget machine. Wouldn't it be great if I could import modules from my servers, like import the Active Directory module from my domain controller onto to this machine here, and then use those as if I had those modules loaded an installed on this machine.
14:56That's what implicit remoting is all about. It's going to allow us to just have these dumb clients with nothing installed on them, and any time we need to utilize tools from another machine, we just pull them over. And it's going to create, essentially, proxies to those commandlets in that module. And we can use them on those machines as if they were installed on this machine. And I'm going to give you this example using IIS and the IIS commandlets. So the first thing we're going to do is install IIS on our App Nugget machine. So let's do an invoke Command. We're going do this all using remoting, of course. And let's do a script block here.
15:28And our script block is going to be Install-WindowsFeature. We're going to install the role web server. All right and let's pass that over to the computer name, App Nugget. There we go. So what that's going to do is it's going to install IIS our App Nugget machine, which will also install all the IIS commandlets. And then I'm going to show you how we can use implicit remoting to get all of those IIS commandlets onto our client machine here without actually installing them. They're really only going to be installed on App Nuggets, but we're going to use them is if they were installed on this machine.
16:00Perfect. There it is. All done. Success. We've got to IIS all up and running over there on App Nugget. And now, just to prove a few things, let's head over to App Nugget here. And let's fire up PowerShell. And let's see if we have those modules installed. So let's just do a-- how about a help here on get website. I know that's an IIS commandlet. And there it is. We got help on it. So we know that it's there. And now, if we just Control C out of this, let's do just a get module here. Let's see, we got web administration. There it is. These are all the IIS commandlets. So that module is loaded up here. And all those commandlets are here.
16:30We didn't actually need to do that. We didn't need to physically load up the module on this machine. It's already installed and it's there. So now if we go back to our client machine, let's do the same thing help, oop, here we go, help get website. It's searching help for get website. And look at that, can't find it, can't find it because we have no module. We don't have that module. In fact, we could even do this, get module, or we could just search for-- we could just do a search here. Let's do a get- command- module- web administration. Nothing.
17:00Nothing at all. All right, so here is implicit remoting. Here's how it works. First, let's get a session going here. Let's create a session. We'll call this newps session, and we'll create this to App Nugget. All right, so now we've got a session ready to go. So here's the trick. We can do an import module. Web administration was the name of that, yeah, web administration. And then, we're going to use the PSSession parameter and pass in that session. So what this is doing now is it's actually creating shortcuts on our local machine here to the module, all the commandlets, everything inside of that web administration module that is installed over on our App Nugget machine.
17:36So now if we do a help get website, it should work. Look at that, there it is. And now if we call get website, it should work. It's actually getting the website over there on our App Nugget machine. How cool is that? So that's all done through the magic of remoting. Its all done under the hood, hence implicit. It's actually exporting and importing. There's actually two commandlets importPSSession, exportPSSession. It's just totally, basically automating that process for us. And it's importing those commandlets from that machine and giving us a way to access it remotely.
18:06But this is so cool that now we no longer have to manage software on all of our machines. We don't have to install these modules, and install any specific management software, on our client machines. They can stay clean and empty, meaning it'll just make it so easy for us if we, oh look, there's a machine over there. Man, I wish I could use that to hit my servers, but I don't have all my tools installed. Well guess what? With this, you don't. Fire up PowerShell. As long as remoting is enabled, you can easily do things like this. Just import the module from that machine, and boom, you've got everything you need without having to install everything to work with it.
18:41Very, very, very powerful stuff. So that remoting in a nutshell. Here's all the commands we used in this Nugget. Go through some of these. Especially go through the help topics for things like invoke Command. That is a very deep commandlet with a lot of options, and there's a lot of things you may come across, especially things like the throttle limit. By default, we can hit up to 32 machines. You can up that by using the throttle limit to as many connections, or threads I should say because it's a thread per connection, that your client machine can handle. Check out things like use SSL. That's another big one, especially if you want to hit machines are outside of your domain.
19:12You'll need to set up SSL to do so. Or if you want just a secure connection over HTTPS, then you can do it that way. And there's a lot of other ones, so certainly scan the help topic. Get familiar with some of those parameters because they can be very useful. Let's look at the challenges for this Nugget. Challenge number 1, connect to another machine using an interactive one-to-one session, get services, and exit the session. Pretty straightforward here, just getting you familiar with enter PSSession and exit PSSession to create that one-to-one interactive session. Challenge number 2, run a command to view the most recent 10 system event logs across multiple servers using invoke Command.
19:43Another straightforward one that we did, just getting you familiar and comfortable there with working with invoke Command. Challenge number 3, create a new session to another machine, store a list of processes in a variable, disconnect from the session, then reconnect to the session from another PowerShell instance and view the variable. Then exit and remove all sessions. All things we've done in this Nugget just to, again, all three of these challenges just getting you comfortable with all the different perspectives of using remoting. Again, you can find the answers underneath these regions, and you can find these challenges inside of the Nugget Lab files for this course, down-loadable on the right hand side of the page.
20:15Good luck. In this CBT Nugget, we covered remoting and got a glimpse into the future of remote management at scale. Remoting allows us to send PowerShell commands to many machines without having to really do any work. It's just like writing commands like we have been. It's just that we can target many machines, which is just incredible. So we saw that remoting is really just the WinRM service, which is basically WS-Man protocol, uses HTTP and HTTPS, exposes end points, and creates listeners for communication. And then we saw all the different ways that we can use remoting, from one-to-one, to one-to-many, and even got a taste of implicit remoting.
20:48I hope this has been informative for you. And I'd like to thank you for viewing.
Jobs
0:00Jobs. And we're not talking about your nine to five here-- even though PowerShell's obviously going to help us out quite a bit with our nine to five-- but we're talking about PowerShell jobs. And we've got a bunch of different PowerShell jobs out here, ones that allow us to run our commands in the background-- great for those long running tasks, so we're not locking up our Shell-- as well as scheduling jobs, so we can automate a lot of the things that we're doing in PowerShell. So let's jump right in. Let's get familiar with the different kinds of jobs that are out in PowerShell, the purposes that they serve, and then we'll get into a demonstration here to show you how to use each type.
0:33So you can see we have a lot of different kinds of jobs here in PowerShell, background, remote, workflow, schedule, there's even one I didn't add in here called WMI jobs. But here's the thing, they're really just all the same thing underneath the hood, right? They are asynchronous background processes. The big difference is scheduled jobs are persistent asynchronous, meaning we can make them repeatable and run them more then once, right? Run them on a schedule, run them on a specific interval, whatever. But asynchronous means that we are taking anything, a command, a script, whatever, and pushing it to the background.
1:04That way, we're not locking up the UI, right? We're not locking up our session waiting for a long running task to complete, we can just throw it in the background, let it do its thing, check its status every now and then, when it's done, we can retrieve the results. That's what jobs are all about. And that's pretty much your basic workflow there with jobs as well. I'm going to bring up PowerShell just give you an idea. So let's say we were going to do something crazy here. Let's recurse, d, colon, backslash, d, colon, backslash, ah. So this would take all day long, right, to go through every directory and file and I'll put it here to the shell.
1:35So I'm going to cancel out of that. This is what jobs are about. So say that we had something like that, maybe not that specifically, but maybe we had a script that was going to take a long time to run but we still wanted to do things in the shell. Well, we could just start a job, we could pass in the file path to the script, or we could just pass in a script block here which is what we're going to, do the same thing. We'll recurse it and boom. Now it's just going to take a second to create the job, but it's running in the background so I'm free to do other things inside of the Shell here. So I could sit here and just continue to get the status, there it is, all right, running, running, running, or I could stop it here. Let's do a Get-Job and let's pass that to Stop-Job.
2:07Boom, and now if we get the job, it stops. And now if we wanted to see how far that job got, we could do a receive-- oh, i before e except after c, I'm always forgetting that with a Receive-Job-- ID 2, there's how far it got before we cancelled it. Cool. So what we just witnessed there was a background job. Background jobs are tasks running asynchronously in the background on the local machine. We also have remote jobs, and this is just our remoting commandlet, Invoke-Command, with the AsJob switch parameter turned on.
2:37If we do that, whatever machines we target in that Invoke-Command commandlet, using the computer name parameter, will get their command sent to the background and store it inside of a job that we can reference, manage, and view the results from our local machine, the machine that we kicked off the Invoke-Command commandlet from. We can also set up our workflows to run as jobs, which is very cool. If you're unfamiliar with what workflows are, we've got a Nugget in this course dedicated to workflows, so check that out. But essentially it allows us to take a bunch of scripts, or a bunch of commands, and coordinate them.
3:08Run them in parallel, run them in sequence, run them across machines. We can do check pointing, so if we have a really big process, we can checkpoint after the long part so if something bad were to happen later in the script, we can restart it from that point. Really, really cool stuff, so definitely give workflows a look. Last, and certainly not least, and probably most useful here, are scheduled jobs. This is what's going to allow us to automate those repeatable tasks. So a scheduled job is one that persists, meaning we're going to set it up on a schedule and it's going to run on that schedule. And that's what's also by the way known as a job trigger.
3:40So we're going to set up a trigger, which is going to be run this daily at this time, or weekly on these days at this time, or whatever interval we can think of. And then we can set up job options as well, and it will fire up and run against whatever we have defined inside of the test. And it'll run on those times with that option. And you know what's funny is these are actually viewable and manageable inside of the Windows Task Scheduler. So that's all it's doing, it's just sitting on top of the Windows Task Scheduler, creating these jobs, and we can manage them from there, or we can manage them in PowerShell as well.
4:11So here's a look at many of the common commandlets that you'll be utilizing when creating and working with jobs. Just to go over a couple of them here, Start, Get, Stop and Receive-Job, these are all working with background jobs. And remember, everything is really a background job. So for instance, a scheduled job, it's really just a container that contains the options in the trigger. But when that job starts, it's really going to be a background job. And you can still manage these scheduled jobs that are running, the instance jobs as we call that, with these commandlets. Invoke-Command with the AsJob switch parameter is known as a remote job.
4:42But again, it's really just a background job in the remote machine that you fire up from your client machine, and manage from your client machine. And then, we've got lots of commandlets here to work with that scheduled job container. So Register and Unregister to Create, and Delete, Get for managing the containers, New-JobTrigger for creating schedules, and New-ScheduledJobOption for managing all the different options. Let's jump into the Virtual Nugget Lab and put some of these commandlets to use. All right, welcome back to the Virtual Nugget Lab. Let's jump right into the ISE here and start writing some commands. So let's start a few jobs.
5:16So this is very similar to the first one we did, the difference is we give it a name this time. And we just Get-ChildItem rather than dir, and we're just hitting the system drive environment variable rather than statically typing it in. But I'm going to hit Enter, and that's going to set us up with a job. So while that's running, let's create another one here. We'll do a Start-Job. Let's also give this one a name, we'll call this, ThisIsBad, and we'll add a script block in here. And let's just do a test connection here. There we go, test connection-- this will be like a ping essentially. And let's pass in the computer name for the ping here, how about we'll do Bad,NUGGET.
5:49So two machines, but we know those are both bad. So I'm going to hit Enter, and then that one's going to start as well. Now if we do a Get-Job, we should see both of these jobs and their states. Both of their states are running, so at this point, we could sit here and wait, or we could do some other things. But eventually, that state will change to complete, at which state we could go and retrieve the results to see what happened. If it succeeded, or failed, or whatnot. But we can actually stop a job too, here. Let's do a stop-job, and let's just do this by ID. We could do it by ID, we could do it by name. And we know that our big recursion one there is ID number 6, as we can see over here.
6:20So if we stop that, now it's going to get stopped. So now if we run a Get-Job, we can see that has stopped, and it has some data in there, which is going to contain the result of the operation. So this is where receive-job comes into play. So if we do a receive-job-- and again, there's a number of ways we could retrieve it. We could receive it by ID, by name. Let's just do name here, and let's do recur system drive as the first one. And then now, if we just run this right now, it's going to get those results and dump them from memory. So they'll be gone, and the HasMoreData flag will be switched a false, and you won't be able to retrieve the results any more.
6:53So this is why we've got a keep here. If you use the keep switch, it'll keep that data around. So here's the results from-- as far as it made it until we stopped it anyway-- on recursing the system drive. Let me just cancel out of that. And if we do a Get-Job again, we should see it still has more data. So if we didn't run our keep-- run this with our keep switch, it would go away. So if we do this, cancel out of it, and then do a Get-Job, it no longer has more data. So we can no longer see the results of that job. So those are background jobs and that's pretty much your workflow there as well. Start-job will fire up that job container, put it in the background, and put your commander script inside of it.
7:27When it's done running, it will contain your results, which we can then get using Receive-Job. And then, of course, use Get-Job here to view the current state of all of your jobs. Oh, by the way, we didn't look at ThisIsBad. We know that this failed, so let me just show you the results of that. Again, we can do a Receive-Job here, and we could just pass in the name here, ThisIsBad, there we go. And we won't even keep it, we'll just look. So there it is, so there's the results. This time it was a failure, because Bad is not a host name and neither is Nugget. Cool. Next up, let's take a look at remote jobs.
7:57And this is going to be all about using the AsJob switch parameter on Invoke-Command. So let's do an Invoke-Command here, set up some remoting, pass in a script block, just going to throw in a quick script block here, Get-Eventlog. How about we get the system event log, how about the newest 10, for entry type error. Sounds good, great. And it will pass in the computer name parameter here. Let's do this across all our servers, DCNUGGET, APPNUGGET, FSNUGGET. And here's the trick, ready, AsJob. That's it, that's the trick.
8:28So just add that parameter to anything remoting that you do, and it'll spin this up in the background on all of those machines. We won't be sitting here waiting for that to finish in on any of those machines. So I've hit Enter. There we go, now it's running on all three of those machines. Now, here's another thing, if we do a Get-Job here, this is just going to show us the parent, the top level ones. Notice how it's skipping ID numbers here? The last one we did was 8, then 10. And now if we do another one, it would actually probably jump up to 14. Because what it does is it creates a ParentJob, and then the ChildJob is actually the task that's performing the work.
9:03And you can actually see this if we do a Get-Job -IncludeChildJob. Look at this, so here's our ParentJob, recurse file system. Here's the actual task that does the work, here's our ParentJob, ThisIsBad, here's the task that actually does the work. And then right here is our remote job, and because we sent this to three machines, there's going to be a task for each machine. So that's why it has a command for each machine going over there. All right, and also notice our PS job type here, remote job as opposed to background job. Oh, no, that failed. Look at that, our remote job failed.
9:33What did I do? Oh, this is a telltale sign right here. When you see a failed status and it doesn't have any more data, that's a good sign that is probably something syntax related. Because usually it will stay completed, and then it'll have more data which contains the error message. But if we head up here, those of you with sharp eyes probably noticed that I typed in newest one dash rather then newest 10. So let's come back down here, recall my last command here. There it is. And let's just fix that right there, turn that into a zero. All right, cool. Now it's running, now if we do a Get-Job, we should see that it completed.
10:09All right, its job number 14. So let's do a receive-job here, pass in the ID of 14, and let's do a keep on this because I want to show you something else as well. There it is, and look at that. So there's the results, there's the top 10 error system logs for each of those machines. But we could do this as well. Let's do a Get-Job, let's -IncludeChildJob. Say that we only wanted to retrieve the results for one of these tasks, we could do the same thing. Receive-Job, let's do it for, how about 17 there, we'll get rid of keep, and there we go.
10:39Just for FSNUGGET in that case. And if we do another one now, we don't have any more data here for this, so we couldn't go and get those results again because we didn't keep them. So that is remote jobs. Essentially they're just background jobs running on remote machines that we can kick off from our local machine using the power of remoting. Let's take a look at scheduled jobs. These are amazing. You will definitely be using these quite a bit here, especially if you want to automate any tasks. But just to show you the commands we are going to be working with here, let's do a Get command. The module therein is psscheduledjob, and there they are.
11:11So Register-ScheduledJob is how we're going to create a brand new scheduled job. We'll tie a trigger to it, we'll tie some options to it, and that will create it in Windows Task Scheduler, and then we can remove it using unregister. So we've got lots for working with job triggers here, for job options, and then also for the actual scheduled job itself. So our goal for the scheduled task, as I head over to our file share, is to keep our Help updated. So let's head over to FS Nugget PSP4, we've got this Help directory here, right? And this Help hasn't been updated been a while, since we did our Help Nugget.
11:44So our goal is to keep this updated. So every morning at 3:00 AM, we want a job to kick off that goes and does a Save Help and specifies this as the destination path. So our Help will be updated every morning, every day. And then in our client machines, we could have them spin up a job, put into their profile script, that in the background, the first time they launch PowerShell for the day, it goes and downloads help from this file server. Cool? All right, let's do it. So let's start by setting up our job trigger, and it'll just pass this variable right into Register-ScheduledJob. And we'll do the same thing with our job options.
12:16This will make it easier on the eyes when we're typing this all out. So we're going to a New-JobTrigger here, and there's all kinds of things we can do with this job trigger. We can do it daily, weekly, we can specify intervals, so we can do it every third day, every second week, there's so much we can do. Specify days of the week, specify users, we can do it at start up, at log-on, just once. We're going to do this one daily, so let's do it daily at-- here, there's the parameter at-- how about 3:00 AM. Perfect, so there's our job trigger. That was easy, that was our schedule. Now next, we want to set up a job options-- I'm going to do another variable here, we'll call this option-- and we'll do -New job-- ScheduledJobOption, there it is.
12:52And here, just a bunch of options if you want to turn them on or off. Right, so here, let's say we want to wake to run, because if we're on a client machine like this, and we have those power options set and it's sleeping, it certainly won't wake to run. So this will make sure that it wakes to run. Let's do another one here, how about StartIfOnBattery. There's another one, perfect. So now we've got some options. Now we're ready to create the actual scheduled job itself, so let's do a Register-ScheduledJob. And let's give this one a name here, how about we'll call this GetNewestHelp. That sounds good, GetNewestHelp.
13:22This is going to be a script block, and that script bob-- script block is just going to be Save Help, right? Save Help, we'll give it a destination path here of our file server, fsnugget, psv4, backslash, help. There it is. That's it. So we just want to put this on a schedule. And then our trigger is going to be our t variable that we just created and our options here after scheduled job option is going to be our o variable. That's it. Done.
13:52Now, guess where you can see this? Sure, we can see it in our session here by running a Get-ScheduledJob, as I just did here. Not Get-Job, but Get-ScheduledJob. Remember, Get-Job will show us if it's running it will show up in Get-Job job, because these are the instances of it running, not the actual container. That's-- you'll need to use ScheduledJob to see that container. But you can also see it in the task scheduler. So if we do a search here for Task Scheduler, this is pretty cool. Expand task scheduler library, Microsoft Windows, head down here to PowerShell, there it is, and scheduled jobs.
14:25That there it is GetNewestHelp. So we've got some general information here, some more options you can work with. Here's your trigger, and you can modify this by going into properties if you want to change the schedule or anything else associate with your trigger. You have your actions, which in this case is just going to be you start a program, it's going to start PowerShell, pass in all the stuff that we defined when we set up the job. You've got your conditions, which are going to contain more of your power options, and idling options, and network options down there, settings, and history. So really cool that it does show up here, and it's just another layer on top of Task Scheduler that we can control all through PowerShell.
14:57Now, if we wanted to test that out and start that job rather than wait around till 3:00 AM, we can do a Start-Job, and we can pass in the definition name here. Definition name is going to be the name of the scheduled job, GetNewestHelp. There it is, and that is going to fire it up. So now we can use the standard job commandlets to work with this job. But right now, it's running and downloading all the latest help into our Help directory over there on our file server. So that will ensure that our Help is always the latest and greatest on that share.
15:28And then on the client side, which I'll show you how to do once you get into profile scripts, we could easily set up a background job to run when we fire up PowerShell to do an Update Help from that file share. And that way, we'll keep all of our clients nice and fresh with the latest and greatest help. Let's finish up by looking at the challenges for this Nugget. Again, you can find all the commands we worked with here inside of the commands.ps1 file for this Nugget. Here are your challenges. Challenge number one, start a background job on your local machine to retrieve the system event log, check the job status, and when finished, retrieve the results by ID.
15:59Pretty straight forward, they're just using a background job. So you'd be using Start-Job, and then remember to use Receive-Job, only pass in the ID parameter specifying the ID that was returned when you created the job. The second one here, start a remote job across multiple machines to retrieve the system event log. Check the job status, including ChildJobs, and when finished, retrieve the results. Use a variable to store and work with the job, then cleanup by removing all jobs. So same kind of deal as the first one, except you're going to be working with multiple machines, so there's going to be a lot of ChildJobs or child tasks underneath the ParentJob.
16:31And the big difference here is use a variable. So when you create the job using Invoke-Command, stuff it inside of a variable. That way you have a reference to the ParentJob, and you can use that to check the results as well as then retrieve the results. The other big one here, challenge number three, schedule a job to retrieve security event logs with an eventtype of error, daily at midnight. Run the scheduled job manually, view the results, and then unregister the scheduled job. So same thing we did in the first two, except rather than a local-- or remote job, this is going to be a scheduled job. So schedule a job to run at midnight that gets all the security event logs, run it manually, view the results, and then unregister it.
17:07And here all the steps here to help you out along the way. And as always, good luck. And don't forget, you can download all of the support files, all of our Nugget Lab files here, on the right hand side of the course page. In this CBT Nugget, we covered jobs in PowerShell. How to take commands and scripts and run them in the background. So we covered background jobs, remote jobs, and we even looked at scheduled jobs. I hope this has been informative for you, and I'd like to thank you for viewing.
Workflows
0:00Workflows. One of the greatest features that came out of PowerShell version three was integration with the Windows Workflow Foundation Engine. This gave us the ability to essentially turn commands and scripts into steps. And we can coordinate those steps across machine boundaries in parallel or in sequence, and we could even recover from failures. So it gave us a lot more flexibility and control over those long-running processes. So our goal for this Nugget is to get you up to speed on what workflows are all about, how they differ from scripts, and how we can write them. Let's do it. So workflows are special functions in PowerShell.
0:31And I know we haven't gotten into functions yet, but we'll cover them in great detail when we get into scripting. But they're very simply just a named block of reusable code. So in PowerShell we have a function. We start out by stating function as the key word. We give it a name, like get, dash, whatever using PowerShell naming conventions. And then we can accept parameters. We can define our parameters here, and then we list up some PowerShell code, right? And then what we call this, we call it just like a cmdlet. We call it by name. We pass it the parameters. And it gives us a way to reuse a block of code. Workflows are very similar to functions. In fact, they work the same way, except that we define them using the workflow keyword.
1:05We give it a name, we can define parameters, and then inside of here we set up steps which are commands or scripts that we can execute. But there's fundamental differences in how these two work. Functions are a PowerShell thing. Workflows are actually outside of PowerShell, inside of the .NET Windows Workflow Foundation Engine. So anything we do inside of here is actually going to get translated to that engine. That's going to mean things are going to work a little bit differently, as you'll see when we get into our demonstration. About the only thing that's similar between these two things is, it's a way for us to group commands together and call them by a name.
1:37There's a lot of differences. Functions are a PowerShell thing, right? They're executed by PowerShell. They are single-action processing. They start, they run, and they finish. And if something were to happen in between, like the power goes out or the network goes down, that's it. We've got to restart everything from the beginning. Workflows, however, because they're executed by the Workflow Engine, support parallelism. So we can execute commands in parallel. They can pause and restart. They can persist beyond computer restarts, whether it's by design, or whether the power goes out, or the network goes down, we can resume them, because we can create checkpoints within them.
2:11So think of workflows as that last thing you'll do to glue together a bunch of tasks, right? You have this huge process that contains many scripts and commands. And you want to coordinate everything, have it executed in a specific order. That's what workflows allow us to do. So here's an example. And these commands in here could also be scripts. So let's say that we've got four scripts that we need to run that make up a process. And they need to be run, at least two of them, in a specific order. They can all run at the same time, but we need at least two of them to run in a specific order. So here we go. We define a workflow, we give it a name here, get something cool.
2:43And then we define in a parallel block, saying commands one, two, we'll call this command two here, and command three, they can all run in parallel, as long as command 2-A executes before command 2-B. So if we visualize this, here we go. We start our workflow. So here's our workflow, up here. This, then, will be our parallel declaration. And inside of here would be our sequential declaration. So here's command one, here's command two with A over here and B over here. A needs to go off before B. And here is three. So all these would run at the same time, but command A would run before command B.
3:16So that's the general idea of a workflow. Now, let's turn this into something more real-world. So let's say that we had a fresh Windows server 2012 machine, nothing on it, and we wanted to turn it into a Hyper-V machine, install a bunch of virtual machines, and then configure them, right? Maybe turn one into a domain controller, one into a database server, one into an IS server, a file server, all that stuff. So the first thing we would need to do, and this could just be a command, is install Hyper-V on that box, right? We could just use Install dash Windows feature, that cmdlet pass into Hyper-V, and do all that. Which would also, by the way, require a restart.
3:48Which right away, we couldn't do this from a function because that would ruin the whole function, ruin the whole process. But with a workflow we could certainly do it. Now the next step, then, we would maybe have a script. This would be a script called create-vms. And this would actually, physically create those virtual machines in Hyper-V. And then we would have another script here called configure-vms, which would install the specific roles on specific vms, and maybe this one would even require a little manual intervention. So we could do this, just like down here, except it would have sequence in parallel flipped because we would need to start here with Hyper-V. That would be the first one, that one could just be a command.
4:22Then inside of parallel, we could create our 5, or 10, or however many virtual machines. All those could get created in parallel at the same time. Otherwise it would take forever to install one, wait, install another one, wait, install another one, wait. And even inside a parallel here, we could checkpoint after each one was done. That way, if something were to go wrong even in the parallel world, the ones that finished would be fine, because we checkpointed after every one completed. And then the final step here is to configure them. And if this required manual intervention, we could even suspend the scripts for manual intervention, maybe send an e-mail to an administrator.
4:55Say, hey, this script needs you to go do this manually. When you're done, execute this command to resume the job. So we get a lot of options here, with workflows. They allow us to checkpoint. They allow us to survive past restarts. We can resume as soon as that computer comes back up, after the Hyper-V is installed. And it's just, there are so many great use cases for workflows. It really takes it to the next level, allowing us to coordinate our scripts and our commands, and just gives us a lot more control over the whole process. Let's jump over to the Virtual Nugget Lab. We'll see a lot of how this stuff works, how we can build workflows, and some of the really cool things we can do with them.
5:28Here we are, in the Virtual Nugget Lab. Let's bring up the ISE here and get a feel for the basic structure of a workflow. So it's very much like defining a function, only instead of the function keyword we use the workflow keyword. Then we give it a name. This is how we're going to call it, just like we would call a cmdlet, call it by its name. We can optionally accept some parameters here. So we're going to define a parameter of the string data type. And here it is. It's going to be a variable that we reference inside of our workflow. And then we're just going to send back as the output here, hello. And then whatever they passed in. So, let's go head and create this workflow. We'll highlight that all, we'll execute that code. And now we have a workflow.
5:58So now we'll be able to do things like run a Get-Command for all things workflow. Let's do it. Watch this. And look at that, it comes up as the command type of workflow, and there it is. We could even get help on it. Let's get help, to see what we get here. Now, here it is, the name of it. Here's the syntax. It accepts our You parameter that we defined. And it bolts onto it, WorkflowCommonParameters. And there's a lot of WorkflowCommonParameters in here, such as PSComputerName. We'll talk about PSPersists which is how we're going to do checkpointing as well as all the common parameters that every kind of function, or anything in PowerShell gets.
6:32So more on those in a little bit here. But to call this now, we can just call it like a cmdlet. Get-MyFirstWorkflow, if we do a dash here, let me get rid of this here, look at that. There's our parameter, You. And I'm just going to pass in Me as the parameter. If we execute this, it's going to execute it. And look at that. Hello, Me. Cool. Now, let's get to the cool stuff. How about a parallel workflow? We can define a parallel block here as one way. I'll show you another way here shortly. And anything inside of this block will get executed in parallel. So if we do this on the local machine, first let's go ahead and create this. We can just execute this, we're not accepting any parameters here so we can just call it Get-SystemStuff.
7:05If we execute it, it's going to execute all these in parallel. So there's no guarantee in what order they'll come back. Because they'll come back as they finish. And we could add on here, if we do a PS, these are all of the workflow common parameters. So this is built on top of remoting, which means of course you need remoting enabled on your destination. So we can do a PSComputerName here. Let's pass in, how about our domain controller here, DCNUGGET. We'll do APPNUGGET, and we'll also do our file server, FSNUGGET, here. Highlight all that, I'm going to hit F8 on the keyboard. And now it's running all of those in parallel, across all of those machines.
7:37And you can see, because our results are all over the place. We get some event logs coming back here, and then we get a process. We get some more event logs. And it shows us what machines they're coming back in. But the cool part there is all of those are getting executed in parallel, across all of those machines. A couple of things to note here. Even though we're in PowerShell and we're putting PowerShell cmdlets in here, remember this is all workflow stuff here, so most of the cmdlets have been mapped into the Windows Workflow Foundation Engine. So that's why we're able to execute these commands, no problem.
8:08But each one of these gets executed in its own run space. That's another big difference from functions. In functions, we're all in one big run space. So we can declare variables, we can get objects back and work with those objects. We can still declare variables in here, no problem. So we could declare a variable here, a equals, say-- we'll just do a Get-Service here, for instance. So we can do this. But here's one thing we can't do with this variable. Try to execute any methods. Look at that. It's not going to let us do it. Because each one is in its own run space here. And these are de-serialized objects going over remoting.
8:40So we wouldn't be able to do things like that. But that is where the inline script comes into play, here. Inline script, and then we can pass in a block of code here. Now we can do PowerShell stuff. So once you're in an inline script, you have full access to PowerShell. So now we could do the same thing. We could declare a variable here. We get that equal to get service. And then we could do things to that service, like start or stop the service, no problem. Because we're in PowerShell at this point. And that's why we can still use any cmdlets that we can't use, that haven't been mapped into the engine.
9:13Because they will implicitly get wrapped inside of an inline script, and they will still work. But again, most of the major cmdlets have been mapped over, so we can easily use them outside of inline scripts within our workflow blocks. Oh, I should also mention you can still pass data to them. So let me get these back, here. So we could do something like this. If, for whatever reason, we needed to work with this variable from inside of our PowerShell inline script, then we can use this right here. Using. So we need to use the Using scope modifier, and that will allow us to access that variable, just like so.
9:45So that will still certainly work. And that's how you'll pass data between blocks, in between scripts, and all that here from inside of your workflow. Let's look at another one, another way to do parallel workflows. This one will be a little more useful. So now we're going to create one called Copy Files Here. So we're going to accept a couple of parameters. We're going to accept a source and the destination. Then we're going to get all the files at the source, and we're going to do a Foreach-parallel loop. So this is another way to do parallel execution. That means each item in this collection is going to get executed in parallel. This is pretty cool.
10:15So what we're going to do here, and this is pretty useful, is we're going to create a Copy-Files workflow, meaning every single file in here is going to get copied in parallel. Very cool. So let's go ahead and execute this, to create that workflow, all right? And now we can call it, in fact here, let's create-- what we're going to do is, we're going to take all the files from our install directory up there on our file server, let me get this open here to show you. Whack-whack, FSNUGGET, PS4, and if we head down here to Installs, here they are. So we're going to copy all of these over in parallel, meaning each one is going to be on it's own thread getting copied over.
10:46So we're going to copy this down onto our local machine. So we'll run a new item here to create that installs directory locally. Perfect, now we have it. And now we're going to run our workflow here by pulling down, passing in the Installs directory there up on our file server, as the source and as the destination, our local directory that we just created. And it's going to copy these all down in parallel. And when each one is done, it's going to report back. So look at that. Copy, copy, copy, it's on the last one right now. I put one huge file in there, so I can show you down the road. We'll expand this, and I'll show you how we can do checkpointing. We'll actually turn off our file server in the middle of this process, and we'll see how we can recover from it.
11:20So there it is. Copy files, complete. So it wrote it output here, that that file was copied when that file was done. And then when everything was done, it said copy files complete. So those are parallel workflows. You can use the parallel block. Everything in that block, then, will get executed in parallel. Or you can do, for each parallel, or each item in that loop, each item in that collection will get executed in parallel. Let's take a peek at sequential flows. So what we're going to do hear is, first we're going to put everything in a parallel block, right? So this command's going to get executed, these commands are going to get executed, and this last command here, all these are going to get executed in parallel.
11:52But inside of this sequential block here, Get-Process A, B, and C are going to get executed sequentially. So this one first, second, and third, while all three are going off at the same time. So let's go ahead and create this one. And now, what we should see here is both our service calls to services that start with A and B, those went off right away, as well as this one. So all of these were executed in parallel, but these three, well actually there's only one. We only have see processes here. Let's do something a little bit different here. Let's go, we know C is there.
12:23I know W will be there. And then P, for PowerShell. All right, there we go, CPW. And by the way, if we just re-execute this, it'll just overwrite that workflow that's currently in our session. All right, so now let's try this again, here. Let's execute that. And now we should get the same thing. So first we get all of our services. There's our A services, here's our B services. And while that was going on, there's our C processes. There's our P process, and there's the W processes. So those went off sequentially, but together all three of them went off in parallel. So that's all. You need to define sequential flows. Just wrap them inside of a sequence block.
12:55Now, this last piece I want to show you here is one of the neatest features in the Workflow Engine. And that is having the ability to checkpoint at any point within the workflow. This is how we can make our workflows resilient. And especially when you're implementing long, complex processes-- you have a lot of scripts, a lot of commands, maybe you're archiving data and you have a process that takes six hours to run. Wouldn't that stink if, when it's almost completed, something bad happens? The power goes out, the network fails, something happens that would cause us to have to restart the whole script from scratch?
13:26Yeah, that's where workflows can help. Because we can implement the Checkpoint Workflow command here. And any time it sees this command, it's going to save the state of our workflow to disk. So we can spin up jobs, let them go, and implement our own check flows. And if that job, for whatever reason, hits a suspended state, when everything comes back online we can just resume the job, and it'll pick up right where it left off. Really neat. And there's a number of ways to implement these. This is definitely the way that will give you the most control. Anytime it hits this Checkpoint Workflow, it's just going to save the state right there. But you can also do this on cmdlets that have been converted over to the Workflow Engine.
13:58Get-ChildItem is one of them, and most of them have been. But PSPersist, there you go. That would automatically put a checkpoint after this command. Another way to do it is just have it automatically checkpoint after every single command. So down here on our call, we could do a PSPersist. So putting this parameter right here at the end of our call to the workflow will do a checkpoint after every one. That could affect performance a little bit. That's why I like to just do this on my own. So after a really long running script or command, just checkpoint it right afterwards. And then it'll get saved, and that will give us the ability to resume from that point, should something bad happen.
14:31All right, let's do this demo. So this is the same exact workflow as above. The difference is we took out the parallel. We're going to do this sequentially so we can see it happen. And we added checkpoint workflow after each copy item. And we also put a little sleep in here, so we have time to shut down the machine. Because what we're going to do is, we're going to run this as a job, and then we are going to shut down our file server, just completely force the shutdown in the middle of it. And what we'll be able to see is, that job should go from a running state to a suspended state. And it'll sit in that suspended state until we intervene, and we do something about it.
15:03But again, you can automate this whole process for events like this. If you have a process that requires rebooting the computer, you can certainly reboot the computer. And then again, put inside of a scheduled task on start up to find that job and resume it. So you could totally automate all of this without a problem. But we're going to do it here with a little manual intervention. Oh, and as I mentioned you could manual intervene, too. So if you have a bunch of processes and then you need some manual intervention, this is where suspend workflow comes into play.
15:34So you can certainly do that as well. But let's run this. Let's first create our workflow here. All right, it's good to go. Now, before we run this let me just show you I have no tricks up my sleeve here. On our local machine, our installs directory is completely empty. Over on our file server, we have all of our files ready to go. All right, so here's what we're going to do. We're going to fire this job up. Let's do it. Let's go ahead and execute that. All right, so it's running. If we do a good job here, you can see currently it is running right now. So let's just give that a second to run a few. All right, good. Now let's crush our file server.
16:06Boom, we forced the-- not even a restart, we just totally shut it down. And as soon as that command finished, I just saw over in my Hyper-V server here, that the state of that machine went off. So it's completely down. And now what I want to do is, we could do this right here, but this is going to give us inconsistent results here. The problem is our file's right here, and we're totally connected to our file server with these scripts. So what I'm going to do is, I'm just going to fire up a new PowerShell session. And let's do a get-job. It should no longer be in a running state, but it's in a suspended state. See that? So how do we know how far it got?
16:39Well, we could do it a number of ways. Probably the best way to do this, because it'll work no matter what kind of process you have, is just look at the results of our job so far. But since we're copying these locally, we can come in here and check. Oh, we can see, look. Our big file, that zip, made it over. So if we do a receive job here, let's do a get-job. We only have one job here, so we can just do a get-job and pipe this to receive-job. And, oh, it's not recognized because I typed it in wrong. Receive-job. Boy, I really butchered that one, huh? There we go. Look at that.
17:09Big dash file dot zip copy. So that's how far it got. So we know that there's more files to be had there, right? So now what we need to do is, well, I need to restart my Hyper-V server here. So let me get back over there and restart our file server. All right, starting, it's starting right now. Cool. So that's starting up, and as that's starting up here, what we can do is when it comes up, is just resume the job. That's it. And again, if we had a startup script over on our file server for a scheduled task with the trigger there of on startup, then we could look for this job.
17:42And we can look for any jobs in a suspended state in that machine and fire them up, doing a resume job. So file server's up. Let's do a get-job. And let's just pipe this to resume job. Cool. Now it's back into a running state. And it'll probably finish pretty quickly. Yeah, there we go. Because those other files were pretty small. And it's done. And we can verify that it finished, and look at that. There's the rest of those files that are copied over. So how cool is that? We just had failure happen in the middle of nowhere, but thanks to check pointing we were able to resume from where it left off.
18:17Just an incredible feature, there. Let me give you your challenges for this Nugget. Challenge number one: create a workflow that retrieves the newest five system event logs from multiple servers in parallel. Pretty straightforward, just create a basic workflow, use a parallel block, and then use the get-event log cmdlet with the newest five. Send that across a couple of servers, and you'll see they will all execute in parallel. Challenge number two: build on the previous workflow by accepting an entries parameter to accept the number of newest entries. So we're taking this hard-coded five value out, moving it to a parameter, and then that way when we call this we'll be able to pass in any number.
18:50So we'll turn that into a variable, there. Pretty nice. Can I just gave you an example of what how you call this workflow? So I named it get-system event logs, and then here's your entries parameter, pass in whatever number of entries you want to retrieve. And you can send that across multiple machines as well. Challenge number three: create a workflow that calls three scripts or commands and creates a checkpoint in between them. Run the workflow as a job, and terminate your session shortly after starting it. Launch a new session. View the suspended job, and resume to let it finish. So same thing that we just saw, only you can also simulate this by using your session and just terminating your session.
19:24That will suspend the job, and then you can open up another PowerShell session and resume that job and let it finish. Remember, you can find the answers underneath these regions. And you can find all these files in the Nugget Lab files, downloadable on the right-hand side of the course page. Good luck. In this CBT Nugget, we covered workflows. We saw that workflows is an amazing feature that we can tap into from PowerShell, that really utilizes the .NET framework's Windows Workflow Foundation Engine. And it allows us to take those long-running processes that involve many tasks, many commands, many scripts, and have a little more control over them. We can coordinate them across machines.
19:56We can run them in parallel. We can run them in sequence. And we can even checkpoint and save our work, so we can resume in the face of disaster. I hope this has been informative for you, and I'd like to thank you for viewing.
Scripting - Getting Started
0:00Getting started with scripting. So we've got a handful of scripting Nuggets ahead of us, and no better place to start than talking about how to execute scripts. So we'll look at the basic anatomy of a script. We'll look at how to execute scripts. And we'll also get familiar with all the different security features here in PowerShell. And at the end here, I'll also show you how we can sign our script. We'll look at the process of creating our own self-signed certificate and then the benefits, of course, of digitally signing our scripts. So let's jump right into the virtual NuggetLab and get familiar with the basics of scripting.
0:30All right. Let's jump right into the ISE here and get familiar with the script that we're going to be working with throughout this Nugget, called test-remote.ps1. So this script is going to test remoting. It's going to do so by first seeing if we can ping the machine. If we can ping the machine, then it's going to set up a PSSession. And this script will tell us if remoting is enabled on a machine. Pretty basic script. But right off the bat, you're going to notice something that we haven't seen yet in this course. This is known as comment-based help. And it allows us to provide help for our script. So if someone were to run a Help or a Get-Help against our script, it would look just like running Help or Get-Help against the command line.
1:03And it's very simple to set up. We have a dot followed by keyword and then the value we want to provide for that. So if we want to provide a synopsis description, list out all the parameters, give some examples, we can easily do that. Check out the About topic for comment-based help for more and to see a list of all the different keywords here that we can provide. Next up, the first thing we're doing in this script is setting up a parameter block. And this is what's going to allow us to accept parameters to make our script a little more dynamic. Very simple, right? Parameter, open parenthese, close parenthese. Inside of here we list our parameters, which are really just variables.
1:36And that's how we're going to use them inside of our script. And if you want multiple parameters, you can comma-delimit them. You can set up mandatory parameters, optional parameters. Here we have a default value for our parameter. So as you can see, our example here, one of these examples we're not providing a parameter, which means it's going to execute using the default value for this parameter. Now, we're going to get more into parameters. I'll show you how we can create some pretty big and complex parameter blocks when we get into our Essentials Nugget on scripting. All right. Let's get into the meat of this script. So this script has two functions defined, one called CanPing and one called CanRemote.
2:09And again, more on functions when we get into that Essentials Nugget. But just think of a function as a named block of code. We'd implement code reuse, because we can wrap all that inside of a function and call it by name multiple times in our script. And a function's either going to just do something or it's going to do something and return a result. So our first function here, CanPing, is going to return either true or false if we can hit a computer. Our second function isn't going to return anything. It's just going to do something. And the reason we did this is because we're going to run a little if statement in the main block of our script here that says if CanPing-- in other words, if this machine is online-- then we're going to run a CanRemote to see if remoting is enabled, because why bother even checking if remoting is enabled if we can't even ping it?
2:50So that's why our CanPing is going to return true or false. That'll allow us to see the results of this. And if it's online, awesome. We'll check remoting. If it's not, we won't even bother checking remoting. Now, with our CanPing function, we're just going to run a test connection against the variable ComputerName-- or I should say the parameter that's coming in that we reference here as a variable inside of our script. So we'll run a test connection. And this is going to return-- now, if you don't include the quiet parameter, it's going to return a ping object with all those different properties we can see and query in the response. But if we run it with the Quiet parameter, it's just simply going to return true or false.
3:25And that's exactly what we want for this kind of function. We just want a true or false value. Is it online or is it not? We don't care about all the data that comes back inside of that ping object. Also, notice our ErrorAction here. We're going to get more into error handling in that Essentials Nugget as well. But we're just saying if something bad were to happen, just keep going. Don't bomb the script out right here. Keep going. Just let it return false and that's fine. That'll tell us that it's not online. So that's our script. Let's take a look at how we can utilize this script. And we're going to do this through the console. Oh, by the way, that script that we're going to be working with is up in our NuggetLab files on our file server under 17 scripting1, test-remote.ps1.
4:00So let's just bring that file locally. That way we have one up there on the file server and one down here to work with. All right. So there we go. A little copy item, specify our path there. And our destination will be our current directory. All right. There we go. If we do ls, it should be in here. And there it is, test-remote.ps1. Perfect. All right. Let's execute our script. Now, here's one security feature. You can't just do something like this, right? That's not going to work. It's not a command. That is looking for a command. So in order to execute scripts, you need to actually supply a path.
4:31And we can do this using absolute paths or relative paths. So this is going to say, in the current directory we can do a test-- and you can use Tab completion there-- test-remote.ps1. Let's hit Enter. Uh-oh. What's that? What does that say? Cannot be loaded because running scripts is disabled on this system. And that gets us into security. Now, before we go down the execution policy rabbit-hole, let's just take a step back and talk about the security measures that the PowerShell team put in place here in PowerShell. And the first thing to note about that is that these are not measures that are here to stop a malicious user from doing malicious things.
5:07If you have somebody that knows what they're doing and they want to do something malicious to your system, they're probably not going to use PowerShell to do it. And that's also why we have other security measures in place, principle of least privilege, firewalls, malware, and virus scanners and detectors, all that kind of stuff. That's how you stop malicious users from doing malicious things. No. The security measures in PowerShell are really to help us, number one, not shoot ourselves in the foot, and number two, stop those users who have no idea what they're doing from doing things that they shouldn't do.
5:38So here's security measure number one. That's why you saw right here we need to type in a path to execute a script. Otherwise it's going to treat it like a command. And the command is not going to have the same name as your script, so it's not going to work. Number two is execution policies, which we'll dig into shortly. It brings a lot of benefits here, especially signing your scripts, because that will do a lot of great things for us. And then the third one-- and this is an awesome one. This is what's going to stop Bob from navigating the company directory to do something, is-- let's find our script. Actually, let me do our local one that we did.
6:08Let's just do a start here, bah, buh, boo. There it is. So here's our script, right? All right. Let's double-click on it. Hey, look at that. It just opens it up. That's an awesome security feature. It's not going to launch the script when you double-click on it. It's simply going to open it up. Now, that's not going to stop somebody from copying our code into PowerShell session. But chances are if they're just a user who doesn't know what they're doing, they're probably in the company share, they're not going to know that that's PowerShell code, nor are they going to have access to PowerShell. All right. Back to execution policies. So let's do a quick Get-ExecutionPolicy here.
6:38And we can see that we are in a restricted execution policy mode. And that is the default. That means no scripts are allowed to execute on the system. So no scripts, local or downloaded, can be executed. We can change that with a Set-ExecutionPolicy. We've got an ExecutionPolicy parameter here. And that can be a couple of values here that we'll look at shortly. And you also have a scope associated with this. And a scope is going to determine if it's the current user, the machine, machine policy based on group policy, user policy, or if it's based around the PowerShell process.
7:09Let's just do a help here on Set-ExecutionPolicy. help, Set-ExecutionPolicy. Let's look at the full help here. And let's take a peek. So here's our parameters for ExecutionPolicy, Restricted. That's the default. Does not load configuration files or run scripts. The next one is AllSigned. It requires that all scripts, no matter where they came from, will need to be signed by a trusted publisher with a digital certificate. More on that here towards the end of the Nugget. RemoteSigned requires that all scripts and configuration files downloaded from the internet-- so whenever you download something from the internet, it's going to add a header into the metadata for that file that signifies that it's been downloaded from the internet.
7:45So this just means all of our local scripts, anything we build on our network locally, will be fine. They'll be able to get executed. But anything that's downloaded from the internet will need to be signed by a trusted publisher. Unrestricted is something that you never want to use, because it will allow you to run anything at any time. And those are going to be your big four right there for ExecutionPolicy. And you can set the execution policy in group policy as well. And just to show you where that is here, let's fire up Group Policy Management here. And right into the Default Domain Policy.
8:16I'm just going to hit Edit. We'll go down here into Computer Configuration, Policies, Administrative Templates, Windows Components. And it's down here, Windows PowerShell. There it is. So turn on Script Extension. If we enable this, we can choose Allow only signed scripts, so there's AllSigned; local scripts and remote-- Allow local scripts and remote signed scripts, so there's your RemoteSigned; and then Allow all scripts is Unrestricted. So you got those three options to choose from. So you can easily use group policy to set your execution policy across the enterprise. So now that we can execute scripts, let me show you one really cool feature before we move on to signing our scripts.
8:50And that is called dot sourcing. First let's do this. Let's just run our script again. test-remote.ps1. And pass in dcnugget-- actually, let's just run it like this. Perfect. So this is going to run our script against the local host using that default parameter. And when it's done, it's done. Script has gone. It's out of memory. In fact, we can verify that, because if we try to access that function-- let's try to access the CanPing function. Let's just run it. Look at that. It can't. It can't, because it's out of scope. It's out of scope. And that's what scope is all about, by the way. Let's just go in here for a second. So everything that was in here was scoped at the script level.
9:22So when it was out, when this script was done, it's all gone. Script is out of scope, right? And everything within that script is gone, out of memory. So let's do something interesting, thought. We're going to put a dot space and then execute our script. test-remote.ps1. Watch this. So same result, just going to execute it against the local host. But we did something known as dot sourcing there. By adding that dot space before the path to our script, what that did is took everything out and put it inside of our session scope.
9:55So it left everything that was declared at the script level there. Watch this. CanPing is going to work now. But everything that was defined at the script level-- meaning this is scoped at the script level, our functions. This parameter scoped at the script level. But everything inside of our function, this is scoped at the function level. So we wouldn't be able to access this response variable, because it went in and out of scope when that function executed. But watch this. This is really cool, because now we also have access to the computername variable, which was a parameter.
10:28And there i is. Now, we could even alter it. Equal-- how about APPNUGGET? Let's see if our APPNUGGET machine is online. And now we can do a CanPing against that, because we modified the variable. That's dot sourcing. Dot sourcing is awesome because it essentially takes everything that was at the script level scope and brings it into our session so we can use it. And that's extremely useful for doing things like this, for testing, because now you can modify those parameters and still execute your functions and see what the results will be. And there's just a lot of other use cases. I guarantee you, live in PowerShell long enough, you'll come across certain cases where you're like, man, I wish I had access to that function or variable after I executed the script, maybe to use it in another script or whatever.
11:05So that's called dot sourcing. And it's a very cool little feature. So signing scripts gives them two things, identity and integrity. Identity, because we're going to sign these things with a certificate from a certificate authority, a trusted certificate authority, and integrity because scripts that are signed can't be modified by malware or malicious users. In fact, we can actually see this. Let's start up the pshome directory here. And everything in PowerShell here, all these files, all these format and type files-- in fact, let's just open up DotNettypes. These are signed by Microsoft. Microsoft's a trusted certificate authority, so they created a code signing certificate and they digitally signed all these files.
11:41And that's what this is down at the bottom here. This is their signature. So this is why we can't directly modify these format files, because if we did, they would be invalid and we would break PowerShell, because they are signed. So that's what we can do to our scripts. So you can go out and get your own code signing certificate from a trusted authority, like Thawte or Verisign or whatever. Or you can also create your own self-signed certificates, which are great for working in your own environment and for testing and development purposes. And you can view these signatures in PowerShell with Get-AuthenicodeSignature.
12:11So here, let's just do the pshome here. And let's just pass in, how about types? There we go. So if we Get-AuthenicodeSignature here, check it out. So we've got our signed certificate, the status is Valid, and there's a path. Let's do that against our own here. If we do this against our test-remote.ps1, you can see it's not signed. So if we were to put this on the internet for someone to download, then if they have their execution policy set as RemoteSigned, then they wouldn't be able to execute this script. But if we signed it with a valid certificate authority and put it up there on the internet, yeah, they would be able to execute it.
12:45So let me show you the process here for creating your own self-signed certificate. Let's head back into the ISE here. I'm just going to open up our commands file. And you can use what's known as makecert.exe. And you can actually get this through the Windows SDK, which I also just happened to download. And I've already got it installed here. And that will give you access to the makecert utility. But I put it inside of our installs. Here it is, sdksetup. You can run this. That will install the Windows SDK, which gives access to makecert. There's also a commandlet that you can use called New-SelfSignedCertificate.
13:17There it is, right there. But this actually in PowerShell version 4 won't work for code signing certificates. In PowerShell version 5, it does. So we still in version 4 and prior need to use makecert. So the first thing we're going to do is create our own local certificate authority here using makecert. That's what the first command is going to do, so let's execute that. There we go. You need to give it a key here, so I'm just going to put a password. Oop. You've got to confirm it here. All right. There it is. And there it is. All right. So not that we've created our local certificate authority-- we can actually see this here if we-- let's just fire up our MMC snap-in here.
13:51And let's just Add and Remove Snap-in here. Let's just add certificates in here for the local machine. And we'll do this for-- yeah, we'll do this at the user level here. Hit OK. And here we go. So here's our trusted root certificate authority, so if we come in here, we should now have a PowerShell one here that we just created. There it is. PowerShell Local Certificate Root. So now the next step is to create a self-signed code signing certificate with that root. So we're going to run another makecert command here, which will do just that. And there we go. We put in the password. And now if we head back here, head into Personal, Certificates, there it is, PowerShell User.
14:26So now we have a certificate. So now we can sign our scripts with this certificate. So let's head back here. And what we're going do is just go ahead and create a cert object. And by the way, you can use providers here to view that. So let's view all of our code signing certs in here. Let's just execute that little block of code. And there it is. So there's our certificate. So what we're doing now is just create this, put it inside of a variable. So there we go. Now we've got that code signing cert within there. And now we can use Set-AuthenticodeSignature to sign our script with that certificate.
14:56And if we do that, now it should be signed. Now, we could verify that just by running Get-AuthenticodeSignature again against our file, against our script. And we could see, there it is. There's our SignerCertificate. Status is Valid. So we now have signed it. And then we could also-- let's just cat this. Let's just take a peek at what it looks like here, because now that it's signed, it has a digital signature. So if the script were to change at all, it wouldn't match the signature and it would no longer be valid. Cool. So now that it's signed, we should be able to execute this. And let's just head back to the ISE here. Let's change our execution policy.
15:26Execute that. Yeah. We're going to change it. And now we can execute-- let's execute an unsigned script first. So this is our script sitting over on our file server. And by the way, to execute remote scripts using a UNC, then you can use the invocation operator here, otherwise known as the call operator. And so this will execute this unsigned script. And what will happen is we'll get an error. Sorry, this is not a signed script. But this one is. And if we try to execute it, look at that. It's going to work, because it's signed. Very cool.
15:56So there you go. Now, you could also export that certificate if you want to utilize it on other machines in your network. Or again, you could get a real certificate from a trusted certificate authority if you wanted to distribute your scripts outside of your network. So there it is. Let's take a look at your challenges here to finish up this Nugget. Challenge number 1, set the execution policy to Restricted, verify the setting, and execute the test-remote.ps1 script locally. What happens? Obviously, you should get an error message, right, because you're restricted. No script execution at all. Challenge number 2, set the execution policy to RemoteSigned and execute the test-remote.ps1 script.
16:29Attempt to execute the CanPing function from outside of the script. Execute test-remote dot sourcing and execute the CanPing function from outside of the script. What did dot sourcing the script do? So that'll show you how you can take everything that was at the script scope there and pull it into session scope so you can utilize things from outside of the script. And the big one here, Challenge number 3, set the execution policy to AllSigned and execute the test-remote.ps1 script. And we know that that should fail. Then generate a self-signed certificate and sign the test-remote.ps1 script, view the definition to verify the signature, and execute it.
16:59So the demo that we just saw there, try it out on your own. Here are all the steps to make it happen. Again, all these files here are in the NuggetLab files, downloadable in the right-hand side of the course page. And as always, good luck. In this CBT Nugget, we saw how to get started with scripting. We started by getting familiar with just a basic script that contains comment-based help, had a parameter, had a couple of functions, and even a very tiny one-liner script body down there to utilize those functions. And then we saw how to execute scripts and the many security features we have here in PowerShell. We then took a big look at the execution policy setting, which is what we're going to need in order to execute scripts on the system.
17:35Restricted is the default, meaning no scripts are allowed to execute. We took a look at all the different options there and even saw how to create a signed script and saw the benefits that that brings to us. I hope that this has been informative for you and I'd like to thank you for viewing.
Scripting - Essentials
0:00Scripting essentials-- so now we're really get into the meat of scripting. And I'm talking about the core language concepts here, things like variables, things like conditional logic, how to control the flow of code within your scripts by using if statements and switch statements. I will talk about looping, do-while loops, for-loops, for-each loops. And it's important to understand the difference between these so you choose the right tool for the job when it comes time to write your scripts. We'll also get into air handling, and, of course, we'll talk about functions. And at the end here, we'll bring it all together with a pretty cool script that will monitor our network and send us email notifications when any servers go down.
0:37So let's jump into the Virtual Nugget Lab and get coding. And we're back in the Virtual Nugget Lab. Let's bring up the ISE and let's start here with variables. Now, variables are very important when it comes to scripting because it's how we store information. A lot of the times when you're writing these big, long one-liner pipelines, you don't need variables. You don't need to store anything. You're doing it all in one shot. But with scripting, we need to put our data somewhere. Take this as an example. We get a bunch of services through getService. We store that in a variable, and then now we can do something with that variable.
1:08We can analyze it. We can get a count. How many services did that return? We can loop through it one at a time because that'll contain a collection of variables. So we can loop through one at a time, interrogate it, make decisions on it. Is it stopped? Let's try to start it. If it doesn't start, let's wrap error handling code around it, and maybe output that to a log file or a web page or an email, perhaps, for some kind of notification. But that's really why we need variables. We need variables as a place to store our stuff. So we've been using variables quite a bit throughout the course. But we haven't actually talked about them. So let's talk about them a little more.
1:38Any time you declare a variable, you give it a currency symbol followed by a name. And then you can also set it equal to a value, kind of do it all one shot here, which is what we're doing. And this how you'll see variables declared a lot. And when you're doing quick things, it's generally OK to do this. And what we're doing here-- I'm going to go ahead and create that variable, and now I'm going to view it. There it is. The value of 10. But what we're doing here is PowerShell's actually going to analyze that value going in and infer the data type. Meaning it's going to figure out which data type is best suited for the data that's going in, and that's the data type it's going to get.
2:11So if we'd run it getMember against this, it's going to say, oh, yeah, his is an int 32. That's what it decided the data type for this variable should be, based on the value we assign, which is great. But I've got to say, I'm a fan of strongly typing out variable. Sure, that's great for quick jobs. But when you're writing big complex scripts, it just makes it a whole lot easier to read to strongly typed your variables. And what that means is you are defining the kind of data that goes into it. So what do you think is going to happen here? If we say this variable A that we're creating, we're going to say it's of integer data type, and we're going to put a character data type [INAUDIBLE] of it, a string.
2:45What do you think is going to happen here? Yeah, it's going to bottom out, right? It's going to fail. No, sorry, you're trying to put something that isnt' an integer into a variable that you declared that's going to be an integer. So we would have to then, of course, declare this as a string in order to get it, and there we go. Now, if we look at A once again, now it's a string data type because, by the way, we overwrote the one that we had previously. So I like to use strong typing not only for readability purposes, but also because you will get access to all of the members of that data type. And here's an example.
3:16Say that we were going to run a getDate, and we're going to put in a variable, and we strongly typed it as a strength. It's going to be a string data type, so we wouldn't be able to call any of the members on the actual date that is returned from here because it was converted to a string when it was put inside of here. Case in point, if we execute this, we're not going to get anything out of it because it's a string. It doesn't support that day-of-week method. Where if we strongly type it is a date time to getDate, or not at all, which, in this case, would infer it to a date time, then we would be able to call the day of the week function, which return the current in the week, which is Tuesday.
3:50So let's imagine we have a handful of commandlets, which will give us a little more control over our variables, just to show you a list of these-- clear-variable, get-variable, new-variable, remove-variables, set-variable. So you have a little more control, especially when creating them. For example, let's say we wanted to create a read-only variable, we could use the new-variable commandlet, pass in the name. That's going to be dirs, so we'll reference it with a dollar sign dirs, or we could use get-variable and pass in dirs without the dollar sign. assign a value to it, get-child item, blah-blah-blah, and then option read-only. So you can create read-only and write-only variables, all that kind of stuff, which is nice because now, just to verify that we have the dirs variable here, which is a collection of directories, by the way, and here are those directories all stored inside of that variable.
4:28But just to show you, if we try to write to it, it's going to say, no, sorry, that is a read-only variable there. So those are user-defined variables, variables that we can create and work with. We also have automatic variables. These are all the variables that PowerShell creates on start up. And so these are configuration variables here for the shell, lots of them in here. And you can use the variable drive there, the provider, to see those. And, of course, we have environment variables as well, which you can also view the provider drive there to see all the environmental variables on the system.
4:59Moving onto conditions, conditions are what allow us to make decisions in our code. So we can do some branching. We could say, if this condition is true, execute this block of code. If it's not true, execute this block of code. And the first one we're going to look at here is if-else. So if-else is great because it allows us to just make a simple decision. So here we're going to create a variable. And I know I'm not following-- I'm not strongly typing it. But it'll result in less code, easier to look at. So, in this case, it'll be all right for learning purposes. So we're going to create a number variable, put 100 in it.
5:32So that's going to get inferred to an integer data type. And then we're going to run an if-statement; if this number is greater than 100, it's going to pipe to the screen using a right host num is larger than 100. If it's not, then it's going to say, num is less than or equal to 100. Let's just highlight all this here, hit Execute, and what do we get? Yeah, 100 is less than or equal to 100. So the if-statement analyzed this expression right here, num greater than 100. And it said, you know what? 100 is not greater than 100. It's equal to 100.
6:02So it skipped this block of code. That never ran. And it ran our else, this block of code right here. That's the if-else statement at the most basic level. We also have an if-else-if statement. In other words, we can have many else-if conditions within here, so we can analyze multiple conditions in one go. So the same thing here-- we're going to leave our num in memory there at 100. And here we're going to say if num is greater than 100, then num is larger than 100-- there we go-- else if num is equal to 100, it's exactly 100, else it's a less than 100. So we're just really just expanding this less than or equal and putting them in their own code blocks, and that's what else-if helps us out there, with multiple conditions.
6:39And there it is. So 100 is exactly 100, so it ran this block of code right there. Now things can get a little crazy when we have a lot of conditions. Like this is almost unreadable, right? And this is what you kind of want to avoid when you're building scripts. Because unless you're the only one maintaining them and you're cool with it, then cool, but if you're on a team, and people are going to be utilizing your scripts, they're going to put things in your milkshake when you're not looking because it's not fun to read this kind of code.
7:10But what this is going to do is we're going to prompt the user here. What size milkshake would you like? And they're going to type in small, medium, large, extra large or something that isn't any one of those. And we've got lots of else-ifs in here to analyze all the potential values that they could type in to the console and give us something back. So let's try out. Let's hit Enter. What size milkshake would you like? Let's say, I'm feeling like a large today. And it's going to say, living large. And we can do that again. Let's run that again. And now let's just typing in a bunch of gibberish, and it says, that's not size we offer.
7:42So, yeah, be careful when you have a lot of conditions. There's a much better way to do it. And that much better way to do it is with the switch-statement. So it's much less code. So here we're going to create an integer variable here called value. We're going to do readh-host, what size milkshake would you like? Give them a little instruction here. Type in the number that corresponds to your milkshake, and then we'll do a switch, which is going to analyze this. If it's one, it's going to run this code block. If it's two, it's going to run this code block. Three, four, so on and so forth, and default if they enter something that isn't any of our choices.
8:13But the switch-statement's awesome just because it's far less code. It's perfect for making a lot of decisions. So let's run this, and let's type in extra large. All right, great, extra large, that's exactly what we wanted. Let's do another one. Let's type in eight. That size is not available. Cool, so those are your conditional statements for making decisions, branching off code, and really controlling the flow of code within your scripts. Let's move on to loops. Now, loops are very, very powerful. This is what's going to allow us to execute the same block of code over and over, until either a condition is met, until we're at the end of the collection, or otherwise.
8:50We have really full control. Which one of those loops we want to execute is going to be dependent on what we need to do. But just to give you an idea here, the first one, this is not using the language construct. This is using the command line. So this is good for pipeline stuff. I just wanted to put it in here for reference. So here we're saying, from 1 to 10, do a for-each. So for each item in a collection, meaning it's going loop 10 times, starting at one, then two, then three, all the way up to 10, it's going to output this right here. So just to give you an idea here, let's go ahead and execute this. And there it is executing-- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. But again, that's the pipeline commandlet.
9:21What if we wanted to loop within our scripts? Generally what you're going to do is you're going to have a getter for the for-each loop. And a for-each loop, by the way, loops through a collection, starting at the beginning and going to the end. So generally you're going to have a little getter to go get something. You're going to put it in the variable. Like here, this is a perfect example. We're going to go get a bunch of files. So let's just execute that, and actually, let's just view it right here. Let's take a look at the files. And they're there. There's all the files. So we've got a bunch of files and directories here stored inside of this variable. Then we're going to say for-each, and here we're going to say, File In Files.
9:55So here's our collection of multiple files, and this file is a placeholder variable. Meaning for each time we go through this loop, this file's going to represent one of those files. The first file it's going to represent is this one. Then in the next iteration of the loop, it's going to be this one, then this one, then this one. And this is going to allow us to do things to each file in that collection. So a lot of the times when you're in a loop, you're going to, again, you're going to interrogate that object or that item, figure out what you want to do with it. And then maybe you'll have some logic statements, some conditional statements down below this that will say, hey, if this file is in this state, let's do something to it, that kind of thing.
10:31But this one we're just going to output the name of the file. So let's just highlight our loop here. It's going to loop through each one and just return the name. So that's the for-each loop. It's all about just looping through a collection from top to bottom. Here's a more are real world example of using a for-each loop with a conditional statement, our switch statement. So the first thing we're going to do is store all of the disks from get-cimInstance. We'll get all the disks here from the Win32 logical disk class. And let's see what we got in there. So we've got three disks in here-- A, C, and D. Now we're going to write a little for-each.
11:02We're going to see for each drive in the disk-- or you could do something like this; that doesn't make any sense. I like doing this-- disk in disks. And we would store disk. There we go. That makes a lot more sense to me. So our disks is our collection of disks. And then we're going to represent each disk through this disk variable right here. And now we just need to replace all of these with this disk-- perfect. So now inside of the loop we have a little switch statement. It's going to look at the drive type, which is going to come back as a number one through six. If it's one, it's going to output unknown, two, floppy removal, all the way down here to RAM disk.
11:37So it's just simply looking at the drive type, and then it's going to return back the device ID as well as that name. This is a pretty cool one. So let's go ahead and just run that for-each, and what do we get? We're going to get those three drives back. First one is A, it's a floppy removal. C is a hard drive. D is a CD drive-- exactly what I have in my local system here. Next up we have a do-while loop. And do-while loops are good when you want to run something until a condition is met. So you don't know how many times you want to run it. You're going to run it. You're going to run a block of code, which you're going to put after the Do inside of this is block here, and it's going to run it.
12:10It's going to then analyze, after that code is ran, the condition in the While. So it's saying loop while this condition is true. So it's going to continue to loop until this condition is true. If the condition value is false, it's going to run that block of code again and again and again. So this is good for running things until a state of something is flipped or until whatever condition here is met. So in our example here, we're going to ask the user for some input, and they're going to be stuck in an infinite loop until they guess what the magic number is. And we put the magic number here as 1337.
12:41So it's just going to run this block of code, ask the user for a number. They're going to type in a number. If they type in the right number, great, it's going to exit the loop and say, whoa, you got lucky. If they enter a number that isn't our condition, then it's going to run that block of code again and again and again. So let's try this out. Let's go ahead and execute this. Hey, oh, and by the way, this always confuses me when I look in the shell. This is actually just our block of code that's running here. But here, guess the magic number to escape. Let's do it. Let's type in 30. Is that the magic number? No. 40?
13:12No. No, no, no, no-- I could guess all day long, until it's 1337. And then, hey, you got lucky, and it exited the loop. So that's what do-while loops are for running it until a condition is true. The last loop we have here is our for-loop. And this is for when you want to run it a specific number of times. So you have your initializer here as the first type. We define all these variables here inside of our for block. So our initializer is what a variable starts out as. We're saying i is going to start out at one. Then we have our condition; loop until this condition is true.
13:45As long as i is less than or equal to 10, it's going to continue running this block of code, and increment it-- this is our incrementer here-- and increment it by one every single time. So this loop is going to run once. This value is going to become two. It's going to evaluate the condition. Is two less than 10? No, run it again. OK, it's going to run it again in increments of three. Same thing-- less than three? Nope, it's going to keep going until it's 10. And then it's going to run it and exit the loop. So let's try this out. We'll execute this. It's going to run all the way up to 10.
14:15Once it hits 10, it's going to exit it out. So for is good for when you want to run something a specific number of times. So for-each looping through collections, do-while looping until a condition is met, for looping a specific number of times. Let's move on to error handling. So error handling is how we're going to trap for errors here in our code. And generally what you'll do is you have a block of code that could potentially cause and error, especially when you're dealing with a network or dealing with files and directories. If something bad were to happen that's unexpected, we can gracefully recover from that error, try to do something about it before trying more code.
14:47Now, I just want to mention these here. We've got our errorVariable and errorAction common parameters. Common parameters are those parameters that are common to every single commandlet out there, so these are on every commandlet. And what we can do is use the errorVariable common parameter to store that error inside of a variable, and then maybe do something with that variable down the road. Or we have an errorAction, which we can say, this is what we want to happen, or how do we want to continue on an error were to occur. Continue means it'll still throw the error, but it'll just continue executing our code. Stop, on the other hand, would stop. It'll immediately halt execution of our script.
15:21And that is going to be useful when we get into try-catch-finally. This is really how we're going to handle errors here in PowerShell. With the try-catch-finally block, as we call this. And what we're going to do is wrap potentially error prone code inside of a try-block, meaning try this code. And if that code were to fail and we have an errorAction of stop, it's going to stop immediately right here and jump down to the first catch block. And what we can do now is we can trap for specific errors, like we're doing here. We're saying run this block of code, if that error that was thrown is of this type.
15:57So it's going to analyze the exception type on that error . And if it's an item-not-found exception, which we will get from this because this file doesn't exist, by the way, then it's going to run this block of code. So we can trap for specific errors in our catch blocks and then maybe do something about it. Say, hey, user that file doesn't exist. Go create it.Or maybe, if we're totally in control of this process and that file doesn't exist, we would create it. And then we could continue on with our code. Or we can catch generic errors. If we don't know the kind of error that's going to be thrown, then we could just run a catch block and then give them a nice message; sorry, couldn't complete the process.
16:28Please try again-- that kind of thing. And then you're finally block is going to run no matter what, great area here for clean up, destroying those database connections or releasing things back to the file system, closing files, that kind of thing. So let's run this block of code. What's going to happen? What do you think is going to happen here? Is this first line going to run starting some code? Yep, sure is. Is this line going to run? Yes, but it's going to throw an error. And what happens when it throws an error? It's going to stop. Does that mean this line is going to run? No, we should never see this line of code because this is going to jump here to our first catch, and you can have many catches inside of here.
17:00If you want to catch for many different kinds of exceptions, you can certainly do that. But it's going to run this one, and this will be the type of error that is thrown. So that's why then it should run this code. This will not run because we already caught it. And then our finally block will always run. So let's go ahead and try this out here. Let's run this and see what we get. So it's just showing us our block of code in here, and here's what happened. Starting some code, check the path to your file, and have a nice day. So it started some code. An error occurred, and it was caught and sent to the first exception.
17:32And it matched the exception type, so it said, hey, check the path to your file, and then the finally ran. So that's error handling. Definitely wrap try-catches around code that could potentially cause an error. The last thing we're going to look at here is functions, and functions are awesome. This is what allows us to get a little bit of code reuse inside of our scripts. So especially if we're calling the same block of code over and over, why duplicate that code? Why not put it into a function that we can use? A good thing to do is to create a utility script with all your functions in it. You can put that in your profile script, and that way every time you launch the console, you have these functions available to you, and you can just call them whenever you need to.
18:08So here's an example of a very simple function called get-computerInfo. You would use the function keyword, give it a name. We're going to specify a parameter block as well because you can accept parameters in functions. And we're going to accept an array of computer names. Then we're going to specify two commands here-- get-service , where the status is running, and get-process, where the CPU is greater than one. And we're going to pass in from the computer name parameter to the computer name parameter here on these invoke commands. So we're going to highlight all this and create the function. Now that we have the function created, it's in memory, and now we can run that function, call all those commands by using the name get-computerInfo, the name of the function, and we'll pass in as the parameter here a couple of servers.
18:47So let's hit execute, see what happens. There it is. Both of those servers-- there it is. It's still running across all those servers. But there it is. Just ran that block of code by the name that we have it when we defined that function-- very cool. Here's a little more of an advanced function here. This one, and this is useful, and this is one I use all the time, is called Send Gmail Message. So here's a function I threw together that will actually send a message through Gmail, so a little more involved with our parameter declaration because we're specifying that we want this first parameter to be mandatory.
19:21So we can set up a parameter attribute up her, specify the property mandatory equals true. That will make the recipient parameter mandatory. That's how you can create mandatory parameters. Also are from parameter here has a default on it, so that means we don't need to supply it. If we do, it'll override it. If we don't, it'll pick up the default here in the from. Then we have a subject and a body. These are optional parameters because we didn't specify any sort of parameter attribute above them. But that's it. So we're accepting all these different kinds of parameters. And now here's a really cool technique called splatting. This is great. Because rather than type out all of the individual parameters, and especially when you do stuff like this, when you start specifying parameters, and then we use the tilde be there to make it more readable instead of just one long line.
20:02It gets pretty ugly with all these still tildes, right? Well, we can get away from that entirely by using splatting, a really, really cool little feature that allows us to just wrap all the parameters, just as long as we match their names-- just use their names in here-- inside of kind of like a hash table here, where we have an ampersand. Then we have an open close bracket. Then we specify all the parameters and their values within here. Put that inside of a variable and pass that variable using at and then the name of the variable to your commandlet. It will match up everything inside of the hash table here to all the parameters inside of your commandlet.
20:35Again, that's known as splatting, and that's just an awesome technique. Definitely use that because it makes code much more readable. So this is a very simple little function that does a lot. Now, the only thing with Gmail, it has to be sent on port 587, have to have SSL enabled here, and then we need credentials. So this is actually going to be an interactive function because it's going to prompt the user for their credentials. But let's go ahead and create this function. All right, good, it's created. And then we can call it Send Gmail Message. Here's a recipient-- I'll send it to my Nugget Lab account-- subject, and here's a body.
21:08Let's go ahead and see if this works. Now, it's going to prompt me for my credentials, which is cool. I can do that. And as long as we don't get any errors back, that should have worked. All right, we can verify that. Let me bring up the browser here. Wow, that was quick. There it is, done. There it is-- test from function. Hello, from PowerShell 4 Foundation. So we just sent a Gmail. We sent an email through Gmail, using a function. All right, let's bring this all together with a cool little script called get-serverStatus.
21:38So this going to email a machine status report. It's going to generate an HTML email with the machine status, being online and offline and up time. So we've got a couple of parameters in here. One, it's going to be an array of computers. And the other's going to be a switch called offline only. So here's how you build a switch parameter. Just give it the type here of switch. So what we're seeing here with this is it's only going to send the email if they're unresponsive, if they're offline. We've got two functions in here, and then we've got a body that's going to generate some HTML, and then send the email using the function we just created.
22:11So let's go through this line by line here. Start here with our first function. This is called get-computerUptime. And what this is going to do is accept a computer name parameter which will flow in from our upper script here when we call this function. So we're first going run get-W on my object to get the Win32 operating system. And then we're going to use the convert-to-date-time method that is on the get-wmiObject and pass in the property last boot up time. So that's going to give us the last time this machine was booted up. And to get the up time, we're just going to subtract that from the current date and time, and that'll give us how long this computer has been up and running-- pretty cool.
22:42And then we're going to use the static method here, called format-on-the-string object, or the string type, I should say. And we're going to pass in a big string, and this is how you can do formatting here. This is really, really cool formatting. So we're saying this is the first one, second one, third one, fourth one. This is going to map here to one, two, three, four. That's how you map the values into this string. That's all it is, so first, second, third, fourth, first, second, third, fourth. So that's how we're going to get days, hours, minutes, and seconds.
23:13And this is the format string we're going to use, so zero, zero is just saying format this with two places in the number. That's it. So this is actually just going to return that value as a string. Our next one here is our send Gmail message that we just looked at, same exact thing. The big difference, though, what I want to show you is right now this is interactive. We can actually make this totally automated. We can use that kind of a cool technique here that will get the credential, save it to an XML file on the local machine. It'll hash it out and store it securely, and we can read that file in any time we want to reuse that credential.
23:49In fact, let's just improve this function right now. This is super useful real world stuff. In fact, I had a buddy from CBT Nuggets, one of our sys admins call me up last week. Kurt, shout out to you, buddy. And he said, hey, Garth, I've got this PowerShell script. It needs to prompt for credentials. How do I get rid of that prompt and automate this? That interactive thing just won't work for this script. And I'm like, hey, you came to the right place, buddy. Let me show. And here's how it works. We'll do a cred, get-credential. So we're going to prompt ourselves right now. And then we're going to pipe that to export CLI XML.
24:21Let's just put this in a file on our local machine here called, how about, pass.dat. There we go. And now let's call this. Put my stuff in here. This is the only time I'll need to do this. And there we go. Now, we should have that on the file system. Check this out. Let's go in our C drive. There it is-- pass.dat. Let's open this up with Notepad, and there it is. There's our credential object. Notice, the password? Yeah, that's right; it's hashed. Not only is it hashed and secure, but it's hashed on this machine. It's tied to this machine.
24:53So if we were to move this file, or somebody were to get a hold of it and move it to another machine and try to use it, wouldn't work. It's tied to this machine-- Awesome stuff. So now that we did that, we can get rid of this. And now right here, we can just do an import CLI XML. There we go. that's it. Now we went from an interactive script to one that we can totally automate-- very cool. All right, so those are functions. We've got those both inside of our script ready to go. Now the next thing we're going to do is we're going to create a little for-each loop here. And the results of this for-each loop are going to be our own custom object with the computer, which is going to contain the name of the computer, if it's online or not.
25:31We're going to do that running our test connection, which is just going to return true or false because we're using the quiet parameter here against the computer that's currently in the loop. So if we pass in 10 computers, this is going to create a PSCustomObject for each computer that was passed in, and each object will have these three properties-- name of the computer, whether it's online, true or false, and then the uptime, which we'll call our function of above, pass in the computer, give us the up time for that computer. All of that will get stuffed. The results, meaning we'll have however many computers were passed in, that number of custom objects stored, inside of this variable.
26:02Then we're going to create some HTML here. Now this is kind of interesting. See this right here-- the beginning and end here surrounded with an ampersand? This is known as a here-string. This will allow us to create a big block of character, of text, without having to terminate it and do all kinds of crazy stuff with multiline entry. So this is great when you have a big block of text or whenever that you want to store. So that's what we're going to; we're going to store our HTML header in here, which contains our CSS, our Cascading Style Sheet there. There we're going to generate some HTML. Before we do that, we need to use an if-statement to see if that offline only parameter is passed in.
26:35Because if it was passed in, we're going to put a little where condition in here that says, we only want to work with objects that are offline. Hence the word object online equals false. And I did this just for readability. There's a much better way to do this because of all the duplicated code we have in here. But for readability purposes, a nice simple if-statement to say, if that online only, offline only flag was piped in, then we're only to work with computers that are not responding. Otherwise, if it wasn't passed in, then we're going to get all the machines that the user passed in.
27:06So what that'll do is generate some HTML here using convert to HTML. We'll pass our header in. We'll pass our pre-content, which will happen first, then our post-content, which will happen last. pre-content's just going to say server status report. Then our post-content's going be generated and the date that it was generated, with our header being our CSS. And then everything else is going to be the results because that's what we're piping over to our HTML commandlet there. And finally, we're going to say, if the results that count is greater than zero-- we've got to have results.
27:37Otherwise, why send an email? Then we'll use our send Gmail function to send our server status report via email. So that's our script. Let's save it. So let's execute it. Let's fire up a shell here, and let's just check our execution policy real quick just to make sure. OK, I did. I removed it from all sign back to remote sign-- good deal. So we're good. We'll be able to execute this. Then we'll use our call or indication operator. There it is. And since this script is sitting on a remote file share here, we need to do that. FS Nugget PS V4. This is 18. Scripting to, and the name of the script is get-serverStatus.ps1.
28:12Now we want to pass in some parameters here, ready? What parameter is that? Uh-oh, did I-- yep, computer name. I was going to say, it's not auto-completing. I didn't type the path in. But I did, because there it is, computer name. What do we want pass in? Let's test out all our computers here-- DCNugget, AppNugget , and FSNugget, all our servers. Hit Enter, and it's going to run, and it's done. How do we know that that did anything? Maybe we should add some output or some logging to our script. definitely easy to do, but we'll keep it simple here. Well, we can check because we can go to my inbox here and see.
28:44We've got an email. Let's see what we've got. Check it out. Now, unfortunately, Gmail is our email client here, and it's not a fan of HTML emails. You could do it. It's still even trickier. There's a lot of gotchas. But if you wrap your CSS to an inline CSS, it can work. But even that's iffy. So let's do this. Let me just copy our code here. And let's fire up Notepad and paste it in here. We'll save this as server-report.html right on the desktop.
29:16And let's see what we've got. Hey, there's what it looks like, cool. So all of our computers are online, which is true. And here is their up time, which is accurate because we just rebooted FS Nugget in a previous Nugget not long ago, very cool. So this would be a good script to turn into something like this. Instead of emailing this, we could maybe generate a report for each machine, put that in an IS server somewhere. And then any time we need to check the status of that machine, we could just hit that machine's specific page. I'll save that one for a future Nugget or maybe our real world course, or maybe it'd be good project for you to try out on your own.
29:49Well, let's finish this Nugget up with a look at your challenges. Challenge number one, write a function that accepts a computer name parameter and retrieves stops services with the startup type of automatic for the machines passed in and call the function Pretty straightforward here-- it's just going to be a one liner. Write a one liner to get-services that have a status of stop and start a type of automatic. But we're going to wrap a function around this and then accept a parameter. So really just kind of getting you familiar with writing your own function, Then challenge number two here's going to build on this. Write a script that utilizes the previous function and stores the results in a variable.
30:22Loop through the services variable and attempt to start them, utilize error handling to catch errors that may occur. So store the results of that function inside of a variable, then loop through it one a time, which is going to be what kind of a loop? Because we're looping through a collection, it's going to be a for-each loop. Loop through it and try to start each one of those services inside of that loop and also wrap that with a try catch. So that way, if any errors occur, you can decide what to do. Do you want to continue trying to start other services? Do you want it to totally stop executing? What do you want to do then? And of big one here, challenge number three-- write a script that generates an HTML file-- this sounds familiar-- containing information, services, and event logs, accept parameters for the computers, type of event log and status of services.
31:04This is a fun one. So the whole idea here is that you're going to have a file any time you execute this, one for each machine. And it's also, as the name implies here, the naming convention-- day dash month dash year underscore machine dot HTML. So you're going to use WMI or CM or both to capture machine information-- get things like the operating system, the number of disks or what disks are on a system. That kind of stuff-- stuff we've worked with. Then, step number two, you're going to use get-service to capture service information, pass a parameter to the status value so that way whoever's running the script can say, hey, I want stop services.
31:36No, maybe I won't run any services, or maybe I want both. Then, step number three, use get-eventLog to capture event logs. Again, pass a parameter here for the log type. So if they want to retrieve the system or the application, or maybe they want to retrieve them all, you can put some logic in there to say, if they don't pass anything in. we're going to give them all of the event logs. And then finally, you're going to use Convert HTML to generate that HTML file, and you can use methods of get-date to name the file here. So use get date dot day dot month dot year, and then you can use your computer name to name the file, and output that wherever you want-- maybe in the temp directory or wherever.
32:08But there you go. There's your challenges for this Nugget. As always, good luck, and you can find the solutions underneath these regions. All these files are, again, downloadable on the right-hand side of the course page. In this CBT Nugget, we covered the scripting essentials. We took a big look at all the core language constructs there. We took a look at variables. We saw how to work with things like control of flow statements or ifs and your switches. We looked all the different looping constructs out there, talked about error handling, and saw how to write some functions. And at the end here, we pulled it all together in a fun little script to monitor the server status of all the servers on our network.
32:41I hope has been informative for you, and I'd like to thank you for viewing.
Scripting - The Real World
0:00Scripting-- The. Real world. In this Nugget, we're going to have some fun. We're going to look at two scripts, one simple one to import users in Active Directory and one that's a little more complex that will monitor all the servers in our network. So the goal of this Nugget is number one, to have fun. Number two, to learn how to decipher other people's scripts and read code that isn't necessarily your own. And number three, I'm going to show you how to debug scripts. So let's jump into the Virtual Nugget Lab and get to it. Welcome back to the Virtual Nugget Lab. Let's jump over to our Nugget Lab files here. And what I want to do first is just give you a little context around what we're going to do.
0:33Script number one, we are going to import users into Active Directory. So I've got a bunch of users here. We've got a CSV file containing a bunch of users. And you may have recognized some of these users. That's right, we're going to import some Star Wars characters. Good times. So how's it going to work is let's flip over to our domain controller here. And inside of Active Directory Users and Computers, we've got a couple of OUs. We've got a Light Side OU and we've got a Dark Side OU. So the whole idea here is to import Dark Side users into here. We'll also create a group on the fly and put our admins into a group.
1:04And we'll do the same thing over here for the Light Side. So back over to our client machine here. This is what our CSV file looks like. You can see we've got fields such as our given name, surname, initials name. Their Sam account, the department they belong in, the forceID-- which is our employee ID so know that that's not going to line up with any field inside of Active Directory. The side that they're a part of, Light or Dark. The role. If they're an admin or a user. This can help us determine what group they go into. And then if their account is enabled. And we'll give them a default password here. So this is our CSV file.
1:36Let's jump into PowerShell. And here is the script that we're going to look at. So I tried to keep this one as simple as possible. This could certainly be optimized. There's a lot of things we could do to make this a lot better. But just to get us a simple script to work with here to see how to import Active Directory Users and create groups and add users to groups, this will definitely do for round one. We'll look at a more complex script here coming up shortly. So the first thing we're going to do here is just define a parameter block. We're just going to accept one parameter, the CSV path. So when we call the script, we're just going to pass in the path to wherever that CSV may be. Then we're going to create some groups. We're going to create a Light Side admin group and a Dark Side admin group.
2:08So we can throw the admins for those users into these groups. So the first thing we're going to do is to check. We need to make sure that these groups don't exist. Because we don't want to create them if they already exist. We'll get an error if that's the case. So we'll create a variable here called Light Side Group. And we're just trying to get AD group where the object name is the same name that we're going to use to create the group with. If it doesn't exist-- and we can check that by comparing it to the null value, meaning this object doesn't contain anything-- then we will run the new AD group commandlet and pass in everything we need to make that group.
2:40So the name, the Sam account, name the category, the scope. And then we've got some other ones here, such as the path. We want it to go inside of the Light Side organizational unit that we have created there in Active Directory. And if that all successful, if we create it, then it'll output to the screen Light Side Group created. So that's step one. Create the Light Side Group. Then we do the same exact thing for Dark Side Group. You know, we could actually just test all this out right now. Just this block right here. Let's highlight that block of code. Let's run the selection and see what happens. Cool. Light Side Group created. Dark Side Group created. We could verify that by heading over to-- here we go-- our domain controller here.
3:14And let's just refresh. Right there. Hey, look at that. We've got our Light Side admins. And if we head up the Dark Side here, we can refresh in here. And we've got our Dark Side admins. And here's the data. We included those Imperial jerks. And there's our members. We have no members in it yet. So once we add those users in, we will add the members that have the admin role in their record in that CSV file to this group. Now if we ran that again, we should get nothing. Yeah, nothing happens, right? Because it's already created. So it hit this IF statement, and it wasn't null because this returned a value.
3:48In fact, we can just test this out as well. And we see that's going to return something. So that object would not be null, meaning this IF statement would fail. And it would just skip the block entirely. So that's why it would only ever get created once. Now the next block here is creating our users. So we're going to run an import CSV against that CSV path and pipe all of those records into the for each object command line. Meaning this block of code right here, all of this, is going to run once for each record inside that CSV file.
4:19So the first thing we're going to do is set up a little splatting here. That way, it'll make it very easy to pass all these parameters into the new AD user commandlet. So you've just got to make sure that these all line up with the parameter names inside of that commandlet. So this is a good thing to do just because it makes it more readable than a big long command line. But also makes it easy to do things like this. Right here, employee ID. I'm going to map that force ID. And we saw another way to do this using custom properties in our Pipeline Two Nugget when we revisited the pipeline. And so this is just another way to do that using splatting.
4:51Same result, though. So we're just passing all of those objects, those properties of those objects, into what will be the parameters to new AD user. And also notice this right here. This is interesting. So we're setting up the path. So we make sure that those users go into the right side. And we're using what's called the sub-expression inside of here. Makes it a lot more readable and easier than concatenating strings together, especially when you need to stuff something in the middle of a string like we're doing here. So this will resolve to either a Light or Dark, and that'll put them in the proper organizational unit depending on the side of the property of that record object.
5:25So cool. And another thing we're doing here, this is another interesting thing, is we have the value true. Let me open up our CSV again. See this value here? It's true. But it's actually a string coming in. So we need to convert that string to a Boolean, and that's why we're prefixing this property with Boolean. That will convert that. So you'll see yourself doing that quite a bit when you need to convert to and from data types. The only other thing that's interesting here is-- oh yeah. Let's see. The account password. We need to convert this, because it's plain text, to a secure string to pass it in here. And we're also going to force the user to change the password at log in.
5:58So we wrap this new AD user inside a try catch block. Good thing to do because if any data was invalid or something that Active Directory didn't like, it would cause an error. And if we didn't wrap this in a try catch block, it would bomb the whole process. It wouldn't continue on because we have the error action stop here. So that's why we're going the try catch around this. And a real good thing to do inside of the catch here would be to set up some logging. So we could output anything that did happen, any errors that occurred, we could upload it to a log. And then maybe do some manual intervention for those users that didn't make it in or fix their records and rerun the import kind of thing.
6:30Now back up here. If the import of that user was successful, then we're going to check the role. If they're in the admin role, then we're going to run the Add AD group member and add this, this member here based on their same account name, to the appropriate group. And we're using the Sam account name. There's a bunch of ways that you can identify a group here, one of them being the Sam account name. And this is the Sam account name of the group that we defined above. So it's either going to be Dark Side admins or Light Side admins. And we're doing the same thing we did here in organizational unit two to build this string using a sub-expression.
7:01And when it's all said, it's just going to say Import Complete. Now, there are some things missing from the script that I'll challenge you to add on your own. Number one, what if we ran this multiple times? And that user already existed. It would probably throw an error, which wouldn't be a big deal because we have a try catch around here. But one thing you could do is run a query against Active Directory to see if that user already exists. And if it does, maybe run a set rather than an add. So that way if anything changes in that spreadsheet over time, you can just rerun it and it'll just update those specific properties in Active Directory. Another good one would be to set up a profile path.
7:32So if you have users' profiles on network share somewhere, you could easily set that up and tie that to their Active Directory account. There's a lot of things you could do with this script to expand it. But just a couple of things to think about there. So I think we're ready to rock here with this script. Let's flip over to commands.ps1, and let's give this script a whirl. And it's executing, creating groups, even though it skipped the group creation. Then created Active Directory Users. Import Complete. If we head over to our domain controller and refresh our Dark Side organizational unit, check it out. There's all of our Dark Side employees.
8:02And if we head into our group there, Dark Side Admins, head into Members, there there. We have Vader and Emperor. Because if we head back to our CSV file here, we'll see we have the admin flag turned on here for Skywalker and Princess Leia, as well as Vader and the Emperor. Everybody else there is a user. So back to our domain controller. If we head down to the Light Side, let's do a refresh here just to make sure everybody made it. They did. Head into our Admin group. Check out our Members. And there they are. Very cool. So there you go. Just a simple little script just to show how easy it is to import users from a CSV into Active Directory.
8:35Moving on here, let's take a look at the next script. Now, this next script is really cool. And it's not one that I wrote. This is actually in the gallery over on TechNet. And this is a very popular script that will monitor all the servers in your network. In fact, this individual here, shout out to Ben Wilkinson who made this. This is just a fantastic script. It's a good script for learning. It's a good script to use in production. It's just a great script all around. And the reason I liked it and I wanted to use it in this Nugget is because he uses a lot of great techniques in scripting, a couple of them that I want to point out and show you.
9:07And this is just a great script that you can use in your environment. It's tried, true. It's tested. And this is actually the old version I'm going to walk you through. There's a new version out with a lot more bells and whistles. It's a little more complex. I wanted to use the first version here because it's a little easier to walk through and understand, especially for beginners here in PowerShell. So this has been used across a few hundred servers and it does work very well. I would totally agree with them. I've used this quite a bit myself. And it's just a fantastic script. So I've downloaded this and I've got it here in our network. Let's go ahead and open it up here.
9:37It's in the Virtual Nugget Lab here for this Nugget in the directory called Start, Monitor, Online. So the goal of the script is to essentially just run in a big loop this script all day long. And it's going to run and it's going to monitor all the servers in your network just by doing one ping. It's going to send a ping. And if that ping doesn't respond, then it's going to do some more pings. And if those pings don't respond, then it's going to send an email. But what's really cool about this script is number one, he uses a do while loop. This whole script just runs on a do while loop. So another reason I wanted to show you this, because it's a great implementation of how to use a do while.
10:12So rather than create a script and put it on a schedule to run every five minutes or whatever, you can use a script like this, have it fire up on startup, and just let it run all day long. That's the design that I absolutely love here. And he's got another great technique that he uses, it that he initializes all the variables inside of the loop, meaning we can do things while the script is running. And every cycle, it'll pick up those changes. So let's start at the top here. Now, all of these variables outside of the loop, they're going to get initialized.
10:45They're declared outside. So the scope is we can see them throughout the whole script. But they're initialized once, when the script starts. And that's it. Everything then inside of the loop is again refreshed on each cycle. But the first variable we have here is outage hosts. So this is how we're going to keep track of the hosts that are not responding. We've got an email time out. This is the time you want email notifications resent for hosts that are down. So if we have a host that's down, we don't want to keep spamming ourselves with email every time the script cycles. And right now, the script is set to cycle every 45 seconds.
11:18So obviously we can tune these all to our environment. In fact, I did make some changes to this script so it works with Gmail and a few other little things I'll point out. But that's the next variable here, is the sleep time out. Meaning after the loop finishes, how long do we want to wait before we ping all the machines in our network again? And the default here that he has it set up at is 45. We also have the max outage count. This is the maximum number of hosts that can be down before the script is completely aborted. So if we have a network problem, if we have many hosts that go down, we don't want this to keep running and spamming emails all over the place. So we have the maximum host set at 10.
11:50And so if we only have three servers in our network, I'm going to put this down to three. Three servers. So if all three servers are down, we're going to abort this script entirely because obviously we've got bigger problems here. Then we've got our notification to and from. I set this up to go to my Nugget lab account from the admin Nugget lab account. And we've got our SMTP server settings as well here. Notice we're using our credentials that we stored in a previous Nugget here to verify or validate or authenticate, I should say, with Gmail to send the email. So those are our global variables here, our script level variables.
12:23Then we start the big old loop right here. We're going to set up a variable. This is going to get refreshed every time the loop cycles through. So this is going to store the list of available hosts, ones that are responding and the ones that are not responding. Then the first thing that's going to happen is we're going to write the data out to the screen. So this is the script that we could leave running on a monitor somewhere so we could always see it fire off. Or we could put this, again, on a scheduled job and just let it do its thing under the hood and email whenever things are down. Now, the next thing it's going to do is it's going to run a get content. So we need a file out there with a list of servers.
12:55This is our control file with all of the servers in it. So these are the servers that you want to test for connectivity in your network. So you'll have a big list of all your servers that you want to test. And a nice little thing you put in here is if you put a hash here or a comment sign in front of any server-- maybe you're doing maintenance and you don't want that server checked for whatever reason-- if you put this hash sign in front of it, it'll skip it. So this is only going to grab all the servers where the match does not equal this. So it just runs to where it'll only pull up those servers where it doesn't have a hash inside of it.
13:29So that's what this little block here is all about. Then it's going to loop through all those objects. So all those servers. It's going to do this one server at a time. The first thing it's going to do is test a connection. Just do one ping. One ping, we've got error action to silently continue so it keeps going without worrying about any errors. This is either going to return true or false. So if it's true, meaning the servers are online, great. Then it's just going to output it to the screen that the servers are online. And it's going to store that server inside of an array here, inside of our available variable that we have declared above here. So that's just going to put all the servers that are available in there. But more importantly, it's just going to write it out to the screen that yeah, the host is good to go.
14:02And that's it. It'll then go to the bottom of the loop. Now, if for whatever reason that server isn't online or not responding, then it's going to go to this else here. It's going to write, OK, we've got an unavailable host here. And so it's going to do one more test just to make sure. Maybe the network was slow. Maybe that just didn't respond in time for whatever. So it's going to run one more test connection to ping it four times. And we know if we don't get anything back after four pings, we know something is definitely wrong. So we're going to say this host is officially. We'll write unavailable host to the screen.
14:34Change the background color to red, the foreground color to white so we can actually see it in the console there. And then we'll pop that server name into the not available array. Now is where the fun begins. And this is the real guts of the loop right here. So we're going to look at this outage host variable. And we're gong to say does this not equal null, meaning we've already initialized a variable. We've already had a host that was down that was in here at some point. Then it's going to run this big block code we'll look at here shortly. But if we haven't, meaning this is the first time anything's gone down since we've started the script, it's going to run this little else block, which is going to initialize the variable, add the server, add the date that that server went down, and send the email.
15:09Now if that's already happened at some point, then the next cycle in here is going to run this block of code. Because outage host will no longer be null. It'll not equal null, which means it's going to start this block of code. And it's going to run a contains key against this collection. And it's going to look for the server name. That's what this always represents, the current object that we're working with in the loop. And that's because we ran a for each object. So it's just sending these objects in one at a time. But it's going to look for that key inside of outage host. And if it doesn't exist, it's the first time this specific server went down.
15:42So it's going to add this server into the host. Again, date stamp it next to it. And then it's going to send the email. Now if this server was already in the list, then it's going to run this else block here. And this little else block is going to say, you know what? This server is already in the list. And what it's going to do is do a get date minus whatever the date of that server was inside of that list and grab the total minutes of the result of that. And if that total minutes is greater than our email timeout of 30 seconds, then it's going to remove it from the list.
16:13So that way, it'll come back in the next cycle. It'll get a next email, and it'll go through this again. But if it was underneath the email time out, it's just going to skip all of this and go through again and again and again until it hits this block of code and it removes it. So that's all this code here does. The else just initialize the variable. It's the first time anything's been down. And it adds it to the list and sends the email for that host. And then on subsequent runs here, cycles, it's just going to check to see if that server is in there. If it is already in there, then it's going to check to see if that email timeout has passed and do nothing.
16:44If it has passed, then it's going to remove it from the list so it'll get back in on the next run. So if it's not in there, that's when it gets added to the list and it sends an email. And that's what this big block of code is all about. All right, make sense? If not, I'll show you an easy way to make it make sense. And that is with debugging. Debugging scripts is the coolest thing ever because it allows us to pause scripts during execution, analyze variables, change variables. We can do so much during debugging. So hang on for that. I'll show you that, because it's extremely valuable in writing scripts or even trying to learn somebody else's scripts because you can walk through it line by line to see this stuff happen.
17:16So after all that logic is run-- and we're still in the loop here-- it's going to output just a bunch of information to the screen here. The available count, the not available count, the not available host by putting that outage hosts variable to the screen. And then it's going to say, hey, we're going to take a nap here for whatever your sleep time out is, which, again, the default is 45 seconds. So it'll say sleeping for 45 seconds. That's literally what it's going to do. The loop is going to take a little nap for 45 seconds. And when it wakes up, it's going to do one more comparison here. It's going to say the outage hosts dot count. So if we have three hosts down, and that's greater than our max outage count-- which we have set at three.
17:48In fact, we should probably change this for us. We'll put an equal there. If our count is greater than or equal to the max outage count, then it's going to set exit equal to true. This is our way out of the loop here. And it's going to generate an email here just to let us know, hey, something really wrong is going on. So I'm going to totally abort the script for now until you figure that out so we don't continually spam you with emails. And the last thing we're going to do is our while. This is our condition. So as long as exit does not equal true, it's going to keep going. It's going to keep cycling through these loops.
18:18But if for whatever reason the only way out of the script is for us to manually stop it or if our hosts are greater than our max outage counter. In our case now, greater than or equal to our max outage count. So that's the whole script. Let's go up here and modify this a little bit. Let's actually change this to two so we can bring down two servers and see what it looks like. And then our sleep time out. Let's push this down to about 10 seconds here. And everything else looks pretty good. Let's save it. Now let's flip over to our commands file here. And let's go ahead and let's just execute our monitor. Let's start it up. Let's see what happens.
18:49And look at that. So here it goes. Here's what happens. It looped three times through each one of our servers that we have defined inside of our list-- which, by the way, I have up on our own file server here. Here it is, Files. So here's our server list. We just have all three of our servers in here. So that's our control file. And what I really love about this, and why he initializes and reads this file during every single cycle is we could come here and change this. Maybe we're taking our file server down. We could do that. We could save it. And then it'll skip that for as long as that is there. We could add servers on the fly. We could remove servers on the fly.
19:20So that's what's really neat about this script, is we can change things on the fly. And every cycle, it'll pick up those changes. So look at that. It's still going. It's still going. Everything's great. Now what I'm going to do is I'm just going to fire this up. Let's stop our computer here. Let's stop-- how about App Nugget. Let's bring down App Nugget. And we got to force it here, just in case users are logged in. It won't let us do that. So we'll force that. Now it's down. And now let's see what happens here with our script. Let's see if it picks that up. And I should also get an email here as soon as that happens here. Let's do this.
19:50There we go. So I've got new emails over here. Oh, unavailable host. So that's the first ping. The first ping, it didn't. So it's trying four more pings now. And once those four pings fail, we should get an email. And it should output that host to the screen and the time it went out and all that good stuff that we saw there at the end of that loop. So there it is. Unavailable host App Nugget. And now it's sleeping for 10 more seconds. And there it is. So there is the outage host variable outputted to the screen right there. See, it just has two fields inside of there. It's got the name of the server and the time that it went down.
20:20And that's what it uses for its comparison. And I just saw an email come through over here too. There it is. App Nugget has not responded for five pings. And there is the time date that it has not responded. So now the next time it's going through here, we're not going to get another email because we have this sleep timeout set out at 30 seconds. So it's going to see that. And there it is. So it didn't see it again. But because we were under that time out, it just ignored removing it from the list. So it's just going to stay inside of this list and we're not going to get any more emails until that time out happens. Al right, let me stop this.
20:52Now let me show you something incredibly useful here. How to debug a script. So let's say we want to walk through this line by line. We want to see things happen. We want to change variables on the fly, read variables on the fly. This is just a great way to learn what scripts are doing and to watch it execute. So we're going to add a break point. Now, we could do this at the very top and just watch it from the beginning and step through it. That's certainly one thing we could do here. But what I want to do here is let's say we're having a tough time understanding what the heck this part does. So what we're going to do is set a break point right here.
21:24Toggle break point. You could also use F9 on your keyboard here. Definitely get used to all of these. Your favorite ones are going to be F11 to walk through line by line and F9 to set break points. And also to stop the debugger here, Shift-F5, and to start it up, F5. But let's do this. We got a break point here. Let's also set one up here. How about right about here. Yeah, this looks good. So toggle break point. Perfect. So what we should see here is this will be the first one that hits. Simply because App Nugget's down. We're going to leave App Nugget down.
21:55It's totally shut down right now. So this will be the first thing that happens. So what I'm going to do is I'm going to start this up. Let's fire it up. What's going to happen is when it's-- and this is also when I'm debugging, I like to go back to split screen mode here because we can do both. We can work with the script as well as do some debugging down here and view variables and things. So that's going. It still hasn't hit our break point. And it'll turn yellow when it does. And we should see this is the first thing that it's going to hit, because App Nugget's down. And look at that. So unavailable host App Nugget. So the last thing that happened here was right here. Unavailable host App Nugget.
22:25It outputted that with a background color of red, foreground color of white. And then it ran out little IF statement here and then it went down into our ELSE, because this is the first time that it hit this. Because outage hosts was not equal to null. It was null. So that's why it jumped down here to our ELSE. And now it's going to write out the next thing when I hit F9 on a keyboard-- or excuse me, F11, which is the same thing here as stepping into, meaning it's just going to execute the next line of code. This line of code. Watch this. F11. See that? Adding App Nugget to outage hosts.
22:57I'm going to hit it. Now, if we were to take a peek here at outage hosts, it should be empty. Outage hosts empty. But if we hit F11 again, now we've initialized that variable. Let's do that again. Let's take a peek at outage hosts. And there it is. So this line right here added App Nugget along with the date that it was added in here. And that's going to set us up for when we get back into this and cycle again, then it's going to use that date right here, the total minutes to see if it's passed our email time out. So I'm going to keep hitting F11 here. And it's going to create the body of the email.
23:27And let's say, oh, we want to see what that body of the email looks like. Make sure everything looks OK. Let's do body. And there it is. It's the same exact text we got in our email. So now it's actually going to send the email here. I'll hit F11. I'll take a second. It's authenticating with Google servers, sending the email. And now it's done. So now it's going to cycle through again for the next server. and we're going back up to the top, cycling through, cycling through, testing the connection, so on and so forth. And now it was done. It went through all the servers. And now it is. And the reason that it didn't go through DC Nugget because we set our break point right here.
24:00And DC Nugget was up. It was fine. So it went through. Then it did App Nugget. We were actually in the second cycle by the time it hit our break point for the first time. Cool. So it's going to keep going. I can keep hitting F11 or I can hit F5 to continue on. And now it's going to go until it hits another break point. So it's doing its thing right now. And the next break point it should hit now is right here. Because outage hosts, we know that it's not equal to null anymore. There's something in there. App Nugget's in there. So it's actually sleeping right now for 10 seconds.
24:31And then it's going to go through this. And the next thing it should hit is right here. So we'll give it a second to do that. It's still pinging away there. Oh, you know what it's doing? It's pinging App Nugget again. Yeah, see? So it went through DC Nugget fine again. And then it pinged App Nugget. And now we stopped right here because outage hosts had some data in it. So now it's going to look for the key for App Nugget. Is that key in there? You bet it's going to be in there. So it's going to jump down here and run our little check. This App Nugget, it's already in the list.
25:02So we need to check, is the total minutes here greater than our email time out? And it wasn't. So it didn't remove it from the host, meaning it's not going to spam us with another email. Cool. So that's it. That's debugging. Set break points. Walk through your code line by line. You have full access to the debugger down here, so you can analyze every single variable in here. You can even change them. So if while we're debugging, maybe because we're spending some time in here, we want to expand that time out. We want to expand the sleep time out. So we can come here and do just that. We can expand the sleep time out to say, maybe, 60 seconds.
25:33There we go. Now we've just changed it, and it'll sleep longer when we're debugging. So I just hit Shift-F5 which stops the debugger and stopped the script. You could also do that in the Debug menu. But I'll tell you, learn how to debug. It's an invaluable tool, not only for your own code and your own scripts-- because when things aren't doing what you expect them to do, you can easily figure it out by walking through line by line and analyzing your variables-- but it's especially an incredible learning tool for learning other people's scripts. And let's face it. PowerShell isn't going anywhere. More and more companies are jumping on the PowerShell train.
26:04There's going to be PowerShell scripts everywhere in the future. And chances are good a script is going to land in your lap that you didn't write. You're going to need to figure out what it's doing. And no better way to do it than run that script against a test environment and walk through it line by line to see exactly what it's doing. So I'm not going to give you any challenges for this Nugget. You've probably seen enough code for now. But if you do want to do something, take this startmonitoronline.ps1 script and set it up in your environment. Or set it up in our Virtual Nugget Lab environment and play around with it. It's a truly fun and useful script to get the hang of. In this CBT Nugget, we looked at scripting in the real world.
26:36We took a look at a couple of fun, real world scripts there. One that imported users into Active Directory, and another that monitored all the servers in our network. We also saw how to debug and walk through the code in our scripts. I hope this has been informative for you, and I'd like to thank you for viewing.
Desired State Configuration - Getting Started
0:00Getting started with Desired State Configuration, by far the coolest technology to hit since PowerShell. And the fact that we can utilize it from PowerShell, leveraging our existing PowerShell skills, is just icing on the cake. So it's all about declarative management. And by the end of this Nugget, you're going to say to yourself, where have you been all my life, declarative management? Because it's really cool stuff. And it's really easy to use. So we're used to standing up servers on our own. We get a server up, we go and we install the software on it, we configure it. We do it all manually by hand. But why? Machines know how to install software.
0:31Why do we need to hold their hand and walk them through the process? Wouldn't it be great if we could just describe that state of the machine in a file using PowerShell? And then just send that file over, and let DSC take care of the rest. And not only install it and configure it for us, but ensure that that machine stays in that desired state. That's what DSC is all about. And that's we're going to learn about in this Nugget. So let's get to it. So DSC is a management platform, management being an umbrella term for all the things we do to a machine, installation, configuration, deployment, everything; in PowerShell for declaratively configuring a machine state.
1:04That's the key word here, declaratively. Because once again, machines know the how. They know how to install software. So why do we need to do it for them? Wouldn't it be great if we could just tell them the what, and they do the how? That's what it's all about. And on top of that, ensuring that it stays that way. DSC solves a couple of problems that we've just kind of dealt with, we've accepted it. It's one of those, it-is-what-it-is kind of things. That's where we've been. But DSC changes that entirely. And one of those big challenges was configuration drift. We get a machine up and running.
1:34We get everything exactly the way we want it. We get all the software we want on it, all the services. We get everything configured the way we want it. And then over time things happen. We're fighting fires, or we've got a lot of hands in the cookie jar here, making changes, configuration changes. And over time that machine looks nothing like it did when we set it up. That's known as configuration drift. And that can cause a lot of problems down the road. So that's one of the big problems that DSC solves. Another really big plus here is the separation of state and machine. This is the world that we're heading to, especially with the cloud.
2:07Is machines should just be dumb pieces of hardware. And we should easily be able to take this state, the environment, the software, configuration; everything that's on that machine, and just spin up another machine in that state. Wouldn't that be a dream? Because I remember the old days. Oh, do I remember the old days all too well, where you really cared about your machines. You had, take a web server for instance, you have IAS, you've got .net, you've got ASP. You've got all this other supporting software. And if something were to happen to that web server, if that baby were to go down, that's a project on your hands, spinning up another server and trying to get it to that exact same state.
2:40So separation of state and machine is a dream come true. Because now our environments are portable. Everything that's on that hardware, portable, awesome stuff. And finally, this is enabling a whole new level of management at scale. Need to stand up a farm of SharePoint Servers, SQL servers, web servers? No problem. We can take one configuration, send it over to all those machines in one go. All right. Let's get familiar with DSC at a technical level here. And then we'll jump into the Virtual Nugget Lab, and I'll show you what a pleasure it is to work with. So first before we even dig into all the components, we'll do this as we go along here.
3:13But Microsoft has a phased approach to DSC. And that first phase is the authoring phase. So we are going to author our configurations in PowerShell using PowerShell scripts. And here's an example of a configuration. So this is what we're going to be building in PowerShell, it's simply just a PS1 file, just a PS1 script with some special keywords that describe the state of a machine. So we start everything off here with a configuration keyword, and we give our configuration a name, more on that shortly. Then we have this node parameter down here, which is the computer that we want to apply this configuration to.
3:50And you can hard code computers, so any time you run the script then it will generate a configuration file for that machine. Or you can use parameters. Because it is a script after all. And we can make it dynamic. So that's what we have here. We have a dynamic configuration. Once we build what's known as the MOF file, more on that shortly as well here, it's going to apply to that machine. And then we have what are known as resources. So we have three resources here in this configuration, a file resource. And we're saying here is we want this directory to live on that machine. So when we apply this configuration, it's going to create this scripts directory.
4:24We can also say we want this service, the Windows Update service, to be a running state. And we also want this Windows feature to be installed, to be present here, and also include all sub features. So you'll notice something familiar here. We've been working with commandlets throughout the course. You'll notice that these are properties of those objects that come back from those commandlets. Get child item. We get a file object. Yeah, these are all the properties on that object. The service object, we've got a name, a startup type. We've got a state, yeah, just properties that we can manipulate.
4:54The Windows feature commandlet allows us to install Windows features. We can do that here as well. So that's all these are, these resources-- and there's a list of them I'll show you when we get into the Virtual Nugget Lab-- these are configurable resources. We declare what those resources are, and what they look like. And when we apply this configuration to a machine, it's just going to run through and get it in that state, get all these resources that we define in that specific state. So step one is to create your configuration. Step two then is to call the configuration, pass in any parameters. And it's going to create an MOF file.
5:25And this MOF file is the compiled version. It's what DSC understands. It's what the local configuration manager understands, more on that shortly. So step one is author. Step two is stage. And that's really just a matter of generating the MOF file, or taking that MOF file and putting it somewhere. Putting it somewhere so we can either push it to servers, or we can have servers pull it. There's two deployment models here, push and pull. So we're going to look at the push model here, in this Nugget. And then we'll take a deeper look at both push and pull in another Desired State Nugget called Desired State Configuration, Making it So.
6:02And by the way, that's the last phase here. It's called the make-it-so phase or the execution phase, a little Jean-Luc Picard down there saying, make it so. But that's really the process. We offer these configuration files, which is just us defining the state of the machine. We then compile them by calling them by name, and passing in any parameters. And it will generate an MOF file. In this case, if we passed in three computers, we'd get three MOF files, one for each machine. Then we take those MOF files, and we send them, and start them up with the local configuration manager, which by the way is on every machine.
6:37And we have control. There's a lot of settings we'll get into in the local configuration manager. But that's just simply kind of the controller. It's the one that's going to take these MOF files and apply them. And then another thing we can do is we can set up the LCM here to monitor that machine. And then auto correct, as you'll see is one of the settings. And it will actually take a look at the state of that machine. By default, it's every 30 minutes. And it will say, hey, if this machine is not in the state that this MOF file here, our configuration says it should be in, then it will reapply the configuration to put it back into that state.
7:11How powerful is That Just to illustrate how powerful it is here, let's get a web server up here. Say we've got a web server. We've got IS on it. We've got .net on it. We've got ASP on it. We've got websites underneath IS with some virtual directories down here that contain our website content. And some joker gets on this machine, and tries to ruin our day, deletes our website content directories, deletes those websites, uninstalls IS, .net, ASP; just totally trashes our machine. And then the LCM comes along and says, hey, wait a minute.
7:41This isn't in the desired state. Because it compares that with our configuration, and then it reapplies it. It will take that, reapply it, and get it back to the desired state. And now the joke is on the joker. I know that's an extreme example. But it works all the same. Because that's how awesome DSC is. All right. You're probably ready to see this stuff in action, huh? Me too. Let's jump over to the Virtual Nugget Lab and make it so. All right, let's jump right into the ISE and look at a configuration. So I've got a configuration here called Nuggetlab-Config.ps1.
8:11The name of the configuration is NuggetlabConfig. So that's what we will do we call this. It's just like a function. We're going to put this configuration in memory. We're going to call this just like we want a function. And that's going to generate those MOF files. You'll notice we're also accepting parameters here. So we can pass in a bunch of computer names. And it'll generate an MOF file for each computer. And if we don't pass in one, it's going to just default to the local host. And that's what will get fed in here to the node block. So we've made this dynamic. You could also hard code specific computer names in here. And it'll generate the MOF file then for that machine.
8:42So this is purely, all this stuff here is just for creating the MOF files. When we pass parameters in here, we're just simply defining how we want to create that MOF file, and for what machine we want to create it for. Now inside of the node block is where we define our resources, and the state of those resources. And I'll show you can get a list of all the resources out there, and even how to get all the resources. But we've got the File resource, the Service resource, and the WindowsFeature resource that we're utilizing inside of here. So you declare the resource, and then you give it a name.
9:13And this is the name you'll reference if you set up resources with dependencies. So a lot of these have a DependsOn property that you can use. See that? DependsOn, and that means that resource must exist before this resource. So you can set up dependencies, and set up the order in which they need to get installed or configured. All right. So here's our File resources. And what this is going to do is just pull down the installs directory onto the local machine, and ensure that it stays there. We also have-- we're going to show you that the Windows Update service is running. And then we're going to ensure that this feature, the Windows Server Backup feature, is installed.
9:46So a very simple configuration here, but you kind of get the idea of how this stuff works. Configuration, accept parameters, specify a node, specify your resources, and their properties. And when you're all done, then you just call it just like you would a function, passing in any parameters. And that's going to generate the MOF file. So let's do that. Let's go ahead and run this. We didn't treat it like a function, and run this first. So let's get that configuration created in memory. There we go. And now we can call it. And now when it's done, it'll show us that it made it.
10:19And we passed two computers in there, DCNUGGET and FSNUGGET. So it created two MOF files for that. And we can actually see them. Let's just do a start here in our directory. And it's going to create a directory. See that? So here it is, NuggetlabConfig, if we go inside of here, there it is, DCNUGGET.mof, FSNUGGET.mof. And you can actually look inside of these. Let me show you here. And see that it's going to generate a little comment here for who generated it, when and what, and what machine it was on, and what our target node is. And then here it is. Here's the actual version that the local configuration manager understands is what's it's going to use then to apply this configuration.
10:55We're going to deploy this configuration. We're going to push it over to these machines to the local configuration manager. And it's going to apply it. All right. So that's how to create a very simple configuration, and then generate your MOF files. Let me show you a few other things here. First let me show you all the commandlets here for DSC. So Get-Command with the Noun dsc wildcard, and here they are. So Get-DscResource will give us a list of resources. And we can also see all the configurable properties for that resource that we can use in our configurations. We also have a bunch of DSC configuration commandlets.
11:27So Get will show us the current configuration on a node. We've got Stop, which will stop it; Test, which will test for configuration drift to tell us if the machine is currently not in the desired state; Start, which we'll be using here shortly to send a configuration to push it over to a machine; and Update. And we'll also talk about Get and Set DscLocalConfigurationManager. There's some other ones in here as well, like New-DsccheckSum. We'll be using that when we get into pull deployments. All right. So that's that. Let's take a look at all the resources on the system here. So if we just do a Get-DscResource, here they are.
11:58So check it out. We've got things like file. Hey, and there's the one we just created, NuggetlabConfig, Archive, Environment, Group, Log, Package, Registry, Script for a catch-all here. If none of these resources line up, you can just set up and run a script as a resource. Service, User, windowsFeature, windowsProcess, and you can get a lot more of these. In fact, if you look in the PowerShell Gallery, it's all resources. They start with an x, which stands for experimental. And Microsoft releases them in waves. And so there's a ton of them out there. You can go, go out there to the PowerShell Gallery.
12:29I'll give the URL for that. And take a look at all the different resources. And you'll treat them like modules. You'll add them into your modules directory, import them, and then you can start using them here in PowerShell. And you could also, there's actually a dynamic one called import-dsc, DscResource right here, so you also need to use that to import the module to get all the resources inside of your configuration or to get specific resources in the configuration. But back to our commands here, let's say that we wanted to take a deeper look at that service resource.
13:00We can pipe this to select and expand the properties. Because if we look here, we've got this properties over here. Those are all the configurable properties. Well, let's expand that out so we can see it for service. And you'll see here's all the ones that we can set, State, StartupType, DependsOn, Credential, BuiltInAccount, and the name of the service. We can do the same thing here for the file resource that we configured there in our configuration. And here's a lot of things. So we use SourcePath and DestinationPath. We also Recurce, set up the recurse flag on it, so pretty cool. And it also shows you the values you can provide for them as well.
13:30So you can get a lot of good information here for the resources. All right. Back to where we were. Let's say that we wanted to deploy this to our machines. First, let's go take a peek at those machines just to show you. Here's DCNUGGET, just to show you we have no magic trickery going on. If we go-- if go into the C drive, there should be no installation folder. There's no installs folder here. Also let's just fire up PowerShell, and let's do a get-windows feature, get-windows feature for windows-server-backup. See if this feature is installed. It is not. See that? That's not installed. And then the last thing here, let's do a get-service.
14:01And we want to look for the display name here of windows update. And that is currently stopped. So our goal is to ensure that this is always installed, ensure that this is always running, and ensure that our installs directory is always on here with those files that live on the file server. And the domain controller will do the same thing then to our file server, and same thing. There's no install directory here. The Windows Update service has stopped. And what Windows Server Backup is not currently installed. So let's go back to our client machine here. And all we do is a Start-DSCConfiguration.
14:34We're going to pass in the path here to our NuggetlabConfig. Let's do it. And there it is. See it spins up a job. So now we can get the job here. We can see it's probably to be running for a little bit here. Because it's going to install those services on those machines, and also copy down that installs directory and start the Windows service. There it is. Completed. That didn't take too long. But now we can verify this a couple of ways. But let's just do it the easy way here. Let's go over to DCNUGGET. Let's open up the file system here, and go into the C drive. And look at that. There's our installs directory, looks good.
15:04What about let's fire up PowerShell here, and let's just do a get-windowsFeature. And let's look for that windows-server-backup. There it is. It's installed. And finally let's do a get-service here against our display name of windows update. And that is currently in a running state. So awesome. That worked. And the same thing happened over on our file server. There's our installs directory. And we know the other ones are there as well. So pretty nice, pretty nice, right? It did everything we told it to do automatically.
15:36Now here's the real cool thing. The real cool thing is if we were to delete something, let me take the installs directory off of FSNUGGET here, let's just get that out of there, get it totally out of here. And now let's go back to our CL8 Nugget machine here. And let's run a test configuration. Let's run this against FSNUGGET. This is actually going to test the configuration that's over there on that server. And look at that. It's not in the desired state. What if we did that against DCNUGGET though? We didn't make any changes over there. Look at that, True. It's in the desired state. So that's just a great little commandlet to run to see if we have any configuration drift going on.
16:11We can also see the current configurations over on those machines by running a Get-DscConfiguration and passing in the name of the machine here, for your Sim session. And it's going to show us what our current configuration looks like. And here it is. They're there. So here are all three. We're ensuring that these are present. We're ensuring that the Windows Update service is in a running state. And we're also ensuring that the Windows Server Backup is also present. So really nice. Now I do want to mention that this is heavily reliant on remoting, as most things are, most of these big features are in PowerShell. So make sure that remoting is enabled.
16:42It's the only way you'll be able to do this. And then the other thing is that working with the local Configuration Manager, again this is the component that does all the work. So if we do a Get-DscLocalConfigurationManager here, and let's just get them for both machines. This is going to show us our settings. And here's our settings for DCNUGGET. Here's our settings for FSNUGGET. Let's go over some of the big ones here. ConfigurationMode, this can be one of three values. And this is what determines how the LCM applies our configuration, and whether or not it checks for configuration drift. So the three values are Apply, which just simply means it will apply any new configurations that we push over.
17:15Or if it detects any new configurations on a pull server, it'll pull them down and apply them. ApplyAndMonitor, which is the default, means it will do everything we just talked about with Apply, as well as monitor for configuration drift. And if it detects any configuration drift, it will output it to a log file. The last setting is ApplyandAutoCorrect, which is the ultimate in ensuring that your machines stay in the desired state. Because not only will it do everything with Apply, but if it detects configuration drift, it'll reapply our configuration to get it back to that desired state. We also have our configuration mode frequency in minutes, how often it checks for configuration drift.
17:48The default and minimum value here is 15 minutes. Let's see. What else do we have in here? We've got RebootIfNeeded. So that Windows feature that we just installed, the Windows Server Backup, that actually required a reboot afterwards. But we have the setting at false. So it didn't reboot. If we have to true, it would have rebooted the machine after that feature was installed. And we also have ActionAfterReboot. There's ContinueConfiguration, and there's also StopConfiguration. Let's see another one here, RefreshMode, you can see the default here, which is PULL. And we also have RefreshFrequencyMinutes.
18:19This is only relevant if you are in a refresh mode of PULL. That's how often it will check the pull server for new configurations. Now how we change the settings of an LCM is very similar to creating a configuration here. So let me open up another script I have here, called LCM-Config. And it's very, very similar. So we set up a configuration block, give it a name. We can optionally set parameters. So we can create, again, these are going to be meta.mof files that we create that contain all the settings for LCM. So we can create them for multiple machines, set up a node block, and here's the important part, LocalConfigurationManager, put in the name of the property, as well as the setting.
18:53And then we generate this. Let's go ahead and put this in the memory here. And now let's run LCMConfig, and let's generate this for both DCNUGGET and FSNUGGET. That generated, as you can see here, meta.mof files. And now instead of calling Start-DscConfiguration, we call Set DscLocalConfigurationManager, pass into the path to that directory, which contains both of those meta.mof files that we just generated. And that's it. Now it applied them. Now we can verify that it applied them, again by running a Get DscLocalConfigurationManager. And we should see that we are now in ApplyandAutoCorrect mode.
19:26So what that means is within 15 minutes on our FSNUGGET machine, the LCM is going to detect configuration drift. And then it's going to re-run that configuration, which is going to re-download that installs directory onto this machine. And we'll be back at the desired state that we specified there in that configuration file. So what do think of Desired State Configuration? Pretty incredible stuff, right? I mean extremely powerful for how simple it is to get up and running. And again, check the internet. Look at the PowerShell Gallery for resources, or just Google search for desired state configuration resources.
20:00There's a ton of them out there for almost anything that you can think of. And we're only going to get more and it's only a better over time. All right. Let me give you your challenges for this Nugget. Challenge number one, create a basic configuration to ensure the BITS service-- that's the Background Intelligent Transfer Service-- is running. Compile an MOF, and push it to the machine. We covered all that in this Nugget, very simple. Create that configuration function. Call it with the target machine that will generate the MOF file for that machine. And then use Start-DscConfiguration to apply it. Step number two, stop the BITS service, and check for configuration drift on the machine you applied the configuration to from above.
20:35So remember how to check for configuration drift? Right, it was the Test-DscConfiguration command line. And challenge number thee, create an LCM configuration for the target machine you used in the previous steps. Change the configuration mode property to ApplyandAutoCorrect. Set the configuration on the target machine and stop the BITS service, checking after 15 minutes to ensure the configuration was reapplied. So this is just so you can see the whole process in action. You can watch the LCM fix the configuration drift that you caused by stopping the BITS service. All right, so again, you can find the solution underneath these regions.
21:07You can find all these files in the Virtual Nugget Lab files downloadable on the right-hand side of the course page. And as always, good luck. In this CBT Nugget, we saw how to get started with Desired State Configuration. We defined what DSC is. We saw some of the challenges that it solves, namely configuration drift. We got familiar with the components. We saw Microsoft's phased approach for developing and working with DSC. And that is the authoring phase to generate their script and generate the MOF file. We saw that the staging phase is all about taking that MOF file and deploying it to a machine.
21:39And then we saw that the make-it-so phase is how it applies the configuration to the machine. From there, we jumped into the Virtual Nugget Lab. And we got a nice little demo here to see the whole process, from creating our script, to generating the MOF file, to applying it through the LCM, the Local Configuration Manager. I hope this has been informative for you. And I'd like to thank you for viewing.
Desired State Configuration - Making it So!
0:00Desired State Configuration-- making it so. In this Nugget, we're going to look a little closer at the deployment models here in DSC. We'll compare and contrast the push and pull deployment models, and then we will get into the Virtual Nugget Lab, and I'll show you how we can set up a pull server to orchestrate all of our deployments from one centralized location. Let's begin. So we've got two deployment models in Desired State Configuration-- the push deployment model, and the pull deployment model. We took a good look at the push deployment model in our Getting Started with DSC Nugget, where we saw it's really simple, right? It's a very manual process.
0:31We generate the MOF from our configuration function, and then we manually push it over there with a Start DSC Configuration. That sends it over, and then applies it, and then potentially monitors it based on our configuration mode. So total manual process. No centralized server orchestrating deployments. We simply author our configuration script, and then run it to generate and compile that MOF file, and then we just push it over there, and it gets applied by the LC on the Local Configuration Manager. So this is good for small setups, right?
1:03If you don't have a lot of servers and a lot of configurations, then this will be great because you don't have the scaling problem. On the other hand, if you do have a lot of configurations, you have a lot of servers that need to be in a specific state, then this could get a little hairy to manage, and that's why we have a pull deployment model. So in this model we have a centralized server that hosts our MOF files. The LCMs on the target nodes will then pull that server based on a refresh interval and grab any new configurations if it's changed. So it's a little more difficult to setup because we need to configure that pull server, but it's a lot easier to scale if you have many configurations.
1:37So there's a couple of ways that we can set up our pull server here. We can use SMB, HTTP, or HTTPS, and how this works is SMB and HTTP are going to be good for private networks. SMB for small, simple private networks. You know, once you start involving subnets and firewalls, then you can get into some problems with SMB. HTTP is going to be good for those complex, private networks, and HTTPS is what you're going to want to use when you have to do any sort of public communication because all of our configurations are getting transmitted over in clear text. So we want to reduce the chances of those potentially getting messed with because that could cause a whole host of problems, right?
2:14So I'm going to show you in our demo here how to setup an HTTP pull server. Now, just a couple of differences I want to point out in the process from authoring to staging. In the push deployment model, when we run our configuration it's going to generate that MOF and name it after the node, right? So if we were to generate a configuration for APPNUGGET, it would be APPNUGGET.mof. Over here in the pull deployment model, that's still going to happen, but we need to change the name of that to a random unique identifier, and I'll show you how we can create a GUID, global unique identifier, here, and rename that file before we push it over to the staging, and then when we set up our LCMs, we're actually going to use that GUID, and that's what's going to tie the LCM to that configuration on the pull server, and yes, we can use that one GUID across many servers.
3:00If we have a farm of servers that all need the same state, then we can tie them all to that one configuration file. Another thing we need to do is generate a checksum on our MOF file, which is what clients are going to use to validate the integrity of that configuration. So, just a couple of extra steps here before we stage that MOF file to our pull server, but it's really not that bad. All right. Let's jump into the Virtual Nugget Lab, and see how to set up a pull server. Welcome back to the Virtual Nugget Lab. So there's a few ways to set up a pull server. The current recommended way of doing this is using DSC to configure DSC.
3:32In other words, we're going to download the resource kit, which will give us access to the DSC resource, the PS Desired State Configuration resource, that we can then use to set up a pull server. Currently, this is the best way to do it. Now, keep in mind, all this DSC stuff is still very young. There's a lot of areas that still need to get fleshed out, and this is one of them, but you'll see as time goes on it's just going to get better and better. So, let me take you over to the script center here, and here is the DSC resource kit. It contains all the waves that Microsoft has released, and if we scroll down here, you can get a look at all the different resources that are in here.
4:04So if we head down here, there's something for Azure, Active Directory pack up there, DHCP server disk, Exchange, there's a big one for Exchange in here, and let's see. There's some Firefox. There's one for Chrome. There's one for Hyper-V. We're going to work with this one here in this Nugget. XInternetExplorerHomePage, that'll be a fun one, and then what we're really looking for is this one right here, PSDesiredStateConfiguration. Contains improvements to built-in DSC resources, as well as resource for configuring a DSC pull server, exactly what we're going to be doing. So I already downloaded this, and popped it into our modules directory here.
4:37C: Program Files or system drive Program Files, Windows PowerShell, Modules, exactly like we would install any other module. Here is the zip. So I just extracted all of those resources into here. Now we could do something like this. Watch this. Let's just do a get-DSCResource here, and now, instead of just those core resources, we should have all of these new resources that are inside of the resource kit, and look at that. We've got tons of them to work with now. So we could create configurations around virtually anything. All right. So now that we've got that ready to go, let's take a look at set up a pull server.
5:10Just like creating a standard DSC configuration. We started off with configuration. Give it a name. This is what we'll call when we generate the MOF file. Then we're going to import the DSC resource. We're actually going to import all the resources inside of the PSDesiredStateConfiguration module, then we're just going to target our APPNUGGET node. We already have IIS on that node, and that's going to be required here, because we're going to end up creating two web services. We're going to add a Windows feature and create two web services, a pull server web service as well as a compliance server web service, and just to show you APPNUGGET here, you can see we do not have the DSC service currently installed.
5:44Here it is. This is what's going to do all the heavy lifting here for DSC and for our pull server. We do have IIS installed, and I also wanted to mention here, we needed to copy the DSC resource kit over here onto this machine as well, since this is where that configuration is going to be running, it's going to need access to those resources that we're using inside of this configuration for setting up the pull server. So that's why this also needs to be on the machine that is going to be your pull server. We just happen to be doing all this on our client machine. All right, so the first thing we going to do, then, is add that Windows feature, the DSC service windows feature.
6:16Then we're going create our pull server, and now this pull server is just a web service, as you can see right here, that's going to run inside of IIS. So we're going to ensure that this is true. Here's going to be the endpoint name. Here's going to be the port that it listens on, and then it's going to create this as the physical path there, instead of IIS' virtual directory, there, wwroot, and this is going to be unencrypted HTTP traffic. So it's just standard HTTP web service here, and then we also have our module path. More on this when we get into creating a configuration because if we have any modules, which we will because we're using a custom resource.
6:50You don't have to worry about this if you're using all the built-in resources, but if we're using a custom resource, we need to ensure that the LCM can download it on the target machine so it can use it locally. So we're going to need to zip up the resource that we use, generate a checksum for it, and put that into this directory. We also have our configuration path. This is where we're going to, again, create our MOF files. Once we rename them with a GUID, unique identifier, we're going to put them into here, and then we're also going to generate a checksum for them. So these are the two directories you'll be working in to put your resources, any modules that you're configurations will need, as well as the MOF files themselves.
7:27All right. So we're going to ensure that the state is started, and this is going to depend on the service. So we're setting up order here. We're saying that this must run before our DSC web service resource runs, all right? And then the next one here, the last one, is our compliance server. Now, there isn't much we can do with this right now because this is one of those areas that really needs to get fleshed out, but think of this as just kind of a database that all the targets are going to report to. Eventually, I can imagine us getting a nice web interface that will allow us to monitor configuration drift and manage our configurations in real-time on top of this data, but we can still get it up.
8:02So we can start tracking that data now. You can get at some of the data in here, but it's not extremely useful, and it's kind of difficult to get at. So I just want to point that out. So, we're still going to set it up, ensure present. Here's the name. This is going to listen on port 9080. Here is the directory here for the compliance server, just standard HTTP server, again. It's going to be started, and here's the big one-- IsComplianceServer. Set that to true, that'll set this up as a compliance server, and we have two dependencies here, the service as well as our pull server. So this will go off last, here, for our configuration, and that's it. So let's go ahead and put this into memory here.
8:35All right. Function is created, and now let's create our pull server. So this will create APPNUGGET.mof. There it is, and now let's do it. So this is going to start it, and also, by the way, the weight parameter here will pipe out everything to the screen. So it won't fire it up as a job. Without the weight parameter, as we saw in our Getting started with DSC Nugget, when we push those configurations over, we did it without weight. So it spun it up as a job. So this will make it easier. You won't have to get the status of the job, receive the job if anything goes wrong to view the messages.
9:05This will just pipe it all to the screen for us. So let's do it. Let's spin it up. So here it is. Now, it'll shoot back any errors right off the bat if you have any resource configuration errors. So if you didn't copy everything over to this modules directory over here, for instance, you'll definitely get some errors back, but hey that looked like it worked. It worked, and we can verify that because we can head over to APPNUGGET here. Let's go right into wwroot. Look at that. We've got our directories here, and let's just verify our DSC service is installed. It is. There it is, and then, oh yeah. Let me fire up Internet Information Services Manager here as well just to make sure that those sites were created and they're up and running.
9:41There they are. Excellent. Both running. Very good, and one more thing. That's going to create a DscService directory. Here it is. So this is our pull server. This is where we're going to plant those MOF files. This is where we're going to need to zip up and plant any modules or resources that our clients will need to download to run their configurations, all right? So, good. Everything looks like it's set-up perfect from our pull server side. Now, it's time to test it all out, right? And the first thing we're going to do, because eventually we're going to need to configure all the LCMs on those machines, set their configuration to pull, and then I'll show you that configuration last, but first let's create something here.
10:23Let's create a simple configuration that we're going to deploy and stage onto that pull server. So we've got a configuration named SetIEHomePage. We're going to acceptt some parameters here, the first one being mandatory, the start page URL, the second one being secondary start page's URL. So how this works is, when we fire up Internet Explorer, it's going to fire up two tabs. One with the start page and then another one with the secondary start page. So that's all we're doing here, and we're going to use that custom resource inside of the DSC resource kit xInternetExplorerHomePage to do so. So we'll import that module.
10:53Doesn't matter what name we have here because we're going to overwrite it with the GUID anyway, but here's the resource that we're utilizing here. We're calling it IEHomePage, and then we're just tying these to the parameters that are getting passed in, and here is how we will generate the MOF file that we're going to need to deploy to our pull server. So we'll just call this. We'll set up the start page as CBTNuggets.com and the secondary URL as Bing.com. So let's go ahead and create this. Put that in memory, excellent, and now let's create our MOF file. There it is, localhost.mof. Again, the name does not matter because it's going to our pull server, and here's how we're-- the next step is what we're going to need to do to the name.
11:29We're going to change it to a globally unique identifier. So we're going use the static class here, and we're going to tap right into the .NET framework to hit the GUID class and call the static method newGUID() on that type, all right? So we'll do that. That's going to generate it and spit it back into the screen here. Here, just, I'm going to copy this because we're going to need this here when we get into configuring the LCM, all right? Cool. So we got that down. Now the next we're going to do is copy that MOF file up to our pull server with this GUID that we just generated that's inside of this variable as the name.
12:01So we're going to set up our source here as that MOF file we just created. Our destination, we're going to go right through the administrative share over there on our APPNUGGET machine, and plant this right into that configuration directory with the GUID that we just generated .mof. So let's run this. That's going to copy it up, copy it over there, and rename it to the GUID that we just created. All right. Excellent, and now we need to generate the checksum for that as well. Perfect, and you know what? Let's just verify that real quick. Let's go over to APPNUGGET, PowerShell, DscService, Configuration, and look at that.
12:36There is our mof file. It made it. Awesome. So, and a checksum. So, perfect. Now, at this point, we could go and change the settings to pull and see it all in action, but it wouldn't work. It would fail because we're using a custom resource. If you were using one of the built-in resources, you'd be done at this point. you just configure the LCM for pull, and it'd be good to go, but because we are using a custom resource we need to do an extra step, and that is provide this resource to the pull server so clients can download it and use them on their local machines.
13:06So that's what we're going to do next. We're going to zip up this xInternetExplorerHomePage module, which is right here by the way. Let me go into PowerShell, modules, and xIE. There you are right here. So we need to zip this up. See this, here it is, the resource with the psd1, and here is the actual resource involved. There is the schema. There is the module. So this is what we need to send over. So we need to zip this up, and name it with the naming convention that it expects, which is the name of the resource underscore version, all right?
13:39So that's what we're going to do. So this is a reference to the resource, the actual directory where they all live that we were just looking at. Here is the new name, the zip file name underscore 1.0.0.0.zip, and here's the destination. We're going to put it inside of the modules directory over there with this name. Now, in PowerShell version 5, it's very easy to zip up files. There's a brand new command called, I believe it's create_archive, or create-archive. Not so much in version 4. We need to do the old school method of tapping right into the .NET type.
14:09So we're going to add this type, and then we're going to call the static method on that type to zip up our file. All right, and then we're going to copy it right up there, and then we'll generate the checksum for it as well. So let's do all that in one shot. Ready? All right, that looks like it succeeded. Let's verify that. Let's head over to APPNUGGET here. Let's head to DscService, right into modules, end, hey. Awesome. There is our resource all zipped up. There's the checksum, and now we're ready for the final step, which is configuring the LCMs on our machines that we want to hit that pull server and pull that configuration down from.
14:40So, simple enough, right? We've done this in our Getting Started DSC Nugget. We're going to set up an LCM pull config. We're going to have a couple of parameters here. The first one is for the computer name so we can pass in multiple machines and generate a meta.mof file containing all those settings for each machine, and here's the important part, the GUID. So we're going to set up in the configuration ID-- this is one of the settings in the LCM-- this is how we tie the local LCM on the machine to hit that package up on the pull server. That's how it all gets tied together. And normally I'd have this all in one script so we could just flow that GUID variable all the way through, but I broke it out.
15:14So you can kind of see the steps here, and that's why I copy the GUID to the clipboard. So that's one of the big settings. The other one here is the refresh one. We need to set this to pull. Remember, push is the default. So we set it to pull, and then we need to point this LCM at our pull server. So we're using HTTP. So we're going to specify WebDownloadManager as the DownloadMangerName here, and we're just going to point it to the server URL, which is going to be the web service, APPNUGGET port 8080. Here is the name of that service. This is also where you'd set-up SMB. So if you wanted to set up an SMB fileshare as a pull server, then you would set that up and specify the UNC path to that sharing, and you'd be good to go.
15:49All right, so let's go ahead and create this configuration. Awesome, and now let's go ahead and create those meta.mof files, our settings files for both of these machines, and there they are. Perfect. So, now the last step is to set it, right? And what's this going to do? Boom, it's going to send those configurations over, and now we can verify that with a get local configuration manager, and look at that. It worked. So our DC Nugget's in pull mode. Our FS Nugget is in pull mode, and our refresh frequency minutes is 30.
16:20So every 30 minutes, it's going to check that pull server for a new configuration. If that configuration's changed, if checksum has changed, it's going to pull that down and apply it. Also notice that we're in ApplyAndAutoCorrect. So if somebody were to change our home pages, within 15 minutes it would get changed right back. All right. Let's head over to our FSNUGGET and see if it all worked. Now one thing you can do to kind of check to make sure that the resource phase worked, because when you're doing custom resources there's a lot of little things that can happen along the way there. So run a Get-DscResource.
16:52If we see that resource in here-- hey, look at that-- that's generally a good sign that it made it over. All right, now let's really verify here. Let's fire up Internet Explorer. What do we get? Hey, hey. Look at that. It worked. Well, we've never used Internet Explorer over here apparently. So here we go. There it is. Yeah, yeah, yeah. We'll add them all in here. Oh, boy. I should just turn that off, huh? That's annoying, but there we go. So there's our main page, CBTNuggets.com, and here is our secondary page, Bing.com. Very, very cool, and if we were to change these settings, which is difficult to do for the secondary page.
17:25It's a registry setting. So no user's probably going to go turn that off, but anybody go in the settings and turn the home page off, and within 15 minutes it will get auto-corrected and put it right back to it. All right. Very good. Now, troubleshooting. If you try this stuff on your own, because there's a lot of moving parts here, all this stuff is still, again, relatively new, it's inevitable that you're going to come across issues. So the Event Viewer is your friend. There is an event log here for DSC underneath applications and service logs, Microsoft Windows.
17:55All of our machines, clients, and the pull server will have a Desired State Configuration log here. You've got an admin log, and you've got an operational log. So check these out if you have problems, and that will help you hunt down where the problems are coming from. All right. We're going to skip the challenges for this Nugget because that was a pretty big demo, and if you really want to try this out, do it on your own. Do it in our Virtual Nugget Lab if you have access to it. If not, try it on your own equipment. It's a lot of fun, and I would advise, for your first time, just use one of the built-in resources to get it all working, and then you can start introducing custom resources into it and add those extra steps in.
18:28In this CBT Nugget, we saw how to make it so with Desired State Configuration. We started with a quick overview of both deployment models, push and pull, and then we jumped into the virtual Nugget lab, and took a big demo on how to setup an HTTP pull server, and we went through the whole process from author to stage to make it so. I hope this has been informative for you, and I'd like to thank you for viewing.
Tips, Tools, and Resources
0:00Tips, Tools and Resources. We're going to finish this course off with this real quick Nugget here to show you how to use profile scripts, talk about some of the popular tools that are out there that will assist you in building PowerShell scripts and just making it generally easier to work with PowerShell, and some excellent resources so you can continue your journey to becoming a PowerShell master. Let's do it. We're going to start this one in the Virtual Nugget Lab because I want to get you up to speed on profile scripts first. So profile scripts, what are they all about? Well, if you find yourself doing a lot of the same things every time you launch a session, whether that's in the ISE or the Shell, then it may be a good candidate put in your profile script, because it'll automatically load all these things up for you every time you launch a session.
0:41So things like customizing the Shell, things like functions, if you find yourself running a function all the time, put it in your profile script. It'll automatically be available. You won't have to manually load up that function. Setting up PS drives, importing modules, all kinds of things are good candidates for your profile script. But what I want to do is show you the About topic here, About_profile. This is great because there are actually multiple profile scripts that you can create at different scopes. So Current User, Current Host. Right, host being the ISE or the Shell, the actual PowerShell.exe down here.
1:13The Current User All Hosts, All Users Current Hosts, All Users All Hosts. So if you run the profile variable by itself, it's going to return the path that you'll need to create your profile script in for the Current User, Current Host. Our host right now is the ISE. That's why it sent back this one. If we did it for something specific like All Users, All Hosts, this one is going to show us that, oh, yeah, we'll need to create this inside of the PS Home Directory. Now it doesn't create it for you automatically because if we were to test this path, this is going to return false.
1:44See that. Because it doesn't exist. It's just showing us where that file should be, and what it should be, if we were to create that profile script. So that's why we're going to do a new item, specify the path as the profile variable, automatic variable, .AllUsersAllHosts. Type File and Force in, in case it already exists, which we know it doesn't, and now it'll create it. And now it's created. And if we a test path against it again, it will return true. Awesome. Let's go and start that up and we're going to throw some interesting commands in here. One common thing you'll do is customize your environments.
2:15We'll set up the window size, the buffer size, here's where you can do your foreground and background colors and all that. And we'll change the window title to PowerShell Ninja. And then we'll set our location as the C Drive. We'll clear the host, because we need to see that every time we launch the Shell. And then this is super fun. I advise you to put this in your profile script because it's great. So this will get a Random cmdlet, right. Get-Random cmdlet is awesome. And this will get a random About Topic, and then we'll put a nice message every time we launch the Shell. Welcome to another fabulous session. Here's your random cmdlet. Here's your random About Topic, and you'd get Help against those variables to see Help for either of those topics.
2:49These are variables that will be available throughout the entire session. So I'm going to copy this right up to here, I'm going to piece that into our profile script. Since we did this for All Hosts, now we should just be able to launch the console here. And look at that. There it is. Welcome to another fabulous session, oh, look at that. Our random cmdlet was Update Help. That's funny. And then our random About Topic was about operators. Let's try that again. Whoosh. Hey, this time it's Disable-Scheduled Job. And again, these are variables that are available to us. Now we can just do a get-help, pass in cmdlet, and there we go.
3:22We get the help topic for that cmdlet. Awesome. So that's profile scripts. Pretty simple, pretty straightforward and extremely useful, especially again if you find yourselves doing a lot of the same thing every time you launch the Shell. Toss it in your profile script. You'll save yourself some time down the road. How about some tools here to make your lives easier when working with PowerShell. The Script Browser and Script Analyzer are great. These are add-ons to the ISE, so you can head over this link to download them. There's also, by the way, if I just show you real quick in the ISE. The add-ons menu, you can open the Add on Tools web site.
3:54There's a ton of add-ons out there, so you can certainly make your experience in the ISE that much better. Lots of them out here on this page, so again you can access this right through the ISE. There's all kinds of good ones in here to, again, help you increase your productivity there inside of the ISE. We also have PowerShell tools for Visual Studio. So if you're a fan of Visual Studio-- I'm a big fan of Visual Studio. I love it. There's a great extension out now for Visual Studio 2015, and you just get access to PowerShell through Visual Studio. So it's a lot easier for debugging.
4:24If you build your own cmdlets, it's obviously going to be the tool of choice for doing so. It's basically the ISE on steroids because you can do so much more with it than you can with the basic ISE. And then PowerGUI.org, which is right here, is another really nice tool there. Dell actually took it over and this will redirect you to Dell's website and you can download it. You can essentially write your scripts without writing any code at all. It's totally graphical. If you don't like writing code, you like clicking around in the GUI, then you got access to all of your cmdlets in visual form, and you can just fill out their parameters and stuff here, using GUI tools and it'll generate the scripts for you.
5:04And another really popular one is Pester, which is a unit testing framework. This is another very popular and very good tool for unit testing your PowerShell scripts. Now on the resources front. I'm going to give you one of my all time favorite PowerShell for resources. It's right here. Print these out because they will save you a ton of time and they're just a fantastic learning tool and reference tool. So I going to actually show you this. Let me head over to Microsoft's web site. Here's where you can download it from. Hit the Download button here. And it's got reference guides for virtually everything in here.
5:36I downloaded all of them here. Let me show you the Language Reference Guide. This is just so cool. If you find yourself working with PowerShell every day, print these out, put them wherever you may be and you'll thank me later, because they're great. Useful Commands, here's a list of all the Operators in here. Scroll down. Here's Arrays, Comments, Strings, Variables, Object Properties. It just gives you every possible way you can think of, of working with these things, just an incredible quick reference. Look at this, all the methods over here. Here's all the variables and a description of them.
6:07Let's see, Automatic Variables, Preference Variables, the list goes on and on. Resources at the bottom. It's just an incredible, incredible tool. Here's the ISE reference. God, I love this one too, right. Here's all your general shortcuts, Script Pane shortcuts, Execution, Debugging shortcuts, and so on and so forth, just good stuff. What else do we have in here, DSC. Yeah, we love Desired State Configuration. Check it out. Here's a quick overview of DSC, and some quick examples here of how to work with all of the core resources, which is fantastic, little bit on some of the cmdlets, and here's your Local Configuration Manager.
6:40So there you go. Download this one. It's a big, big time saver and just a great learning tool around. Obviously we've got the Technet Scripting Center. We've used that quite a bit throughout the course here. That's a great reference. And then, PowerShell.org, one of the greatest non-profit sites out there. Great community and they keep it up to date pretty good. So check that one out as well. That's it for Tips, Tools, and Resources and that also concludes our course here on PowerShell 4 Foundations. I hope you learned a ton. I hope you had fun. And I hope you stick around because PowerShell is going to be in our lives for the foreseeable future.
7:13So stick with it. Never stop learning and stay tuned to CBT Nuggets for more PowerShell goodness down the road. I hope this has been informative for you and I'd like to thank you for viewing.
Frequently asked questions
What does the Microsoft PowerShell 4 Foundations lesson cover?
The lesson walks a team member through installing PowerShell 4.0, getting started in the console and the ISE, using the help system, command terminology, objects, the pipeline, and extending the shell. Later segments build on that foundation with scripting essentials, debugging real-world scripts, workflows, and Desired State Configuration.
How long is the PowerShell 4 Foundations lesson, and how does it fit the full PowerShell course?
The lesson runs 7h 57m within a PowerShell curriculum of about 68 hours per learner. Training Managers can assign foundations content like this for onboarding, then route infrastructure and automation staff to the more specialized topics later in the course.
Which PowerShell help and discovery commands does this lesson teach?
Learners use Get-Command to search for what they need, and the three help cmdlets Update-Help, Save-Help, and Get-Help. They practice reading syntax, parameter sets, and examples, and use Show-Command to open a GUI that builds a correctly structured command, such as New-Service.
Why does the lesson cover PowerShell objects before the pipeline?
The trainer explains that objects come first because the pipeline is how data returned from a cmdlet gets passed along. Objects have properties that describe them, methods they can perform, and events that can happen to them, and cmdlets both return objects as output and accept objects as input.
Does the PowerShell 4 Foundations lesson include hands-on practice?
Yes. Demonstrations run in a Virtual Nugget Lab environment, starting from a Windows 8 client machine, and segments include challenges with answers in downloadable Nugget Lab files so a team member can practice each concept.
What real-world PowerShell tasks can a team member handle after this lesson?
The lesson includes scripts that import users into Active Directory and that monitor network servers and send email notifications when a server goes down. Team members also learn to debug scripts line by line against a test environment, which helps them understand scripts they inherit from others before using them in production.
Team training path
Turn this skill into assignable team training
This free skill is a preview of the courses your team can assign, track, and report on with CBT Nuggets.
Free training library
More free lessons from CBT Nuggets
Microsoft Windows Server
Administer Active Directory Domain Services
Free lesson from Microsoft Server 2019 Essentials · 1h 21m
Microsoft Windows Server
Implement Windows Containers
Free lesson from Microsoft Windows Server 2016 Installation, Storage, and Compute (70-740) · 1h 19m
DevOps
Docker (v18.06.3)
Free lesson from Docker · 2h 6m
Networking
Border Gateway Protocol (BGP): Basic Operations
Free lesson from Border Gateway Protocol (BGP) · 60m
Networking
Define Wireless Network Architectures
Free lesson from Wireless Design Professional Training · 55m
Python
Introduction to Programming and Python
Free lesson from Certified Associate in Python Programming (PCAP) · 57m
$59
seat / mo, billed annually
