Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support getting an object by an instance path in Get-CimInstance #15247

Closed
conioh opened this issue Apr 16, 2021 · 23 comments
Closed

Support getting an object by an instance path in Get-CimInstance #15247

conioh opened this issue Apr 16, 2021 · 23 comments
Labels
Issue-Enhancement the issue is more of a feature request than a bug Resolution-By Design The reported behavior is by design. WG-Cmdlets general cmdlet issues

Comments

@conioh
Copy link

conioh commented Apr 16, 2021

Summary of the new feature/enhancement

I'd like to get a WMI object by providing an instance path to Get-CimInstance as is possible in most other WMI interfaces. This is possible both with from programmatic ones - the IWbemXxx COM interfaces, the Active Scripting interfaces (SWbemXxx objects), .NET, etc.) - and from the management and testing tools (wmic.exe, wbemtest.exe).

I'd like to do in PowerShell the equivalent of:

Set locator = CreateObject("WbemScripting.SWbemLocator")
Set service = locator.ConnectServer(machine, namespace)

Set instance = service.Get("Win32_Whatever.Property=value,OtherProperty=other_value")

Currently none of the cmdlets in the CimCmdlets allows me to do that as far as I'm aware.

It is possible to use the System.Management.ManagementObject class via the [wmi] type accelerator (in contrast with the Microsoft.Management.Infrastructure.CimInstance used by the CimCmdlets module) to get an object by an instance path, but that seems to only works on the local machine, similarly to VBScript's GetObject function.

But VBScript and C++ and .NET and everything else are also able to get objects by instance paths from remote machines, like in the example at the top.

(Even if it is somehow possible to use [wmi] for remote objects it would still be nice for Get-CimInstance to be more complete.)

Proposed technical implementation details (optional)

Get-CimInstance should have a -Path or -InstancePath parameter and if it is present it will pass the properties to Microsoft.Management.Infrastructure.CimSession.GetInstanceAsync like in the example at: https://docs.microsoft.com/en-us/windows/win32/wmisdk/retrieving-an-instance#:~:text=To%20retrieve%20an%20instance%20of%20a%20WMI%20class%20using%20C#%20(Microsoft.Management.Infrastructure)

@conioh conioh added Issue-Enhancement the issue is more of a feature request than a bug Needs-Triage The issue is new and needs to be triaged by a work group. labels Apr 16, 2021
@iSazonov
Copy link
Collaborator

iSazonov commented Apr 16, 2021

Please look examples from docs https://docs.microsoft.com/en-us/powershell/module/cimcmdlets/get-ciminstance?view=powershell-7.1 and say what scenarios are not covered?

The Get-CimInstance cmdlet gets the CIM instances of a class from a CIM server. You can specify either the class name or a query for this cmdlet. This cmdlet returns one or more CIM instance objects representing a snapshot of the CIM instances present on the CIM server. If the InputObject parameter is not specified, the cmdlet works in one of the following ways: If neither the ComputerName parameter nor the CimSession parameter is specified, then this cmdlet works on local Windows Management Instrumentation (WMI) using a Component Object Model (COM) session. If either the ComputerName parameter or the CimSession parameter is specified, then this cmdlet works against the CIM server specified by either the ComputerName parameter or the CimSession parameter. If the InputObject parameter is specified, the cmdlet works in one of the following ways: If neither the ComputerName parameter nor the CimSession parameter is specified, then this cmdlet uses the CIM session or computer name from the input object. If the either the ComputerName parameter or the CimSession parameter is specified, then this cmdlet uses the either the CimSession parameter value or ComputerName parameter value.

@iSazonov iSazonov added the WG-Cmdlets general cmdlet issues label Apr 16, 2021
@conioh
Copy link
Author

conioh commented Apr 17, 2021

Please look examples from docs https://docs.microsoft.com/en-us/powershell/module/cimcmdlets/get-ciminstance?view=powershell-7.1 and say what scenarios are not covered?

As I have said, the scenario not covered is getting an object from an instance path:

