Monthly Archive

Categories

PowerShell

ISE or VS code?

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

Mass dismount VHDs

I’m going to be creating, using and discarding a number of VHDs for my diskpart and PowerShell series. When I have a number of them mounted I want a quick way to dismount them. Assuming I consistently keep them in the same folder then this very nicely does the job

Get-ChildItem -Path C:\test\ -Filter *.vhdx | Dismount-VHD

 

Why does it work?

Because Get-ChildItem emits System.IO.FileInfo objects that have a Path property and Dismount-VHD accepts pipeline input for the Path of the VHD to dismount:

-Path <String[]>
    Specifies one or more virtual hard disk files for which the corresponding virtual hard disks are to be dismounted.

    Required?                    true
    Position?                    1
    Default value                none
    Accept pipeline input?       true (ByValue, ByPropertyName)
    Accept wildcard characters?  false

Diskpart and PowerShell–part 3: Initialize disk and create volume

Last time we created a virtual disk and mounted it. In this post we’ll initialize the disk and create a volume.

Start by remounting the disk

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

 

You can now initialize the disk:

Initialize-Disk -Number 1

 

Create a partition:

New-Partition -DiskNumber 1 -DriveLetter F –UseMaximumSize

 

Ignore the message about formatting as you want to control that:

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

 

Your new disk is ready to use.

The diskpart equivalents can be found here: https://technet.microsoft.com/en-us/library/cc766465(v=ws.10).aspx

 

You can perform the creation and formatting of the disk in one pass:

New-VHD -Path C:\test\Test2.vhdx -Dynamic -SizeBytes 10GB |
Mount-VHD -Passthru |
Initialize-Disk -PassThru |
New-Partition -DriveLetter G -UseMaximumSize |
Format-Volume -FileSystem NTFS -Confirm:$false –Force

 

Parameterize the path, size and drive letter and you have a handy function to set up disks

Diskpart and PowerShell–part 2: Create a virtual disk

Before we start digging into the diskpart/Storage module functionality we need a disk to practice on. I don’t recommend using your machine’s system disk – bad things will happen.

The Hyper-V module has  a New-VHD cmdlet so lets use that to create a disk to play with. The great thing about virtual disks is that you can delete then if everything goes horribly wrong.

There is a New-VirtualDisk cmdlet in the storage module but that works with storage pools. We’ll cover that later in the series.

Lets create a virtual disk:

New-VHD -Path C:\test\Test1.vhdx -Dynamic -SizeBytes 10GB

 

You can access the virtual disk using the path

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

 

You need to mount the virtual disk before you can work with it

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

 

Once mounted you can use get-Disk to identify the virtual disk

PS> Get-Disk | select Number, FriendlyName, PartitionStyle

Number FriendlyName               PartitionStyle
------ ------------               --------------
1 Msft Virtual Disk          RAW
0 Samsung SSD 840 PRO Series MBR

 

The clue is in the friendly name and that the partition style is RAW.

Next time we’ll look at formatting and partitioning the new drive. For now we’ll just dismount the virtual disk

Dismount-VHD -DiskNumber 1

DiskPart and PowerShell–part 1

An attendee at the Summit made the statement that the DiskPart utility didn’t have any equivalent in PowerShell. That’s not strictly true as the storage module provides a lot of functionality that maps to diskpart functionality.

The module contents include:

PS> Get-Command -Module Storage | select name

Name
----
Disable-PhysicalDiskIndication
Disable-StorageDiagnosticLog
Enable-PhysicalDiskIndication
Enable-StorageDiagnosticLog
Flush-Volume
Get-DiskSNV
Get-PhysicalDiskSNV
Get-StorageEnclosureSNV
Initialize-Volume
Write-FileSystemCache
Add-InitiatorIdToMaskingSet
Add-PartitionAccessPath
Add-PhysicalDisk
Add-TargetPortToMaskingSet
Add-VirtualDiskToMaskingSet
Block-FileShareAccess
Clear-Disk
Clear-FileStorageTier
Clear-StorageDiagnosticInfo
Connect-VirtualDisk
Debug-FileShare
Debug-StorageSubSystem
Debug-Volume
Disable-PhysicalDiskIdentification
Disable-StorageEnclosureIdentification
Disable-StorageHighAvailability
Disable-StorageMaintenanceMode
Disconnect-VirtualDisk
Dismount-DiskImage
Enable-PhysicalDiskIdentification
Enable-StorageEnclosureIdentification
Enable-StorageHighAvailability
Enable-StorageMaintenanceMode
Format-Volume
Get-DedupProperties
Get-Disk
Get-DiskImage
Get-DiskStorageNodeView
Get-FileIntegrity
Get-FileShare
Get-FileShareAccessControlEntry
Get-FileStorageTier
Get-InitiatorId
Get-InitiatorPort
Get-MaskingSet
Get-OffloadDataTransferSetting
Get-Partition
Get-PartitionSupportedSize
Get-PhysicalDisk
Get-PhysicalDiskStorageNodeView
Get-PhysicalExtent
Get-PhysicalExtentAssociation
Get-ResiliencySetting
Get-StorageAdvancedProperty
Get-StorageDiagnosticInfo
Get-StorageEnclosure
Get-StorageEnclosureStorageNodeView
Get-StorageEnclosureVendorData
Get-StorageFaultDomain
Get-StorageFileServer
Get-StorageFirmwareInformation
Get-StorageHealthAction
Get-StorageHealthReport
Get-StorageHealthSetting
Get-StorageJob
Get-StorageNode
Get-StoragePool
Get-StorageProvider
Get-StorageReliabilityCounter
Get-StorageSetting
Get-StorageSubSystem
Get-StorageTier
Get-StorageTierSupportedSize
Get-SupportedClusterSizes
Get-SupportedFileSystems
Get-TargetPort
Get-TargetPortal
Get-VirtualDisk
Get-VirtualDiskSupportedSize
Get-Volume
Get-VolumeCorruptionCount
Get-VolumeScrubPolicy
Grant-FileShareAccess
Hide-VirtualDisk
Initialize-Disk
Mount-DiskImage
New-FileShare
New-MaskingSet
New-Partition
New-StorageFileServer
New-StoragePool
New-StorageSubsystemVirtualDisk
New-StorageTier
New-VirtualDisk
New-VirtualDiskClone
New-VirtualDiskSnapshot
New-Volume
Optimize-StoragePool
Optimize-Volume
Register-StorageSubsystem
Remove-FileShare
Remove-InitiatorId
Remove-InitiatorIdFromMaskingSet
Remove-MaskingSet
Remove-Partition
Remove-PartitionAccessPath
Remove-PhysicalDisk
Remove-StorageFileServer
Remove-StorageHealthSetting
Remove-StoragePool
Remove-StorageTier
Remove-TargetPortFromMaskingSet
Remove-VirtualDisk
Remove-VirtualDiskFromMaskingSet
Rename-MaskingSet
Repair-FileIntegrity
Repair-VirtualDisk
Repair-Volume
Reset-PhysicalDisk
Reset-StorageReliabilityCounter
Resize-Partition
Resize-StorageTier
Resize-VirtualDisk
Revoke-FileShareAccess
Set-Disk
Set-FileIntegrity
Set-FileShare
Set-FileStorageTier
Set-InitiatorPort
Set-Partition
Set-PhysicalDisk
Set-ResiliencySetting
Set-StorageFileServer
Set-StorageHealthSetting
Set-StoragePool
Set-StorageProvider
Set-StorageSetting
Set-StorageSubSystem
Set-StorageTier
Set-VirtualDisk
Set-Volume
Set-VolumeScrubPolicy
Show-VirtualDisk
Start-StorageDiagnosticLog
Stop-StorageDiagnosticLog
Stop-StorageJob
Unblock-FileShareAccess
Unregister-StorageSubsystem
Update-Disk
Update-HostStorageCache
Update-StorageFirmware
Update-StoragePool
Update-StorageProviderCache
Write-VolumeCache

In this mini series I’m going to go through a number of the diskpart options and show you how to do the same with the Storage module cmdlets.

I’m not sure if all diskpart options are available but it’ll be fun to find out.

The Storage module was introduced with Windows 8/Server 2012.

ls $pshome\modules\storage

or

Get-ChildItem $pshome\modules\storage

if you prefer shows a number of cdxml files. This means that the cmdlets are based on CIM classes which you can see at

Get-CimClass -Namespace ROOT/Microsoft/Windows/Storage

These classes aren’t available on versions of Windows prior to Windows 8/Server 2012.

I’ll also have a look at some of these classes to see if there’s anything we can do that isn’t covered directly by the storage module cmdlets.

PowerShell Summit 2017 thoughts

2017 saw our largest Summit to date. 250 PowerShell fanatics (I use the word advisedly) descended on Bellevue Washington. The conversations had already started when I arrived at the hotel on the Friday night before the Summit!

We had a planning meeting for Summit 2018 on the Saturday. Some good ideas came from the meeting that we’ll share in a little while. If you thought this year was good next year will amaze you.

The Summit opened on Sunday with 3 hour Deep Dives morning and afternoon. During the morning I discovered that the issues Delta airlines were having was causing problems for speakers travelling to the Summit. In the end we only had one speaker unable to reach the Summit. We have a plan to mitigate any future issues with speaker drop outs that we’ll be implementing for Summit 2018 and later (yes we do plan more than a year in advance).

Monday saw the PowerShell team presenting on PowerShell now and in the future with team members showing what they’re working on now!

Tuesday and Wednesday morning saw some amazing standard length sessions and the first outing for the Three Furies of PowerShell – who knows they may appear again sometime.

Wednesday afternoon saw the Community Lightning Demos – everything I’ve heard says it was amazing – I was moderating 2 panel discussions. We also had some longer technical sessions.

I saw a large number of people I recognised from previous Summits. I asked why they came back and consistently received two reasons:

- the high level of the technical content

- the ability to talk to speakers, MVPs, team members and other attendees about their PowerShell problems and get answers to those problems

Be assured we’ve taken those 2 things on board and are committed to preserving those aspects of the Summit.

A huge thanks to the speakers, the PowerShell team and the attendees for making a fantastic Summit. A little while to reflect and catch my breath and then its time to dive into the work for next year

PowerShell Direct failure

PowerShell Direct is introduced with Server 2016/Windows 10. it enables you to create a remoting session from the Hyper-V host to a VM using the VM name or ID. I recent discovered a PowerShell Direct failure that I couldn’t explain until now.

Normally you do this:

PS> New-PSSession -VMName w16cn01 -Credential (Get-Credential w16cn01\administrator)

Id Name    ComputerName  ComputerType  State  ConfigurationName  Availability
-- ----     ------------  ------------    -----  -----------------  ------------
1 Session1       W16CN01  VirtualMachine  Opened                       Available

But on one particular machine I was getting this

