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
Comments
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:
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
|
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 The equivalent of 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 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
Note that we didn't just create a new instance ourselves. We actually can't. 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
|
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
|
This is completely wrong. Not even close. Please read again what I said in my original post:
Here is a code sample adapted from the Microsoft example and exapnded to a full program that works with 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 All that is needed is to expose this capability through the
|
Only code where we create PowerShell/src/Microsoft.Management.Infrastructure.CimCmdlets/CimNewCimInstance.cs Line 262 in 720c615
|
Unfortunately this is once again completely incorrect. As I have said in my original post, the implementation for Here is the direct link to the implementation of
which creates a CimInstance object on its sixth line:
PowerShell/src/Microsoft.Management.Infrastructure.CimCmdlets/GetCimInstanceCommand.cs Line 478 in 3c7f4b5
I have investigated the code and therefore I know what I'm talking about. |
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. |
Yes. Because I actually read both the documentation and what other people write to me.
Well, you say "[T]he same you can make with" but it's not the same. My code sets both the
That's why I gave both properties in the C# sample and in the Here ya go: |
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:
I think we definitely need to improve documentation around this. Does this satisfy your use case here? |
I think it would be much preferable to support instance paths since:
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 The issue for the software product known as "PowerShell" and the standard cmdlets that are built into it remains. |
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. |
Instance path (aka 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 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.
|
@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. |
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 "[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, We can actually see in 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.
|
@SeeminglyScience @vexx32 I am amazed that you have not been aware of this painful problem for many years. 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.
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. @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". |
Did someone ask for that in this thread?
They're not removing CIM, they're just not relying on it for DSC specifically because it's not (easily) cross platform.
Just to reiterate, adding a helper method or parameter set like |
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. |
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 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. If those APIs change we probably should revisit it, but for now, we've accepted their limitations so it is by design |
@JamesWTruher, @jdhitsolutions, @SteveL-MSFT:
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.
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. I don't see how the Working Group addressed the points I raised earlier:
|
This issue has been marked as by-design and has not had any activity for 1 day. It has been closed for housekeeping purposes. |
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 - theIWbemXxx
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:
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 theMicrosoft.Management.Infrastructure.CimInstance
used by theCimCmdlets
module) to get an object by an instance path, but that seems to only works on the local machine, similarly to VBScript'sGetObject
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 forGet-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 toMicrosoft.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)The text was updated successfully, but these errors were encountered: