Content when creating applications

Hi,

I'm trying to bulk-create Applications in CM2012, but I've run into a problem running the apps from Software Center.

Looking in Appenforce.log shows:

The content path is not specified for DeploymentType ScopeId_6478C138-793A-41C4-9769-E15DF9005319/DeploymentType_d7488ebc-5d0d-4f4c-9d59-95f43bf2567b.  Content is assumed to be locally available. AppEnforce

I'm using the example from http://msdn.microsoft.com/en-us/library/jj155378.aspx replacing only "null" with my testapp's folder.

Everything seems to work fint, imported fine and looks as expected.

I then replace the detection rule with a working (product code of my test MSI) and replace the Install command with msiexec.exe /i mymsi.msi /qn

But I still get the error above.

To fix it, I do the following:

Open the DT and change Content path to some other folder and Apply. Then change it back to my test apps folder and apply.

Now the application works from Software Center. So either the example doesn't work or is missing something important.

Thanks,

July 10th, 2012 1:02am

Hi,

I'm trying to bulk-create Applications in CM2012, but I've run into a problem running the apps from Software Center.

Looking in Appenforce.log shows:

The content path is not specified for DeploymentType ScopeId_6478C138-793A-41C4-9769-E15DF9005319/DeploymentType_d7488ebc-5d0d-4f4c-9d59-95f43bf2567b.  Content is assumed to be locally available. AppEnforce

I'm using the example from http://msdn.microsoft.com/en-us/library/jj155378.aspx replacing only "null" with my testapp's folder.

Everything seems to work fint, imported fine and looks as expected.

I then replace the detection rule with a working (product code of my test MSI) and replace the Install command with msiexec.exe /i mymsi.msi /qn

But I still get the error above.

To fix it, I do the following:

Open the DT and change Content path to some other folder and Apply. Then change it back to my test apps folder and apply.

Now the application works from Software Center. So either the example doesn't work or is missing something important.

Thanks,

Hi,

I have the same problem. As a workaround, I put the path in the DT Description field instead of Content path. After running the program, I edit the DT, do a cut and paste from Description to Contant path and apply the changes. Not elegant but do the job... for now.

I'm still looking for a clean solution. In the meantime if someone has a solution, please share.


Thank you.

Free Windows Admin Tool Kit Click here and download it now
August 21st, 2012 2:20pm

This should help: http://blog.lechar.nl/2012/04/11/application-wont-download-content/
August 21st, 2012 2:35pm

Assuming your application is created correct, the following works for me (following the application creation). It doesn't really build on the example you're giving, but I'm sure it can be adapted to your code.