PS> New-PSSession -VMName w16as01 -Credential (Get-Credential w16as01\administrator)
New-PSSession : [W16AS01] An error has occurred which Windows PowerShell cannot handle. A remote session might have ended.
At line:1 char:1
+ New-PSSession -VMName w16as01 -Credential (Get-Credential w16as01\adm ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotin
gDataStructureException
+ FullyQualifiedErrorId : PSSessionOpenFailed

I couldn’t find an explanation for this particular PowerShell Direct failure

I’ve been working with PowerShell v6 and OpenSSH the last few days and I noticed that the PowerShell directory had been removed from the system path by the installation of one of these pieces of software.

W16AS01 had been the first machine I experimented with PowerShell v6/OpenSSH and it was the first to experience this PowerShell direct failure.

I checked W16AS01 and sure enough the PowerShell folder was missing from the system path. Adding the Powershell folder back onto the path (and restarting the machine for luck) then retrying PowerShell Direct gives:

PS> New-PSSession -VMName W16AS01 -Credential (Get-Credential W16AS01\Administrator)

Id Name            ComputerName    ComputerType    State         ConfigurationName     Availability
-- ----            ------------    ------------    -----         -----------------     ------------
1 Session1        W16AS01         VirtualMachine  Opened                                 Available

Looks like I’ve found a solution for this particular PowerShell direct failure

PowerShell v6

Tried PowerShell v6 yet?

Its the open sourced latest version of PowerShell – runs on Windows, Linux (various flavours) and MacOS

Its available from - https://github.com/PowerShell/PowerShell

Before you get too excited there’s a few things you need to remember:

- its ALPHA code. That means its still under development and subject to change

- its not production ready

- it only provides the core parts of PowerShell – for instance all the CDXML modules aren’t available

- it uses .NET Core rather than  full .NET  - it doesn’t have the GUI libraries for instance

- it does install side by side with out of the box PowerShell (on later versions of Windows only)

- it does enable remoting between Windows and Linux using SSH

Its worth testing for 2 reasons. First you can see what’s happening with PowerShell and the changes that are coming. Secondly, you can feed back directly to the project and directly influence the future of PowerShell

Summit 2017–one week to go

With one week to go before travelling to Seattle for the 2017 PowerShell & DevOps Summit I’m putting the finishing touches to my presentations and the Summit organisation.

The agenda was published last October but we’ve had to make a few changes recently to cover for speakers that have dropped out. Check out the final version before deciding on the sessions you’ll attend.

We’ve already started planning the 2018 Summit – more details will come later – but we think you’ll like what we’re planning. All your favourite Summit features and more.

If you’re going to the Summit don’t forget to sign up for the Lightning Demos – your chance to speak and share your discoveries.

Get-SupportedFileSystems

I stumbled on the Get-SupportedFileSystems cmdlet today. Its part of the Storage module and is defined as a function. Digging a bit further its from a CDXML module based on a CIM class. But which CDXML file contains the definition?

PS> Get-ChildItem -Path 'C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Storage' -File | Select-String -Pattern 'Get-SupportedFileSystems' -SimpleMatch

C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Storage\Storage.psd1:117:        'Get-SupportedFileSystems',
C:\Windows\System32\WindowsPowerShell\v1.0\Modules\Storage\Volume.cdxml:405:      // Get-SupportedFileSystems

Looking in Volume.cdxml shows we’re working with the ROOT/Microsoft/Windows/Storage/MSFT_Volume class. You can use this directly

PS> Get-CimInstance -Namespace ROOT/Microsoft/Windows/Storage -ClassName MSFT_Volume | select DriveLetter, FileSystem

DriveLetter FileSystem
----------- ----------
D
NTFS
NTFS
C NTFS

When you use Get-SupportedFileSystems all you get back is the filesystem

PS> Get-SupportedFileSystems -DriveLetter C
NTFS

The DriveLetter parameter can take an array of chars but if you supply a driveletter where there isn’t a defined filesystem you get an error

PS> Get-SupportedFileSystems -DriveLetter D
Get-SupportedFileSystems : Failed
Activity ID: {25bde807-4d9f-4216-8640-94268ff80624}
At line:1 char:1
+ Get-SupportedFileSystems -DriveLetter D
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (StorageWMI:ROOT/Microsoft/...age/MSFT_Volume) [Get-SupportedFileSystems],
CimException
+ FullyQualifiedErrorId : StorageWMI 4,Get-SupportedFileSystems

or if the drive isn’t defined

PS> Get-SupportedFileSystems -DriveLetter E
Get-SupportedFileSystems : No MSFT_Volume objects found with property 'DriveLetter' equal to 'E'.  Verify the value of the property and retry.
At line:1 char:1
+ Get-SupportedFileSystems -DriveLetter E
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : ObjectNotFound: (E:Char) [Get-SupportedFileSystems], CimJobException
+ FullyQualifiedErrorId : CmdletizationQuery_NotFound_DriveLetter,Get-SupportedFileSystems

The DriveLetter parameter accepts pipeline input by propertyname BUT it has to be a Char not a string.

What would be useful would be to get the drives using Get-PSDrive and pass to Get-SupportedFileSystems

PS> Get-PSDrive -PSProvider FileSystem | Format-Table -AutoSize

Name Used (GB) Free (GB) Provider   Root CurrentLocation
---- --------- --------- --------   ---- ---------------
C       202.61    273.55 FileSystem C:\          Scripts
D                        FileSystem D:\

Get-PSDrive outputs the driveletter as the name property and just make life fun its a string.

Time for some PowerShell magic.

This looks good

Get-PSDrive -PSProvider FileSystem |
select @{N='DriveLetter'; E={[char]$_.Name}} |
Get-SupportedFileSystems

but it fails because D doesn’t have a filesystem defined.

So try this

Get-PSDrive -PSProvider FileSystem |
foreach {
$props = [ordered]@{
DriveLetter = $_.Name
FileSystem = Get-SupportedFileSystems -DriveLetter $_.Name -ErrorAction SilentlyContinue
}
New-Object -TypeName PSObject -Property $props
}

DriveLetter FileSystem
----------- ----------
C           NTFS
D

A simple way to check the filesystem used on your Windows machines