PowerShell Remoting

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 nine in the series, PowerShell remoting. 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. In the Learn Powershell series so far we've learned how powerful PowerShell can be when managing just a local device. But now we're gonna expand on that capability and learn how to manage hundreds or even thousands of servers using PowerShell. This episode is a little bit different than previous episodes in that it assumes some general systems knowledge outside of PowerShell. We're going to be establishing a connection between two devices, and so a general understanding of network protocols, firewalls, routers, and general server management is required in order to be able to troubleshoot and understand how to get a connection from point A to point B. And all of that occurs outside of general PowerShell. Once we establish that connection we're also going to have to be able to authenticate to that end device. So an understanding of authentication protocols is also required. So things like Kerberos, NTLM, basic authentication, negotiation, and CredSSP are helpful in understanding how some of this operates behind the scenes. When you're done with this episode you're going to have a pretty solid understanding of how to touch every device inside of your environment. So, you should be at an experience level where you have some grasp on these networking and authentication concepts. To further complicate matters there are many possible connection scenarios. Take a look at this graphic. Every single one of these is gonna require a slightly different configuration. This video can't cover every single one of those. So you are likely going to have to do some additional research on this topic depending on the setup of your environment. Don't feel put off by the complexity of this topic. If you're wondering why you should invest time or resources into learning how to implement PowerShell remoting inside of your environment remember that PowerShell remoting is one of the most powerful capabilities that PowerShell has to offer. This is the component that turns a three-week task into a five-minute task. If you get a ticket that would normally take you say half an hour to accomplish on various devices inside of your environment. This is the capability that turns that into a five-minute task. So this is definitely something that's worth investing in. Let's dive into the code with Windows PowerShell remoting first. We are going to be covering quite a bit of code in this episode and it's code that you're likely going to want to refer back to later. Keep in mind that this series not only has a corresponding blog article, but it also has a corresponding GitHub. So I'll make sure to include a link to this in the description below but you can come on to the GitHub for the series click on the learn PowerShell folder and find every single episode and the code that was demoed in each of these. So if you click on episode 9 you'll find all of the code for easy reference that we're going to be demoing today. Okay so winrm is the protocol that PowerShell uses for establishing remote connections inside of Windows. And what you need to understand about winrm is it's not something that's natively set up by default inside of Windows. So you don't just get this in your environment you need to configure it to listen for winrm calls. winrm comes in two pieces a client and as a service I'll be showing you that in just a moment. So the client is used to establish outbound calls and the service is what's going to be listening for inbound calls. So we can use this cmdlet, Test-WSMan to see if this device is configured for winrm. so I'll go ahead and click f8 and if you get this back that means that the device is configured for winrm access. If we hop over to a different device and run the same command if you give back this error that's an indication that winrm has not been configured and set up on this particular device. To get winrm setup the easiest thing to do is just to run winrm quickconfig. And this will set up winrm the client and the service with all the default settings. There are many different winrm settings that you can configure. I'll be briefly touching on a couple of those but you can still use the quick config to do things like configure whether you want to use HTTP or HTTPS for your remote connections. This will start to make a little bit more sense when we look in the actual winrm settings. We can do that using the winrm command winrm get and then we can look at the client and we can also look at the service let's start with the client. I'll go ahead and run F8 on this line. And if we take a look at this so what this is telling us is that this client is able to use the following authentication protocols. And it's configured to use the default ports when connecting outbound so to other devices so this will use 5985 for HTTP traffic and 5986 for HTTPS traffic. And the trusted host currently loaded into this is just one. Okay so if you're wondering why you would ever use HTTP over 5985 keep in mind that for domain to domain traffic so like a Windows Device joined to a domain and this other remote device here that I have that's also joined to the same domain, that that's supposed to be within the confines of your trusted network. And that means that you shouldn't be going out over the Internet's all contained within side of your own enterprise network. So by default especially within the same domain winrm is going to default to 5985. Again depending on the various configuration scenarios you will likely find that you have to jump out to HTTPS instead. But after running winrm quickconfig this is very typical for what you're going to be seeing set up for your clients. Let's go ahead and look at the service now and this is the error that you'll get when you're not running as an administrator. So I'm gonna go ahead and copy this out real quick I'm going to close VSCode and I'm gonna relaunch it as administrator. You can shift right click and run as administrator. Okay and I'll go ahead and run that winrm service command. Notice we get a little bit more information because this is what's actually listening for inbound communications. So we can see things like this is not accepting every single authentication protocol. In the current configuration this is only accepting Kerberos and negotiate. It is configured to use the default ports of 5985 and 5986. We are currently allowing remote access to this device, and again all of this is configurable using the winrm commands to configure every single one of these settings depending on the needs of your individual environment. Now let's go ahead and take a look at the listener and the listener is the thing that's actually actively listening for winrm connections. So I'm gonna run the command winrm enumerate in the winrm config listener again you don't have to memorize these they're available for easy access on the GitHub. So what this is telling us is that winrm is currently listening on these IP addresses. So if your server or device has multiple NICs or multiple IPs you can configure which of those IPs are going to be responding to winrm calls. This is currently configured for HTTP only and it will listen in on any address inbound. So again this is can be very granular and very secured so you can tell winrm that it's only able to accept remote connections from certain addresses over certain protocols using certain authentication mechanisms. So its a very powerful and highly secure way that you can manage your environment. OK so let's go ahead and introduce our two devices that I'm going to be using today for demonstrating Windows remote access. On the right here we have a remote device called MDT which is joined to the ark domain. And on this side I have will use our environment variable computer name. This is HUB. And if we look at in the environment variable of user domain this is also on the ark domain. So both of these devices are on ark and by default that means they're going to be using winrm HTTP because this is a trusted network on this domain. This is a very common remote access scenario for your enterprise environment. Ok so let's go ahead and remotely verify if this device MDT is configured and accepting winrm commands from this device over here. We can continue to use the Test-WSMan cmdlet to do that. Before we get started on that let's go ahead and learn how to use the Get-Credential cmdlet. Notice that I'm loading the results of Get-Credential into the credential variable. I'll go ahead and run f8 and notice that immediately prompts me to enter the credentials that are going to have access to this remote device. Since these are on the same domain I'm going to go ahead and enter my domain credentials that have access to the MDT server. So notice if I pound out credential in the console down here that credential contains the username and password. But I can drill into the sub property of username and see that, but notice that if I drill into the sub property of password that I'm unable to see that. It is stored securely. So this is a nice safe way to store your credentials and send them over the wire. So now I use Test-WSMan to establish a connection to MDT, negotiate what type of authentication should be utilized in this transaction, and I'll use the credentials that we just specified to establish that connection. So I'll go ahead and click f8 and notice that we get the same return as when we're testing locally indicating that our credentials are good, our authentication method is good, and that MDT is configured for winrm and accepting connections. So just a quick way to verify if your remote devices are configured for winrm. Here's another useful cmdlet for verifying that you are actively listening on 5985 which is the default winrm port on Winows. So you can run the Get-NetTCPConnection cmdlet and specify that 5985. Remember depending on which version of PowerShell that you're running that not all cmdlets are available versus 6 versus 5.1. Definitely check out my video on PowerShell history on why that is operating that way. So I'll go ahead and copy this cmdlet, hop over to PowerShell 5.1 and run. And we can see that we are listening on 5985 on this particular device. You can also use Test-NetConnection to see if a remote device is also listening and responding on port 5985. So these are just some helpful cmdlets so you can see if the network is configured both locally and remotely to accept winrm traffic. Okay now we've got some of those basic configurations out of the way let's have some fun getting set up for establishing a remote connection to this device and doing things on that remote server. So again we've already established the credential and loaded it in here and that variable is still available in our current PowerShel session. So now we'll use the Enter-PSSession and what this is going to do in if you're familiar with SSH at all in the Linux world this is very similar to that. So we're going to enter a PowerShell session on the remote device so I'll change this example to MDT, and we're going to drop into a PowerShell session on the MDT server. Let me show you what that looks like. So notice if I type in hostname down here that we are currently on HUB. But if I enter this PS session on MDT and I click F8, notice that we get this front-loaded MDT indicating that we're no longer on HUB. We are actually running commands now in the context of the remote MDT server. So you'll notice that if I type in hostname now, that the return is MDT because it ran on that remote device. This is a fantastic way to replace RDP in your Windows environment. You don't need to RDP to a server anymore you can do everything as you need to do from this console now. So if you want to check the service of bits on that remote device you can see that MDT currently has that service stopped. And any other management that you need to do from a PowerShell perspective can now be executed and run under the context of MDT. When you're ready to drop back to your local device simply type exit and notice that we're now back on our normal PowerShell session, and if I type in hostname again we're back on HUB. So Enter-PSSession is a fantastic way to manage a remote device but it is only capable of managing one device at a time. So you are inside of that session on the remote device and only for that remote server that you've specified. So this is a great way to manage a remote device but we can use winrm to influence a great many servers, not just one at a time. And in order to do that we're going to have to start establishing sessions. So this is where we're going to start to get into the New-PSSession. So a new PowerShell session cmdlet. So let's walk through this real quickly. We're going to be running this New-PSSession cmdlet specifying the computer name that we want access to. And of course the credentials that have access to that remote device. So again we're going to be specifying MDT as our remote device and using the credential variable that we've already loaded using Get-Credential. So I'm gonna go ahead and run F,8 and notice that nothing seems to have really have happened so let's look at this session variable. What this is saying is that this is now loaded with an open and active connection to that remote machine. So we can leverage this session for a wide variety of different cmdlets. It's kind of an open gateway to that device now. So let me kind of show you what that might look like. We'll come down here to our Invoke-Command because Invoke-Command is the way that we're going to be leveraging these sessions to perform different various tasks. So I will use the Invoke-Command, I will specify the session parameter, provide the session variable that we just created which is an open active connection to that remote machine and I'll go ahead and specify the script block parameter down here and I will open and close some curly braces. And we can put things in here like hostname. Lets track what this is going to accomplish. We're gonna invoke a command against the session that we just previously established, and it's gonna run the script hostname. So what do you expect to be returned by this? Let's go ahead and click enter and find out. It returned MDT. So we just ran a command against a session and it returned the host name which is the script that we specified for it to run. Let's come back up to these session variables and notice that we can create sessions to multiple devices. So we can do things like specify a list of servers. You could even specify using Get-Content an entire list of hundreds of devices. So that would load an entire list into the devices variable and then you could establish a multi session to multiple different devices inside of that list using the same credentials. So I will alter this example to include not only MDT but will include another device as well. So I'll go ahead and do MDT and I have a another computer in this environment called DC. So we already have our credentials loaded, we'll establish a multi session, so a New-PSSession to both of these computer names. I'll go ahead and click F8. Notice if we pound out the multi-session variable down here that this now has two active and established remote connections to this machine. We can push the up arrow on our keyboard a couple times, come back to this Invoke-Command, and this time we'll change this session to multi session. So I'll come over here and change this to multi session and tab for auto completion. And again we're just going to run hostname against both of those devices. Go ahead and click enter. And we just ran that hostname request against two devices very quickly very easily utilizing some basic PowerShell to establish those PS sessions to those remote devices. I hope you're starting to see the power behind this capability. Now again there are some advanced features in here and I've included some examples for you to reference depending on what you have in your environment. Which you can establish things over SSL. Once you start using SSL for winrm you are gonna have a start managing certificates. You may need the ability to skip a check for authority, or some type of certificate revocation is going to be skipped so there's options in here for your PowerShell sessions on all kinds of different factors that you might encounter inside of your environment. So definitely come back here reference some of these advanced examples. One thing to note is that when you are establishing connections over IP versus hostname in a domain environment you are gonna have to fall back to SSL so that's something to keep in mind. All right so now let's take a look at some of the more advanced Invoke-Command examples to start getting a sense of how powerful this capability really is. I'm going to change this session to the multi session that we had a second ago which is still active and open. So if we check down here we still have open and active sessions to those machines. I'm gonna change this session variable in this Invoke-Command to multi session and the script block that we're gonna be running this time is a Get-CIMInstance and we're gonna be finding the number of logical processors that that remote device has. So this is a quick way to check how many CPUs the remote device has. So again we're running the Invoke-Command against those sessions previously established, and running the following command in our script block. So I'll go ahead and click f8 and now I just audited my environment and we can see that the first one has three, and the first one has two. Now this is what I want to caution you about when you're running commands remotely in this fashion. Which device is which? Well they don't run in order. What happened is Invoke-Command runs in parallel. And, what it's getting back is the first machine to respond. So this is something you definitely have to keep in mind when you're running Invoke-Command against multiple sessions using winrm. So this is representative of a device that responded first not necessarily the device that you had first in the order inside of your list. So it will come back in an out-of-order fashion depending on which device is the fastest. And so you'll need to take additional steps to identify the devices returned, so you might want to include the computer name inside of your script block or something to that effect so that you can see which device has actually responded. I've included a couple more examples here of checking the RAM on the remote device and checking the free space on the C Drive, but the sky's the limit. If you can imagine it and write some PowerShell code to do it, you can have that code execute against an unlimited number of devices very rapidly inside of your environment. So try to imagine a ticket coming into your queue, or some type of task coming down from leadership where you have to stop the bits service on every single device inside of your environment. I mean normally that would be a pretty huge undertaking if you were to start RDP'ing to those devices inside of your environment. You might have to get with the active directory team to establish some type of group policy to start pushing that out, or you could you know get with your change management team and with one line you could stop all the bits service inside of your environment. So how would you go about that? Well it's the same thing you can just copy this bring it up here invoke that command against the multi session and you would simply stop service named bits. And this would stop bits service on every single remote device that's loaded inside of the sessions variable. Let's go ahead and hop over to Linux now. Notice I've got two Ubuntu machines here and instead of winrm Linux is going to be using SSH to establish remote connections inside of PowerShell. That means you will need to have SSH setup on the device and you will need to have it configured to allow PowerShell to engage SSH. So this is going to vary a little bit between distros but at a high level you're just gonna be installing SSH and configuring it for PowerShell. I've linked a couple examples in the techthoughts.info blog and you can search around online to find out how to configure PowerShell for your individual distro. So we'll install the open SSH client inside of Ubuntu. I've gone ahead and already done that which you can run the following command and we'll also do that for the OpenSSH server to get that installed. Once you've got that set up you will need to go ahead and edit your sshd config file with a couple of settings specific for PowerShell. So we'll go ahead and open up the following location for edit which is etc/ssh/sshd_config we will need to make sure that password authentication is set to yes. So make sure that that is set that way. And we'll also need to go ahead and add PowerShell as a sub system. So make sure the following is also included in your config. If you don't feel like typing all that out go ahead and reference the GitHub. You can go ahead and quickly copy that into your config file. And once we've got that saved and inside of your config you can go ahead and restart the SSH service. Once you've got past this initial configuration for SSH inside of PowerShell you can go ahead and essentially run the same commands that we were running previously except with one caveat of specifying the ssh transport. So we'll go ahead and establish the session using New-PSSession. We'll specify our hostname. Lets go ahead and check what our remote host name is. So we'll go ahead and punch that in. We'll specify our username that has accessibility to that remote device, and will specify the ssh transport parameter. So let me highlight this so you can see a little bit better. We're establishing the session variable, New-PSSession to our remote host name, specifying our username, and using the ssh transport. So i'll go ahead and click enter. That's gonna prompt me for a password to the remote device and I now have if I pound out session a remote open session to this remote Ubuntu device over SSH, very similar to what we just accomplished in Windows a moment ago. I can of course use Invoke-Command against that remote device. Specify our session in our session variable and our script block open and close braces and we can run Get-Process. Ah, the mistake I made here is that you do not need to specify the computer name because that is already included inside of our session variable. So I'm going to back out that computer name and include just our session variable and execute that and this is returning the processes from that remote device. Notice that we get the return from that remote device name whereas I am currently on this particular device. So pretty straightforward. Same commands slightly different use of the ssh transport parameter but you can establish remote connections using PowerShell over ssh between linux devices. One question you may be wondering is can you do Linux to Windows, and Windows to Linux? The answer is yes! That is a little bit outside the scope of this particular episode but you can definitely search around and find some advanced configuration techniques for making that a possibility. I would expect over the coming months and years for that to be come a lot more seamless but today it requires a little bit of tweaking in order to get remote connections from Linux to Windows, and Windows to Linux. But by the time you're watching this episode that may have become a more easy task to accomplish. Let's hop back for really quickly and take a look at some more advanced configuration techniques. And I'm gonna go through these kind of quickly because again this is just an introductory episode into remote capabilities in PowerShell, but there is the concept of trusted hosts. Especially when you're dealing with devices that are outside of your domain and you may only have local credentials to you'll often see the need to add the server name as a trusted host. So you may need to specify a device name and add that in to winrm as a trusted end device. So I've included some examples on how to accomplish that so in your lab at home or with a couple of devices that you have in your home network you may need to add those device names in order to connect to them. Again by default most of your devices are going to establish winrm connections over HTTP which is an example that we shown earlier. Whereas if you start testing devices outside of your domain or start using IP addresses you're going to need to start connecting to those using HTTPS, which is gonna require you to configure your winrm listener to use HTTPS, and specifying certificates and thumb prints for those winrm connections. I've included guidelines on how to setup that inside of the techthoughts.info blog so you'll find some additional reading links to get started if you need to use SSL for winrm. And again here's an example of using winrm to connect to a remote device over IP which is gonna require the use of SSL. And a couple of other advanced techniques of changing the default port if you don't want to use the default winrm ports, and as well as some native cmdletsfor checking winrm settings Get-WSManInstance if you don't want to use the winrm commands themselves. Again all that's available for reference for easy access on the GitHub which I've linked in the description below. I know this episode has covered a lot of ground and requires a lot of external knowledge outside of PowerShell, but I want to leave you with this final example to kind of really drive home how powerful this capability really is. This is gonna be our most complicated final example to date in the series but we are nine episodes into the series now so we're going to start introducing some more advanced concepts. At a high level what we're going to be accomplishing is establishing a list of servers and remotely connecting to all of them to perform an audit about some basic information very quickly. Lets walk through this and see how it operates. The first thing we're going to do is load some servers into this servers variable. How you do that is entirely up to you. You can specify the names provide a list what I'm going to elect to do is pull every single server that's inside of my domain. So I'm gonna run Get-ADComputer and I'm going to filter star. So I'm gonna pull in every single device that's inside of that and the only thing I'm interested in from those AD object returns is the name, so I'm going to go ahead and wrap that in parentheses and just pull out the name and load that into servers. So I'm gonna go ahead and click F8, and now you'll notice that if I pipe that to measure I have 24 servers in my domain that are loaded inside of that. So we'll be reaching out to 24 devices to audit them. The next thing up is to specify some credentials that have access to those particular devices. I'll go ahead and run F8 and load that into the credentials variable. So I'll go ahead and specify my creds here. Next up is to create an array. We need to store our results inside of this array so that's going to be at open close parenthesis for a nice blank array. I'll go ahead and click F8. Now this is a new topic for us that I'm introducing in this final example which is splatting. It's a very cool concept and what we're doing here is we're pre determining the parameters. So let me explain what that's actually doing. The syntax for this is @ and then the open curly Q brace and close curly Q brace and on the left side here what you're seeing is the parameters and then the values of those parameters on the right side. Don't try to over complicate this this is the exact same thing as if I came down here in an Invoke-Command and ran ComputerName here and specified the computer names directly here. Rather than specifying the ComputerName parameter, the credential parameter, or the error variable parameter and the ErrorAction parameter all inside of this line one at a time, what I'm instead doing is specifying those parameters in a predetermined fashion into the invoke splat. And so all of these parameters are predetermined and then I'm splatting those parameters utilizing this special @ here and so all of those are predetermined and are going to actually be inside of here, inside of that splat invoke splat. So let's talk about some of the parameters that we're specifying. We're going to be touching every single server that I just pulled in from the domain. We're gonna be using the creds that I just specified here. I'm going to do any errors that are encountered and send those to a custom error variable. So if you've watched my error episode on PowerShell you'll know that by default that will go out to the Error variable pipeline, but I'm gonna send this to a specific error so we can capture any errors that are encountered in our remote command run into the connectErrors variable. And then any action, any error that we encounter I just want it to silently continue. So what does that mean? Well that means that as we loop through in parallel using Invoke-Command against all of these different servers that we're pulling from the domain. I don't want to see any errors in red on the screen as we loop through those. I just want to silently continue and try to connect to every single device on my domain. Now remember in your environment there's a wide variety of reasons that a device might not respond. It could be down for maintenance, or it could not be configured for winrm. So we're gonna capture those and put them out to the error variable and then silently continue and try to reach every device for our audit that we're trying to accomplish. So we're using those parameters in the Invoke-Command with our splat, and the script block that we're gonna be running is pretty involved. So every single thing that's included in between this orange curly brace, and this orange curly brace is the PowerShell logic that is going to be run against our remote device. So I could take all this away to reduce the complexity and really what we're doing is running commands inside of this script block against all those remote devices using the credentials that we specified. I'll go ahead and return that back in, and let's just briefly cover the logic behind here. I'm going to declare a custom object because we're gonna be running some code here inside of this that is not native cmdlets. And so what do I mean by that? Well I want to capture multiple different pieces of information in this audit. I want to capture the computer name, I want to capture the number of CPUs, memory, and free space. Well there's not a cmdlet that returns those four things natively. And so I'm declaring up custom PowerShell objects that we're going to be setting up to actually capture those individual pieces of information from various different cmdlets. So notice that I'm loading all of that into the object variable. So now $object will have the capacity to store the name of the computer, the number of CPUs, the amount of memory, and the amount of free space on the hard drive. So this may seem complicated to you but let's walk through how easy this is. So this object variable the CPU parameter I'm going to store the results using Get-CIMInstance. So you can see this as the CPU results for this $object that we've created up here is going to be whatever is returned from this PowerShell logic here. The same for this the object memory is going to be running some logic using Get-CIMInstance to evaluate the memory of the box, doing some math to round out the bytes to actual gigabytes so on and so forth. And then again our drive data we're going to be loading some common logic for getting the PS Drive, selecting how much is used versus free, and just performing some calculations using simple math on how to calculate how much free space is left on the drive. Once we have that information we're gonna load that into the object free space and return that object back to our management device. This may seem a little complex to you but once we execute it I think you'll start to see it all come together. Again, in this episode it's not so much important to understand how we're achieving the actual audit logic. it's more important to see how we can send a piece of code out to as many devices as we want and have them gather information or perform tasks for us. So that's our Invoke-Command here which is going to store the results and the remote results. And then we're going to take that connectErrors variable and remember our connect errors variable is where we're sending any error that we encounter out to that particular variable. And we're gonna loop through that basically using Where-Object and Select-Object and determine hey, did you have any problems connecting to any of those devices? Again this may seem a little confusing about what it's accomplishing to you but once you see it in action I think it'll start coming together. I'm gonna load all this code the error code and the execution code inside of our window here. So I'm gonna highlight all of this and I'm gonna run the selection again you can use F8 to do that. So this is running that code against every single device that we gather from the domain. So auditing for CPU, hostname, how much free space is in the drive, how much memory every single one of those devices has. So let's just take just a moment to run in parallel against every single device that we gathered in. Okay so just in a few moments that's already completed, and because we loaded the remote results into the remote results variable, all of my successes should be in there. And we loaded this variable remote failures with evaluation of that connect errors variable with some criteria. Let's explore what our end results were. So I will look at my remote results first and unsurprisingly we see the exact same custom object that we specified. So notice that our custom object was named CPUs, memory, and free space. And we see that exact same return here with a little bit of additional information from the remote call which is always appended when running Invoke-Command. So we see our name, CPUs, and free space against DC, MDT, and another device called RDPG. So we can see here very quickly and easily the RDPG has two CPUs, one gig of memory, and 64 percent free space remaining on the hard drive. And we got this information in literally seconds against every device inside of our environment. Well now let's go down to remote failures and we now see here that these following devices it was unable to connect to you for a variety of different reasons. But what we have at the end of this audit is those devices that we need to go explore and adjust. Maybe they don't have winrm set up and we have a list of devices that were successfully audited. So this is a great and easy way to shotgun out a quick question to your environment to ask it any question that you need answered for your team or your management. And again if you had run something that made a change against your environment definitely go through those proper change controls but you could definitely make some very quick and easy changes to your environment using this methodology as well. Again this is one of the more complicated topics inside of PowerShell, but it's one of the most empowering. Definitely get a handle around this! Ask questions inside of the comments section below. If I can help you out I'll do my best to do so. If you found this video helpful go ahead and click that like button, and subscribe for more tech thoughts videos.
Info
Channel: TechThoughts
Views: 23,370
Rating: 4.992806 out of 5
Keywords: PowerShell, Learn PowerShell, PowerShell Training, learn powershell online free, learning PowerShell, PowerShell Tutorial, PowerShell Examples, PowerShell Remoting, Remoting, PowerShell remote access, winrm, Windows Remote Management, Linux SSH, SSH, New-PSSession, Enter-PSSession, remote, Invoke-Command, Get-Credential, remote device
Id: qvJRaYlxI1w
Channel Id: undefined
Length: 37min 11sec (2231 seconds)
Published: Fri Dec 06 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.