I'd like to get a WMI object by providing an instance path to Get-CimInstance as is possible in most other WMI interfaces. This is possible both with from programmatic ones - the IWbemXxx COM interfaces, the Active Scripting interfaces (SWbemXxx objects), .NET, etc.) - and from the management and testing tools (wmic.exe, wbemtest.exe).

I'd like to do in PowerShell the equivalent of:

Set locator = CreateObject("WbemScripting.SWbemLocator")
Set service = locator.ConnectServer(machine, namespace)

Set instance = service.Get("Win32_Whatever.Property=value,OtherProperty=other_value")

You see that line where there a class name followed by a period and then a list of property names and values? That. That is the scenario not covered by Get-CimInstance.

The Get-CimInstance cmdlet gets the CIM instances of a class from a CIM server. You can specify either the class name or a query for this cmdlet. This cmdlet returns one or more CIM instance objects representing a snapshot of the CIM instances present on the CIM server. If the InputObject parameter is not specified, the cmdlet works in one of the following ways: If neither the ComputerName parameter nor the CimSession parameter is specified, then this cmdlet works on local Windows Management Instrumentation (WMI) using a Component Object Model (COM) session. If either the ComputerName parameter or the CimSession parameter is specified, then this cmdlet works against the CIM server specified by either the ComputerName parameter or the CimSession parameter. If the InputObject parameter is specified, the cmdlet works in one of the following ways: If neither the ComputerName parameter nor the CimSession parameter is specified, then this cmdlet uses the CIM session or computer name from the input object. If the either the ComputerName parameter or the CimSession parameter is specified, then this cmdlet uses the either the CimSession parameter value or ComputerName parameter value.

@vexx32
Copy link
Collaborator

vexx32 commented Apr 17, 2021

