PowerShell for Windows Admins


May 26, 2017  8:53 AM

Diskpart and PowerShell – part 6: Multiple partitions on a disk

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Disk storage, Powershell

So far we’ve looked at creating a single partition on a disk. This time we’ll look at how you can create multiple partitions on a disk. The are good reasons not to do this but its something I’ve seen done on a frequent basis.

Lets create a 20GB disk as an example and mount it

New-VHD -Path C:\test\Test1.vhdx -Dynamic -SizeBytes 20GB
Get-VHD -Path C:\test\Test1.vhdx | Mount-VHD

Initialise the disk

Initialize-Disk -Number 1

Now we can create some partitions

New-Partition -DiskNumber 1 -DriveLetter F -Size 5GB
New-Partition -DiskNumber 1 -DriveLetter G -Size 5GB
New-Partition -DiskNumber 1 -DriveLetter H -Size 5GB
New-Partition -DiskNumber 1 -DriveLetter I -Size 4.87GB

The reason that the last partition is only 4.87 G is that 128MB of disk space is reserved

PS> Get-Partition -DiskNumber 1 | Format-Table -AutoSize


   DiskPath: \\?\scsi#disk&ven_msft&prod_virtual_disk#2&1f4adffe&0&000003#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}

PartitionNumber DriveLetter Offset         Size Type
--------------- ----------- ------         ---- ----
1                           17408        128 MB Reserved
2               F           135266304      5 GB Basic
3               G           5503975424     5 GB Basic
4               H           10872684544    5 GB Basic
5               I           16241393664 4.87 GB Basic

You can format the 4 new volumes in one pass

Get-Partition -DiskNumber 1 | 
where Type -ne 'Reserved' | 
Format-Volume -FileSystem NTFS -Confirm:$false –Force

PS> Get-Partition -DiskNumber 1 | Get-Volume | select DriveLetter, FileSystem, Size

DriveLetter FileSystem       Size
----------- ----------       ----
          H NTFS       5368705024
          G NTFS       5368705024
          I NTFS       5229244416
          F NTFS       5368705024

The Storage module can be used to simply and easily create multiple volumes on a disk

May 23, 2017  11:35 AM

PowerShell in Azure Cloud Shell

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Azure, Powershell

if you are an Azure user see this post from the PowerShell team about the Azure Cloud Shell – https://blogs.msdn.microsoft.com/powershell/2017/05/23/coming-soon-powershell-in-azure-cloud-shell/


May 22, 2017  1:11 PM

Diskpart and PowerShell – part4: Remove a partition

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Disk storage, Powershell

So far you’ve seen how to create and modify partitions and volumes. Its now time to look at how you remove a partition.

Mount the test VHD

Get-VHD -Path C:\test\Test1.vhdx | Mount-VHD

You can’t remove a volume – you have to remove the partition. Identifying the CORRECT partition to remove is the challenge

PS> Get-Partition | select PartitionNumber, DriveLetter, Size, Type

PartitionNumber DriveLetter         Size Type
--------------- -----------         ---- ----
              1                134217728 Reserved
              2           F   8589934592 Basic
              1                367001600 IFS
              2           C 511269232640 IFS
              3                470810624 Unknown

Not every partition has a drive letter and partition numbers are repeated. The partition object holds the disk number

PS> Get-Partition | select DiskNumber, PartitionNumber, DriveLetter, Size, Type | Format-Table

DiskNumber PartitionNumber DriveLetter         Size Type
---------- --------------- -----------         ---- ----
         1               1                134217728 Reserved
         1               2           F   8589934592 Basic
         0               1                367001600 IFS
         0               2           C 511269232640 IFS
         0               3                470810624 Unknown

So the combination of disk number and partition number is unique and will identify any partition. Remove our 8GB partition

Remove-Partition -DiskNumber 1 -PartitionNumber 2 -Confirm:$false

and the 128MB partition

Remove-Partition -DiskNumber 1 -PartitionNumber 1 -Confirm:$false

Get-Partition will show that the drive F: has been removed

Looking the disk organisation

Get-Disk -Number 1 | Select @{N='Size'; E={[math]::Round(($_.Size / 1GB), 2)}}, @{N='AllocatedSize'; E={[math]::Round(($_.AllocatedSize / 1GB), 2)}}, @{N='LargestFreeExtent'; E={[math]::Round(($_.LargestFreeExtent / 1GB), 2)}} | Format-List

Size              : 20
AllocatedSize     : 0
LargestFreeExtent : 20

The whole of the disk is now available for re-use


May 21, 2017  1:50 PM

Diskpart and PowerShell–part 4: Expand a volume

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Disk storage, Powershell

You’ve seen how to create a volume but how do you expand a volume?

Let’s create a new disk and mount it

