Creating a Package and Programs Using SMS Classes

Packages contain programs that you can distribute to any client or user defined in your Microsoft® Systems Management Server (SMS) system. You can create packages for commercial software, in-house software, configuration scripts, and data files using packages.

Important  Although SMS lets you install software on multiple computers, you are still required to follow the licensing agreements for any commercial software you use.

You can specify more than one program per package. Programs are commands, associated with an SMS package, that run on clients when the software is distributed. You can associate virtually any activity with a program. For example, you can use a program to install new software on clients, distribute data files, run virus detection software, update client configurations, and so forth. Make sure that the package source directory contains all the files and subdirectories needed to complete the program, including any scripts.

The following example shows you how to create a package and program using the SMS_Package and SMS_Program classes. This example is continued through the other software distribution topics.

[C/C++]
This example assumes the IWbemServices and IWbemContext (context qualifiers) objects have been created. For information on connecting to SMS, see Connecting to the SMS Namespace. For information on creating a context object, see SMS Context Qualifiers.

  [C/C++]
    HRESULT CreateProgramAndPackage(IWbemServices* &pServices;)
{
	HRESULT hr;
	IWbemClassObject  *pclsPackage = NULL;        //SMS_Package class definition
	IWbemClassObject  *pinstPackage = NULL;       //Instance of SMS_Package
	IWbemCallResult   *pPkgPath = NULL;           //Use to get PackageID
	IUnknown          *pUnknown = NULL;
	IWbemClassObject  *pclsSchedule = NULL;       //SMS_ST_RecurInterval class
	IWbemClassObject  *pinstSchedule = NULL;      //Instance of SMS_ST_RecurInterval
	IWbemClassObject   *pclsProgram = NULL;       //SMS_Program class definition
	IWbemClassObject   *pinstProgram = NULL;      //Instance of SMS_Program
	IWbemClassObject *pSMSContext=NULL;
	BSTR               bstrPath, bstrPackageID;
	_variant_t         vTemp,vTokens;
	SAFEARRAY         *psaTokens;                 //Array of schedule tokens
	SAFEARRAYBOUND     saBounds;
	long               lArrayIdx = 0;

	try{


		//Create the package. The package contains a single program that generates a
		//status MIF. The program uses source files that are updated daily on the
 		//distribution point from the package source location.
		hr = pServices->GetObject(_bstr_t(L"SMS_Package"), 0, NULL, &pclsPackage;, 0);
		hr = pclsPackage->SpawnInstance(0, &pinstPackage;);
		pclsPackage->Release();

		
		vTemp = L"Status MIF example";
		hr = pinstPackage->Put(L"Description", 0, &vTemp;, NULL);

		vTemp = L"ABC123 Inc.";
		hr = pinstPackage->Put(L"Manufacturer", 0, &vTemp;, NULL);

		//The following four properties must be the same values as the status MIF
		//values that your program creates.
		vTemp = L"CkStatus.mif";
		hr = pinstPackage->Put(L"MIFFileName", 0, &vTemp;, NULL);

		vTemp = L"Check Status";
		hr = pinstPackage->Put(L"MIFName", 0, &vTemp;, NULL);

		vTemp = L"ABC123 Inc.";
		hr = pinstPackage->Put(L"MIFPublisher", 0, &vTemp;, NULL);

		vTemp = L"1.0.001";
		hr = pinstPackage->Put(L"MIFVersion", 0, &vTemp;, NULL);

		vTemp = L"Check Status";
		hr = pinstPackage->Put(L"Name", 0, &vTemp;, NULL);

		vTemp = (long)536870912;      //USE_SPECIAL_MIF (bit 29)
		hr = pinstPackage->Put(L"PkgFlags", 0, &vTemp;, NULL);

		vTemp = (long)2;              //STORAGE_DIRECT (2)
		hr = pinstPackage->Put(L"PkgSourceFlag", 0, &vTemp;, NULL);

		vTemp = L"D:\\Scripts";
		hr = pinstPackage->Put(L"PkgSourcePath", 0, &vTemp;, NULL);
		//Create an   array of schedule token objects  derived    from  SMS_ScheduleToken.
		//This  example uses SMS_ST_RecurInterval   to  create a daily                            update schedule
		//for  the source files.
		saBounds.cElements = 1;

		saBounds.lLbound = 0;
		psaTokens =SafeArrayCreate(VT_UNKNOWN, 1,  &saBounds;);
		hr = pServices->GetObject(_bstr_t(L"SMS_ST_RecurInterval"),  0, NULL, &pclsSchedule;,0);

		hr =   pclsSchedule->SpawnInstance(0,   &pinstSchedule;);
		pclsSchedule->Release();

		pclsSchedule =   NULL;
		vTemp = (long)1;
		hr =  pinstSchedule->Put(L"DaySpan", 0, &vTemp;,   NULL);

		vTemp = L"20000314050000.000000+***";
		hr = pinstSchedule->Put(L"StartTime", 0, &vTemp;, NULL); pinstSchedule->QueryInterface(IID_IUnknown, (void **)&pUnknown;);

		SafeArrayPutElement(psaTokens, &lArrayIdx;, pUnknown);
	
		pUnknown->Release();
		pUnknown =    NULL;

		pinstSchedule->Release();
		pinstSchedule =  NULL;

		vTemp.vt =   VT_ARRAY | VT_UNKNOWN;
		vTemp.parray =     psaTokens;
		hr =  pinstPackage->Put(L"RefreshSchedule", 0,   &vTemp;,   NULL);
	
		hr=SafeArrayDestroyData(psaTokens);
		hr=SafeArrayDestroy(psaTokens);

		VariantInit(&vTemp;);
	
	
		vTemp = L"1.0";

		hr = pinstPackage->Put(L"Version",
		0,  &vTemp;, NULL); //Use the CallResult  (pPkgPath)  parameter  to get the PackageID, which is
		//used to create the relationship  between  the  program, the distribution
		//point  and  the advertisement.

		hr =  pServices->PutInstance(pinstPackage, 0, NULL,  &pPkgPath;);
		pinstPackage->Release();
		hr =   pPkgPath->GetResultString(0, &bstrPath;);

		bstrPackageID = SysAllocStringLen((wcschr(bstrPath, '\"') + 1),
		8);
		pPkgPath->Release();			


		//Create the program.
		hr = pServices->GetObject(_bstr_t(L"SMS_Program"), 0, NULL, &pclsProgram;, 0);
		hr = pclsProgram->SpawnInstance(0, &pinstProgram;);
		pclsProgram->Release();

		//This program simply calls the InstallStatusMIF DLL function. Make sure the
		//values for the function parameters match the MIF property values in the
		//package.
		vTemp = L"StatusCheck";
		hr = pinstProgram->Put(L"CommandLine", 0, &vTemp;, NULL);

		vTemp = L"Checking InstallStatusMIF";
		hr = pinstProgram->Put(L"Comment", 0, &vTemp;, NULL);

		vTemp = bstrPackageID;
		hr = pinstProgram->Put(L"PackageID", 0, &vTemp;, NULL);

		//Set bits UNATTENDED(13), USERCONTEXT(14), USEUNCPATH(20), ANY_PLATFORM(27)
		vTemp = (long)135290880;
		hr = pinstProgram->Put(L"ProgramFlags", 0, &vTemp;, NULL);

		vTemp = L"Check Status";
		hr = pinstProgram->Put(L"ProgramName", 0, &vTemp;, NULL);

		vTemp = L"D:\\MyPrograms";
		hr = pinstProgram->Put(L"WorkingDirectory", 0, &vTemp;, NULL);

		hr = pServices->PutInstance(pinstProgram, 0, NULL, NULL);
	

		pinstProgram->Release();

		
	catch(...)
	{
		// clean up after error condition;
	}
		
		return hr;
}

[Visual Basic]
This example assumes the SWbemServices and SWbemNamedValueSet (context qualifiers) objects have been created. For information on connecting to SMS, see Connecting to the SMS Namespace. For information on creating a context object, see SMS Context Qualifiers.

  [Visual Basic]
    Dim instPackage As SWbemObject              'SMS_Package instance
    Dim instPath As SWbemObjectPath             'Path to the package instance
    Dim PackageID As String
    Dim instProgram As SWbemObject              'SMS_Program instance
    Dim instOSDetails(0 To 2) As SWbemObject    'Array of SMS_OS_Details instances


    Set instPackage = Services.Get("SMS_Package").SpawnInstance_

    instPackage.Description = "Office 2000 installation"
    instPackage.Manufacturer = "Microsoft"
    instPackage.Name = "Office 2000"
    instPackage.PkgSourceFlag = 3        'STORAGE_COMPRESS
    instPackage.PkgSourcePath = "E:\"    'CD-ROM

    'Use this share for the distribution point, instead of the SMS default.
    instPackage.ShareName = "MyDPShare\Office2000"
    instPackage.ShareType = 2            'SHARE_SPECIFIC
    instPackage.Version = "9.0.2720"

    'Create the package instance using the context object qualifiers. Specify the
    'MachineName, ApplicationName, and LocaleID (optional) context qualifiers.
    'These are used in the audit status message to identify which component created
    'the package. Use the returned object path to get the PackageID; the PackageID
    'is used later to create the program.
    Set instPath = instPackage.Put_(, SMSContext)
    PackageID = instPath.Keys("PackageID")


    Set instProgram = Services.Get("SMS_Program").SpawnInstance_

    instProgram.CommandLine = "Setup"
    instProgram.Comment = "Installing Office 2000 from CD"
    instProgram.DiskSpaceReq = "400 MB"
    instProgram.PackageID = PackageID        'Returned from the package put instance
    instProgram.ProgramFlags = 1064960       'USERCONTEXT(14), USEUNCPATH(20)
    instProgram.ProgramName = "Office 2000 Setup"
    instProgram.Requirements = "75 MHz or higher Pentium processor" & vbCrLf & _
                               "32 MB or more of RAM"

    'The values for the SMS_OS_Details instances come from SMS_SupportedPlatforms
    Set instOSDetails(0) = Services.Get("SMS_OS_Details").SpawnInstance_
    instOSDetails(0).MaxVersion = "5.00.9999.9999"     '9999 signifies all
    instOSDetails(0).MinVersion = "5.00.0000.0"        'versions of Windows 2000
    instOSDetails(0).Name = "Win NT"
    instOSDetails(0).Platform = "I386"

    Set instOSDetails(1) = Services.Get("SMS_OS_Details").SpawnInstance_
    instOSDetails(1).MaxVersion = "4.00.9999.9999"     '9999 signifies all
    instOSDetails(1).MinVersion = "4.00.0000.0"        'versions of Windows NT 4
    instOSDetails(1).Name = "Win NT"
    instOSDetails(1).Platform = "I386"

    Set instOSDetails(2) = Services.Get("SMS_OS_Details").SpawnInstance_
    instOSDetails(2).MaxVersion = "4.10.9999.9999"     '9999 signifies all
    instOSDetails(2).MinVersion = "4.10.1998.0"        'versions of Windows 98
    instOSDetails(2).Name = "Win 9x"
    instOSDetails(2).Platform = "I386"

    instProgram.SupportedOperatingSystems = instOSDetails

    'Create the program instance using the context object qualifiers.
    instProgram.Put_ , SMSContext