I'm not super familiar with that syntax, so if I'm overlooking something just let me know (the docs referencing it don't really explain it super well from what I can see)... but it looks like it's just a different way of filtering the results? Get-CimInstance provides a WQL -Filter parameter for that.

The equivalent of Set instance = service.Get("Win32_Whatever.Property=value,OtherProperty=other_value") would more or less be something like this -- I think?

Get-CimInstance Win32_Whatever -Filter "Property = 'value' AND OtherProperty = 'other value'"

I'm not familiar enough with the history of why the specific syntax isn't still supported, but the functionality is very much there, if I understand your use case correctly.

@conioh
Copy link
Author

conioh commented Apr 17, 2021

I'm not super familiar with that syntax, so if I'm overlooking something just let me know (the docs referencing it don't really explain it super well from what I can see)... but it looks like it's just a different way of filtering the results? Get-CimInstance provides a WQL -Filter parameter for that.

The equivalent of Set instance = service.Get("Win32_Whatever.Property=value,OtherProperty=other_value") would more or less be something like this -- I think?

Get-CimInstance Win32_Whatever -Filter "Property = 'value' AND OtherProperty = 'other value'"

I'm not familiar enough with the history of why the specific syntax isn't still supported, but the functionality is very much there, if I understand your use case correctly.

Well, that's just the thing. Some objects aren't available using filters or WQL queries. Their providers generate them on the fly, when asked for a specific instance by a specific instance path. A bit more information about instance paths is available at https://docs.microsoft.com/en-us/windows/win32/wmisdk/describing-an-instance-object-path and adjacent pages.

I can't tell you if that's "legal" according to whatever (WMI, CIM, ...) specification, but the fact is that major Windows providers act that way, for example the StorageWMI provider.

You can try, for example, this (as admin since mounting VHDs require being an admin):

PS C:\> New-VHD "C:\new.vhd" -Dynamic -SizeBytes 1GB | Out-Null
PS C:\> Get-CimInstance -Namespace "root/Microsoft/Windows/Storage" -ClassName "MSFT_DiskImage"
PS C:\> Get-CimInstance -Namespace "root/Microsoft/Windows/Storage" -Query "SELECT * FROM MSFT_DiskImage"
PS C:\> $img = [wmi]'\root\Microsoft\Windows\Storage:MSFT_DiskImage.ImagePath="C:\\new.vhd",StorageType=0'
PS C:\> $mount = $img.Mount(3,0)
PS C:\> Get-Disk | Select-Object Number, FriendlyName, Size, PartitionStyle

Number FriendlyName                 Size PartitionStyle
------ ------------                 ---- --------------
     2 Msft Virtual Disk      1073741824 RAW
     0 INTEL SSDPEKNW020T8 2048408248320 GPT

PS C:\>

Or, if you have an ISO file available, not necessarily as admin:

PS C:\> Get-Volume | Where-Object -Property DriveType -eq "CD-ROM"
PS C:\> Get-CimInstance -Namespace "root/Microsoft/Windows/Storage" -ClassName "MSFT_DiskImage"
PS C:\> Get-CimInstance -Namespace "root/Microsoft/Windows/Storage" -Query "SELECT * FROM MSFT_DiskImage"
PS C:\> $img = [wmi]'\root\Microsoft\Windows\Storage:MSFT_DiskImage.ImagePath="path\\to\\file.iso",StorageType=0'
PS C:\> $mount = $img.Mount(3,0)
PS C:\> Get-Volume | Where-Object -Property DriveType -eq "CD-ROM"

DriveLetter FriendlyName         FileSystemType DriveType HealthStatus OperationalStatus SizeRemaining    Size
----------- ------------         -------------- --------- ------------ ----------------- -------------    ----
E           SSS_X64FRE_EN-US_DV9 Unknown        CD-ROM    Healthy      OK                          0 B 4.51 GB

PS C:\> dir e:

    Directory: E:\

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-r--          30/10/2018     1:33                boot
d-r--          30/10/2018     1:33                efi
d-r--          30/10/2018     1:34                sources
d-r--          30/10/2018     1:34                support
--r--          30/10/2018     1:28            128 autorun.inf
--r--          30/10/2018     1:28         408074 bootmgr
--r--          30/10/2018     1:28        1452856 bootmgr.efi
--r--          30/10/2018     1:28          82440 setup.exe

PS C:\>

You can make the same test using wbemtest.exe:

  1. Connect to the correct namespace:

image

  1. Enum Instances... of MSFT_DiskImage:

image

  1. Query... SELECT * FROM MSFT_DiskImage:

image

  1. Open Instance... MSFT_DiskImage.ImagePath="C:\\new.vhd",StorageType=0:

image

Note that we didn't just create a new instance ourselves. We actually can't. New-CimInstance will fail and so will the Create Instance... button in wbemtest.exe. This instance created by the provider contains the correct value for StorageType. Even though we passed the value corresponding to unknown we got an object with a value corresponding to "VHD". See the possible value at: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/stormgmt/msft-diskimage#:~:text=VHD

If you try that with an ISO you'll get there 1.

To summarize: Using WQL is not the use case. It is exactly not what I want. Using a filter isn't too. Getting all objects from a certain class and then filtering them with Where-Object isn't either. Because all those methods don't work. I want to get an object by and instance path.

An instance object path describes the location of an instance of a given class within a specific namespace.
Represents a disk image.

@iSazonov
Copy link
Collaborator

iSazonov commented Apr 18, 2021

I guess tis comes from Microsoft.Management.Infrastructure dll limitations. If so this will be never implemented.

You could use [wmisearcher] accelerator https://social.technet.microsoft.com/wiki/contents/articles/22799.powershell-use-the-wmiclass-accelerator-to-query-a-remote-host.aspx

Technical articles, content and resources for IT Professionals working in Microsoft technologies

@conioh
Copy link
Author

conioh commented Apr 18, 2021

I guess tis comes from Microsoft.Management.Infrastructure dll limitations. If so this will be never implemented.

This is completely wrong. Not even close. Please read again what I said in my original post:

Proposed technical implementation details (optional)

Get-CimInstance should have a -Path or -InstancePath parameter and if it is present it will pass the properties to Microsoft.Management.Infrastructure.CimSession.GetInstanceAsync like in the example at: https://docs.microsoft.com/en-us/windows/win32/wmisdk/retrieving-an-instance#:~:text=To%20retrieve%20an%20instance%20of%20a%20WMI%20class%20using%20C#%20(Microsoft.Management.Infrastructure)

Here is a code sample adapted from the Microsoft example and exapnded to a full program that works with root\Microsoft\Windows\Storage:MSFT_DiskImage instead of with root\cimv2:Win32_LogicalDisk:

using System;
using Microsoft.Management.Infrastructure;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args) 
        {
            string wmi_namespace = @"root\Microsoft\Windows\Storage";
            string wmi_class_name = "MSFT_DiskImage";

            CimInstance wmi_object_instance_synth = new CimInstance(wmi_class_name, wmi_namespace);

            wmi_object_instance_synth.CimInstanceProperties.Add(CimProperty.Create("ImagePath", @"path\\to\\file.iso", CimFlags.Key));
            wmi_object_instance_synth.CimInstanceProperties.Add(CimProperty.Create("StorageType", 0, CimFlags.Key));
            CimSession wmi_session = CimSession.Create("localhost");

            CimInstance wmi_object_instance = wmi_session.GetInstance(wmi_namespace, wmi_object_instance_synth);

            Console.WriteLine(wmi_object_instance.CimInstanceProperties["StorageType"]);
        }
    }
}

