I have searched and read many articles about Windows PowerShell but did not find any comprehensive article that take you from basic to advance knowledge specifically related to Internet Information Server and PowerShell Remoting. So i tried to make things easy for you, lets get started
This article is about
- Introduction
- Extensions
- Basics
- Cmdlets
- Working with IIS
- Working with Windows Servers/VMs
- Deep dive into PowerShell Remoting
You can download it from here
Introduction
Advancing command prompt, Microsoft released Windows Powershell in 14th November 2006, designed by Jeffrey Snover, Bruce Payette and James Truher providing more interactive, powerfull, Multi-paradigm that includes Imperative, pipeline, object-oriented, functional, reflective, providing strongly typed and type safe implicit and dynamic environment. The stable version was released on 29th July, 2015.
Extensions
Following are the supported extensions in powershell
- .ps1 for Script
- .psc1 for Console file
- .psd1 for Data file
- .ps1xml for XML Document
- .psm1 for Script Module
- .pssc for Session Configuration File
- .cdxml for Cmdlet Definition XML Document
Basics
PowerShell introduced over hundreds of new commands to make powershell more powerful. There are many command that are same as MS-DOS commands.
Hello World
The tradition of programming forefathers is “Hello World”. How we can start without it, So to write this on your terminal use
PS C:> Write-Host Hello World
or
PS C:> echo Hello World
You can create variables in powershell by using $ sign for example
PS C:> $message = 'Welcome to PowerShell'
and then print that variable using
PS C:> echo $message
Getting used to with help is most important in be an expert. To get help in powershell use
PS C:> get-help
You can use get-help command by passing arguments too. For example to get help specifically for “dir” (explained below) use can use
PS C:> get-help dir
This will give you detailed description about using dir command, its name, its syntax, aliases and remarks. For the above command it will give you
- Name: Get-ChildItem
- SYNTAX: Get-ChildItem [[-Path]…….
- Aliases: gci, ls, dir
- Remarks: Get-Help cannot find files……..
To open the Microsoft site that explains the key word you want to get help of in browser use
PS C:> get-help dir -online
Manipulation with Directories
To list all the item that are in the current directory use the same command as in MS-DOS
PS C:> dir
To change the current directory use the same command as in MS-DOS
PS C:> cd d:
CD stands for Change Directory
To go backwards from current directory again use the same command as in MS-DOS command.
PS C:> cd..
To navigate back to the root directory use
PS C:> cd
you can also use alternative to goto specific directory
PS C:> Set-Location D:
or
PS C:> Set-Location 'D:New FolderNew Folder'
To make new directory use
PS C:>md testDirectory
To delete directory use
PS C:> del testDirectory
System Information
You can get the machine name by using
PS C:> [System.environment]::MachineName
Getting the directory of command line (powershell)
PS C:> [System.environment]::CommandLine
To get the information that whether you system is 64-Bit or not use
PS C:> [System.environment]::Is64BitOperatingSystem
Getting Operating system version use
PS C:> [System.environment]::OSVersion
To get current user name use
PS C:> [System.environment]::UserName
Network Information
Same as MS-DOS you can get your network information using
PS C:> ipconfig
For specifically getting IP address and its detailed information you can use
PS C:> Get-NetIPAdress
or
PS C:> Get-NetIPAdress | Format-Table
or to only get a single property of IP Address use
PS C:> Get-NetIPAddress | Format-Table -Property IpAddress
for getting mac address you can use
PS C:> GetMac
Looping
To execute loops in powershell use
PS C:> 1..2 | % { // Do Stuff here }
For example
PS C:> 1..2 | % { echo 'In-Loop' }
or
PS C:> 1..2 | % { GetMac }
Cmdlets
There are special commands in powershell that are called cmdlets. They are always typed after the prompt and execute on pressing enter. Cmdlets follow the naming convention of “Verb-Noun”. Cmdlets actually return the object but it appears that they are writing in console. The method of passing cmdlets returned object to another cmdlets is called piping
For example
This will give you the operating system version
PS C:> [System.environment]::OSVersion
but you want to pass this to another cmdlet as an input to display a list for you. For this you will be doing
PS C:> [System.environment]::OSVersion | Format-List
In above command the symbol “|” is piping sign. The above command will get the output of first command and pass it as a pipeline to the second command as an input, So result will be displayed by the second command not the first one.
Few other examples are
PS C:>dir | Get-ItemProperty | Format-List
or use can pass the output of second pipeline to the third and write its output in the text file for example
PS C:> Get-NetIPAddress | Format-Table | Out-File 'D:powerShellOutput.txt'
Working with IIS
To start with remoting we need to import a web administration module, to do that use
PSc C:>Import-Module 'WebAdministration'
May be you wont need that if already imported to check that if module already installed or not use
PS C:>Get-Module -ListAvailable
above command will list all the installed modules in it and you need to search for the web administration module. To make it quick command written below, this will only give you the module information of the given name if it exists
PS C:> Get-Module -ListAvailable webadministration
To get Web Administration related cmdlets use
PS C:> Get-Command -Module WebAdministration
or to be specific for website related cmdlets use
PS IIS:> Get-Command -Module WebAdministration -Noun '*website*'
Changing to IIS directory
To change the current directory to IIS use
PS C:> IIS:
This will change you working directory from local drive to IIS and will now looks like
PS IIS:>
If you check all the directories in IIS by using dir/ls/gci you will get Sites, WebApplications ApplicationPools, and other directories.
PS IIS:> ls
Now change you current directory to Site by using
PS IIS:> cd Sites
Working with Site in IIS
to view all sites try listing all sites in it by using
PS IISSites:>dir
you will get all the list of already created sites whether they are stopped or running. To get details of specific site use the site name as an argument with the below written command
PS IIS:Sites> Get-Item 'TestSite'
or to be very specific use
PS IIS:Sites> Get-Item 'TestSite' | Select-Object *
To Start a site use
PS IIS:Sites> Start-WebSite 'TestSite'
and to stop it use
PS IIS:Sites> Stop-WebSite 'TestSite'
Creating New Site
PS IIS:Sites> New-Item TestSite
The above command will create the new site but there are many other information associated with the site you need to configure that too, So let use the complete command and i will explain it after that
PS IIS:Sites> New-Item IIS:SitesTestSite -Bindings @{protocol="http"; bindingInformation=":80:www.TestSitePowerShell.com"} -physicalPath C:inetpubwwwrootnewFolder
In above site you are specifying Bindings, Protocol and Physical path. Protocol can be ‘ftp’, ‘https’ or what ever your requirements are. Binding Information include the port number and the binding address that you want to give to a site and physical address the the path of the folder where it physically located in the drive.
Updating properties of Site
To update properties of existing site for example to update binding information of a site or a protocol or port number or physical address the command that is used is
PS IIS:Sites> Set-ItemProperty IIS:SitesTestSite -Name bindings -Value @{protocol="http";bindinginformation="*:80:www.abc.com"}
In above command we use Set-Property to Update property of the element and then we will specify the name of the property that we are updating in above case we are updating bindings and then we are providing its new values
Adding new properties
To add new properties to existing site we use the command written below
PS IIS:> New-ItemProperty IIS:SitesTestSite -Name bindings -Value @{protocol="http";bindinginformation="*:8080:www.xyz.com"}
The above is the example in which i assume that the site is already created but its binding properties are not given at the time of creation, so we are adding it now. Its simple, we just need to use New-Property function with Property name and its values as an argument.
Removing properties
To remove/Clear specific property form existing site use
PS IIS:> Clear-ItemProperty IIS:SitesTestSite -Name bindings
Given the Name of the Property it will be removed from the specified object given as a first argument of the Clear-Property function
Renaming the Site
To rename the site use
PS IIS:> Rename-Item IIS:SitesTestSite TestSiteFromPowerShell
Deleting Site
To delete site from IIS use
PS IIS:Sites> Remove-Item 'TestSiteFromPowerShell'
Working with Servers/VMs
Now that seems thrilling but let me surprise you. To work with any Virtual Machine you just need to connect with it and then you are able to do whatever we have already done above. So lets connect to the server
PS C:> Enter-PSSession -ComputerName abc.xyz.net -Credential abc.xyz.netusername -UseSSL
You need to run this and then a password dialog prompt appears, Enter your password and that all you need to do. You are now connected with the server, for example
[abc.xyz.net]: PS C:UsersusernameDocuments>
you can run same command that to get information like
[abc.xyz.net]: PS C:UsersusernameDocuments> dir [abc.xyz.net]: PS C:UsersusernameDocuments> Get-NetIPAddress [abc.xyz.net]: PS C:UsersusernameDocuments> cd [abc.xyz.net]: PS C:> Write-Host 'Welcome to the Virtual Machine'
You can create sites remotely using powerShell on your servers. Now we are done with commands, lets develop some scripts to see the strength of powershell. Below is the example of a powershell script that creates a new ApplicationPool, create new physical directory and then creates a site in it with all the relevant configuration.
Import-Module WebAdministration $dirName = 'PowerShellMagic' $siteName = 'PowerShellSite' $poolName = 'DemoPool' New-Item C:inetpubwwwroot$dirName -ItemType Directory New-Item IIS:Sites$siteName -Bindings @{protocol="http";bindinginformation="*:80:www.firstapplication.com"} -PhysicalPath C:inetpubwwwroot$dirName New-Item IIS:AppPools$poolName Set-ItemProperty IIS:Sites$siteName -Name applicationPool -Value $poolName Write-Host "All Done"
Before executing the above script, You need to make sure that your powershell is configured to run multi-line scripts. For this first check your execution policy by running the following command
[abc.xyz.net]: C:> Get-ExecutionPolicy
if the above command gives you the output of “RemoteSigned” then you are good to go for executing scripts otherwise run the following command
[abc.xyz.net]: C:> Set-ExecutionPolicy remotesigned
Save the above written script with any name, i am using siteSetup.ps1. Let execute the script
[abc.xyz.net]: C:> Invoke-Expression D:setupSite.ps1
or
[abc.xyz.net]: C:> .setupSite.ps1
Deep dive into PowerShell Remoting
Let’s dive more deepen into PowerShell remoting.
Legacy VS PowerShell Remoting
In legacy approach all the commands will execute in sequential manner that may take a huge time in many scenarios.
For example: you have 10 servers and you want to configure few setting on them remotely and then you want to deploy you application on them.
In the scenario explained above legacy approach will take a lot of time as already explained it executes your commands or scripts sequentially.
So there comes the power of PowerShell remoting where you can do all this in parallel for all 10 servers. Yeah! That’s cool.
Protocols
One other aspect that I want to share is the underline protocols used.
Legacy approach use DCOM or RPC protocols whereas PowerShell remoting use WSMan protocol.
DCOM and RPC protocol are designed in the era where the firewall concept was not well grown so these protocol were designed with not considering the firewall concept in mind that means they are not firewall friendly and if you are using these any services that uses these protocols then you need a lot of complex firewall configurations. Moreover the security in these protocols are questionable and I addition to this they may not work with cloud based environment. Keeping the above scenario in mind where you are running a long scripts on multiple server all these scripts would process locally.
Contrary to that approach powerShell uses WSMan protocol that is based on “Industrial Standard Network Protocol” and is managed by WinRM services is a firewall friendly and designed in keeping the firewall concept in mind. That mean you don’t need any kind of complex firewall configuration. They are secured and all the communication is encrypted, so no packet sniffing using any tool like wireshark. They connect over a single port that is 5985 but you can configure SSL over 5986 and uses Kerberos authentication. In addition to this they are ideal for cloud environment and they process the scripts remotely. They connect to a defined endpoints where service listens to incoming connection and the endpoint passes the control to the defined application (PowerShell). PowerShell needs admin privileges for managing all the stuff you are doing remotely.
PSSessions
PSSession are used to make a connection between 2 machines. These sessions are maintained at the remote end with powerShell runspace for running cmdlets functions and scripts.
There are many types of PSSessions
- Interactive PSSessions
- Disconnected PSSessions
Enabling PSRemoting
To configure remoting you need to start the service named WinRM and discussed above. So we will configure WinRM to auto start. To do that use
[abc.xyz.net]: C:> Start WinRM
Then to enable remoting use
[abc.xyz.net]: C:> Enable-PSRemoting –Force
To test the connectivity and WinRM is running use
[abc.xyz.net]: C:> Test-WSMan
You may need to restart the machine to properly pick the configuration, for that use
[abc.xyz.net]: C:> Restart-Computer computername.net –Force –Wait WinRM –Credentials
The above command will wait for the WinRM service to start and then will show its status
To disable remoting use
[abc.xyz.net]: C:> Disable-PSRemoting
One-TO-One Remoting
One to one remoting is the case where you have only one server that you want to connect with and want to do some actions. For that lets have an interactive session with the server.
[abc.xyz.net]: C:> Enter-PSSession –ComputerName comutername.net –Credential username –UseSSL
This will prompt the dialogue where you will enter your password to connect.
Now we are connected with the server remotely with interactive session. All the command that you execute are processed remotely and only return the result in de serialized XML objects.
To check the user session use
[abc.xyz.net]: C:> Get-Process wsmprovhost –IncludeUserName | Select Username, startime
To get Installed Windows Features on Server use
[abc.xyz.net]: C:> Get-WindowsFeature web* | where installed
To getting Running Windows Services use
[abc.xyz.net]: C:> Get-Service | Where { $_.status –eq ‘Running’ }
To get specific Service use
[abc.xyz.net]: C:> gsv WinRM
To getting installed Modules use
[abc.xyz.net]: C:> Get-Module web* -List
To get all process use
[abc.xyz.net]: C:> Get-Process
To filter the process result use
[abc.xyz.net]: C:> Get-Process | sort WS –Descending | Select –First 5
PSSession
As mentioned above the Enter-PSSession is an interactive session that we have used above to connect to server. But there are also other kind of sessions. lets discuss them
New-PSSession
Using this we can save the session in a variable to use that in future and connect to it whenever we want to
PS C:> $s = New-PSSession -ComputerName abc.xyz.net -Credential username -UseSSL
Now you can connect to this session whenever you need to like
PS C:> Enter-PSSession -Session $s
In this approach the command
[abc.xyz.net]: C:> Exit
cannot remove the session.
You can also execute scripts and command using this session variable like
[abc.xyz.net]: C:> icm -ScriptBlock { $p = Get-Process | Sort WS -Descending } -Session $s
and print them in other script because the scope of variable $p is stick to the Session variable now that is $s in this case. these variables are created on the remote site. So if you want to use $p locally or in other session other then $s you cannot get it because $p is only created on one server yet.
SO ultimately that mean you can use the variable created before in future commands like below we are printing the result from the variable that we created in previous command
[abc.xyz.net]: C:> icm -ScriptBlock { $p[0..4] } -Session $s
The above command is not possible without “-Session $s” because $p only exist in the $s session
You can get deserialized XML or version of Process from server by using
PS C:> icm -ScriptBlock { $p[0] } -Session $s | Get-Member
Removing Session
To remove this offline kind of session use
PS C:> Remove-PSSession -Session $s
One to Many Remoting
Fanning out
To connect with many server form one machine is knows as “Fanning out”.
Lets take an example that we have all server names in a text file, Lets read them
$computer = get-content D:computers.txt | New-PSSession –Credential username
Now you have all the server names in a variable $computer.
Lets now execute a script in all servers.
PS C:> Invoke-Command –ScriptBlock {get-service wuauserv } –Session $computer
The above command will take the sessions from $computer variable and execute the script/command on each of the server. or you can pick a script from local drive and execute it on all servers
PS C:> Invoke-Command –filepath D:script.ps1 –Session $computer
One thing to remember that you can use/pass local variable to server as demonstrated below
PS C:> $log = 'System' PS C:> icm { Get-EventLog $using:log -Newest 5 } –ComputerName $computer
Or pass by creating function and passing parameter
PS C:> $sb = {param($log, $count) Get-EventLog $log -Newest $count}
here $sb is the function that we have defined that takes two arguments, lets call it
PS C:> icm $sb -ArgumentList "System", 3
Background Jobs
If there are some scripts that takes time and you have like 10 servers, so you prefer to use the background jobs to do the task
PS C:> icm { Get-HotFix } -Session $computer -AsJob | tee -Variable hot
In above statement we are executing a command “Get-HotFix” as a Job defined by “-AsJob” and passing its output in variable named “hot”. once the execution is done we can fetch result from this variable, lets check the status of that Job
PS C:> $hot
or
PS C:> $hot.childjobs
We canalso wait from the specific job to complete by using
PS C:> Wait-Job $hot
lets receive data from that job
PS C:> $result = Receive-Job $hot -Keep PS C:> $result.count
The function that we have created before named “$sb” run locally, lets redefine the function and run it remotely as a Job
PS C:> $sb = { Start-Job { Get-EventLog system -EntryType Error } -Name SysErr }
We have defined the function as a Job and named it “SysErr”, lets execute it
PS C:> icm $sb -Session $computer
When you get the status of this job. you should get same ids on all servers because this is not running on servers. By running locally you will get unique id’s for all server and that is obvious. To get status of this job use its name
PS C:> icm { get-job SysErr } -Session $all
You can measure the command execution time using
PS C:> Measure-Command { Get-Service }
Removing all PSSessions
To remove all alive sessions use
PS C:> Get-PSSession | Remove-PSSession
Adding Server as a Trusted Host
PS C:> $cred = Get-Credential abc.xyz.net PS C:> Get-Item wsman:localhostclienttrustedhosts PS C:> Set-Item wsman:localhostclienttrustedhosts -Value abc* -Concatenate PS C:> test-wsman codingbots.cloudapp.net -Authentication Default -Credential $cred
2nd Hope Problem
If you are on server A and creates a PSSession to connect to server B. That is the first hope. Moving further if you want to connect to Server C from Server B that will be your 2nd hope and that says “Operation failed”. This is because powershell do not allow server B to delegate your credentials to other machines. But you can enable it using the following configuration.
PS C:> icm { Get-WSManCredSSP } -computername c PS C:> enable-wsmancredssp -Role Client -DelegateComputer server2
It is considered as a besk practice to disable multi hoping whenever you are done with your tasks. To do so, use
PS C:> Disable-WSManCredSSP -Role Client PS C:> icm { Disable-WSManCredSSP -Role Client } -computer abc.xyz.net
That is it from my side. I hope you have enjoyed stepping into the world of Windows PowerShell.
Feel free to contact.
Happy Coding 🙂