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

Done!

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.

Cya
/bye


15 comments:

  1. Great! Very useful blog and post!
    I create full topology on 4 remote secondary sites with your posts! Thx!

    ReplyDelete
    Replies
    1. Thanks vich668rus,

      Glad it helped you :)

      Delete
  2. Is it possible to move the complete Folder to another target-folder with powershell?

    ReplyDelete
    Replies
    1. It should be possible.
      Did you try it ? Errors ?

      Delete
  3. How can we search Package/ID in Packages when we have 100 of subfolder/Subpackages

    ReplyDelete
    Replies
    1. Having folders shouldn't hinder you from searching packages.
      If I recall correctly there will be instances of the package class which you can most definitely query/ filter using WQL.

      Try and let me know, if this doesn't work.

      Delete
  4. Hi Dexter,

    Is there anyway that I can move a specific application from powershell without entering the root.

    I mean I just want to run a command from Powershell ISE to move one application to one folder is that possible.

    ReplyDelete
  5. I want to run a command to copy an application from one folder to another without opening powershell from root. want to run it from powershell ISE how will I be able to do that.

    ReplyDelete
  6. Hi Devraj,

    In order to use ISE, you will have to import the CM PS module first as shown below:
    #Load the ConfigurationManager Module
    PS> Import-Module -Name "$(split-path $Env:SMS_ADMIN_UI_PATH)\ConfigurationManager.psd1"

    Now it is a pre-requisite to change to the CMSite before running the CM cmdlets, so change to it in the ISE and then you can use the cmdlets mentioned in this post.

    ~Dex~
    For more info on loading the CM module, checkout my getting started post.

    http://dexterposh.blogspot.com/2014/06/powershell-sccm-2012-getting-started.html

    ReplyDelete
  7. Hi Dexter,

    i have excel sheet having three application name.
    how to move all three to specific folder using powershell in sccm.

    ReplyDelete
    Replies
    1. Is the Excel sheet a CSV file ?
      If yes, then you can run Import-CSV to get objects and then iterate over them to get the CM application object and then pipe the output to Move-CMObject cmdlet.

      Note- Check the help for the Move-CMObject cmdlet to see if it supports passing values by pipeline.

      Delete
    2. OK! Thank you for the super quick response.
      I will try this...

      Delete
    3. You're welcome.
      The trick with using PowerShell is to embrace the Object-Oriented nature of it and look under the hood how the pipeline works.
      Once you have that pinned down, things will be easier to follow through.

      Have fun :)

      Delete
  8. Hello Dexter,

    This blog is really awesome.Thanks for creating such a nice posts.

    I have a question, i am trying to read an excel file and trying to move application type to ONHOLD folder and package type to ONHOLD folder and same for Tasksequence in SCCM 2012. Excel sheet having both application, packages name. How can i can differentiate in powershell if application comes move to onhold, if package name comes move to onhold. Any hint :-)

    ReplyDelete
  9. Hi,

    I'm not a big fan of a tree folder structure in sccm (or spaces in naming standards by the way), I've tried it so many different ways, and it just complicates things in a large environment. You have search at your finger tips, why browse trough folders?
    If you have a good naming convention you don't need folders, just use search. The most annoying thing with folders is that there is a long standing bug in the sccm console when wanting to search subfolders. The search subfolder option is not available if you click the search field immediately after you select a folder. You have to wait ~1 sec before selecting the search folder for it to be displayed which is annoying as hell.

    I found this post very useful though when creating a script to move apps from folder to folder using status messages.

    What I did was implementing a flat or almost flat structure everywhere and put just 3 main folders, Development | Quality | Production.

    For example applications are always created in Development folder and then when the user selects the Quality Security Scope the app is automatically moved to the Quality folder and a mail is sent saying that the app needs reviewing.
    After the quality step the QA sets the security scope to production and the app is moved in the Production folder.
    Apps in with the Development or Quality security scopes can only be deployed on a few test collection that contain test machines, never in production. Also setting the security scope to production is available only to a limited number of admins.

    Of course this does not work for everybody but it works for us and it gives us confidence when giving other people access to create applications or other items that naming standards will be used and every app that is created is quality checked.

    Very nice post it helped me a lot, thank you!

    ReplyDelete