New-VHD -Path C:\test\Test1.vhdx -Dynamic -SizeBytes 20GB
Get-VHD -Path C:\test\Test1.vhdx | Mount-VHD
Initialize-Disk -Number 1

This time we’ll create a volume that only uses part of the disk

New-Partition -DiskNumber 1 -DriveLetter F -Size 5GB

And now format the partition

Get-Partition -DriveLetter F |
Format-Volume -FileSystem NTFS -Confirm:$false –Force

The disk is organised like this

Get-Disk -Number 1 | 
Select @{N='Size'; E={[math]::Round(($_.Size / 1GB), 2)}}, 
 @{N='AllocatedSize'; E={[math]::Round(($_.AllocatedSize / 1GB), 2)}}, 
@{N='LargestFreeExtent'; E={[math]::Round(($_.LargestFreeExtent / 1GB), 2)}} |
Format-List

Size              : 20
AllocatedSize     : 5.13
LargestFreeExtent : 14.87

Lets expand the partition

Get-Partition -DriveLetter F | 
Resize-Partition -Size 8GB

And re-examine the disk organisation

Get-Disk -Number 1 | 
Select @{N='Size'; E={[math]::Round(($_.Size / 1GB), 2)}}, 
 @{N='AllocatedSize'; E={[math]::Round(($_.AllocatedSize / 1GB), 2)}}, 
@{N='LargestFreeExtent'; E={[math]::Round(($_.LargestFreeExtent / 1GB), 2)}} |
Format-List

Size              : 20
AllocatedSize     : 8.13
LargestFreeExtent : 11.87

The extra space is added to the volume and formatted to match the existing filesystem on the volume


May 18, 2017  2:24 PM

Table or List

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A question on the forum asked why a object is displayed in a table if it has 4 or fewer properties and as  a list if it  has more than 4 properties:

PS> [PSCustomObject]@{P1=1; P2=2; P3=3; P4=4}

P1 P2 P3 P4
-- -- -- --
 1  2  3  4


PS> [PSCustomObject]@{P1=1; P2=2; P3=3; P4=4; P5=5}


P1 : 1
P2 : 2
P3 : 3
P4 : 4
P5 : 5

This is a built in mechanism in PowerShell and is done automatically.

The quick way to get the output in table format is to use Format-Table

PS> [PSCustomObject]@{P1=1; P2=2; P3=3; P4=4; P5=5} | Format-Table

P1 P2 P3 P4 P5
-- -- -- -- --
 1  2  3  4  5


May 10, 2017  3:39 AM

PowerShell v6 beta

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

PowerShell v6 has reached a significant milestone – the release of the first PowerShell v6 beta version. There have been 18 releases of alpha code since August 2016 when the open source PowerShell v6 project started.

There is no indication of how many beta releases there will be before PowerShell v6 is ready to ship.

Code is available from https://github.com/PowerShell/PowerShell/releases


May 9, 2017  3:23 AM

Are your domain controllers real?

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, CIM, Powershell

A question on the forum asked about discovering if domain controllers are physical or virtual machines. In other words Are your domain controllers real?

This will do the job:

foreach ($domain in (Get-ADForest).domains) {
 Get-ADDomainController -filter * -server $domain |
 sort hostname |
 foreach {
 Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $psitem.Hostname |
 select PSComputerName, Manufacturer, Model
 }
 }

Get the domains in your forest and then for each domain get the domain controllers. Get-ADDomainController outputs an object with a property of hostname – but you need a computername for Get-CimInstance. So, use a foreach-object and use the Hostname property as shown (you could create a property ComputerName on the pipeline object but its more work) and get the results. A virtual machine will show under the Model. You can sort or whatever once you have the results.


May 3, 2017  10:07 AM

OpenSSH

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

PowerShell v6 enables remoting over SSH between Linux and Windows machines. SSH connectivity is established using OpenSSH. You can use remoting over SSH in any of these scenarios:

Windows – Linux
Linux – Windows
Windows – Windows
Linux – Linux

You can also establish traditional WinRM remoting sessions and send commands to a mixture of WinRM and SSH based sessions.

A couple of new initiatives around OpenSSH need widespread participation.

First off – OpenSSH security testing

The PowerShell Team is getting OpenSSH production ready and as part of that are arranging for security testing. Details of how you can be involved are available from:

OpenSSH Security Testing Kick Off

Secondly – installing OpenSSH involves a significant number of manual steps. An OpenSSH Universal Installer is available for testing

https://cloudywindows.com/post/unveiling-the-openssh-universal-automated-installer/


May 1, 2017  3:33 PM

Positional parameters

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

Positional parameters have been around since the beginning of PowerShell. Positional parameters assume the parameter you mean from the position of the value in the command you supply. For instance you can do this:

Get-ChildItem -Path C:\test\ -Filter *.xml

