How to Create a Basic App using the Configuration Manager 2012 Beta 2 SDK

With System Center Configuration Manager 2012 comes a new powerful way to manage apps called the Application Model. The new Application Model (App Model) unlocks the vision of User Centric computing or user targeting. User targeting in Configuration Manager 2007 was technically possible however it was not practical as platform specific issues had to be managed at the collection level. The App Model solves this problem along with many other short comings of what is now called Classic Software Distribution. A.K.A Packages and Programs which we are all familiar with. There are a lot of pieces to the new App Model to discuss. I want to focus on the most basic scenario in this post and show how to create a simple Application with a single deployment type.

Quick note: The App Model SDK is still under development and some of the class referenced below are bound to change between Beta 2 and RTM.

Start with Application

To get started you’ll need to add a reference to the following assemblies found in the CM 2012 Console install directory:

  • Microsoft.ConfigurationManagement.ApplicationManagement.dll
  • Microsoft.ConfigurationManagement.ApplicationManagement.MsiInstaller.dll

The first step in creating your first Application in the 2010 App Model is to create an instance of Microsoft.ConfigurationManagement.ApplicationManagement.Application.

 //creat an instance of Application 
ObjectId appId = new ObjectId("Authoring_Scope_Id",
 "Application_"+Guid.NewGuid().ToString());
Application app = new Application(appId);
app.Title = "New App";
app.Version = 1; 

The constructor for Application takes an instance of ObjectId which indicates the Authoring Scope and Logical Name of the Application. These are in the form of “ScopeId_5D0545B8-46E1-4F48-B165-B8870DAE1C1C" and “Application_b3628303-eeb6-41af-a15c-175c12f3bd6a” respectively. The Authoring scope is unique per Primary Site Server and you can get that from WMI. Supplying a fake Authoring Scope ID should work just fine for testing purposes. If you plan on deploying this to a client you should do the work to get the actual Site Scope Id. It should also be noted that the “Version” property does not refer to the version of the Application that your are creating. It indicates the revision of the app in terms of Application revisions which is a new feature in 2012.

Add Localized Display Info

The various Application properties such as Title are what we see in the Admin Console. The end user via Software Center or the Software Catalog see different information. The end user sees information contained in an instance of DisplayInfo that can be localized to the language of the end user. This is done by adding an instance of DisplayInfo along with localized metadata for each language you want to support.

 //cerate DisplayInfo //this is the localizable info that the end user will see in Software Center 
AppDisplayInfo displayInfo = new AppDisplayInfo(); 
displayInfo.Title = "My App"; 
displayInfo.Language = CultureInfo.CurrentCulture.Name; 
displayInfo.Description = "My first App"; 
app.DisplayInfo.Add(displayInfo);

Here I am using the same language as the current executing process “en-US”, but you could use any language identifier.

Add a Deployment Type

For those not familiar with the App Model the Application is the abstract definition of an application and the Deployment Type represents the concrete instance of the app. To make our app work we need to associate an installer and content with the Application instance. This is done with a DeploymentType.

 //Add DT ObjectId dtId = new ObjectId("Authoring_Scope_Id",     
 "DeploymentType" + Guid.NewGuid().ToString()); 
DeploymentType dt = new DeploymentType(dtId, MsiInstaller.TechnologyId); 
app.DeploymentTypes.Add(dt); 
dt.Title = "My First DT";
dt.Version = 1; 

Again we see the use of ObjectId but we are using the “DeploymentType_” prefix for Name. Once we have the DeploymentType created we add it to Application.DeploymentTypes. The TechnologyId paramter in the DT constructor indicates what type of DT we are creating. We are creating an MSI type DT so we use the static property found on Microsoft.ConfigurationManagement.ApplicationManagement.MsiInstaller that equates to the string “MSI”.

Setup the MsiInstaller

Our new DT has been added to our Application. DeploymentType has a property called “Installer” that exposes the instance of Installer that we need to work with. The DT constructor was nice enough to supply us with an instance of MsiInstaller so we just need to configure it.

 //configure MSI installer to have a product code detection method 
MsiInstaller installer = dt.Installer as MsiInstaller; 
Guid fakeProductCode = Guid.NewGuid(); 
installer.ProductCode = "{" + fakeProductCode.ToString() + "}";

//set commandline 
installer.InstallCommandLine = "MSIExec /i MyApp.Msi";

One critical component to any DT is its Detection Method. The Detection Method indicates how the CM Client is suppose to know if the app is installed or not. This is critical as the App Model is state based. If you get the Detection Method wrong the client will think the app is not installed and will attempt to install it every time Global Evaluation runs (every 7 day I believe) even if the app is installed. The nice part about working with MSIs is that we can just specify a Product Code and the rest is handled for us. The Product Code format is a Guid wrapped with { } such as {27aae8e3-e733-4256-a37f-dc1e0287da9f}.

Add Content

Next we need to associate our DT and MsiInstaller with actual content so the client has something to install.

 //Add content to the DT 
Content installerContent = new Content(); 
installer.Contents.Add(installerContent); 
installerContent.Location = @\\SomeServer\content\MyAppDir; 
//add MSI file to content 
ContentFile msiFile = new ContentFile(); 
msiFile.Name = "MyApp.Msi"; 
installerContent.Files.Add(msiFile);

When setting the Name property on ContentFile use a path that is relative to the path specified by “Location”.

Serializing the Application

We are almost ready to send our app to the site to deploy to clients. Before we do that we need to serialize our instance of Application. We use a special serializer found in Microsoft.ConfigurationManagement.ApplicationManagement.Serialization called SccmSerializer. This serializer will do some addition verification for us to check for invalid properties.

 //serialize app. string appXml = SccmSerializer.SerializeToString(app, true);  

Committing the App to the Site

The last step to creating our app is to use the CM WMI provider to save our serialized data to the site server. To do this we need to create an instance of SMS_Application. I’m not going to go into great detail on working with WMI here as there are a ton of articles that cover that subject. But here is a basic method for getting an instance of SMS_Application from the provider.

 //serialize app. 
string appXml = SccmSerializer.SerializeToString(app, true); 
ManagementObject appInstance = null; 
ManagementPath path = null; 
ObjectGetOptions options = null; 
ManagementClass appClass = null; 
try 
{
 ManagementScope scope = 
 new ManagementScope(@”\\SiteServer\root\Sms\Site_SiteCodeGoesHere”);     
 path = new ManagementPath("SMS_Application");     
 options = new ObjectGetOptions();     
 appClass = new ManagementClass(scope, path, options);
 appInstance = appClass.CreateInstance(); 
} 
finally 
{
 appClass.Dispose(); 
}

The only property we need to set here is SDMPackageXML. We set SDMPackageXML to the serialzed XML string stored in appXml and call Put() to save our app to the site.

 appInstance.Properties["SDMPackageXML"].Value = appXml; appInstance.Put();

You should now have an app that is ready to deploy!

There are a lot of other properties associated with the App Model that we did not explore that can impact how an App behaves on the client. This post covers jus the most basic. In upcoming posts I’ll cover more advanced topics such as DT dependencies and Enhanced Detection Methods.