As most people could see, this code uses Microsoft.Management.Infrastructure.dll, specifically the Microsoft.Management.Infrastructure.CimInstance and Microsoft.Management.Infrastructure.CimSession classes. and demonstrates they have no such limitations.

All that is needed is to expose this capability through the Get-CimInstance cmdlet. Just as I said:

Proposed technical implementation details (optional)

Get-CimInstance should have a -Path or -InstancePath parameter and if it is present it will pass the properties to Microsoft.Management.Infrastructure.CimSession.GetInstanceAsync like in the example at: https://docs.microsoft.com/en-us/windows/win32/wmisdk/retrieving-an-instance#:~:text=To%20retrieve%20an%20instance%20of%20a%20WMI%20class%20using%20C#%20(Microsoft.Management.Infrastructure)

Retrieving an instance is one of the most common retrieval procedures you are likely to perform in WMI.

@iSazonov
Copy link
Collaborator

Only code where we create CimInstance is New-CimInstance cmdlet. I have played a bit with the code but MMI.dll always returns "The requested operation is not supported." for me.
See

if you want to investigate more.

@conioh
Copy link
Author

conioh commented Apr 19, 2021

Only code where we create CimInstance is New-CimInstance cmdlet. I have played a bit with the code but MMI.dll always returns "The requested operation is not supported." for me.
See

if you want to investigate more.

Unfortunately this is once again completely incorrect. As I have said in my original post, the implementation for Get-CimInstance obviously uses the CimInstance class.

Here is the direct link to the implementation of GetCimInstanceInternal:

protected void GetCimInstanceInternal(CimBaseCommand cmdlet)

which creates a CimInstance object on its sixth line:

GetCimInstanceInternal is called by GetCimInstance (a few lines above) which is called by GetCimInstanceCommand.ProcessRecord:

I have investigated the code and therefore I know what I'm talking about.

@iSazonov
Copy link
Collaborator

Unfortunately this is once again completely incorrect.

Sure?

If we look your C# example #15247 (comment) you do "new CimInstance(wmi_class_name, wmi_namespace);", then assign values to properties. The same you can make with

$a=New-CimInstance -Namespace "root/Microsoft/Windows/Storage" -ClassName "MSFT_DiskImage" -Property @{ ImagePath="C:\temp\qqq.iso" } -Key ImagePath -ClientOnly

Then docs say we could do:

Get-CimInstance -CimInstance $a

but this return an error for MSFT_DiskImage class. The example work for other classes.

@conioh
Copy link
Author

conioh commented Apr 19, 2021

Unfortunately this is once again completely incorrect.

Sure?

Yes. Because I actually read both the documentation and what other people write to me.

If we look your C# example #15247 (comment) you do "new CimInstance(wmi_class_name, wmi_namespace);", then assign values to properties. The same you can make with

