powershellwmishadow-copy

How to create a VSS shadow copy in Powershell using only CIM cmdlets (not WMI cmdlets)?


Powershell newbie here, so please bear with me if the following question is silly ...

I'd like to create a VSS snapshot in Powershell and have found many examples which use the WMI functions to do this. Common patterns are

# Pattern 1
$class=[WMICLASS]"root\cimv2:win32_shadowcopy"
$class.create("C:\", "ClientAccessible")

# Pattern 2
(gwmi -List Win32_ShadowCopy).Create("C:\", "ClientAccessible")

All code I saw was using Powershell's WMI cmdlets. However, I have got the impression that we shouldn't use WMI cmdlets any more, according to quite a number of references (e.g. here).

So I tried to find out how to create a VSS snapshot using only CIM cmdlets, but with no success. The first idea was to create a new Win32_ShadowCopy instance, to set its properties as desired and to call the Create method on it. This failed in the first step:

PS C:\Users\Administrator> New-CimInstance Win32_ShadowCopy
New-CimInstance : Not supported 
At line:1 char:1
+ New-CimInstance Win32_ShadowCopy
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotImplemented: (Win32_ShadowCopy:CimInstance) [New-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x8004100c,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

Apparently New-CimInstance is not implemented for Win32_ShadowCopy.

During further research, it also turned out that (in contrast to the WMI cmdlets) the CIM cmdlets don't return objects on which the Create method can be called (I have removed some empty lines from the output in the following code):

PS C:\Users\Administrator> get-cimclass -Class Win32_ShadowCopy

   NameSpace: ROOT/cimv2

CimClassName                        CimClassMethods      CimClassProperties                                                 
------------                        ---------------      ------------------                                                 
Win32_ShadowCopy                    {Create, Revert}     {Caption, Description, InstallDate, Name...}                       

PS C:\Users\Administrator> get-wmiobject -List Win32_ShadowCopy

   NameSpace: ROOT\cimv2

Name                                Methods              Properties                                                         
----                                -------              ----------                                                         
Win32_ShadowCopy                    {Create, Revert}     {Caption, ClientAccessible, Count, Description...}                 

To my understanding, the above shows that the objects returned by get-cimclass and get-wmiobject both should expose the same methods. However, when we try to invoke the Create method:

PS C:\Users\Administrator> $(get-wmiobject -List win32_shadowcopy).Create("C:\", "ClientAccessible")

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     : 
__DYNASTY        : __PARAMETERS
__RELPATH        : 
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         : 
__NAMESPACE      : 
__PATH           : 
ReturnValue      : 0
ShadowID         : {8918619B-BE7F-4FE2-9B9C-C6B3B71CC749}
PSComputerName   : 

PS C:\Users\Administrator> $(get-cimclass -Class Win32_ShadowCopy).Create("C:\", "ClientAccessible")
Method invocation failed because [Microsoft.Management.Infrastructure.CimClass] does not contain a method named 'Create'.
At line:1 char:3
+ $(get-cimclass -Class Win32_ShadowCopy).Create("C:\", "ClientAccessib ...
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Obviously, I can't use get-cimclass to create a shadow copy. The same is true for get-ciminstance; the latter fails with the same error message as get-cimclass if at least one snapshot already exists, and otherwise throws another error because the returned object is empty then.

So what do I need to do to create a shadow copy using only CIM cmdlets?


Solution

  • I just started playing with this but this command seems to work:

    Invoke-CimMethod -MethodName Create -ClassName Win32_ShadowCopy -Arguments @{ Volume= "C:\\" }
    

    Just as you noticed you can't invoke CIM methods directly on an instance though. Since Cim cmdlets work through remoting the instances aren't live (some say dehydrated) and the methods are removed. Hence, the "Does not contain a method named..." Invoke-CimMethod is meant to address this.

    I do find discovery can sometimes be tricky, but it is doable. For example, I've never worked with this class before, but easily found possible invocation examples with something like:

    (Get-CimClass Win32_ShadowCopy).CimClassMethods
    
    Name   ReturnType Parameters                  Qualifiers
    ----   ---------- ----------                  ----------
    Create     UInt32 {Context, Volume, ShadowID} {constructor, implemented, static}
    Revert     UInt32 {ForceDismount}             {implemented}
    

    I did all within a minute...

    Note: You are correct Get-WMIObject and the like are deprecated and have been removed from PowerShell 7+. Best to continue with Cim cmdlets, and get through these adjustments as they present...

    Introduction to CIM Cmdlets

    Scripting Guys CIM Vs WMI