Core Concept: Everything You Wanted to know about Hashtables with Kevin Marquette

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everyone to February virtual research triangle PowerShell user group we're super excited and super thankful to have Kevin Marquette come and and join us I'm gonna let you take it away Kevin go ahead one of my most popular articles on my blog is mom all right do it nice beautiful deep dive into a hash tables and can you guys see that just fine there we go awesome all right so so yeah you know MVP I kind of do a lot of stuff in the community and I definitely tend to focus on the fundamentals the you know the things that really get you started with PowerShell I run PowerShell explain calm and actually from my homepage here I've got some beautiful reference pages and a lot of the stuff I covered today I'll have more information or related information on a post here about hash tables but here's some common topics that you need more fundamentals to dive down into it's a great jumping-off point and before I open up my presentation I do want to point out that I do like to keep all my presentations on github so if you want to download any of the information there the presentation scripts that I run today you can go to hash tables off github a hash table presentation I love this because you can download the entire repository as a sip file if you're not familiar with git or since you guys just went through a demo of this you could easily grab the link yourself and go to a power shell and get cloned that link and oh that's alright git clone the link and you have a local copy right there for you so let's jump into hash tables now this presentation I do cover a lot of ground pretty fast and I do kind of do it in a certain order so if you have questions something that already covered feel free to ask those maybe think it might be something that could be coming up I'm just kind of hold tight on those because I kind of have like a method to my madness and to jump right into it pull my first slide here and my slide I mean EOPS code window uh does this size look good for everybody I think it looks awesome awesome okay so I'm gonna start I think about by talking about hash tables by first mentioning arrays because you've probably ran to these first right if they're collections of things so right in front of me I have some very basic syntax for creating an array and assigning it about what seven or so values so when we assign an array the value that up here okay so I now have an array of these values and I can see them all in here beautifully you know and we can index into an array using these these brackets braces so the zeroth element is ten at number one is eleven which aligns to my list up here so beautifully and then if we want to enumerate over an array all right we can use the pipe that we all know and love so we're gonna do a for each and I'm using kiss item here but this could just easily be dollar underbar and we will see well they seem you know process each one and multiply it by two and then assigning stuff into an array is pretty much the same thing here where I have the index I want to assign the value I know that execute this line I'm going to assign 33 into element one and if I see what's in there I have 33 then with alternate syntax is here so we're gonna do a raise of strings on multiple lines and these are all just ways to get values into your array okay so back to a hash table really what is a hash table it's it's another data structure very much like an array except you actually store each value that you place in there using a key instead of an index so it's a traditional key value store from other languages if you come from c-sharp it's the dictionary and I I take the moment to call this out because so often one people learn about hash tables in PowerShell they see it as clips of code here and there like they never see the whole picture from the beginning to the end and that's why I'm starting with such bare basic fundamentals to kind of create the context and let's dive into it so you kind of see how all these concepts build on each other versus how you may have just seen glimpses of a hash table throughout other people scripts so let's create a hash table so the basic syntax is the @ symbol and the curly braces so if I run this I've just created an empty hash table there's nothing in it and I'm gonna start with some of the most verbose syntax you've ever seen but I'm gonna sign I'm gonna have a key named Kevin with the value of 40 and we're gonna add it to the hash table and when I run this now will actually see my hash table has one key of name Kevin and a value of 40 so we can add additional items calling it again and if we look at it now I have the two items and if I want to just access one item out by its name I can call this method on the item method to get the value yeah I do this to highlight that the hash table is just an object that has functions and methods that we can that we can work with this specific syntax you'll probably never see anybody ever use that because they give us these fun accessors - let's index directly into the hash table using our keys so here if I want to access the value that Kevin has I say basically give me the idea of Kevin which is equivalent to this line up above but it's a nice concise syntax and this is also kind of why I showed you the array first because instead of using the numerical index I can now just use the string value of my key and wipe my hash table out here we can also use the bracket to update a at value just as we can put out a 40 Mike he gets this value so if I start with so I'm starting with a very an empty array or hash table here with nothing in it and by just assigning a value to a key I'm automatically adding something into it so you don't have to think about does this key exists yet or not before you add a value you can just assign it and just know that it'll get set and I'm gonna have to use a variable variables to do all this stuff we can just use the keys directly and now I'm back to my two items in my mashed table we can just as easily create the hash table with the values in it to begin with so if I know upfront everything that's gonna be inside my array or my hash table I can specify the key value pairs one on each line and this year will also create my hash table with those values in it and you don't actually need quotes around the name because PowerShell knows you're creating a hash table and it knows user strings it's it's happy to let you just not specify any quotes here to do the exact same side so you'll see this quite often or somebody just calls the the name of the key that they want to assign a value to it and so let's actually use the hash table for something right I've been putting guys in here so I'm gonna create a small lookup table I'm gonna call this my server config or I basically want to specify different environments have different servers it's a very simple config you know we're only have three servers for each environment but I'm able to put these in a hash table that can reference them later and the beauty of this is you know even if my patterns are a little bit ugly like maybe this was you know something even more ugly Lissa's quality doesn't like fit a naming convention we can do this and not worry about like joining patterns together to figure out server name is because servers name is change in this case we're gonna use our key to pull the value out so let's ask for the QA server we do this I got trigger quality o2 and I get just the value a fun trick that many people don't realize you can do with a hash table it's specify multiple keys and you'd actually get out each value so here I'm gonna pull two values out by specifying the dev and QA in this list Oh beautifully yeah I got my Jeff server and the quality server and and this is just an array so if I actually had these in a variable already or an array from somewhere else I basically specify the exact same thing and get both those surfers out and then if I actually try to request a value that doesn't exist at all there's no errors you just get no value at all so here I'm actually testing for null and asking for an environment this just is non-existence and we will get true now with that said yes you have to have created the hash table first if you actually identity miss type this like server configs by mistake I think we'll get an error here because it thinks you're trying to index into an array that doesn't exist right since I haven't actually created this as a hash table is more of a typo I got that error so that's where you know PowerShell will let you just mix us up on the fly well in this case it chokes on the idea that this it doesn't know this should be the respect this to be a hash table but actually initiate it and run this no error because there's actually something there to do the lookup on all right I'm gonna delete those okay so now we have all our values in the list I know how to pull individual items out with the next things you might want to do is actually walk your entire list right walk your entire hash table so maybe there's something you might do on all the servers so you basically clean this up to make sure I know I've got simple values in here and okay so the first thing I do is like see how many items are in there and remember I mentioned the hash table is an object so quite often with an array or collections we can use measure object to get the count of something but in this case because the hash table itself is one object he doesn't enumerate over the pipeline like you expect so I'm only gonna get one for my counts when I'd kind of expect three right because I only have one hash table and that's what it's measuring here instead of measuring what's in it thankfully we're gonna ask the hash table what his count is directly and he knows how many there are and he'll tell me other Street so the small new wants to be aware of but most sound the way you use it you won't run into well you're never counting items in array this way but as you start enumerating over things you'll start to run into something like that all right so let's actually look at this hash table to see what my properties are so I'm gonna have a set of properties here called keys it actually gives me a list of all the keys in the hash table and values actually provide me all the values in the hash table so what I do next so if we look at the values if all I need is the entire list of servers I can just do values and be on my way just give me the contents and you wouldn't need to do with it and we can actually do the reverse like Oh what environments are in my hash table like what environments to have configs for we're gonna ask the keys and get the same thing next look so let's walk the list once I'm going to enumerate the keys we're gonna pass the key to the 4-h so my PS item in this case will be each key and I mean use the key to look up the value in the config to put this string together to say you know basically identifying which environment observers in so def product QA those are in those were the right servers for those environments we can all see this with a for each just as easily where I tend to do a for each key in server to figures and I think this is rates easier I'm actually kind of partial to for each over for each object anyways but this gives me the exact same results as we expect above um you might notice that my results aren't in order and that's actually because hash tables by default aren't ordered I'll show us how to put them in a certain order later but we'll notice that I'm getting a dev prod and QA where I wanted to find this up above I'd definitely put these in a certain order in this hash table especially because hash tables are unordered they might feel like they're consistently ordered but if you go to different versions of PowerShell or even different systems the orders might be consistently different across those and okay so where was I for each can you bring the list getting numerator sometimes you want to use this so the enumerator creates basically a in like a small object for each item in the collection so this is the case where if I at least just see what this burger looks like I don't use this guy often but he passes an object for every item in the the hash table that one has a key and the other one has a value and my measuring example I had before if I run this now it actually does measure 3 because it gets you numerated all three times so when I look at an actual loop on a passing numerator I can do this case item key to get the key and case item not value to get the value some people actually prefer seeing their objects this way versus always looking up the value inside your loop it might be more appearance on the for each so here like for each enumerator in this getting numerator I've got the item key and the I M value I go either way I tend to not lean this direction but I've definitely seen people make heavy use of this but end of the day at least in this example it's the same values I'm getting out so I looked at accessing getting information out of a hash table while walking it there is the Scaccia about trying to put stuff into a hash table while you walk it and the got you there is this guy here is gonna throw an error on me because I cannot modify the keys inside of a hash table while I'm walking while I'm walking it which is kind of counterintuitive at all so when I run this let me get this one error then error occurred while numerating through a collection collection was modified can I ask you a quick question sure so with the enumerators kind of thing is it a preference kind of thing or is there performance but if do you have any insights into that is it so I get a great question out glad you asked I don't notice a performance difference doing that but I do have one edge case here that can actually prepare a case somebody asks that's great here's it here's an example but if somebody decides they want to use a key name of keys or a key name of values weird stuff can happen so I create this hash table and when we look at this write my value is the word none and my keys are actually the words the string values and the string keys okay if I try to do this for each in config data keys PowerShell uses this to index and find the value of keys which in this case is none instead of the two values of keys and values I said when I run this I'm not gonna get what I expected at all because of that nuance now the way you protect against that is using the enumerator then it it gets around that because now you have the thickness in your hash table the key of it and the value of it and this here is where when I run this I get I walk both of them so very much an edge case I still tend to do this first one for his bed everything until I should get bitten by it and I think that's mostly because almost nobody I mean it's rare that people use the numerators in PowerShell you might see a c-sharp dev lien on it a lot heavier so that's kind of why I want you to be aware of it but if you're just starting doing this stuff fresh don't worry about it for now until you find yourself in this case where your dead actually has the word keys and you're trying to use keys to do the enumeration does that make sense yeah I think it makes sense I think it's the crux of oh yeah take away its is to just be aware that you can get bit and then go from there actually it's all the things where sometimes in PowerShell the easy way isn't always the right way for all situations and can't gotta learn where some of those those bumpy spots are but I still lean on using just the indexer for saying it I think I've been bidding on it maybe twice and that's why I've made note to remember it and all the PowerShell that I've written so or is it okay so yeah so getting this error when I'm trying to update this value because for some reason you know it's a bad idea I want to assign all my environments to point to server dev 3 I'm getting this beautiful error saying hey yeah you can't do this you're modifying this thing while you're walking it and it doesn't matter if you're using a pipeline or the for each write both of them will give me this this same air a slightly different air code but the the message is effectively the same and the trick and this is one of those edge cases but you're probably run to this one more often than you'd like to is that we can clone the keys basically make an in-memory copy of it and this gets around that nuance so when I run this now I just over wrote every server in here without a complaining at all with depth or o3 this is because I now have a list of keys that gets passed over the pipe and then it walks that list where I believe what's happening up above it's more like I'm almost getting keys is enumerable in that it's basically a pass each key over the pipe one at a time so when the first key goes across the pipe line is trying to modify it and the second one will go so I think it's powerful magic under the hood that creates this the scenario where you can't update a hash table while you're walking it and this is only an issue if you're actually using the properties of the hash table to walk itself right yeah if you had some other list that you just knew what the values were like I've actually had it and raved like you know dev QA and prod I can walk through that all day long and I make the updates but it's the fact that I'm actually asking the hash table for his keys while I'm making changes and then I'm gonna shift Styles a little bit here so before I've been using the the index accessors but PowerShell that you actually do is like a dot property to access and assign values so here I'm gonna sign you know this key this value by just using hash table dots Kevin equals 40 and I get two items assigned so this starts making things to feel a lot more like objects and might be a syntax you're probably seeing quite heavily in PowerShell so I'm going to shift my example a little bit so everything I've done so far is having like a hash table having values where the value is kind of the same thing but the key is telling me is this for a different person right so it is based like a hash table of ages and I'm using the key as say whose age is it well you see people use hash tables in a second style which is kind of like a collection of properties so here I have a person one property is name and his name is Kevin as other property his age his age is 40 so there's like two mental models that you can use when working with hash tables and it's whatever your need whatever you whatever is best for your need and so let's start with this object this person this me and I can add in let me I'm a city and state on this and when we look at it we see all the values right I'll four of them on here now and we can check to the keys like just by asking for the age if I have an age I'll get it value back you know this one's a little bit dangerous because if the person's age is zero are you asking is there an age or not is zero a false case because what I'm really asking here is is the person's age true and evaluate evaluating anything above zero is true right there's nuances there with this if statements and here I'm being a little bit more explicit where I'm saying you know know if the person's age is null so now I'm handling zero as one scenario versus null as something else now age might be a bad example because if somebody is at ages zero are we talking like newborns where the system doesn't accept it or is it we sure because they don't know or know because they don't know but sometimes you actually want care if the property is there at all so sometimes a null check just tells you if it's not there or if the value of it is null and a hash table has two functions and if you trim like an object you can actually see these functions on there we're actually asking if it contains this item so in your system if your logic needs to be different if a value is just non-existent versus the key is there and you don't know what it is versus it's there but it's just invalid input right if you need to make decisions on those things you can dive into the granularity to test that okay and we can actually remove keys too like if we actually don't want to have age on this person we can just pop it off the object and we just shrink the list by by by that item and if I want to reset the keys you know if I go is assign it to a new empty hash table there's sometimes oh like I'm getting some background noise from somebody a little bit but if you want to maintain this reference of this object you can actually clear it and I'm just point out for more advanced scenarios where somebody knows they need to not assign a new hash table there's an option just to wipe the item out and so geshe-la an empty hash table so it still exists it would be not Noll but absolutely nothing in it okay so that's a quick shotgun blast of all the syntax and style of what a hash table is its most raw form so let's actually do some things with these hash tables and the first one take questions yeah is there any benefit to using a hash table over a PS custom object so yes and the scenario between those two is if I need to be modifying the properties like adding and removing properties of the of the item whatever it is the hash table is real really fast at adding things and removing things but a PS custom object if he's already an object it is really slow to add members to it and especially to remove members from it so if you're doing something where you're trying to build like a JSON object or something that the properties on it matters and you're doing lots of them it can keep something as a hash table as long as possible you'll you'll get performance benefits and I'll show you I have an example later on where actually convert a hash table to its custom object but that's my biggest distinction is yet if I manipulating the properties of it as far as adding or removing I will lean on a hash table as long as I can now if I am giving data back to the user like over something I'm returning from a function I tend to lean towards an object because I feel like okay it's more Bridget it's more sets and the way it looks in the console is a little bit different and when I get to the showing you how to create a PS custom object from a hash table I'll give you some of those examples that help yeah thank you okay so order so sometimes we actually care about the order in our hash table and when that's the case we can actually use this ordered type accelerator to create one that will always stay in this order and then when you add keys they will add to the bottom of the list now there is a under the hoods there is a small performance difference because it's actually storing the data in a different way so where a hash table is like hashing the value and inserting it a ordered hash table is actually like a balanced tree for any of those like computer science stuff but basically means that it has to do more comparisons and it manipulates the order the data a little bit each time you insert something so now it's negligible for most things but if you're starting doing you know a hundred thousand rows or a million records or something nuances like that will just really really jump out to you in line so if you need to just have a hash table on a single line you sue a semicolon ring the middle of it like you can do it after the value and this last one's not actually needed here but that's that's how you do a hash table in a single line okay so here's a use case where you might tend to see that now I actually went in wrapped this is probably the first places that a lot of people saw hash tables for the first time especially the early days of PowerShell right you see some long line like this it says alright look I do a my PS drives here right now and I it tells me they used in the free space but I actually want to get the total space the the go-to example you'd see is somebody creating a select object and in line this this expression so let me clean this put this back down here so it's actually easy to look at and what we're doing here is select object will allow you to specify a hash table where you give it a name of the column header and an expression which is a script block so notice the a little bit too much there a script block that's going to do this calculation on the fly so when I run this now I've got this thing here is my first column header of name and then the second one is name of total space gigabytes and it's doing this calculation here off the properties where this is you know the item the current item in the array you can actually shorten this to N and E I believe and I believe this still works going off script here yes okay yep and that's by the most common common way you'll see that down the wild but name and expression are the long forms of those sometimes I mean I don't like how this makes my pipeline look so if I do use these I tend to put them in a property first like in a variable because it is just a hash table and then we do the Select object actually specify you know specify here so I'm basically making each line stand on its own a little bit more I think something like this is is easier to comprehend what's happening because I like seeing and I suppose I see in my my pipeline as simple as I can't as it can be and this is a little bit should probably actually had named this something else there we go I like that better self documenting right give me variable names that tell me what this thing is so look at my select object I'm it's more intuitive what I'm staring at her in that like a conditional expression or a computed expression or something like that um possibly I honestly don't know what they they're actually calling that but I that sounds great it's not like a good name for it Stephen says aimed expression I think that's right okay yeah cuz I just from people that might want to google that one when you later on today or tomorrow or something so we've got a name expression or uh yeah yeah write it up there and if you're wrong blame Stevie alright so all right we're gonna hold yeah so the fun thing that people tend to not discover on their own and it's usually one the biggest revelations is something called splatting this is what most people tend to get the most value out of from the living hash tables so you notice I've got this command here DHCP serve so he actually has a lot of parameters so many parameters it wraps off the screen and it's hard to keep track of everything right so when I'm over here I can't tell you what the duration is or the subnet lucky if I assumed way out there's a point where he is still running off the screen like I got a zoom way out to build a soupy entire thing now young guys might have your font this small anyways but I look at but but we can use a sliding which is putting all these values into a hash table and then the names still matter and if you use the @ sign here it actually unwraps all of those and will will basically map them for you and in this this would execute as you would expect and yeah so and this is so this is a good way to keep your code really clean especially for those longer commands if I start getting past two properties on a function or command lit I will move to a splat pretty quick I I'm all about like nice clean looking code and if I've got to scroll the right or or it goes off my screen I kind of tend to have you know issues with it so what am i I think when most useful things of sliding if it's not for you know that parameter mapping is dealing with optional IQs so quite often I'll have a function that some I could provide a primer is optional and this one here I think it's a let's say I've got a function where the credential is optional so if somebody provides me a credential I want to add it to my hash table and an ethe and can call this function with it versus if it's not there I'm sitting more completely so I start with a normal splat and based off of this extra optional value I'll add it to the hash table and what I like about this is I only have one line that's executing this function right because the alternate is I have an if statement here or effectively take you know this whole thing and you're doing this right like this is the like this is how people might deal with the optional parameters right like where they're actually if they on the condition and they call the same method twice and eventually code starts getting in here I want to do some verbose stuff in here right or other logic and all of a sudden your your code is starting to grow a little bit so I love just keeping my one line of execution for my main function and then just optionally injecting the parameters that would be calling to it and this is the more valuable when you have more than one you know optional parameter what else Oh weird age thing just FYI more than anything is that you can actually add hash tables together once like so the first time I do this I can actually I have my person if he's still a good object and he is a little more lying there I can actually add a hash table to a hash table and if I check on this I'll actually have added the zip to it now the gotcha there is you know if I add it again because the key already exists it actually collides so I don't know when I'd ever use this but I'm telling you everything I know about hash tables I got a call it out well those party tricks I guess so it's just a simple way to add the hash table after the back but it'll throw an error if it's already existing that's what you're saying yeah it's it's a really quick merge when you've got two hash tables that you think are separate um but be aware of collisions Kevin I've got a quick question for you since you were just talking about splatting parameters on commands I know in some of the older editions of power show using the ISC and so on there were cute little tools that would take when you started building a command with a lot of parameters on it you could in your editor convert that to a splat table very easily is there anything in vs code that does that for you did you know if it is the yes code yes our heavens I don't have it installed if it me knows what it is so there is a module you can load with the PS editor services yeah the editor services that's nice to know because I think I was checking that actually last night and I didn't have installed thank you that that will probably save me several hours work over the next month I get a lot of these to work on so they're sweet yeah you basically put your cursor on it and I get something like I was like all shift s or where the key is o'clock the menu and that's several options to perform actions on your code and the one I use actually the most was the splatting now when I'm like running my own code I'm very cognizant of it so I actually tend to like splat from the beginning so the fact that I don't have it I don't miss it so much but if I was working on another codebase like my work machine where I might be in you know touching work code bases where somebody might not have done that um I definitely have it loaded there so yeah the fact that I'm missing it just is just more adjustment to having just making my own code lately and haven't had to jail how the people's really long yeah that's pretty much exactly the situation I'm facing everything's a little while cleaning up somebody else's good thank you I appreciate it yep all right so now we can get really complex with our hash tables like you can actually nest them like placing hash tables as properties of other hash tables so like if I actually want to be a little bit more robust where my person has a location location has like a city in a state I can do this to effectively create a hash table or the location now he himself is a hash table of two keys um I'll show you how to actually look at that here in a second but if you want to define it in line you can literally just yeah just just nest them just trigger your key and give it a value that is the hash table and you can nest these as deep as you want to and then accessing them we can just just do the dot property off the location to get the city so here I'll be able get Billy Bellevue out of the list and we can get more nesting and here's where I'm kinda bringing those two ideas together where I have this list of people right so my my list of people is Kevin and Alex and their values is a hash table that's treated more as a set of properties so I can ask Kevin's age is or your Kevin Sidious Bellevue versus Alex's similar properties and here's all the permutations are the ways you'd basically able to access into those right these are all I should execute this code first can't skip chunks to the demo so I get the age the city the age in this city so I'd have more out of convention if I'm treating it up so given this example here I might lean on a syntax like this where I like the treats I have a when I have a hash table of things versus a hash table of properties so when I'm asked for properties all dot property off of them I think of as a property but I think there's a list of common objects I tend to index in but one exception is when performance matters if performance matters you will always want to index in the actual dot property is just a little bit slower and in fact I think I have a sample here [Music] here it is okay so I've got a sample here where I'm doing a measure command around a for each and we're gonna do it I don't do it that many times let's start smaller I don't know how long it's gonna take we're gonna do a dot property off of the name just to get the value out and I mean index into the value out so I'm doing two major commands and I'm selecting the milliseconds okay so let me create my dad a sample I'm basically asked for the same value over and over I'm gonna start small my batch and otherwise these two are equivalent and let's okay that's fast let's ramp this up a little bit zero zero let's run these again go wait a little bit on this one there's the first one and like we're not quite twice as fast like I mean over the course of a million records you know I see what almost like a 20-30 percent difference so if performance matters you definitely want to be indexing in versus doing the dot property but if it's not performance wise personal preference probably takes a scuzz people can do i was people people do either one pretty interchangeably I probably more on the index now because I'm aware the performance of it but quite often I isn't that important for me a performance yeah it was a question yes would you just run dollar people so we can see the nested hash tables yeah so let's okay so I'm sure to look I'm in it I have this should I show this sooner actually okay so if I want to see what's in here right I've got this problem where format table it's like you're a sell sheet right I've got this column and the value and the column the value and here it's not actually telling me what anything is inside the nesting so if actually want to see that I do the convert to JSON and that's my go-to way to look at convert all right so long but so using convert to JSON that that's a can I see nested or structured data right so I feel like I can't see I'm not getting a good view from the console the JSON view well actually let me see the nested structure of it so I mean to catch myself in that guy but you actually be effing to be showing us how to look at a nested hash table walking the list very similar to before where I get the name of the keys and quite often if I mean accessing something multiple times I'll just say hey give me the first purpose of the person based off my name and then we can get the properties of it in the loop so this guy here is able to walk it with a bracelet hey Kevin so um your earlier example when you were talking about indexing in for performance versus that the dot equivalent is that when you when you say indexing is that the that the dotnet way of doing it because I see I feel like every time there's a performance improvement with PowerShell it's going to Native net that holds true there yeah that's the syntax you'd use in c-sharp and that the ability to do that the dot property to get to the key is special magic that powerful added for ease of use like I don't think place not in c-sharp I don't think it works that way I can't I can't speak to like the JavaScript world like they might have some of those shortcuts but it's really one of those where yeah the raw c-sharp boy is beautifully fast and PowerShell added a little bit of magic to make it easier and a little bit of magic has just a little bit of overhead okay and here's an example for looking at the Nessa - table let's see we can notice what I point out you can create arrays of hash tables like I should be array of hash tables I think we need to do if we want to look at him you'd actually able to see the JSON we got to see that yeah it's bits and rafe hash tables I tend to find when I'm doing lots of JSON type stuff I trying to work with stuff as hash tables because I feel like that's what I'm manipulating structure and keys the most if you ever need a sort a hash table burner array of hash tables oh yeah okay that's what example in year so it's weird because we won't be able to do like you know that name on this hash table to sort on it because if you think if you treat it like an object that's more natively what you'd want to do but in this case he's not gonna sort on it because it doesn't actually do the dot indexing of the dot properties doesn't work on things like a sort object or like you can like a format table but you can do an inline has table expression to say I want to sort on this expression and then actually acts access the name of that hash table so this guy here would then sort the hash tables the array of hash tables based off of this expression I don't find myself sorting arrays of hash tables really ever but it's just a weird nuance that I could run into once and now I'm getting back to like creating objects okay so when I look at this hash table I'm just do this first part you've probably been noticing in my output it's it's really just oh this code here let me do that again okay it always comes in this names on the Left values on the rights and if I actually cast this as a PS custom object here use it instead you'll notice actually getting my keys across the top and the values in columns and many times that's actually the more preferred view so when I mentioned before where I'm giving a return value to a user from a function I'm more likely to give them an object because I think mentally if they're gonna look at it on the console they're probably gonna see it think of it as an object and want this view I've liked the name and the age or whatever properties across the top and have a row for each item that's the more the PowerShell way you see things and a cool little piece of magic with PowerShell is that you can actually create the object later so you can start the hash table do all the magic we've been doing before you give it to the user or at the last possible moment decide that oh I actually want an object instead you can basically cast it to case custom object and then return whatever that is so this is perfectly valid the one gotcha I suppose important worth calling out is that this won't preserve the order of it whereas the true inline syntax here where it's happening kind of in one execution pasher does a little bit of magic and keeps the order of the keys for the object whereas once he's in a hash table and I don't think I can't move ordered hash tables matter in this situation or not I'll have to test that later but yeah so your order is guaranteed if you if you do the custom object later now back to our sorting example I'm actually more likely if I need to sort it I'm probably gonna look at the output and I will often just in the rare cases I need assorted I'll convert it to a PS custom object and then sort and use the output from that so I said doing that really weird obscure execution on the keys properties I'll just turn to an object and then and then and then sort it and the same goes for saving it to a CSV because when we think of C of these we kind of want the the columns and the rows and I'm finically doing the exact same thing here but then when we export it to whatever your path is we get nice nice clean objects that's assuming it's not nested right if it is nested you want to go right to JSON right you good pipe it and save it as JSON and actually get the body back and convert it from JSON back into was a small gotcha here so convert from JSON will give me objects by default alright so if I take a hash table convert it and save it and then rehydrate it if you will convert from JSON gives me an object now on PowerShell seven actually six something to add the property as hash table to actually get the value back as a hash table to keep using it that way I firmly believe that convert from JSON should have been given us hash tables from the beginning but at least now at least as we moved to PowerShell seven it's an option is way to get those objects and then I've actually got you also a ok so a PSD one yeah usually use those for like module manifests but those actually are just powershell hash tables in a file so very much like json is really just a javascript hash table i open up this guy here he's the PSD one and he just know that he is actually just a hash table in a disc and if you ever crack open a module it generally has at least two files right a PS m one for the module and a PSD one which is the manifest and if you pay close attention you'll realize that that's actually just a hash table saved raw brought a disk now so one way to rehydrate that is we can load it I get the okay get the contents with me actually create a script block and then execute the script block to get us a hash a bottom that lets good run that so if i look at content again looks like a file I didn't I didn't get updated I got my old age in there say I should have picked the wrong example like I needed a difference value because never seen me do this presentation about once a year or go to redo it every year I go through and change all these values and I missed mm-hmm so under what conditions would you use this I like that sounds pretty interesting but I don't think I would ever use this all right kinda think of the use case in which I'd try and use something like this so I think today JSON is a much better option right like I think when this old the early days of PowerShell I don't think Jason was a strong and you're actually fighting with more like XML formats so so what place you could use it is if you write a ton of PowerShell and you're creating a file by hand that's gonna be read and you want to manage it as a hash table like and you find that easier syntax than JSON like that would be the one path to go down um or the other one is like maybe you're writing some strip to manipulate the module manifests of a module maybe worth knowing I I want to use it for something and actually started using it until I needed to program eclis updates the file and PowerShell didn't have any native tools for doing that so well I have this funny fun hack to load the file PowerShell didn't offer a clean way to actually save to a PSD one now I do know there are community modules now that will allow you to you know save and work with them pretty much like you would a JSON but I never adopted them and there's one piece of magic here that if you use this property on a variable it is a long one the Microsoft PowerShell desire state configuration argument to configuration data transformation attributes and assign it to any place on a variable this could be a parameter to an advanced function if somebody provides you a path this will do magic and put a hash table in here so if I run this guy I now have a hash table here because of this attribute on this variable took this as an input and did the magic behind the scenes there's not a lot of cool attributes so this one was kind of a hidden one I can't remember how I tracked him down and I've never actually use a production anywhere but I thought he's a cool thing to call out so effectively was just casting it into that and the output of that that class cut is now a stable yeah yeah absolutely so it is gonna say like hey attributes can do some things like transforms and if that actually interests you I do have a blog post series where I talk about creating custom attributes and custom transforms they do this type of thing for different different data and then a quick reminder that these keys are just strings so if you have a really weird key that's like a space in it or special symbols you just put quotes around it you can you can use it because like before like this here be a comment normally right but if actually want for god knows what reason but actually when he says Mikey I'm just put quotes around it and it becomes about key they could then index you know with a string and funny enough you do the dot property you can specify a string here as well to get whatever odd property exists so if you get some odd data and a hash table and you actually need to access that I'm using this other syntax you can do so and even better victor the example here next ya can actually put the value in a variable and use the variable that you can specify a variable that is actually a string and you'll actually evaluate that first and use that to access the value in the hash table so really ugly like yeah I find this really ugly whereas I mean why do that when you could just easily do this I think that's more easier on the eyes but this is perfectly valid PowerShell it works and if if I was doing I would definitely lean towards the brackets to the indexical at one readability um how do it on time here all right those never good time for questions we're virtual so we can go as long as we want but so long as we stay on topic I think we're doing good and it's been a lot of good questions you know through chat we've been answering some of those as we can and pulling them back into the video as we can so I think we're doing a great job and what more do you want to cover where we can even ask people to reach out and open up the lines and talk about things I I got more things I can dive down here but I felt like this would be a great time to like pick my head up and see there's more questions that we've covered so I get to the really technical stuff well I'm gonna kind of go go abstract and say um do you do you have any like best practices for using hash tables it's like almost you've done a lot of like you know kind of gotchas and stuff like that but some things like a this is you know this really saved my bacon and then also this this is stay away from this it's almost like this you know people are talking in the chat right now I'm like don't use spaces and turkey names wherever possible so that's a big thing hey try to avoid but other you know kind of things like that um yeah if people are calling out the spaces yeah don't put spaces in your key names like so okay so one place that people new to powershell one of the traps they fall into I think hash tables are a beautiful solution for is when I start asking the questions of hey I've got this variable name of creating dynamically how do I update and access it dynamically right they want my guts you know person 1 person 2 person 3 how do I create a list that's gonna go grab and work with all those variables so like anytime you're trying to dynamically work with a variable name just step back and use a hash table instead like I think it's I I I feel very very strongly against the variable names actually having an actually matter mattering for the code like if I have logic and the logic itself cares that if variable is a specific name I think that's a problem because I want to be able to rename and refactor and just pick beautiful names if I see a variable it's not clear make it more clear now I wanna do it consistent across everything but the case is when you might have like data for some reason I'm like I'm loading a CSV and on Row 1 I had this name let me go find the variable that matches that name like that's a case that I'm saying hey you want this hash table is a really simple bucket we can actually have any name you want and you can walk it and you can index into it and everything you're trying to do with variables using get variable or or or new variable you can do so much easier in a hash table and it makes logically more sense I think and I suppose on that same notes let me jump into top of this file so imma shoot another demo to listen to a little bit about performance and show one place where a hash table really really shines so I'm gonna start by creating some test data I've got this this this module here from Doug that name it lets me generate random data so let me just create a list of servers and lissa patches so the scenario is I have a collection of server info that tells me like the owner of something like I could products pan that so I'm creating lists of computers with an owner and a phone number and I still have happen to have a second list that is a computer name but tells me like when the last up it was what the status is okay so let me actually look at the data I generated so server info just gonna work jover my other window sorry find it alright this guy here has one set of data I actually need to merge it somehow with this other set like that's the scenario that I think it's very common that once yeah so as we see this listed added tells me my statuses and this tells me who to call and I basically want a list that combines both of those so I can you know send emails to the people that are unsecured right or call people are unsecured like that's that's necessary to list to work with so a very simple solution is we loop over one list the server and though and then we say all right let me filter the second one to get the item that matches my computer name on face value this actually sounds like pretty straightforward but we're building this performance gotcha really really fast here so let me run this to see our output just to see we're producing here I got a computer name of an owner in a status right like I can't get more properties if I wanted but to keep the demo tight I'm mr. on a map owners so those that aren't tracking what's going on here I have a second I expand this out I take the same I think of the where logic and I do it more verbose so it's actually happening is I'm going to outer for each and then I'm doing a for each again over the server patches and where the computer name equals i i'm creating my object so basically it's gonna walk the server patches list in its entirety every single time I walk one item in the server info list and I think this clipper code here I'm actually measuring that so let's say if I didn't find a match let's measure how many operations we've wasted so let's do this here and my ops is oh well it's gone 20 so there's 20 operations that were wasted now a small set of data that might not matter let's just wrap this up just a little bit let's go 50 items in both these lists let's say I only have 50 servers I think a little bit longer generate I'm gonna jump back down to my same code and we run this again let's see how many operations we wasted or are wasting and then just like just that just keeps going up and up top like like it's it's it looks like such a straightforward solution of the problem but we overlooked that this is actually like an exponential performance hit so it's like an N squared for 50 items times 50 is how long it's gonna take never had a hundred items it'd be a hundred square so hundred times 100 so let's not run that guy to the entirety because he's gonna go on way too long but hash tables offers a really elegant solution to this as the form of like a lookup table so and in fact I don't think I've mentioned this yet a group object has a hash table property that will actually create hash tables for you out of a data set so if I run this it's actually gonna look loop over my server patches and using the computer name to create a hash table for me if I do a quick peek at this guy he is so my server name is the key and the value is actually the object of the row so the entire object is the value and now when I walk one list so I walk the server info I just do a direct look up for the the the info using a computer name and now I have all the information I need between these two objects to create my final object and this here is so instead of doing like 50 squared 50 times of 50 operations I'm walking this list once so that's 50 operations and walking this list a second time that's 50 operations so that's like a hundred operations total compared to 50 squared or however you know so as list grows so what you're basically saying here is this is the the true magic and why you should be why you need to understand this and why you need to you know you need to wrap your head around this yes and let me run this while we're talking here so I got the same demo but gotta measure Commun wrap around it so I'm doing our are where so we're doing one full walk and one full walk and then here I'm just doing the the lookup and actually I'm including the lookup in the measurement because otherwise I'm cheating if I'm not let's run that hopefully 50 is not too many nope fiasco doubt put there we go so I'm not faster than math right but you see a significant difference um already and just in just that one methodology now I can probably do some hacks to make the first one a little bit faster but as long as I'm doing an exponential walk it will always be slower than a single pass through now this is very computer science II like if you guys have that computer science background they call like the Big O notation or they say one is n because I'm walking at once or the first one is actually like the N squared versus the second one which is O and but but if you're not few science don't worry about it but specially thing in the hey one is really expensive and the bigger the - that gets the slower it gets so yeah so that's there's the one piece of magic is you can create a lookup table and just pull stuff in and out with one operation really fast which is so much better than trying to filter every single time you walk look at the data and that that alone will give you factors of performance increase so I think one of the the other points is to mention there is that not so much even look up at that Entei pull data back is to go find data so if you needed to basically go search and to see if it's existing and so this idea that I've used it quite often in this in similar fashions is not to even like merge things kind of like we're doing here but to go hey see if it's there if it's not then keep going or if it is there give me the value and keep going and that a whole idea of go find things that I don't even know if it's there so maybe if it is it is and I'm dealing with large data sets even small data sets just better to keep it in this form and if I use it in this form it's like hash table lookups it's super fast and it can find things that aren't really easily found in large data sets and that might be just a good thing to be cognizant of is where is gonna walk in tireless so the larger your data set is the bigger of an impact using where we'll be so if you find yourself calling that quite often especially in a loop that's that that just calls out for I need something that she's going to go give me the value directly like if if you have to walk at least once crate your lookup table and in the beauty of it is right where the hash table is once like I keep saying walking a bit busy you new write the entire list once so if I have a million rows sure I'll walk a million rows once to build the lookup table but if I have to access it just 20 or 30 times those next 20 30 operations will go directly to the item in that list it doesn't have to find it it just knows instinctively where it is but if you're doing aware it will actually check every single item and when it finds your item it will keep going and keep looking so this it's not even sparked at the source circuit this the scan it will search the entire list every time you go to check it and that's the big performance gain that's yeah can you search on more than one key field no but if you're if you kind of have if you know ahead of time what keys you need to look up that could be another case to do like nested hash tables like you could have when you're creating it and you'd have to do it by hand like this this trick here I'm using to create the hash table on the fly like you have to do the work to to build it but I've done it before wherever I think my most complicated one is where I had four levels of nesting well I have my data set is large set of data and as I walked through it I basically create the values inside the hash table based off the first column and and it actually used the check of you know does the the first key exists if not I'll create the propping given empty hash table and and build up the structure as I went okay so it's like in my example if you had first name as one field and last name as another people can have the same first name so you can't always go searching by one or the other you need the combination in order to be unique and so you're saying put those two into a hash table that's one level down from your initial hash table and then you can key off of that yeah I mean I will say your logic it's more cumbersome that way but yeah when you start talking you know Rob forms in speed those will give you gains and then I suppose my last I suppose an additional call out is if performance really matters and you find yourself not calling any powershell commandlets like actually like the functions or commandlets of powershell itself and it's all data manipulation and hash table and logic consider very heavily looking into c-sharp like i think that one case actually i think that case where i actually had like a that four levels of nesting I started in PowerShell and pure performance reasons we reworked that same almost exact same logic in c-sharp and echo a like a three-fold performance increase where I thought we'd already milked as much as we can quit cut out of PowerShell and just changing languages got a drastic drastic improvement over our what we needed I think one of the other points to point out is that when you're doing this kind of thing is that some of the way or and even this form is that it's a it's a cost versus reward thing as far as like hey you can take the entire data set and throw it into a variable into the hash table so you need that much memory so if you're dealing with very large datasets depending upon what you're doing can you put the entire thing in the memory or do you eat well I need to parse through it so I need to use the where so I've been in cases where I'm dealing with large datasets and I can't actually use that much memory and so to keep memory low I had to give up you know memory for time but if I needed a time then I need to take the memory and so then I need to figure out what machine can I run this run boy I need you know why have enough memory to do it or I'm just gonna accept the fact that I'm just saying eat all the memory on the machine so that's one of the points there no that's a great point cuz yeah the hash table is kind of assuming you're here along that entire chunk into memory and I've seen some hacks for people are using like the sequel data provider against you know CSVs for performance or if you you know show up stuff into a steepler my sequel to offload some of that okay it depends on your size what your trade-offs are if yeah time memory space yeah all things go away one of the other comments is that you know - I'm not sure who said that comment as far as first and last name is it it may be beneficial you know you'd have to see what performance is what you're looking for is to actually create a you know he did the example of like look up and created his hash table that way and you could even just create a lookup hash table on the fly that is effectively first-name lastname key pair and then go look that up and use that as the key pair instead of some other parts of the data set and so then the key is the first name last name and then the data of the value is the entire object you're looking for good questions guys anything else I remember last year we were at Chattanooga PowerShell Saturday and Jeff Hicks had done sort of an advanced class prior to the Saturday and there was some pretty smart people in the room that were beating him up a little bit about hash tables arrays custom objects all this stuff about and really trying to drill home the point that you'd be better off using a generic lists and he had he he kind of was advocating that this idea that you know you really don't want to mix PowerShell and like dotnet and I don't know that 100% agree with this but he was basically trying to say that you're gonna get to a point that it makes more sense to learn net and write a net then to keep pulling dotnet into PowerShell for most people staying in PowerShell taking the performance set and staying with the ease of use is far better for almost most people a lot of the examples of G shown here Kevin are really deep dive stuff and I get it but for the guy who's just starting out hash tables and stuff like that making that expensive hit with where it's terrible but it gets them to do what they want to do easily so and that's sort of sort of the like the secret sauce of a PowerShell which is you can start very easily and it's very malleable it's it deals with your mistakes and your crappy code and as you get better it gets faster as you learn the tips and the tricks here like you're talking about tonight but maybe no your use case right if there's people on this call that are beginner and intermediate people taking that performance it isn't necessarily a terrible thing if it allows you to get your job done it makes you understand how to do it rather than sitting there and trying to figure out all these methods that that maybe aren't so that's a great cause I mean tonight we're definitely drinking from the fire hose here especially if you're newer to the posh tables like in a way I want to call he seeds in the back of your mind so we actually hit into something like oh I think I remember Kevin's talking about that and now actually like prompts you to go back to the video and help you chase that thread when the time comes like you're right I keep calling SF for performance when performance matters and you will know like you'll find yourself in the situation like oh I need more anymore anymore and it's when you're actually driving those last little bits is what I want you to start popping up and thinking about these things like there's many tasks that oh yeah I'll use the where filter all day long because I had actually have no performance need oh not whatsoever you know I have something that's gonna sit in a schedule task and be idle for every five minutes like there are times where I want the cleanliness of my code and maintainability of it far outweighs those micro optimizations for performance you know some of the things I called out earlier on in general we're about just I want my code easy to look at I want to be able to you're gonna spend 10 times as much reading code as you will writing it so create code that's easy to read and performance stuff isn't always easy to read yeah that's a good point let's say I got some other odds and ends here let's see I recovered the group object but there's a couple special hash tables like the PS bound parameters like when you're doing a advanced functions the PS bound parameters will actually let you get the values that the person passed in so here I've got a function that I'm checking if they provided I've got first parameter and I want to see if that should pass into value or not so if we run this and I say first so the passing value for first is 90210 and we see the logic says you know there's my first string you contain the key and this guy is just a hash table like I actually could in here do this but I don't like the way this looks says why use the other format here am i again talking about the way stuff looks and feels in fact I like this I just like this so much we're gonna do this instead a string formatter and so it's basically the same code the same logic but now I'm actually asking the parameter what is first value is now this guy's great for a lot of things but he's got some weird new wants us to him and I especially said he's what was passed in alright so if I go to scold test parameter on his own um Nevaeh was provided and it used the default but my logic might might check in the middle didn't didn't execute so default parameters don't count as bound parameters only stuff those passed in and to that regard if they actually pass in null it actually has a value in there so the past in value for first is well nothing because you know we passed in null but that was enough for my thumb parameter to say it contain the key so before when I say in sometimes it matters if there's a key there versus being null this is one of those cases where I actually need to know if somebody passed something in you have to passed a null that contains key is one way to do it but the real reason people use s bound parameters is create what you can't call proxy functions where I have one functions calling a second function and I primis need to pass in almost all the same parameters maybe I'll do something special like you know propose false or something like I might have some changes or some tweaks to my logic but for the most part if all my parameters need to be passed to the next function you can use kiss bound parameters and slide it in so that it would get called I think that's by the number one reason your way people use kiss bound parameters so here I was able to get the BIOS information by splatting the parameters from that and then oh yeah okay this is gem - if you haven't seen this guy before the PS default parameter values like this is something you'd put inside your inside your profile and it will actually specify a list you've basically defined defaults for functions before you actually call them so if I want there's my call format table - auto size equals true I could put this in my profile and for my table would do that I've done that before where I'm like connecting to the same VMware server over and over like oh heck I'll just hard code the server name into my config and I never have to type it again I just call connect to a server gonna pass in this to the server the places they use it actually is it for install module like I want install module just install my modules for me so I override all these others so it just does it like the scope to current user force it true clobber true skip publish check why not write like just let me just go in specific thing so that way I wouldn't call install module installs one trick here if you ever given with multiple repositories install module doesn't like seeing the same module from two of them so I kind of default to the gallery at least in this example and I just override it and I need to pick something else no internally I default to my journal repository but that's a weird edge case but but the other gem you can do is use wildcards so you don't have to talk about the full name like if I want for some reason I need just verbosity or debug values on everything I can say yeah get star verbose equals true and things it would default verbose you just true for everything I call now there's better ways to do that because there are some global variables we can call but maybe for like a credential or probably better yet the ad commandlets like if I'm working in a if my test lab is a different domain and my current one and so I might not have this in my profile but I might just call it directly to say alright for net Rick right now everything I do let's let's talk at the lab I can specify you know star - ad star server equals lab domain and all the commandments we'll hit that lab domain instead of instead of requiring me to specify that each time another beautiful Jim is regex matches like if you used much res X right they got these look like capture groups so when you match a string this capture group will be placed in in this matches collection so if I run this here I should get matches one will be the value in this collection and zero is actually the full stream or everything that matched this anyways so where's the yeah actually it's the full string but the my favorite favorite favorite way to use though is named matches so if I use put a name on there using this special syntax question whatever here I've given this capture group a name and now on my matches I can just do I can just access it off this this object using that same name so this I use all the time because it's so easy to work with so if you look if you if I I found using regex anywhere I'm always using a name capture group and I pretty much always accessing it this way and it sports multiples here so I've got the same example with two things I want to capture on and I know if you guys are really good at regex you probably notice how lazy I'm being here like I I totally just grab a string say I want this I say alright I've got that now nice right like the laziest way to do regex but it's quick it works and it makes examples kind of clean so here's one we're doing two patterns and name is one matches the other if I do the full object I think we'll see name missin and then 0 is the full string that I matched I do have a call out for hash map but basically if you're ever using a hash table Flo's sole purpose of trying to find something that's unique we're like just putting like the number one or the value you're putting in the hash table doesn't matter like I've caught myself doing that when I'm trying to find unique things and here's an example like okay I'm just gonna sit true to the values just so I have like the filtering but I'm not gonna dive in an example just for time sake but there is a way to just call in the.net like a hash set and whatever your data type is and now you basically add an item to it and like the fact that's they're not there tells you something as a way to do some d-do processing I think group object and sort object unique are much much faster in PowerShell seven so I'm actually more apt to use those but I think in partial five there was some of those you know exponential costs that I find myself quite often saying right I want to I need I need all unique server names from this giant list of data I would feed it through like hash set just to know just to get those unique names yeah it's it's no those micro optimizations but a trick to be potentially aware of and I think that's all of my notes I had on special hash tables that was a lot of cool stuff certainly yeah especially some of the last couple items I was like alright so we've we've gone into the weeds and no use all the skills that you've learned in the past hour in 15 minutes and you know actually hour and a half now and certainly use it so I want to certainly thank Kevin for no doing a phenomenal job going over stuff so let's uh let's give the people that are still with us a chance to come around see if they have any questions about anything from the evening or something that just piqued their interest that they always had a question about so you guys have been very active in the chat and I do appreciate the guys have been able to jump in and answer questions in lieu of Kevin and having to do that but if there's somebody who has some questions they'd like to bring forth though just even you know just a something related here's your opportunity guys if not we're gonna end this recording probably in a couple of minutes if the questions get a little thin excellent presentation thank you alright so I guess it's a little thin on the questions tonight I mean you covered so much information so for those are not familiar with Kevin's website one of the great things about Kevin's pages is their fantastic reference information I have a website and I try to post some stuff up there but when people ask about arrays and hash tables I tell them how she'll explain calm it's the default place I said send them to and for the objects that he has covered in his website here I would hasten to say there may not be another better sauce source for everyday usage so if you haven't visited the site definitely want to check it out there's a lot of bookmarkable links that you want to save for future reference when you go how the hell do you do that I forgot that it's the perfect place to go I suppose one example is like the if statement I probably have 3,000 words on the if statement so he could have thought of something simpler in the if statement I cover like so I just like this talk was you know a you know from the firehose like take what you can you know put those seeds out there and come back to it later I think I treat my reference materials the same way like I do not expect people at the beginning and just power all the way through it but get to where you're comfortable read past a little bit seems like alright I'm getting lost a little bit about kind of like what's happening here and then come back in like two months three months or a while later and then you'll find yourself way further down that page and you'll just pick up so much more value the next few reads through and I think actually my favorite ones of gems it's probably the switch statement because there's so much magic in that that command that people don't realize is there so he's when my favorite wants to toss specially like people coming from c-sharp that think they know a lot about you know PowerShell McKee yeah but the swish statement did you know it can parse regex read from the file and loop over items like that's just a crazy thing for one come in to do alright so Kevin take a breath there for a second I'm just gonna we're gonna wrap this recording up for the evening we'll finish it off by saying thank you to Kevin for presenting this information tonight and make sure you join us for the next one will have lots of great stuff and in the future
Info
Channel: Research Triangle PowerShell Users Group
Views: 2,770
Rating: undefined out of 5
Keywords: PowerShell, Administration, Windows, Server, Automation, Scripting, Code, Microsoft, North Carolina, IT, Technology, Education, VS Code, Getting Started, PowerShell Automation, PowerShell Scripting Tutorial, PowerShell Commands, Kevin Marquette, Hashtables, PowerShell Fundamentals
Id: t2umKNzjZp0
Channel Id: undefined
Length: 99min 4sec (5944 seconds)
Published: Sat Feb 08 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.