$a=New-CimInstance -Namespace "root/Microsoft/Windows/Storage" -ClassName "MSFT_DiskImage" -Property @{ ImagePath="C:\temp\qqq.iso" } -Key ImagePath -ClientOnly

Then docs say we could do:

Get-CimInstance -CimInstance $a

but this return an error for MSFT_DiskImage class. The example work for other classes.

Well, you say "[T]he same you can make with" but it's not the same. My code sets both the ImagePath property and the StorageType property, since the key is both of them. That's what C:\Windows\System32\wbem\storagewmi.mof says:

[dynamic : ToInstance,provider("StorageWMI") : ToInstance,locale(1033)] 
class MSFT_DiskImage
{
  [key,read : ToSubclass] string ImagePath;
  [key,read : ToSubclass,ValueMap{"0", "1", "2", "3", "4"} : ToSubclass] uint32 StorageType;
  [read : ToSubclass] string DevicePath;
  [read : ToSubclass] uint64 FileSize;
  [read : ToSubclass] uint64 Size;
  [read : ToSubclass] uint64 LogicalSectorSize;
  [read : ToSubclass] uint64 BlockSize;
  [read : ToSubclass] boolean Attached;
  [read : ToSubclass] uint32 Number;
  [implemented] uint32 Mount([In,ValueMap{"0", "2", "3"} : ToSubclass] uint16 Access,[In] boolean NoDriveLetter,[Out,EmbeddedInstance("MSFT_DiskImage") : ToSubclass] MSFT_DiskImage DiskImage);
  [implemented] uint32 Dismount([Out,EmbeddedInstance("MSFT_DiskImage") : ToSubclass] MSFT_DiskImage DiskImage);
};

That's why I gave both properties in the C# sample and in the wbemtest.exe sample and in the PowerShell using [wmi] sample.

Here ya go:

image

@vexx32
Copy link
Collaborator

vexx32 commented Apr 19, 2021

It's an unfamiliar syntax to me, but from what I can tell that does seem to satisfy your original request, right? I tried with this set of commands:

New-Vhd C:\new.vhd -Dynamic -SizeBytes 3mb > $null

$params = @{
    Namespace  = 'root/Microsoft/Windows/Storage'
    Classname  = 'MSFT_DiskImage' 
    Key        = 'ImagePath', 'StorageType'
    ClientOnly = $true
    Property   = @{
        ImagePath   = 'C:\new.vhd'
        StorageType = 0
    }
}
Get-CimInstance @params | Get-CimInstance

Which gets what appears to be the correct result:

Attached          : False
BlockSize         : 2097152
DevicePath        :
FileSize          : 8192
ImagePath         : C:\new.vhd
LogicalSectorSize : 512
Number            :
Size              : 3145728
StorageType       : 2
PSComputerName    :

I think we definitely need to improve documentation around this. Does this satisfy your use case here?

@conioh
Copy link
Author

conioh commented Apr 19, 2021

I think it would be much preferable to support instance paths since:

  1. There's already code that uses them and depends on them. Writing once inside Get-CimInstance's the code the parses the string and creates the properties is preferable to forcing every user who migrates VBS code to PS to do this.
  2. WMI objects themselves return the path in the __Path system property.

These two facts combined make it very useful to support getting an object by an instance path (e.g. because you save an object's "identity" via it's path, and try to get it at a later time) rather than via creating a "search instance".

The goal is to make it scriptable. That I was able to circumvent the issue because I manually parsed the string doesn't mean that the issue is resolved. (I actually used [wmi] because this time I didn't need remote access, and [wmi] supports paths.)

The issue for the software product known as "PowerShell" and the standard cmdlets that are built into it remains.

@SeeminglyScience
Copy link
Collaborator

