An object is nothing but a combination of methods and properties in PowerShell. Using Windows PowerShell, we can store a reference to an object to a variable and use it in the current shell as required.
We discussed in Chapter 1, Getting Started with Windows PowerShell that PowerShell takes advantage of the underlying .NET framework. So, the objects are a representation of the parts and actions to use it. An object is a combination of the properties and methods (Objects = Properties + Methods).
For example, a Windows service object has properties and methods. The properties are Get
and Set
, and the methods are invoked to perform a meaningful operation.
We have discussed objects in a few of the preceding examples as well. In this section, we will explore the .NET objects in PowerShell. In order to create a .NET object, we will use the same New-Object
cmdlet, but instead of the COM object, we will use different types of objects.
To create a .NET object for the system version, we will use the following code:
$Version = New-Object -TypeName System.Version -ArgumentList 1.2.3.4 $Version
The output is illustrated in the following image:
The points marked in the figure are explained in the following list:
$Version
New-Object
cmdlet–TypeName
to call the .NET framework classSystem.Version
.NET framework class–ArgumentList
to pass values to the constructor of the class1.2.3.4
.As we have discussed a little about typecasting in the previous topics, we can do the same here as well. Run the following command:
[System.Version]"1.2.3.4"
Using PowerShell, we can extend the instance of the .NET object. To do this, we will use the Add-member
cmdlet. In the following example, we will discuss extending the System.String
class:
$string = New-Object -TypeName System.String -ArgumentList "PowerShell Rocks!" ($string).GetType()
The output of the code we just saw is illustrated in the following image:
The points marked in the figure are explained in the following list:
GetType()
method to explore the type name. It's a string.System.String
class is PowerShell Rocks!
String
System.Object
(Note: If we do $var = 123 ; $var.GetType()
the base objects returns System.Value
). In the above code we have created a String object. So, the base type shows the ultimate base class of all classes in the .NET FrameworkNow, let's add NoteProperty
. This will return the total character counts from the value passed through, which is ArgumentList
. Run the following command:
$string = New-Object -TypeName System.String -ArgumentList "PowerShell Rocks!" $String | Add-Member -MemberType NoteProperty "TotalCharacters" -Value $string.Length $string.TotalCharacters
The output is illustrated in the following image:
Let's consider another example where we concatenate the ScriptMethod
object to a string object. Run the following command:
$string = New-Object -TypeName System.String -ArgumentList "PowerShell Rocks!" $String | Add-Member -MemberType ScriptMethod -Name "ConcatCustom" -Value {[String]::Concat($this , " Demo")} $string.ConcatCustom()
The preceding code appended the Demo
string to the ArgumentList
string, PowerShell Rocks!
.
The output is illustrated in the following image:
The points marked in the figure are explained in the following list:
Add-Member
cmdlet is ScriptMethod
CustomConcat
just for demo purposes—You can choose any custom nameValue
parameter defines the script[String]::Concat
method just for simple demo purposesConcat
method accepts two string parameters (string1, string2)
$this
automatic variable as wellDemo
is a string we need to concatenatePowerShell Rocks! Demo
Using Windows PowerShell, we can define a Windows .NET Framework class in the session and instantiate the object using New-Object
. PowerShell allows us to use the inline C# code using a here-string. To define a here-string in Windows PowerShell, we should use @"
and close it with "@
—anything between these marks is a here-string, as shown in the following snippet:
@" "here strings" "@
From Windows PowerShell 5.0 onward, we can write the class in Windows PowerShell. The Class
keyword is supported only in PowerShell version 5.0. For now, let's take a look at how the Add-Type
cmdlet works. In the following example, we will take a look at code with the inline C# code:
$sourcecode = @" public class Calculator { public static int Add(int a, int b) { return (a + b); } } "@ Add-Type -TypeDefinition $sourcecode [Calculator]
The output is illustrated in the following image:
Now, we can call the Add
method directly without using the New-Object
cmdlet. Run the following command:
$sourcecode = @" public class Calculator { public static int Add(int a, int b) { return (a + b); } } "@ Add-Type -TypeDefinition $sourcecode [Calculator]::Add(10,5)
PowerShell allows us to execute the static methods of a class directly in PowerShell. System.Math
has a static method called sqrt
, which can be used as shown in the following command:
[System.Math]::Sqrt(4)
In the following example, we will create a simple class using the Class
keyword:
Class Demo { #Properties [string]$FirstName = "Chen" [string]$surname = "V" #Methods - This will print the values and just for demo [string]GetInformation() { return "$($this.FirstName) $($this.surname)" } }
Following is the alternate method to instantiate the class:
Class
and named it as Demo
$FirstName
and $surname
are propertiesGetInformation
is a method and $this
is an automatic variable used$var
variable and instantiating the class using New-Object
cmdlet. With the same code the class can instantiated using $var = [Demo]::new();$var.GetInformation()
The output is shown in the following image:
Let's explore the property, as shown in the following image:
The class Demo
we created in the preceding section has properties and methods, but we practically don't need the GetInformation
method because it just prints the property values. Let's create another class with the SetInformation
method which updates the property values. Run the following command:
Class Demo { #Properties [string]$FirstName = "Chen" [string]$surname = "V" #Methods - This will print the values and just for demo GetInformation() { $this.FirstName $this.surname } SetInformation([string]$fn,[string]$sn) { $this.FirstName = $fn $this.surname = $sn } } $var = New-Object -TypeName Demo $var.SetInformation("Chendrayan" , "Venkatesan") $var
The preceding code returns the following output:
We will cover more information about the classes in the Exploring Windows PowerShell 5.0 section.
Windows PowerShell scripting is used imperatively to perform complex operations using cmdlets. Windows PowerShell supports variables, functions, branching, loops, structured exception handling and, as we all know, .NET integration.
The PowerShell script file has a PS1 extension. For example, let's save the following file as PS1 and execute it:
Function Get-Information { (Get-Service).Where({$_.Status -eq 'Stopped'}) } Get-Information
The preceding script is a very basic code to retrieve all the running services. Consider the following image:
Before taking a look at the advanced functions, let's consider the fundamentals of PowerShell scripting.
A PS1 file is nothing but a text file that contains a sequence of PowerShell cmdlets to perform certain complex tasks. Before you execute a PowerShell script, ensure that the script execution policy is set as required. There are different types of execution policies; to know them, simply execute the following help cmdlet:
help about_Execution_Policies -Detailed
Before creating PowerShell scripts, ensure that you plan and document the synopsis. Using the Measure-Command
cmdlet, ensure that you optimize the performance of the code as required.
Now, let's take a look at the advanced function and save it as PS1 file. For this demo, I have used the PowerShell ISE, which has a snippet for advanced functions and advanced function complete.
The structure of the advanced function is shown in the following image:
The points marked in the figure are explained in the following list:
CmdletBinding
attribute is an attribute of functions, which makes a function work similarly to a compiled cmdlet that is written in C#Let's take the example of a PowerShell script that retrieves system information and saves the output as an HTML file, which uses the CSS style sheet. Run the following code:
<# .SYNOPSIS Windows Machine Inventory Using PowerShell. .DESCRIPTION This script is to document the Windows machine. This script will work only for Local Machine. .EXAMPLE PS C:> .System_Inventory.PS1 .OUTPUTS HTML File OutPut ReportDate , General Information , BIOS Information etc. #> #Set-ExecutionPolicy RemoteSigned -ErrorAction SilentlyContinue $UserName = (Get-Item env:username).Value $ComputerName = (Get-Item env:Computername).Value $filepath = (Get-ChildItem env:userprofile).value Add-Content "$Filepathstyle.CSS" -Value " body { font-family:Calibri; font-size:10pt; } th { background-color:black; color:white; } td { background-color:#19fff0; color:black; }" Write-Host "CSS File Created Successfully... Executing Inventory Report!!! Please Wait !!!" -ForegroundColor Yellow #ReportDate $ReportDate = Get-Date | Select -Property DateTime |ConvertTo-Html -Fragment #General Information $ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem | Select -Property Model , Manufacturer , Description , PrimaryOwnerName , SystemType |ConvertTo-Html -Fragment #Boot Configuration $BootConfiguration = Get-WmiObject -Class Win32_BootConfiguration | Select -Property Name , ConfigurationPath | ConvertTo-Html -Fragment #BIOS Information $BIOS = Get-WmiObject -Class Win32_BIOS | Select -Property PSComputerName , Manufacturer , Version | ConvertTo-Html -Fragment #Operating System Information $OS = Get-WmiObject -Class Win32_OperatingSystem | Select -Property Caption , CSDVersion , OSArchitecture , OSLanguage | ConvertTo-Html -Fragment #Time Zone Information $TimeZone = Get-WmiObject -Class Win32_TimeZone | Select Caption , StandardName | ConvertTo-Html -Fragment #Logical Disk Information $Disk = Get-WmiObject -Class Win32_LogicalDisk -Filter DriveType=3 | Select SystemName , DeviceID , @{Name="size(GB)";Expression={"{0:N1}" -f($_.size/1gb)}}, @{Name="freespace(GB)";Expression={"{0:N1}" -f($_.freespace/1gb)}} | ConvertTo-Html -Fragment #CPU Information $SystemProcessor = Get-WmiObject -Class Win32_Processor | Select SystemName , Name , MaxClockSpeed , Manufacturer , status |ConvertTo-Html -Fragment #Memory Information $PhysicalMemory = Get-WmiObject -Class Win32_PhysicalMemory | Select -Property Tag , SerialNumber , PartNumber , Manufacturer , DeviceLocator , @{Name="Capacity(GB)";Expression={"{0:N1}" -f ($_.Capacity/1GB)}} | ConvertTo-Html -Fragment #Software Inventory $Software = Get-WmiObject -Class Win32_Product | Select Name , Vendor , Version , Caption | ConvertTo-Html -Fragment ConvertTo-Html -Body "<font color = blue><H4><B>Report Executed On</B></H4></font>$ReportDate <font color = blue><H4><B>General Information</B></H4></font>$ComputerSystem <font color = blue><H4><B>Boot Configuration</B></H4></font>$BootConfiguration <font color = blue><H4><B>BIOS Information</B></H4></font>$BIOS <font color = blue><H4><B>Operating System Information</B></H4></font>$OS <font color = blue><H4><B>Time Zone Information</B></H4></font>$TimeZone <font color = blue><H4><B>Disk Information</B></H4></font>$Disk <font color = blue><H4><B>Processor Information</B></H4></font>$SystemProcessor <font color = blue><H4><B>Memory Information</B></H4></font>$PhysicalMemory <font color = blue><H4><B>Software Inventory</B></H4></font>$Software" -CssUri "$filepathstyle.CSS" -Title "Server Inventory" | Out-File "$FilePath$ComputerName.html" Write-Host "Script Execution Completed" -ForegroundColor Yellow Invoke-Item -Path "$FilePath$ComputerName.html"
Note that the preceding code is not a function—it's just a script. Save this as PS1 and execute the script.
The sample output is shown in the following image:
The script has the following elements:
C:
drive for stylingConsider the following image:
Let's take an example where we will create an advanced function. Advanced functions include help, parameters, accepting pipelines, and so on.
<# .Synopsis A script to retrieve OS information. .DESCRIPTION This PowerShell script will retrieve OS information like Name , OS Architecture, Serial Number and Last Bootup time. This script use CIM instance. .EXAMPLE Get-OSInformation -ComputerName localhost .EXAMPLE Get-OSInformation -ComputerName localhost , remotecomputer .EXAMPLE localhost , remotecomputer | Get-OSInformation #>
The help block has synopsis, description, and three examples.
function
and name it in the Verb-Noun form. In our example, this is Get-OSInformation
, as shown in the following command:function Get-OSInformation { #Code goes here}
CmdletBinding
. Take a look at the following code:[CmdletBinding(ConfirmImpact = 'Low', HelpUri = 'http://chen.about-powershell.com')]
I have set the ConfirmImpact
to low, and I have used HelpUri
from my blog post—just for this example. You can use any valid site that has some information. You may wonder, why do we use CmdletBinding
? It is to ease our function creation and to make additional validation for our parameters. For more information execute help about_Functions_CmdletBindingAttribute
Param ( # Param1 help description [Parameter(Mandatory=$true, HelpMessage = "Please enter valid host name", ValueFromPipelineByPropertyName=$true, ValueFromPipeline = $true, Position=0)] [String[]]$ComputerName )
Use the following code:
Begin { #Intentionally left blank } Process { foreach($computer in $ComputerName) { $params = @{'ComputerName' = $Computer 'Class' = 'CIM_OperatingSystem'} Get-CimInstance @Params | Select Caption , OSArchitecture , SerialNumber , LastBootUptime } } End { #Intentionally left blank }
Now, let's call the function using Get-OSInformation
by skipping the mandatory parameter, as shown in the following image:
Type !?
to see the help text, as shown in the following image:
That's cool! Now, we can see the help message in the parameter block.
Using the help command, we can obtain more information about the command.
The output is illustrated in the following image:
The points marked in the figure are explained in the following list:
RELATED LINKS
—appears by default if you have included .LINK
in the comment block. Used for external web site links.REMARKS
—appears by default.Note that here, the help
command will not show the input and output parameters, and so on.
Use the help Get-OSInformation –Full
command to explore more.
We used the blog post URL in the help message URI in cmdlet binding; so, to make use of this, we can use the following code:
help Get-OSInformation -Online
The complete code is available here:
<# .Synopsis A script to retrieve OS information. .DESCRIPTION This PowerShell script will retrieve OS information like Name , OS Architecture, Serial Number and Last Bootup time. This script use CIM instance. .EXAMPLE Get-OSInformation -ComputerName localhost .EXAMPLE Get-OSInformation -ComputerName localhost , remotecomputer .EXAMPLE localhost , remotecomputer | Get-OSInformation #> function Get-OSInformation { [CmdletBinding(ConfirmImpact = 'Low', HelpUri = 'http://chen.about-powershell.com')] Param( # Param1 help description [Parameter(Mandatory=$true, HelpMessage = "Please enter valid host name", ValueFromPipelineByPropertyName=$true, ValueFromPipeline = $true, Position=0)] [String[]]$ComputerName) Begin{<#Intentionally left blank#>} Process { foreach($computer in $ComputerName) { $params = @{'ComputerName' = $Computer 'Class' = 'CIM_OperatingSystem'} Get-CimInstance @Params | Select Caption , OSArchitecture , SerialNumber , LastBootUptime } } End { #Intentionally left blank } }
In this section, we will explore Windows PowerShell modules.
Windows PowerShell modules are packages that contain the PowerShell commands. Using modules, we can organize our commands and share them with others.
In this example, we will create a simple module as a demo and this will be a script module. We will discuss all types of modules and demos in the Understanding PowerShell Modules section.
A script module is a file (.psm1
) that contains valid Windows PowerShell code. Script developers and administrators can use this type of module to create modules whose members include functions, variables, and more.
In this example, we have two functions—Get-OSInformation
and Get-DiskInformation
. Let's save this as Sysinformation.PSM1
in the temp
folder for now.
Function Get-SystemInformation { param( [Parameter(Mandatory = $true)] [String] $ComputerName ) $OS = Get-WmiObject -Class Win32_OperatingSystem $BIOS = Get-WmiObject -Class Win32_Bios $CS = Get-WmiObject -Class Win32_ComputerSystem $Properties = New-Object psobject -Property @{ "OSName" = $OS.Caption "ServicePack" = $OS.CSDVersion "SerialNumber" = $BIOS.SerialNumber "Manufacturer" = $BIOS.Manufacturer "BootUpState" = $CS.BootupState } $Properties } Get-SystemInformation -ComputerName localhost
Now, we need to import a module; to do this we need to use the Import-Module
command. In the following code the –Verbose
and –Force
parameters are used for a clear output. Take a look at the following image:
The points marked in the figure are explained in the following list:
Import-Module
cmdlet to import the script module we created. The module name is SysInformation.PSM1
.C:Temp
.–Verbose
is used to see the verbose data.–Force
parameter is used to remove the existing script and import it newly.Now, let's call the functions as cmdlet. Take a look at the following image: