Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell's Get-Member cmdlet doesn't report all methods

Tags:

powershell

notepad
$Notepad = Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'"
Invoke-CimMethod -InputObject $Notepad -MethodName Terminate

These statements work correctly, but when I use Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" | get-member -force to find the Terminate method, it doesn't seem to exist.

like image 749
Ding.Frank Avatar asked Oct 03 '16 23:10

Ding.Frank


People also ask

What does get-Member cmdlet do?

The Get-Member cmdlet gets the members, the properties and methods, of objects. To specify the object, use the InputObject parameter or pipe an object to Get-Member . To get information about static members, the members of the class, not of the instance, use the Static parameter.

What PowerShell cmdlet shows all the properties and methods available for services?

The Get-Service cmdlet gets all the services on the computer and sends the objects down the pipeline.

What is the get CimClass cmdlet used for?

The Get-CimClass cmdlet retrieves a list of CIM classes in a specific namespace. If there is no class name supplied, then the cmdlet returns all the classes in the namespace. Unlike a CIM instance, CIM classes do not contain the CIM session or computer name from which they are retrieved.

What is the right syntax to get the methods and properties of any cmdlets?

To get the methods of any object, use the Get-Member cmdlet. Use its MemberType property with a value of "Method".


2 Answers

The Invoke-CimMethod cmdlet invokes a method of a Common Information Model (CIM) class or CIM instance

The Get-CimInstance cmdlet gets the Common Information Model (CIM) instances of a class from a CIM server …

Do not confuse methods of Powershell and CimClass objects:

  • The Get-Member cmdlet gets the members, the properties and methods, of objects.
    Output type: [Microsoft.PowerShell.Commands.MemberDefinition]
  • The Get-CimClass cmdlet gets a list of Common Information Model (CIM) classes in a specific namespace.
    Output type: [Microsoft.Management.Infrastructure.CimClass]

You are looking for something like

PS D:\PShell> (Get-CimClass -ClassName Win32_Process).CimClassMethods | 
    Format-Table -AutoSize -Wrap

Name                    ReturnType Parameters 
----                    ---------- ---------- 
Create                      UInt32 {CommandLine, CurrentDirectory,
                                    ProcessStartupInformation, ProcessId}
Terminate                   UInt32 {Reason} 
GetOwner                    UInt32 {Domain, User} 
GetOwnerSid                 UInt32 {Sid} 
SetPriority                 UInt32 {Priority} 
AttachDebugger              UInt32 {} 
GetAvailableVirtualSize     UInt32 {AvailableVirtualSize} 
like image 118
JosefZ Avatar answered Sep 24 '22 07:09

JosefZ


JosefZ's answer is helpful and offers an effective solution; let me complement it with a different way of explaining the issue:

tl;dr:

To discover the methods supported by a CIM instance via an object returned by Get-CimInstance, access its .CimClass.CimClassMethods property:

PS> (Get-CimInstance Win32_Process -Filter "Name = 'notepad.exe'").CimClass.CimClassMethods

Name                    ReturnType Parameters                                                            Qualifiers
----                    ---------- ----------                                                            ----------
Create                      UInt32 {CommandLine, CurrentDirectory, ProcessStartupInformation, ProcessId} {Constructor, Implemented, MappingStrings, Privileges...}
Terminate                   UInt32 {Reason}                                                              {Destructor, Implemented, MappingStrings, Privileges...}
GetOwner                    UInt32 {Domain, User}                                                        {Implemented, MappingStrings, ValueMap}
GetOwnerSid                 UInt32 {Sid}                                                                 {Implemented, MappingStrings, ValueMap}
SetPriority                 UInt32 {Priority}                                                            {Implemented, MappingStrings, ValueMap}
AttachDebugger              UInt32 {}                                                                    {Implemented, ValueMap}
GetAvailableVirtualSize     UInt32 {AvailableVirtualSize}

To restrict the above to instance methods:

(Get-CimInstance Win32_Process -Filter "Name = 'notepad.exe'").CimClass.CimClassMethods | 
  Where-Object { -not $_.Qualifiers['Static'] }

Alternatively, pass the name of the CIM class to Get-CimClass -ClassName, as in JosefZ's answer.


It is reasonable to expect objects returned from cmdlets to reveal all their members when piped to Get-Member - that's how it generally works in PowerShell.
However, dealing with CIM entities (classes and instances) is a special case:

  • PowerShell and its .NET-based type (class) system on the one hand, and the platform-neutral CIM standard, modeling (typically) remote computing resources on the other, are distinct worlds, with their own entities, that map imperfectly onto each other.

  • CIM instances are partially mapped onto PowerShell objects of type [Microsoft.Management.Infrastructure.CimInstance], as returned by Get-CimInstance:

    • These PowerShell objects are in effect partial, read-only snapshots of the underlying CIM instances.

      • By default, the full set of properties of the underlying CIM instance is represented on the PowerShell object.
        Note: While technically writeable properties are returned as well (e.g., the State property of a Win32_Service instance), assigning to such a property seems to be ignored in practice.
      • However, no methods of the underlying CIM class are present (presumably, because methods are usually used to modify objects, and thus not needed for a read-only representation).
    • You cannot directly modify CIM instances through their local [Microsoft.Management.Infrastructure.CimInstance] representations - dedicated cmdlets are required to modify CIM instances: Invoke-CimMethod to invoke methods, and Set-CimInstance to set properties.

    • Similarly, you cannot directly discover all members of a CIM class/instance by inspecting [Microsoft.Management.Infrastructure.CimInstance] objects with Get-Member, given that they are only a partial representation of their underlying CIM instances.
      As stated at the top, you have two options:

      • Access a given [Microsoft.Management.Infrastructure.CimInstance] object's CimClass property, which PowerShell automatically adds.
      • Call Get-CimClass -ClassName <CimClassName>.
      • Both methods return a [Microsoft.Management.Infrastructure.CimClass] instance that describes the CIM class in terms of its properties and methods, among other things, but note that this introspection information is based on CIM rules.
like image 27
mklement0 Avatar answered Sep 24 '22 07:09

mklement0