1

I am trying to get the following function to work within PowerShell 6.0.2, however apparently Get-WmiObject has been deprecated. Can anyone help me figure out how to replace it with Get-CimInstance which has replaced it?

Get-WmiObject is within the PROCESS area of the code below.

Complete function code provided in case someone is interested.

function Get-DiskFree
{
[CmdletBinding()]
param
(
    [Parameter(Position=0,
               ValueFromPipeline=$true,
               ValueFromPipelineByPropertyName=$true)]
    [Alias('hostname')]
    [Alias('cn')]
    [string[]]$ComputerName = $env:COMPUTERNAME,

    [Parameter(Position=1,
               Mandatory=$false)]
    [Alias('runas')]
    [System.Management.Automation.Credential()]$Credential =
    [System.Management.Automation.PSCredential]::Empty,

    [Parameter(Position=2)]
    [switch]$Format
)

BEGIN
{
    function Format-HumanReadable
    {
        param ($size)
        switch ($size)
        {
            {$_ -ge 1PB}{"{0:#.#'P'}" -f ($size / 1PB); break}
            {$_ -ge 1TB}{"{0:#.#'T'}" -f ($size / 1TB); break}
            {$_ -ge 1GB}{"{0:#.#'G'}" -f ($size / 1GB); break}
            {$_ -ge 1MB}{"{0:#.#'M'}" -f ($size / 1MB); break}
            {$_ -ge 1KB}{"{0:#'K'}" -f ($size / 1KB); break}
            default {"{0}" -f ($size) + "B"}
        }
    }

    $wmiq = 'SELECT * FROM Win32_LogicalDisk WHERE Size != Null AND DriveType >= 2'
}

PROCESS
{
    foreach ($computer in $ComputerName)
    {
        try
        {
            if ($computer -eq $env:COMPUTERNAME)
            {
                $disks = Get-WmiObject -Query $wmiq `
                         -ComputerName $computer -ErrorAction Stop
            }
            else
            {
                $disks = Get-WmiObject -Query $wmiq `
                         -ComputerName $computer -Credential $Credential `
                         -ErrorAction Stop
            }

            if ($Format)
            {
                # Create array for $disk objects and then populate
                $diskarray = @()
                $disks | ForEach-Object { $diskarray += $_ }

                $diskarray | Select-Object @{n='Name';e={$_.SystemName}},
                    @{n='Vol';e={$_.DeviceID}},
                    @{n='Size';e={Format-HumanReadable $_.Size}},
                    @{n='Used';e={Format-HumanReadable `
                    (($_.Size)-($_.FreeSpace))}},
                    @{n='Avail';e={Format-HumanReadable $_.FreeSpace}},
                    @{n='Use%';e={[int](((($_.Size)-($_.FreeSpace))`
                    /($_.Size) * 100))}},
                    @{n='FS';e={$_.FileSystem}},
                    @{n='Type';e={$_.Description}}
            }
            else
            {
                foreach ($disk in $disks)
                {
                    $diskprops = @{'Volume'=$disk.DeviceID;
                               'Size'=$disk.Size;
                               'Used'=($disk.Size - $disk.FreeSpace);
                               'Available'=$disk.FreeSpace;
                               'FileSystem'=$disk.FileSystem;
                               'Type'=$disk.Description
                               'Computer'=$disk.SystemName;}

                    # Create custom PS object and apply type
                    $diskobj = New-Object -TypeName PSObject `
                               -Property $diskprops
                    $diskobj.PSObject.TypeNames.Insert(0,'BinaryNature.DiskFree')

                    Write-Output $diskobj
                }
            }
        }
        catch
        {
            # Check for common DCOM errors and display "friendly" output
            switch ($_)
            {
                { $_.Exception.ErrorCode -eq 0x800706ba } `
                    { $err = 'Unavailable (Host Offline or Firewall)';
                        break; }
                { $_.CategoryInfo.Reason -eq 'UnauthorizedAccessException' } `
                    { $err = 'Access denied (Check User Permissions)';
                        break; }
                default { $err = $_.Exception.Message }
            }
            Write-Warning "$computer - $err"
        }
    }
}

END {}
}

Below is the PowerShell commands that I will run after loading the function, taken from this site: http://binarynature.blogspot.com/2010/04/powershell-version-of-df-command.html

$cred = Get-Credential 'example\administrator'
$servers = 'dc01','db01','exch01','sp01'
Get-DiskFree -Credential $cred -cn $servers -Format |
    ? { $_.Type -like '*fixed*' } |
    select * -ExcludeProperty Type |
    Out-GridView -Title 'Windows Servers Storage Statistics'
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
That1Dude1
  • 11
  • 2
  • 5
  • 1
    Get-WMIObject still works fine and will continue to work for the forseeable future. – EBGreen Mar 23 '18 at 15:32
  • 1
    Having said that your script should work just fine by simply changing Get-WMIObject to Get-CimInstance and Win32_LogicalDisk to CIM_LogicalDisk. – EBGreen Mar 23 '18 at 15:35
  • @EBGreen - I'm not sure that the classname changes; can you point to any documentation of that fact? – Jeff Zeitlin Mar 23 '18 at 15:38
  • 2
    Well, running the code would show you... – EBGreen Mar 23 '18 at 15:41
  • If you want it from the horses mouth just open powershell and type: `Get-CIMInstance *logicalDisk*` – EBGreen Mar 23 '18 at 15:42
  • Actually if you have the ***need*** to do WMI queries in PS6 Core then I retract my prior statement regarding Get-WMIObject working. In that relativily limited scenario then yes, use the CIM cmdlets. But for v5 there isn't a compelling reason to go back and rewrite scripts. Just start using CIM for whatever you write new. – EBGreen Mar 23 '18 at 15:50
  • Oh, and to follow up a little more, unless you are writing scripts on *nix machines, IMO there is no compelling reason to use v6.0 Core and plenty of reasons not to. – EBGreen Mar 23 '18 at 18:00
  • @EBGreen Thanks for the information. Hopefully I can learn something here and piece this thing together. – That1Dude1 Mar 23 '18 at 18:32

1 Answers1

1

As EBGreen stated, this can be resolved by changing Get-WmiObject to Get-CimInstance. There are only two lines in that function that need rewriting:

Current (using Get-WmiObject)

$disks = Get-WmiObject -Query $wmiq -ComputerName $computer -ErrorAction Stop
$disks = Get-WmiObject -Query $wmiq -ComputerName $computer -Credential $Credential -ErrorAction Stop

Changed (using Get-CimInstance)*

$disks = Get-CimInstance -Query $wmiq -ComputerName $computer -ErrorAction Stop
$disks = Invoke-Command -ArgumentList $wmiq { param($wmiq) Get-CimInstance -Query $wmiq } -ComputerName $computer -Credential $Credential -ErrorAction Stop | Select-Object DeviceID, DriveType, ProviderName, FreeSpace, Size, VolumeName


Here is the full function with these changes already made (and cleaned up a bit to my liking). I can confirm that it is working on PowerShell Core v6.1.2

function Get-DiskFree {
    [CmdletBinding()]
    param (
        [Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias('cn')]
        [string[]]$ComputerName = $env:COMPUTERNAME,

        [Parameter(Position=1, Mandatory=$false)]
        [Alias('cr')]
        [System.Management.Automation.Credential()]
        $Credential = [System.Management.Automation.PSCredential]::Empty,

        [Parameter(Position=2)]
        [Alias('f')]
        [switch]$Format
    )

    begin {
        $ErrorActionPreference = "Stop"

        function Format-HumanReadable {
            param (
                $size
            )

            switch ($size) {
                {$_ -ge 1PB}
                    {"{0:#.#'P'}" -f ($size / 1PB); break}
                {$_ -ge 1TB}
                    {"{0:#.#'T'}" -f ($size / 1TB); break}
                {$_ -ge 1GB}
                    {"{0:#.#'G'}" -f ($size / 1GB); break}
                {$_ -ge 1MB}
                    {"{0:#.#'M'}" -f ($size / 1MB); break}
                {$_ -ge 1KB}
                    {"{0:#'K'}" -f ($size / 1KB); break}
                default 
                    {"{0}" -f ($size) + "B"}
            }
        }

        $wmiq = 'SELECT * FROM Win32_LogicalDisk WHERE Size != Null AND DriveType >= 2'
    }

    process {
        foreach ($computer in $ComputerName) {
            try {
                if ($computer -eq $env:COMPUTERNAME) {
                    $disks = Get-CimInstance -Query $wmiq -ComputerName $computer
                }
                else {
                    $disks = Invoke-Command -ArgumentList $wmiq { param($wmiq) Get-CimInstance -Query $wmiq } -ComputerName $computer -Credential $Credential `
                        | Select-Object DeviceID, DriveType, ProviderName, FreeSpace, Size, VolumeName
                }

                if ($Format) {
                    # Create array for $disk objects and then populate
                    $diskarray = @()
                    $disks | ForEach-Object { $diskarray += $_ }

                    $diskarray | Select-Object
                        @{Name='Name'; Expression={$_.SystemName}},
                        @{Name='Vol'; Expression={$_.DeviceID}},
                        @{Name='Size'; Expression={Format-HumanReadable $_.Size}},
                        @{Name='Used'; Expression={Format-HumanReadable (($_.Size)-($_.FreeSpace))}},
                        @{Name='Avail'; Expression={Format-HumanReadable $_.FreeSpace}},
                        @{Name='Use%'; Expression={[int](((($_.Size)-($_.FreeSpace))/($_.Size) * 100))}},
                        @{Name='FS'; Expression={$_.FileSystem}},
                        @{Name='Type'; Expression={$_.Description}}
                }
                else {
                    foreach ($disk in $disks) {
                        $diskprops = @{
                            'Volume'=$disk.DeviceID;
                            'Size'=$disk.Size;
                            'Used'=($disk.Size - $disk.FreeSpace);
                            'Available'=$disk.FreeSpace;
                            'FileSystem'=$disk.FileSystem;
                            'Type'=$disk.Description
                            'Computer'=$disk.SystemName;
                        }

                        # Create custom PS object and apply type
                        $diskobj = New-Object -TypeName PSObject -Property $diskprops
                        $diskobj.PSObject.TypeNames.Insert(0,'BinaryNature.DiskFree')

                        Write-Output $diskobj
                    }
                }
            }
            catch {
                # Check for common DCOM errors and display "friendly" output
                switch ($_) {
                    { $_.Exception.ErrorCode -eq 0x800706ba }
                        {$err = 'Unavailable (Host Offline or Firewall)'; break}
                    { $_.CategoryInfo.Reason -eq 'UnauthorizedAccessException' }
                        {$err = 'Access denied (Check User Permissions)'; break}
                    default
                        {$err = $_.Exception.Message}
                }
                Write-Warning "$computer - $err"
            }
        }
    }

    end {

    }
}
jmjohnson85
  • 347
  • 4
  • 9