Limitation of CIM classes/cmdlets?

This topic contains 10 replies, has 4 voices, and was last updated by Profile photo of Fausto Nascimento Fausto Nascimento 1 year, 6 months ago.

  • Author
  • #24599
    Profile photo of Ana Sofia
    Ana Sofia

    I'm using the new CIM cmdlets released in PS3, but there are a few things I don't seem to be able to do with CIM that I was able to do with the deprecated WMI cmdlets.

    Here is an example:

    ([wmiclass] 'Win32_Process').Properties['WriteTransferCount'].Qualifiers.Remove['read']

    This will retrieve the WMI class Win32_Process, get the property WriteTransferCount and remove the qualifier 'read' from it using the Remove() method.

    Using CIM?

    (Get-CimClass Win32_Process).CimClassProperties['WriteTransferCount'].Qualifiers

    So far so good, this works so far. Now let's invoke the Remove() method as above:

    (Get-CimClass Win32_Process).CimClassProperties['WriteTransferCount'].Qualifiers.Remove['Read']
    Method invocation failed because [Microsoft.Management.Infrastructure.Internal.Data.CimQualifierOfProperty] does not contain a method named 'Remove'.
    At line:1 char:1
    + [Get-CimClass Win32_Process].CimClassProperties['WriteTransferCount'] ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: [:] [], RuntimeException
        + FullyQualifiedErrorId : MethodNotFound

    Right, of course it doesn't, because CIM classes don't expose methods. You need to use Invoke-CimMethod

    But... reading through the help of Invoke-CimMethod, one notices that it accepts either a CimClass object, or a CimInstance object.

    Unfortunately, our object is of type CimQualifierOfProperty, so Invoke-CimMethod refuses to accept it.

    I can't find any way of making this work. I looked up the classes in MSDN, spent over 1h searching the internet, no one seems to be using this class yet (other than PowerShell) and there doesn't appear to be a way to do this using the new Cim objects (notice I said objects and not cmdlets, I'm fine going into .NET territory, but still can't find a way of doing it).

    Is it me or can't this be done at all?

  • #24608
    Profile photo of Don Jones
    Don Jones

    I don't think the CIM objects directly support the kind of action you're trying to take. But I'll ask some other folks to have a look.

  • #24613
    Profile photo of Ana Sofia
    Ana Sofia

    Thx for the reply Don. I know they definitely don't expose any methods, which is why there's the Invoke-CimMethod cmdlet, but like I said it accepts no parameters of the types I'm after.

    Still, there has to be a way, even if going full .NET on it 🙂 (I hope!!)

  • #24683
    Profile photo of Don Jones
    Don Jones

    Well, yes, but "full .NET" isn't necessarily the answer. Keep in mind that most WMI/CIM stuff is native code under the hood. But yes, I suspect if you dug enough, you could do what you're after in something like C# – I'm just not the guy to give you a pointer on that language or that API set.

  • #24684
    Profile photo of Don Jones
    Don Jones

    And I think part of the situation here is that your OLD method wasn't using the WMI cmdlets – you were more directly accessing the .NET client interface for "old WMI." There's no way to do that in pure PowerShell (e.g., without doing something that could be done the same way in C#), so you're limited to the interface the "new WMI" cmdlets (*-Cim*) provide. What you were doing before was, frankly, a lot closer to C# than PowerShell anyway, regardless of the fact that you were running it in PowerShell. Total hair-splitting, I know.

  • #24685
    Profile photo of Fausto Nascimento
    Fausto Nascimento

    Actually we had a look and found that the class CimSession has methods InvokeCimMethod and InvokeCimMethodAsync, which through dotPeeking could tell that's what cmdlet Invoke-CimMethod uses.

    We could use the CimSession.InvokeCimMethod method in PowerShell to invoke a method of a CimClass object and even a CimInstance object, but we can't find any overloads for CimSession.InvokeCimMethod method that would accept anything other than a method of a CimClass or CimInstance object.

    These CIM classes are rather new and as a result we can't find any help in C#/.NET forums, and search engines show no results either.

    Running out of choices and the only option currently still on the table is the depressing though of going back to the deprecated WMI cmdlets. I'm not quite sure who else/where else to ask this anymore.

  • #24686
    Profile photo of Don Jones
    Don Jones


    You weren't using the WMI cmdlets before, you were using the [wmiclass] accelerator, which is a shortcut to getting the raw .NET client interface. Technically.

    And WMI being deprecated shouldn't necessarily be depressing; it's not like it's going away. That said, it also isn't enabled by default on newer versions of Windows.

    I just don't know enough about the new-WMI client interface (what PowerShell is calling CIM) to tell you if it can even do the same thing. My only touch point to the client interface is what PowerShell gives me, which isn't necessarily the entire thing. It's entirely possible that the new client interface just doesn't include the capability you're after, or that the underlying provider has been rewritten in the new MI API instead of the old WMI API, and that the new provider doesn't support the activity you're after.

    Part of it, too, is that old-WMI was all DCOM-based, and it made sense for objects to have properties, which had properties which were objects, which had methods. New-WMI, with its reliance on WS-MAN, which is basically XML, almost by necessity returns a simpler object. That's what Ana already noticed – Get-CimInstance doesn't include methods. That's because the object you get was deserialized from XML, and isn't a "live" object; in old-WMI, with DCOM, you had a "live" remote object. New-WMI is basically HTTP transactions going back and forth, so everything's inherently stateless.

    I suspect whatever eventually works would need to run entirely on the remote machine, a la Invoke-Command, and not as a series of stateless query-response actions using the Cim cmdlets.

    You could also have just run into a situation that nobody at Microsoft ever looked at – and so nobody realized that the new API no longer provides a means of doing that, because the activity itself was tied to the old DCOM capabilities. In that case, a bug on Connect would be helpful. Under the new API, I'd expect the Win32_Process class to provide a direct top-level method that accomplished what you wanted. If the provider doesn't implement that, you may well not be able to get to it via any means other than DCOM.

  • #24687
    Profile photo of Don Jones
    Don Jones

    Also, just for posterity:

    [blockquote]These CIM classes are rather new and as a result we can't find any help in C#/.NET forums, and search engines show no results either.[/blockquote]

    Technically, the classes aren't new. Most of what you get is the same as what you got the old way. What's different is the API for getting it and working with the result. That's an important distinction, because in MOST cases, Microsoft hasn't rewritten the underlying WMI providers, they're just being accessed differently. If they HAD rewritten them, I suspect problems like this could have been solved through a refactoring of the class.

  • #24691
    Profile photo of Fausto Nascimento
    Fausto Nascimento

    Hi Don,

    I agree with what you said, what I meant with depressing is that:

    A) As part of a bigger module, Ana had already written a lot of functions relying on the Cim objects returned by the new cmdlets when she hit this stumbling block, but it makes no sense to have some functions accept/return the new Management.Infrastructure objects while others return Management objects. It would mean having to have both WinRM and DCOM configured and working. It would mean you couldn't pipe results from a CIM function to a WMI function as the objects are different (yes, it could be worked around by transforming the object from one to the other as you have access to the class name, instance name, etc..., but it involves new connections on remote computers, using different methods, and so forth and so on). The 'correct way' would be to either do everything using WMI cmdlets or CIM cmdlets. And swapping to WMI means starting everything over.

    B) WinRM is a lot easier to troubleshoot than DCOM and objects returned via WinRM are much leaner (as you already pointed out). It makes sense that anything created now that queries or modified WMI would use the new CIM methods, which is why Ana started her module with those.

    I will create a bug report on Connect and see what comes of it.

    Just for clarification, when I talked about the new CIM classes, I meant the whole Microsoft.Management.Infrastructure namespace and its classes, where were only introduced with Windows Server 2012/Windows 8. Even though they use the same underlying WMI providers, the classes themselves are different, and so are the properties and methods of the resulting objects.

  • #24809
    Profile photo of Richard Siddaway
    Richard Siddaway

    I'm a bit puzzled by the reason for removing the read qualifier from the WriteTransferCount property but to second Don's comments:

    [wmiclass] 'Win32_Process' creates an empty instance of the Win32_Process WMI class. – System.Management.ManagementClass#ROOT\CIMV2\Win32_Process. The .NET class is System.Management.ManagementClass.

    When you use Get-WmiObject Win32_Process you are accessing System.Management.ManagementObject#root\cimv2\Win32_Process – .NET class is System.Management.ManagementObject

    Get-CimClass uses Microsoft.Management.Infrastructure.CimClass and Get-CimInstance uses Microsoft.Management.Infrastructure.CimInstance

    If you look at the Microsoft.Management.Infrastructure classes on MSDN you will see that they don't have much in the way of methods. This is because the classes are designed to be used over a CIMsession which by default is expecting to use WSMAN. The serialization/deserilaization would strip off any methods so why have them in the first place.

    I'm pretty sure you won't be able to do what you want using the Microsoft.Management.Infrastructure .NET classes. If you could explain why you need to strip off the read qualifier I may be able to suggest another way of completing the task.

  • #24816
    Profile photo of Fausto Nascimento
    Fausto Nascimento

    Hi Richard,

    The read qualifier was just an example to demonstrate that as far as we can tell it's not possible to do this using the MI classes.

    We're working on a module to compliment the existing cmdlets that interact with WMI. Some of these things include creating/deleting namespaces, creating/deleting classes, creating/deleting properties, creating/deleting qualifiers, etc. In short, there is a lot more to WMI than what either the CIM or WMI cmdlets let you do.

    I'm not expecting the direct objects to have *all* the methods like they existed on the 'old' Management classes, as you can read from the very initial thread, we knew already this was the case because the information is transmitted in XML format.

    However, if you go over the MSDN pages you'll notice that pretty much all MI classes have a Create() method, but very close to none have a Delete() method. Deleting clases and instances is pretty easy, as those methods can be invoked via the Invoke-CimMethod or the Microsoft.Management.Infrastructure.CimSession.InvokeMethod method, but deleting properties or qualifiers? Appears impossible.

    There are two main reasons I can think of for not having methods on a deserialized object:

    First it removes the need to transfer names of methods and their declaration, something which you'd never be able to invoke directly anyway, making the object smaller.

    Second (this is obviously closely tied with the first) you don't know what types of methods your object is going to have, they are not static. For example a Win32_Process instance has a GetOwner() method, a Win32_ComputerSystem doesn't.

    However, the one thing you can be guaranteed is that pretty much everything in WMI can be created and can be deleted.

    The Create method is already there for all MI objects. The parameters received by the Create method don't vary from WMI class to WMI class, from instance to instance, from qualifier to qualifier, they're static so there is no information to be read from the client.

    The same can be said for a Remove() method, so it should be present directly on the object in the same way the Create method is.

    Regardless, even if it's not, it's a method that exists on WMI objects and there should be a way of invoking it in the same way that you can invoke a GetOwner() on a Win32_Process instance using InvokeAsyncMethod or InvokeMethod methods, but it doesn't seem to be possible.

You must be logged in to reply to this topic.