Tuesday, April 01, 2014

PowerShell + SCCM 2012 R2 : Create Folders to organize

In the last post we took a look on how to create an Application from a MSI and deploy it using PowerShell :)

But if I take a look at the Application Root node at the moment everything gets listed here . Say if I have 200 applications then it seems a bit messy...Let's organize them in a better way using "Folders" in ConfigMgr 2012.

Applications Node:

Folders are used to better organize Objects and it can have Objects of one type only. We will come to appreciate this when we see the end result.

How do we create Folders ?
Well there are a couple of ways I know of:
  1. Manual through ConfigMgr Console
  2. Using PowerShell CMSite PSProvider (exposed through the ConfigMgr Module)
  3. Using WMI

Manual Way:

I would like to organize the Apps based on the Vendor, so that Apps from same vendor are easy to locate. For Ex: Quest AD Snapin will fall under "Quest" 7-zip will fall under "OpenSource" etc.

So go to the Applications node in the console and right-click it to get an option to create folder. Give it the name "Quest"

Give the name "Quest" and the folder is created

Now I was tempted to drag and drop the Application to the Folder but that is not supported as of now (I wonder why not). So go to your Application and right click Move and select the Folder where you want the Application moved.

Select the folder location


Note that once you move the Application it won't show up under the Root node but instead under the Folder you moved it.

Using PowerShell CMSite PSProvider 

When you click on "Connect via Windows PowerShell" in the ConfigMgr Console then you get a PowerShell Console. By default you are placed inside the CMSite location (same as the sitecode). One needs to run the Cmdlets shipped in with the PowerShell Module from this location only. Try doing a "ls" or Get-ChildItem there, you would see something familiar.

Once you are placed in the PowerShell Console you can traverse the CMSite provider using the same cmdlet you would have used to manage filesystem, registry etc. Note that some of the functionality might not be provided by the CMSite provider.. for ex. do a Get-ChildItem -Recurse

We were talking about creating folders, right.
So move under Applications node by using Set-Location DEX:\Application or cd .\Application.

Now we can create folders here in the same way we are used to using New-Item or Mkdir alias

Above have created a folder named "OpenSource" where the 7-zip application will be moved.

To move an application to the folder we just created we have a cmdlet named Move-CMObject, it takes the FolderPath and ObjectID or InputObject as a parameter...its straightforward if you go through the help for it.

Let's move it then using below:

$7zipApplication = Get-CMApplication -Name "7-zip"
Move-CMObject -FolderPath .\OpenSource -InputObject $7zipApplication -Verbose

See the Change in the Console:


Note - Only folders show up when you do a Get-ChildItem.

Using WMI

Using WMI to do this operation may be a perfect candidate when you don't want to depend on the ConfigMgr Console or the PowerShell Module shipped with it. This could be done from any machine with PowerShell installed on it.

I always use $PSDefaultparameters in my WMI Exploration ventures as it reduces passing Comuptername and namespace again and again:

$PSDefaultParameterValues =@{"get-cimclass:namespace"="Root\SMS\site_DEX";"get-cimclass:computername"="DexSCCM";"get-cimInstance:computername"="DexSCCM";"get-ciminstance:namespace"="Root\SMS\site_DEX";"get-wmiobject:namespace"="Root\SMS\site_DEX";"get-WMIObject:computername"="DexSCCM"}

First we need to get the class, something tells me it has something to do with the name container in the classname ;)
PS> Get-CimClass -ClassName *container*

The SMS_ObjectContainerNode looks like the one, Now if you go to the MSDN documentaion and look for the possible values for Objecttype you will come to know which all things an object can contain which in turn tells which all places folders can be used for Organizing stuff 

PS> Get-CimInstance -ClassName SMS_ObjectContainerNode

Notice for the Folders/ Containers we created to contain applications the MSDN documentation is not up to date. The objecttype for these type of folders is value 6000

These are the first 2 folders created in my environment . Could have filtered based on ObjectType too.

Now read the documentation and try to create the new Instance of this class using New-CIMInstance cmdlet 
$POSHFolder = New-CimInstance -ClassName SMS_ObjectContainerNode -Property @{Name="PowerShell";ObjectType=6000;ParentContainerNodeid=0;SourceSite="DEX"} -Namespace root/sms/site_DEX -ComputerName DexSCCM -Verbose

Note - ObjectType = 6000 tells it that it is a folder which will contain the Applications, ParentContainerNodeId = 0 tells it to create this folder under the Root (for Applications) can specify another Container ID to create nested folders. Stored it in a Folder as we will need it later.

Folder/ Container is created, Now time to move the Application by name "PowerShell Community Extensions" under it.

Yeah I know we can use the Move-CMObject now once the Folder is created....But we are doing it WMI way remember.

In the above Screenshot where we searched for WMI Classes with string container in them....you can see a class by the name SMS_ObjectContainerItem , this class is our clue as it has 2 methods by the name MoveMembers & MoveMembersEx . Now if you go to the MSDN documentation it is not updated and for both it shows the same MOF definition. But we have another Tool sitting right in front of us.....any Guess on what it is ???

PowerShell ;)

Get-CimClass -ClassName SMS_ObjectContainerItem | select -ExpandProperty CimClassMethods | Format-List
This will show up the below:

As mentioned in the Screenshot the qualifier for the MoveMembers Static Method on the Class suggests its deprecated.

Let's go ahead and use the MoveMembersEx method and take note of the Parameters we are required to pass to this method - InstanceKeys , ContainerNodeId, TargetContainerNodeId, ObjectTypeName

But let's take a look at the before Screenshot of the ConfigMgr Console:

The PSCX Applicaiton shows up under the Root of Applications and the folder PowerShell created is empty.

After invoking the MoveMembersEx Method on the Class in below way:

$Application  = Get-CMApplication -Name "PowerShell Community Extensions"
Invoke-CimMethod -ClassName SMS_ObjectContainerItem -MethodName MoveMembersEx -Arguments @{InstanceKeys=[string[]]$Application.ModelName;ContainerNodeID=[System.UInt32]0;TargetContainerNodeID=[System.UInt32]($POSHFolder.ContainerNodeID);ObjectTypeName="SMS_ApplicationLatest"} -Namespace root/sms/site_DEX -ComputerName DexSCCM -Verbose

Note : In the above the Instance Keys and ObjectTypename values will change depending on what type of Objects Folder can contain.

The above should return a 0 value indicating success, if not then keep trying and cast the arguments passed so that it succeeds....I did it this way ;)

Now let's head back to the ConfigMgr Console Refresh the view and see the changes:

Now the important thing to note here is that we can create Folders in various places in the Console but a folder can contain Objects of a specific type only.

For Ex in the above case we created folders under Applications and they can only contain Applications inside them. Similarly we can organize collections, task sequences etc.

Folders are great way to organize stuff in ConfigMgr 2012, so go ahead and try the Fun route of creating these using PowerShell.

That's it for this post.
Till next post.