Path and filter are the 2 positional parameters for Get-ChildItem (cmdlets can have 0, 1 or many positional parameters) so you can also do this:

Get-ChildItem C:\test\  *.xml

If you reverse the values you get an error

PS> Get-ChildItem *.xml  C:\test\
Get-ChildItem : Second path fragment must not be a drive or UNC name.
Parameter name: path2
At line:1 char:1
+ Get-ChildItem *.xml  C:\test\
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (C:\Scripts:String) [Get-ChildItem], ArgumentException
    + FullyQualifiedErrorId : DirArgumentError,Microsoft.PowerShell.Commands.GetChildItemCommand

You can find the position parameters by looking in the help file

PS> Get-Help Get-ChildItem -Parameter path

-Path <String[]>
    Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory
    (.).

    Required?                    false
    Position?                    0
    Default value                Current directory
    Accept pipeline input?       True (ByPropertyName, ByValue)
    Accept wildcard characters?  false

PS> Get-Help Get-ChildItem -Parameter filter

-Filter <String>
    Specifies a filter in the provider's format or language. The value of this parameter qualifies the Path parameter.
    The syntax of the filter, including the use of wildcards, depends on the provider. Filters are more efficient than
    other parameters, because the provider applies them when retrieving the objects, rather than having Windows
    PowerShell filter the objects after they are retrieved.

    Required?                    false
    Position?                    1
    Default value                None
    Accept pipeline input?       False
    Accept wildcard characters?  false

Notice the position values. A parameter that has to be named i.e. non-positional will have Named as the value for position:

PS> Get-Help Get-ChildItem -Parameter include

-Include <String[]>
    Specifies, as a string array, an item or items that this cmdlet includes in the operation. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted.

    The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows\*, where the wildcard character specifies the contents of the  C:\Windows directory.

    Required?                    false
    Position?                    named
    Default value                None
    Accept pipeline input?       False
    Accept wildcard characters?  false

You can also identify positional parameters from the syntax listing

Get-ChildItem [[-Path] <String[]>] [[-Filter] <String>] [-Attributes {ReadOnly | Hidden | System | Directory | Archive | Device | Normal | Temporary | SparseFile | ReparsePoint | Compressed | Offline | NotContentIndexed | Encrypted | IntegrityStream | NoScrubData}] [-Depth <UInt32>] [-Directory] [-Exclude <String[]>] [-File] [-Force]
[-Hidden] [-Include <String[]>] [-Name] [-ReadOnly] [-Recurse] [-System] [-UseTransaction] [<CommonParameters>]

The name of positional parameters are surrounded by square brackets

A question on the forum noted that the help file about_parameters states that positional parameters are numbers 1,2,3… and named parameters are effectively numbered 0 BUT the help file for Get-ChildItem numbers the positional parameters as 0 & 1

What’s happening?

If I remember correctly originally positional parameters were numbered from 1 but that was changed so 0 didn’t mean named. Looks like the about file didn’t get updated.

We can test this this with a function:

function test-pp {
 [CmdletBinding()]
 param (
   [Parameter(Position=0)]
   [int]$x,

   [Parameter(Position=1)]
   [string]$y
 )

 "$x is a number"
 "$y is a string"
}

PS> test-pp -x 2 -y abc
2 is a number
abc is a string

PS> test-pp 2 abc
2 is a number
abc is a string

So using position 0 works for positional parameters. What if we number them 1 & 2

function test-pp {
 [CmdletBinding()]
 param (
   [Parameter(Position=1)]
   [int]$x,

   [Parameter(Position=2)]
   [string]$y
 )

 "$x is a number"
 "$y is a string"
}

PS> test-pp -x 2 -y abc
2 is a number
abc is a string

PS> test-pp 2 abc
2 is a number
abc is a string

Works as well.

I’d recommend starting your positional parameter numbering from 0 and assume that about_parameters needs updating


April 30, 2017  1:26 PM

ISE or VS code?

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

When PowerShell v2 shipped with the ISE it was seen as a great step forward. We now had a decent editor for creating PowerShell code and running that code. You could also invoke the debugger. Some extensions to ISE have occurred, most notably  Show-Command, but its essentially the same editor as in PowerShell v2

Visual Studio Code – now at version 1.11.2 – offers an interesting alternative. It manages a host of other languages as well as PowerShell. I currently have the extensions for Docker, Markdown, SQL, PowerShell, JSON and XML loaded. Many others are available as open source projects.

You can also open a terminal window which can be a command prompt, PowerShell or WSL bash – you could have all 3 open simultaneously if required.

The other big plus is that VS Code is cross platform so I can use the same editor on Windows and Linux. A big plus in these days of heterogeneous environments.

I’m going to try using VS Code instead of ISE for a while to see if it suits the way I work. If so it’ll become my default editor


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: