Well, here is another one of my "How To" topics.

I get asked quite a bit: "How do we interact with MPS so we do not have to use Notepad and Provtest.exe."

So I would call this principle "Calling MPS programatically".

OK. So the good news first:
The MPS Client is a good old fashioned COM Object with a couple of interfaces we can use from almost any programming language. If you keep a basic rule in mind things should turn out pretty well J

Rule #1: Do Not Break MPS Loadbalancing.
Load balancing in MPS is handled by the MPS Client.
When you submit a request to the client, the client will connect to the MPFConfig Database and ask for a list of available MPS Engine servers and then start submitting the requests to each engine in the list in a round robin fashion. So imagine your code does something like this
Disclaimer: Pseudo code ahead! For illustration purposes only.

For i=1 to 10
     myResult= submitMPSRequest strXML(i),strNamespace,strProcedure
next

function submit MPSRequest(string XMLRequest, strNSName, strProcName)
     myMPSClient = CreateObject("MPSClientCOMObject")
     return myMPSClient.SubmitTrustedRequest(strXML,strNSName,strProcName)
end function

So what will happen when we run this?

Correct: Every time a request is submitted a new MPSClient Object is created and that instance will always submit the request to the first engine in the list of results. So no load balancing will occur.
So the correct way to structure this would be

Disclaimer: Pseudo code ahead! For illustration purposes only.

Global myMPSClient = CreateObject("MPSClientCOMObject")
For i=1 to 10
   
myResult= submitMPSRequest strXML(i),strNamespace,strProcedure
next

function submit MPSRequest(string XMLRequest, strNSName, strProcName)
    
return myMPSClient.SubmitTrustedRequest(strXML,strNSName,strProcName)
end function

So what will happen when we run this code?

Every time a request is submitted the same MPSClient Object is used and since it is only instantiated once it will do the correct load balancing between all available engines.

OK now off to real code

Let's say we want to create a bunch of organizations in HMC for the sake of this sample. The first thing we need is a template XML file we can use to fill in our properties before we submit it to MPS.

Sample CreateOrganization.xml file ( I used one from the samples folder on the MPS Engine and cleaned it up a bit )

<?xml version="1.0" encoding="utf-8" ?>
<request
    <data
        <name/> 
        <policyName/> 
        <container/> 
        <description/> 
        <preferredDomainController/> 
    </data
    <procedure
        <execute namespace="Managed Active Directory" procedure="CreateOrganization"
            <before source="data" destination="executeData" mode="merge"/> 
            <after source="executeData" sourcePath="org" destination="data" mode="insert"/> 
        </execute
    </procedure>
</request>

Since VBScript is so old school I will keep this one short and not spend much time with it.

--------------- Script starts here --------

'INSTANTIATE THE MPF CLIENT OBJECT
Set objMPFClient = CreateObject("Provisioning.ProvEngineClient")
For i=1 to 10
 
    Wscript.echo "Created OU: " & CreateOrganization("MyTestOrg" & i, "Customer", "Test Org", "OU=ConsolidatedMessenger,OU=Hosting,DC=Fabrikam,DC=Com")
next

Function CreateOrganization(xi_OrgName, xi_PolicyType,xi_Description, xi_strContPath)

'LOAD THE XML OBJECT

Set objXML = CreateObject("MSXML2.DOMDocument")

'LOAD XML TEMPLATE 
    strXmlFile = "CreateOrganization.xml" 
    objXml.Load (strXmlFile) 

    'SET THE ORG NAME
Set objOrg = objXml.selectSingleNode("/request/data/name")
objOrg.Text = CStr(xi_OrgName)

    'SET THE POLICY TYPE
Set objOrg = objXml.selectSingleNode("//*/data/policyName")
objOrg.Text = CStr(xi_PolicyType)

     'SET THE CONTAINER
Set objOrg = objXml.selectSingleNode("//*/data/container")
objOrg.Text = xi_strContPath

    'SET THE DESCRIPTION
Set objOrg = objXml.selectSingleNode("//*/data/description")
objOrg.Text = CStr(xi_Description)

    'SET THE PREFERRED DOMAIN CONTROLLER
Set objOrg = objXml.selectSingleNode("//*/data/preferredDomainController")
objOrg.Text = CStr(prefDC)

    'SUBMIT THE REQUEST 
    strXMLResponse = objMPFClient.SubmitRequest(objXML.xml, "Managed Active Directory", _ 
                        "CreateOrganization")        

    'GET LDAP PATH FROM RESPONSE 
    objXml.LoadXML(strXMLResponse) 
    Set objOrg = objXml.selectSingleNode("//*/data/org")

    CreateOrganization = objOrg.getAttribute("path")

End Function

Now to something more up to date – Windows Powershell
Note that we need to use a MSXML2.DOMDocument instead of a System.XML Object this is because MPS does not "understand" System.XML Objects.,

$mpsclient=New-Object -ComObject "Provisioning.ProvEngineClient"
function CreateOrganization([string]$strOrgName,[string]$strPolicyName,[string]$strDescription,[string]$strPath,[string]$strDC)

    $xmlRequest = New-Object -ComObject "MSXML2.DOMDocument" 
    $xmlRequest.load("CreateOrganization.xml"
    $xmlRequest.SelectSingleNode("//*/data/name").Text=$strOrgName 
    $xmlRequest.SelectSingleNode("//*/data/policyName").Text=$strPolicyName 
    $xmlRequest.SelectSingleNode("//*/data/container").Text=$strPath 
    $xmlRequest.SelectSingleNode("//*/data/description").Text=$strDescription 
    $xmlRequest.SelectSingleNode("//*/data/preferredDomainController").Text=$strDC     

    return $mpsclient.SubmitRequest($xmlRequest.xml,"Managed Active Directory","CreateOrganization")
}

for($i=1;$i -le 10;$i++)

    CreateOrganization "MyTestOrg_$i" "customer" "Test Org" "LDAP://OU=ConsolidatedMessenger,OU=Hosting,DC=Fabrikam,DC=Com" "AD01"
}

Soon to follow something even more interesting – Calling the MPS WebServices (HMC 4.5) from C# and
Calling the MPS Client from C# and VB.NET

Have fun coding

Till next time

Mike