(After completing the code examples I see it's really a lot of code. I hope you can pull out something useful from it...)

public static void AddDeploymentType(WqlConnectionManager connection, SMS_Application application, string msiFile, string msiInstallCommand, string msiUninstallCommand)
{
	IResultObject outParams = connection.ExecuteMethod("SMS_Identification", "GetSiteID", null);

	string scopeID = "ScopeId_" + outParams["SiteID"].StringValue.Substring(1, 36);
	string fileName = msiFile.Substring(msiFile.LastIndexOf("\\") + 1);
	string path = msiFile.Substring(0, msiFile.LastIndexOf("\\") + 1);

	Application app = SccmSerializer.DeserializeFromString(application.SDMPackageXML, true);

	DeploymentType deploymentType = CreateDeploymentType(scopeID, path, fileName);
	MsiInstaller installer = CreateInstaller(path, fileName, app, msiInstallCommand, msiUninstallCommand);
	Content content = CreateContent(path, fileName);

	installer.Contents.Add(content);
	deploymentType.Installer.CopyFrom(installer);
	app.DeploymentTypes.Add(deploymentType);

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

	IResultObject ro = connection.GetInstance("SMS_Application.CI_ID=" + application.CI_ID.Value);
	ro["SDMPackageXML"].StringValue = appXml;
	ro.Put();
}
private static DeploymentType CreateDeploymentType(string scopeID, string msiPath, string msiFileName)
{
	MsiContentImporter msi = new MsiContentImporter();
	msi.OpenMsi(msiPath + msiFileName);

	string deploymentTypeDescription = "Windows Installer (Native)";

	ObjectId deploymentTypeId = new ObjectId(scopeID, "DeploymentType_" + Guid.NewGuid().ToString());
	DeploymentType deploymentType = new DeploymentType(deploymentTypeId, MsiInstaller.TechnologyId);
	deploymentType.Title = msi.ReadProperty("ProductName") + " - " + deploymentTypeDescription;
	deploymentType.Version = 1;

	return deploymentType;
}

This includes an enhanced detection method, but can easily be striped down to just the product code.

public static MsiInstaller CreateInstaller(string msiPath, string msiFileName, Application app, string msiInstallCommand, string msiUninstallCommand)
{
	MsiContentImporter msi = new MsiContentImporter();
	msi.OpenMsi(msiPath + msiFileName);
	string msiProductCode = msi.ReadProperty("ProductCode");
	string msiVersion = msi.ReadProperty("ProductVersion");
	string msiProductName = msi.ReadProperty("ProductName");

	MsiInstaller installer = new MsiInstaller();
	installer.ProductCode = msiProductCode;
	installer.SourceUpdateProductCode = msiProductCode;
	installer.InstallCommandLine = msiInstallCommand;
	installer.UninstallCommandLine = msiUninstallCommand;
	installer.ExecutionContext = Microsoft.ConfigurationManagement.ApplicationManagement.ExecutionContext.System;
	//installer.DetectionMethod = DetectionMethod.ProductCode

	EnhancedDetectionMethod edm = new EnhancedDetectionMethod();

	MSISettingInstance msiSI = new MSISettingInstance(installer.ProductCode, null);
	msiSI.LogicalName = "MSI_" + Guid.NewGuid().ToString();
	msiSI.IsPerUser = false;
	msiSI.ProductCode = installer.ProductCode;
	msiSI.Annotation.DisplayName = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString("DisplayName") { Text = "" };
	msiSI.Annotation.Description = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString("Description") { Text = "" };

	edm.Settings.Add(msiSI);

	Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation annotation = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Annotation();

	annotation.DisplayName = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString("DisplayName") { Text = "" };
	annotation.Description = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.LocalizableString("Description") { Text = "" };


	Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.SettingReference reference = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.SettingReference(app.Scope, app.Name, 1, msiSI.LogicalName, Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType.Version, ConfigurationItemSettingSourceType.MSI, true, ConfigurationItemSettingMethodType.Value, "ProductVersion");
	Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue constant = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ConstantValue(msiVersion, Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.DataType.Version);

	Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression expression = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.Expression(Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators.ExpressionOperator.IsEquals, new CustomCollection<Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions.ExpressionBase> { reference });
	expression.Operands.Add(constant);

	Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule rule = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule("Rule_" + Guid.NewGuid().ToString(), Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity.Informational, annotation, expression);
	edm.Rule = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule("Rule_" + Guid.NewGuid().ToString(), Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.NoncomplianceSeverity.Informational, annotation, expression, app.Scope, app.Name, 1);

	installer.EnhancedDetectionMethod = edm;

	installer.DetectionMethod = DetectionMethod.Enhanced;

	return installer;
}
public static Content CreateContent(string msiPath, string msiFileName)
{
	ContentFile contentFile = new ContentFile();
	contentFile.Name = msiFileName;

	Content installerContent = new Content();
	installerContent.Location = msiPath;
	installerContent.Files.Add(contentFile);
	installerContent.FallbackToUnprotectedDP = true;
	installerContent.OnSlowNetwork = ContentHandlingMode.Download;
	installerContent.OnFastNetwork = ContentHandlingMode.Download;

	return installerContent;
}

Then add the content to a distribution point:

string packageID = GetPackageID(connection, application.ModelName);
AddDistributionPoint(connection, distributionPointResource.SiteCode, distributionPointResource.NALPath, packageID);
public static string GetPackageID(WqlConnectionManager connection, string modelName)
{
	string retval = "";
	string query = "SELECT PackageID FROM SMS_ObjectContentInfo WHERE ObjectID='" + modelName + "'";

	IResultObject ro = connection.QueryProcessor.ExecuteQuery(query);

	if (ro != null)
	{
		foreach (IResultObject item in ro)
		{
			if (item != null)
				retval = item["PackageID"].StringValue;
			break;
		}
	}

	return retval;
}
public static void AddDistributionPoint(WqlConnectionManager connection, string siteCode, string nalPath, string packageID)
{
	IResultObject ro = connection.GetInstance(@"SMS_ContentPackage.PackageID='" + packageID + "'");

	Dictionary<string, object> parameters = new Dictionary<string, object>();
	parameters.Add("SiteCode", new string[] { siteCode });
	parameters.Add("NALPath", new string[] { nalPath });

	ro.ExecuteMethod("AddDistributionPoints", parameters);
}
CreateDeployment(connection, application, installCollection, "Install", 1);
CreateDeployment(connection, application, uninstallCollection, "Uninstall", 2);
private static void CreateDeployment(WqlConnectionManager connection, SMS_Application application, SMS_Collection collection, string action, UInt32 desiredConfigType)
{
	SMS_ApplicationAssignment assignment = new SMS_ApplicationAssignment();

	assignment.ApplicationName = application.LocalizedDisplayName;
	assignment.AssignedCI_UniqueID = application.CI_UniqueID;
	assignment.AssignedCIs.Add((Int32)application.CI_ID.Value);
	assignment.AssignmentName = application.LocalizedDisplayName + "_" + collection.Name + "_" + action;
	assignment.CollectionName = collection.Name;
	assignment.DisableMomAlerts = true;
	assignment.NotifyUser = false;
	if (action == "Install")
	{
		assignment.OfferFlags = 1;
		assignment.DesiredConfigType = 1;
	}
	if (action == "Uninstall")
	{
		assignment.OfferFlags = 0;
		assignment.DesiredConfigType = 2;
	}
	assignment.OverrideServiceWindows = false;
	assignment.RebootOutsideOfServiceWindows = false;
	assignment.SuppressReboot = 0;
	assignment.TargetCollectionID = collection.CollectionID;
	assignment.UseGMTTimes = false;
	assignment.UserUIExperience = false;
	assignment.WoLEnabled = false;
	assignment.LocaleID = 1033;

	assignment.Create(connection);
}

public void Create(WqlConnectionManager connection)
{
	DateTime currentTime = DateTime.Now;

	IResultObject newApplicationAssignment = connection.CreateInstance("SMS_ApplicationAssignment");

	newApplicationAssignment["ApplicationName"].StringValue = this.ApplicationName;
	newApplicationAssignment["AssignedCI_UniqueID"].StringValue = this.AssignedCI_UniqueID;
	newApplicationAssignment["AssignedCIs"].IntegerArrayValue = this.AssignedCIs.ToArray();
	newApplicationAssignment["AssignmentName"].StringValue = this.AssignmentName;
	//newApplicationAssignment["AssignmentUniqueID"].StringValue = newDeploymentInfo["DeploymentID"].StringValue;
	newApplicationAssignment["CollectionName"].StringValue = this.CollectionName;
	newApplicationAssignment["DisableMomAlerts"].BooleanValue = this.DisableMomAlerts;
	newApplicationAssignment["EnforcementDeadline"].DateTimeValue = currentTime;
	newApplicationAssignment["NotifyUser"].BooleanValue = this.NotifyUser.Value;
	newApplicationAssignment["OfferFlags"].LongValue = this.OfferFlags;
	newApplicationAssignment["DesiredConfigType"].LongValue = this.DesiredConfigType.Value;
	newApplicationAssignment["OverrideServiceWindows"].BooleanValue = this.OverrideServiceWindows.Value;
	newApplicationAssignment["RebootOutsideOfServiceWindows"].BooleanValue = this.RebootOutsideOfServiceWindows.Value;
	newApplicationAssignment["RequireApproval"].BooleanValue = this.RequireApproval;
	newApplicationAssignment["StartTime"].DateTimeValue = currentTime;
	newApplicationAssignment["SuppressReboot"].LongValue = this.SuppressReboot.Value;
	newApplicationAssignment["TargetCollectionID"].StringValue = this.TargetCollectionID;
	newApplicationAssignment["UseGMTTimes"].BooleanValue = this.UseGMTTimes.Value;
	newApplicationAssignment["UserUIExperience"].BooleanValue = this.UserUIExperience;
	newApplicationAssignment["WoLEnabled"].BooleanValue = this.WoLEnabled.Value;
	newApplicationAssignment["LocaleID"].LongValue = this.LocaleID.Value;

	newApplicationAssignment.Put();
}


Free Windows Admin Tool Kit Click here and download it now
September 14th, 2012 10:35am

Hi

The example on the msdn site doesn't work correctly!

In the CreateScriptDt function, you have to add the Content to the property Contents on the Installer Object and additionaly the proprty InstallContent must be set!
This would look like this:

// Only add content if specified and exists.
if (Directory.Exists(contentFolder) == true)
{
  Content content = ContentImporter.CreateContentFromFolder(contentFolder);
  if (content != null)
  {
    installer.Contents.Add(content);
    // Insert this line!
    installer.InstallContent = new ContentRef(content);
  }
}

Hope this helps.

Regards

  • Proposed as answer by RenggliC Monday, September 24, 2012 11:09 AM
September 24th, 2012 11:04am

rec3di,

Having just figured this out on my own, I was surprised to find almost nothing online regarding the "InstallContent" property. Your post, and one other blogger mentioned it. MSDN should fix their examples!

Thanks,
Jason

Free Windows Admin Tool Kit Click here and download it now
October 31st, 2012 4:37pm

Jason, for documentation feedback I encourage you to send an e-mail to smsdocs at microsoft dot com with specific examples of areas you feel are lacking. E-mails sent to this address go to the documentation team and are read by actual people, not bots. When the documentation team gets feedback from real customers like you, this helps to prioritize areas of improvement.

November 5th, 2012 7:53pm

thank you so much!  I'm doing this in PowerShell, but this is the answer I have been looking for 2 days!  thank you thank you thank you!
Free Windows Admin Tool Kit Click here and download it now
August 27th, 2015 2:10pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics