PowerShell Input & Output

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Hello tech world this is TechThoughts and welcome to this special tech thoughts video series focused on learning PowerShell. This is an operationally designed series that aims to get you ramped up and using PowerShell quickly. This is episode seven in the series: PowerShell Input and Output. As always, if you prefer written documentation, the corresponding article for this topic can be found on the techthoughts.info blog which i've linked in the description below. Let's go ahead and get started. Up to this point in the PowerShell series we've been primarily statically assigning variables different values to use as the input for various actions. As you start to progress in your PowerShell capabilities though you're going to want to start taking some more dynamic input. We're going to cover a couple of different ways to go ahead and do that. So one of the easiest ways to do that of course is to utilize native cmdlets. So we can take the $process variable, load that up with Get-Process, and depending on what kind of return is loaded in here you could take various actions. If you haven't checked out the PowerShell logic video, I highly recommend that you do so. So you can use the output of one cmdlet as the input for whatever type of action that you're looking to take. So let's see a more in-depth example of this. So I'll go ahead and load up some code real fast, and we'll be using the Invoke-WebRequest cmdlet to dynamically evaluate a webpage, and we can pull some information off that web page to use as the input for various different activities. So we've got a $webResults variable here we're running Invoke-WebRequest which is going to allow us to go ahead and visit a website that we specify. If you're coming from a more Linux background this is very similar to curl. We're gonna be visiting reddit.com/r/powershell which is the PowerShell subreddit, which is a great PowerShell resource, I highly recommend that you check it out. Note that I'm visiting the json version of this website. Because we're dealing with PowerShell, HTML doesn't do a whole lot for us. We want to work with objects and so i'm visiting the json version of this because json is structured data, and we can use this to get it into native PowerShell object format. I'll be showing you how to do that in just a moment. So I'll go ahead and run this first line with f8 in our console. That will reach out visit the website and pull down the raw data information from that. You'll notice that if I pound out $webResults down here in the console then we've got a couple of different pieces of information like the status code of visiting the website, we got a 200, and then we've got the content of that JSON that we see here. Content is what we're gonna be wanting to work with so we're going to drill down to this particular sub property. So you'll notice in the next line that I have the $rawJSON variable being loaded with the $webResults we just collected dot content. So we'll actually be dealing with this information that's right here and ignoring these other sub properties. We're really after the content of that JSON web page. Now, when dealing with collecting certain types of input remember that there are a wide variety of different conversion cmdlets. So we've collected some JSON from this web page, but we do have that ConvertFrom-JSON cmdlet that's going to allow us to take that JSON and convert it to native PowerShell objects which are really easy and nice to work with. There are several of these different conversion cmdlets and I highly suggest that you get familiar with all of them. They can really make collecting different types of datasets very easy to work with. Sso I'll go ahead and load up the $rawJSON variable with that content, and I'll go ahead and convert that to normal PowerShell object information. And you'll notice that now that I've run that line that if I pound out $objData down here that I'm dealing now with native PowerShell objects. I've got a kind sub property and a data object and if I drill down into that data object you'll notice that we have further sub properties going down until children. I'm getting that children from this sub property right here, which is actually containing the data that we're after from that website. And we can start seeing that we have some different posts that are inside of these children and again we have that data sub property so I'm going to drill down even further into data. And now you can start to see that we actually have all the information associated with each of the posts that we retrieved from that website. So it's no surprise here that you see that I've drilled down and loaded the object data data children data inside of this post's variable. Making it nice and easy to work with. So once we have that post information that we've retrieved and kind of processed into normal PowerShell input, what I can start to do now is work with that like I would normal PowerShell objects. So I can select different things you'll notice we have a variety of different properties to choose from off of this website. And so we're gonna be primarily dealing with a title of the post, and the score or the number of up votes that it's received, and we'll go ahead and sort those posts using Sort-Object by the most popular post. So again using that pipeline to massage that PowerShell object data to get the information that we're after. So I'm gonna go ahead and run F8 on this line. Notice now that we have a somewhat more human readable information set and that's going to be our title, sorted by our number of up votes. So this is a great way to kind of pull in the top information from /r/PowerShell on a day to day basis. So, what could you use this for as far as input? Well, you could start writing some PowerShell logic to email you the top three posts of the day. You could write PowerShell code to text you the top post of the day. The sky's the limit but now that you've been shown how you can dynamically collect input information off the web, you can start coding a variety of very powerful capabilities. Okay so let's expand on this example using another great way to get dynamic input which is going to be the Read-Host cmdlet. So let's load up a quick line, go ahead and separate this out, and what you can see here is that I am loading up the $numPosts variable and making sure that's an integer type. So we're gonna be collecting a number from the user that's prompted. And using Read-Host I can prompt the user or yourself to enter the number of posts to read. If I run this you'll notice that we get that output in the console here asking us for please enter the number of posts read. So I can of course type in five or three or whatever number I wanted, and if we pound out $numPosts down here now, we of course have that integer number. So now that we've used Read-Host to collect that dynamic input I can use the $posts variable that's still loaded with our post information that we collected from the reddit website. We'll still select the object, title and URL this time, and we'll still sort by the most popular posts. But this time we'll only select those objects that are in the first number of posts. So first as a parameter of Select-Object which allows you to select the number of objects that you specify. So this is saying select the first five because $numPosts is currently loaded with the number five. So you'll notice if I run this line then we get five outputs because we told it in using the $numPosts variable to select the first five most popular posts on /r/PowerShell today. Now that you have these URLs you could of course start visiting these, and you would literally be using PowerShell to make yourself smarter at PowerShell! Another great way to get dynamic input is from the actual file system itself. So a lot of times in our operational roles we'll be wanting to evaluate some type of log file. Let's take a quick look at an example of a log file. So here I have something that you might see at work, or in your environment where you have some logging going on for some type of information. You might have some date information and then a status report. And then sometimes you'll have some normal operation information then occasionally you might have an error, and you might want to use PowerShell to identify when these particular types of errors are starting to happen. So you want to utilize the contents of this file as the input for your PowerShell functionality. The cmdlet that we'll be using to accomplish this is going to be Get-Content. So this sample log that I just showed you is located in C:\Test\sample.log and what I'll do is I'll load that into a variable using the Get-Content cmdlet. So here we have a variable, we're getting the content of that particular log. And so you'll notice that if I F8 this, we pound out $logContent down here that it has the exact same information that I showed you in the actual log. Now we've got that inside PowerShell and we'll be able to start working with that dynamic input. So if you were after just the info type things we could of course pipe the contents of $logContent to Select-String, and we could be looking for the pattern, info. And if we run this you'll notice that now we ignore the errors and only return back the normal operation logging. We could of course change that to error, run it again, and this time we only see the errors. There are a variety of ways to parse this type of string data. We could for example, if you're more comfortable with regular expression or regex, we could load up a regex expression. Regex is something that's a little bit beyond this PowerShell series, but you'll offer encounter it in a variety of different programming examples. I just want to demonstrate real quick that we can of course take $logContent, pipe it to Select-String again but this time we'll provide it that regex pattern, and find all matches. And what it's going to do this time, based on those regex is this is the regular expression for an IP address. So this time we'll load this into memory and this will find any IP address that's located inside of that log file. If having an IP pop inside the log file is a critical issue to you, you can very quickly identify that dynamic input, and take the appropriate action. Again, if you're not familiar with regular expression, there are a variety of ways to do this. We of course showed this one up here where we're actually searching for that error pattern, and of course if you were still needed to go after that IP address we could do something like use Where-Object, where the contents of $logContent, so the current objects in the pipeline, is like asterisk dot asterisk dot asterisk dot asterisk. Which is a wild-card for an IP address. So you'll notice that if I F8 this particular line, it also discovers those two errors that contain an IP address inside of that particular string. A word of caution when engaging Get-Content is to become familiar with the different parameters that are available to Get-Content. One of those is the raw parameter. So notice here that if I are load in this line, and we'll change this variable to $raw. That this looks very similar to the one above but I've specified the - raw parameter. And if I load this in, I want to point out that this is now a very different set of information. So notice that if I take in $logContent and pipe that to Get-Member, that there are a variety of note properties and properties here and that this is of type system.string. If I take $raw and pipe that to Get-Member. Oops, error there with the GN! That $raw looks very similar in nature, and also appears to be of system type string. But if we start doing some of those string evaluations that we did a moment ago. So for example I'll take just the errors. I'll replace $logContent with the $raw variable. So we'll look in $raw and try to find the errors. I'll go ahead and click f8. You'll notice that it does not. It returns the entire results of the log file. And that's because $raw is not the same as $logContent. When we did Get-Content against that log, $logContent actually has those lines separated, so you'll notice if I do $logContent[0] it contains one line, the first line. And if I do $logContent[1] that contains the second line. But if I do $raw content 0 notice that it contains the individual character. So this is the raw string information. You can't parse it or evaluate it in the same way that you do when the Get-Content does not have the raw parameter specified. So maybe you want to deal with some files that aren't necessarily just log txt files. You might have some CSV information on disk, that you need to evaluate, as your dynamic input. Get-Content can handle a wide variety of file formats. So here I'm taking a $rawCSV input variable and loading it up with Get-Content C:\Test\tt.csv. If we take a look at this for a moment this is some TechThoughts information that's loaded into CSV format. We have the episode, title, link, and video length. So this just kind of represents you know some CSV information that you might have inside of your environment. And we can of course load that inside using Get-Content. So we now have that CSV information inside of our variable. Again, don't forget about those conversion cmdlets. They work for a variety of different things and we do have a ConvertFrom-CSV cmdlet. So we can take that $rawCSV input, convert it into normal PowerShell objects. So I'll go ahead and run this line here where I'll load that up into $objData. Notice now that $objData is in normal PowerShell object format, and I can start working with a dynamic input in any way that I see fit. Okay so let's switch over to a couple of output examples. So far in this series we've been primarily using Write-Host as kind of our example of showing you how to write things out to the console. And, if you've missed a couple of the earlier videos Write-Host is just the cmdlet that writes a string out to the console. So if I f8 this here you'll notice that the text output to console string got written out to the console. So Write-Host is really easy to implement. Keep in mind that Write-Host only deals with strings. So if I run a cmdlet and load that into a variable. This now contains a PowerShell object. So we have the host info object information loaded up inside of that variable. And if we try to Write-Host that particular variable you'll notice that it's unable to do so. The best it could do is kind of convert the object type to a string name, but it didn't provide us the information that was contained within the object. So make sure that when you're using Write-Host cmdlet that you're giving it an actual string. Notice that one of these sub properties is version, and if I come over here and I take Write-Host and drill down into host info dot version, that is going to be a string and Write-Host has no problem giving us that string output. One of the things that's really attractive for a lot of people about Write-Host is that it has some color capabilities. So we have the foreground color, where we can change the actual text color, and we have the background color where we can change the actual background of the text. This is really great for kind of providing your user or yourself some colored information for easy reading on the console. You'll notice if I click f8 we get warnings in yellow, errors are in red, critical errors have that background color so on and so forth. So Write-Host is really easy to use and those colors make it really attractive, but beyond just kind of tinkering around and making sure that your variables have the information you think they do, you really should not be using Write-Host in any type of production PowerShell. Jeffrey Snover has a really great blog article where he talks about how Write-Host is actually considered harmful and he advocates for the use of Write-Verbose. No seriously, don't use Write-Host. We'll be covering Write-Verbose in later sections of the PowerShell course as we start getting into PowerShell functions, so stay tuned. So again feel free to use Write-Host and kind of like tinkering around but while it can output to the console, you should primarily avoid it. The next one up is going to be Write-Output. And if you've been following along in the series you've already used this quite a bit. And that's because Write-Output is the default method that PowerShell uses to get stuff out to the console. So when I write the cmdlet Get-Process and I f8 that... This output that's being displayed here to the console is actually using Write-Output. So you've been using that the entire time, you just may not have realized it. And so what I want to hammer home here is that all three of these things are accomplishing the exact same thing. So if I run the Get-Process cmdlet that uses Write-Output if I load Get-Process into the $processes variable and then use Write-Output to write that variable that does the exact same thing. Or, if I just take the $processes variable and just run it all by itself without specifying Write-Output, it will also use Write-Output and put that out to the console. Because of the way that this kind of operates you will very rarely see Write-Output actually written inside PowerShell code. It's kind of assumed because when you just put the variable there, just like that, it's accomplishing the exact same thing. The last output that we're going to be covering is going to be Out-File. So while it's nice to be able to put things out to the console, occasionally you'll want to generate some type of logging information, or put the results of whatever you're collecting into some type of actual file that you can send on to your security team or whoever desires that particular information. So we can take our processes, load them up into processes variable and then simply take that variable and pipe it to Out-File and specify a particular path. You can leave it just like here and it will assume that path, or you can actually give it the path parameter, just depends on how verbose you would like to be. So you'll notice that if I load this up, it's gone ahead and created that particular file for me in the processesInfo.txt file. So I'll show you a quick trick where you can go to change directory, C:\Tests and if I type in code, and specify the process file, it'll actually open up that txt file inside of Visual Studio code! It's not a surprise here that we see the output that we would normally see in the console, but now instead represented in a text file. So Out-File is just basically taking the normal output and you can create a variety of different file types. Again, don't forget about those conversion cmdlets. They're super handy when dealing with input and output. So here I'll take that same process information, but this time I'm going to convert it to CSV type. I'm gonna put no type information so that it doesn't add any extra header information to my CSV file, and then I'm going to out that to C:\Test\processes.csv. I'll go ahead and f8 that now I'll take just a second to convert that information over to CSV and if I run code processes.csv you can now see that that output for those processes is now stored in CSV format on my file system. Those conversion cmdlets again are extremely handy, you could generate XML information or a variety of different file types and provide this information in an output file, with the format that the desired team is requesting. Remember that all of this information is available in written format on the techthoughts.info blog. If this video helped you out go ahead and click that like button and subscribe for more TechThoughts videos!
Info
Channel: TechThoughts
Views: 24,905
Rating: undefined out of 5
Keywords: PowerShell, Learn PowerShell, PowerShell Training, PowerShell Input, PowerShell Output, Get-Content, Out-File, ConvertFrom-Csv, ConvertTo-Csv, PowerShell User Input, PowerShell to file, learn powershell online free, learning PowerShell, PowerShell Tutorial, PowerShell Examples
Id: nnTlsNA3hPk
Channel Id: undefined
Length: 20min 53sec (1253 seconds)
Published: Thu Sep 12 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.