I've definitely had a CIM/WMI provider or two force path usage in their APIs. I can't remember which one (I want to say it was SCCM's client SDK somewhere) but I definitely have similar code for translating paths laying around. It'd be really nice to have an API to do this in PowerShell.

@iSazonov
Copy link
Collaborator

iSazonov commented Apr 19, 2021

Instance path (aka __PATH property) is an entity of WMIv1 and old WMI cmdlets (Get-WMIObject and others). The cmdlets was removed from PowerShell Core in 6.0. (Later [wmi] accelerator was added for backward compatibility after the API was ported to .Net Core for backward compatibility too. Notice, [wmi] accelerator works over old WMIv1 API.)

New cmdlets is CIM cmdlets. See docs https://docs.microsoft.com/en-us/powershell/scripting/whats-new/breaking-changes-ps6?view=powershell-7.1#wmi-v1-cmdlets
WMIv1 API is not recommended for use. For this reason, I think the request will never be approved. It's amazing to translate the new API into the old one if we have already started deleting the old one.

Especially CIM and CDXML modules covers all old scenarios and more.

If someone still needs this, then this is rather a topic for the community module. You can see this for an example.

This article summarizes the differences between Windows PowerShell 5.1 and PowerShell 6.0.

@SeeminglyScience
Copy link
Collaborator

SeeminglyScience commented Apr 19, 2021

@iSazonov I don't think there was any confusion over whether WMI was or was not deprecated. Could you elaborate on your objections to adding path support to CIM? It's not a particularly large task to add some helper methods or cmdlets for it, and could ease the transition of code working with some providers.

@conioh
Copy link
Author

conioh commented Apr 19, 2021

Contrary to what was written above, both WMI ("WMI v1") and MI ("WMI v2") are implementations of CIM. The error in basic terminology is indicative of lack of understanding of the issue and adds up to the previous errors from above (such as claiming that two different pieces of code are "same" or claiming that the only cmdlet that uses the CimInstance class is New-cimInstance, etc.). MI intentionally supports WMI.

"[F]ull compatibility with the older Windows Management Instrumentation with WMI" is stated as a fact: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/wmi_v2/what-s-new-in-mi#compatibility-with-wmi and where there is an incompatibility it is a bug.

For example, MI_Application_NewSession's protocol parameter supports two value "WINRM" and "WMIDCOM" and this is exposed in New-CimSessionOptions's -Protocol parameter.

We can actually see in Microsoft.Management.Infrastructure.CimInstance's implementation the intention to add getting objects' path to Microsoft.Management.Infrastructure once MI fixes it. The code is commented out rather than deleted.

While generating a string from properties like in the link provided above is relatively easy, parsing a string into properties is somewhat more difficult and error prone (as are all string parsing operations). To make PowerShell more useful today, PS should not wait for Microsoft to add this to MI, then wait for the .NET wrapper of MI to add this too and then add this to the PS cmdlets. This is fixable right now.

Windows 8 and Windows Server 2012 introduced new ways of creating Windows Management Infrastructure (MI) applications.

@iSazonov
Copy link
Collaborator

Could you elaborate on your objections to adding path support to CIM?

@SeeminglyScience @vexx32 I am amazed that you have not been aware of this painful problem for many years.
I propose to the participants a competition who will find the author of the quote "No plans to port MMI to C#". :-)
Hint 1 See
Hint 2 See 2018 year.

MSFT is very adamant about this. It's also incredible but true that MSFT started work on removing CIM from PowerShell - they are now rewriting DSC to Json.

It's not a particularly large task to add some helper methods or cmdlets for it, and could ease the transition of code working with some providers.

My first question in the discussion was about scenarios. As you understand you need to share huge important scenario so that MSFT change their global policy and agree to port MMI. It is fantastic :-)

To solve a similar situation with PowerShell remoting on Unix @jborean93 forked OMI It is not officially supported and distributed by MSFT but you still can use this.
Somebody could fork PowerShell/MMI but again it will be never officially supported and not distributed by MSFT but in this case nobody can use it in PowerShell until it is completely removed from PowerShell (or you have to have fully custom PowerShell).

@conioh All my statements are from a PowerShell perspective. So thanks for sharing link and confirmation my guess that (PowerShell) MMI does not support "paths".

@SeeminglyScience
Copy link
Collaborator

@SeeminglyScience @vexx32 I am amazed that you have not been aware of this painful problem for many years.
I propose to the participants a competition who will find the author of the quote "No plans to port MMI to C#". :-)

Did someone ask for that in this thread?

MSFT is very adamant about this. It's also incredible but true that MSFT started work on removing CIM from PowerShell - they are now rewriting DSC to Json.

They're not removing CIM, they're just not relying on it for DSC specifically because it's not (easily) cross platform.

My first question in the discussion was about scenarios. As you understand you need to share huge important scenario so that MSFT change their global policy and agree to port MMI. It is fantastic :-)

Just to reiterate, adding a helper method or parameter set like New-CimInstance -InstancePath doesn't require porting anything. It doesn't even require changes to MMI since that cmdlet is in this repo.

@jdhitsolutions
Copy link
Collaborator

I would make the case that this issue isn't so much adding something about how CIM is implemented in PowerShell, but rather how it might be used to manage something like a storage item. I haven't seen a compelling and scenario where a lack of getting an object by path has been detrimental to the PowerShell ecosystem. I would argue that the community fills in the management gap with a command or module that can use instance paths, in whatever manner works.

@jdhitsolutions
Copy link
Collaborator

jdhitsolutions commented Aug 20, 2021

I've been playing with this and have some proof of concept PowerShell functions. https://jdhitsolutions.com/blog/powershell/8541/getting-ciminstance-by-path/

The Lonely Administrator
Here's how I use CIM to get WMI objects by their path in PowerShell. We can use [wmi] in Windows PowerShell but what about PowerShell 7?

@jdhitsolutions jdhitsolutions self-assigned this Aug 25, 2021
@JamesWTruher JamesWTruher added Resolution-By Design The reported behavior is by design. and removed Needs-Triage The issue is new and needs to be triaged by a work group. labels Mar 2, 2022
@JamesWTruher
Copy link
Member

JamesWTruher commented Mar 2, 2022

The Cmdlets Working Group has reviewed this issue and has decided to close it as "by design"

The underlying problem is that the CIM cmdlets are built on top of the Microsoft.Management.Infrastructure APIs which don't support this.
While Microsoft.Management.Infrastructure APIs don't support it, it would make things worse to have a -Path parameter that splits the path, because that creates the expectation this would work.
And if you can't use the path it doesn't make a lot of sense to add it to the returned objects.

If those APIs change we probably should revisit it, but for now, we've accepted their limitations so it is by design

@conioh
Copy link
Author

conioh commented Mar 2, 2022

@JamesWTruher, @jdhitsolutions, @SteveL-MSFT:

While Microsoft.Management.Infrastructure APIs don't support it, it would make things worse to have a -Path parameter that splits the path, because that creates the expectation this would work.

The expectation that it will work is indeed correct and already exists. You won't create it. There's nothing wrong with reinforcing it though since it is justified.

And if you can't use the path it doesn't make a lot of sense to add it to the returned objects.

Perhaps you're right that it doesn't make a lot of sense to add it to returned objects, but it is already "added" to returned objects.
So maybe it's the other way around? Since it is in fact, in the actual reality we live in, there in returned objects, and has use cases that can't be done in any other way (create new instance, get all instances and filter, etc.), maybe it should be added?

I don't see how the Working Group addressed the points I raised earlier:

I think it would be much preferable to support instance paths since:

  1. There's already code that uses them and depends on them. Writing once inside Get-CimInstance's the code the parses the string and creates the properties is preferable to forcing every user who migrates VBS code to PS to do this.
  2. WMI objects themselves return the path in the __Path system property.

These two facts combined make it very useful to support getting an object by an instance path (e.g. because you save an object's "identity" via it's path, and try to get it at a later time) rather than via creating a "search instance".

@ghost
Copy link

ghost commented Mar 4, 2022

This issue has been marked as by-design and has not had any activity for 1 day. It has been closed for housekeeping purposes.

@ghost ghost closed this as completed Mar 4, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Enhancement the issue is more of a feature request than a bug Resolution-By Design The reported behavior is by design. WG-Cmdlets general cmdlet issues
Projects
None yet
Development

No branches or pull requests

6 participants