How to detect CCS

Because ISVs have to support solutions from multiple vendors, I frequently get asked: "How do I know if I am running on CCS?" It's a good question. Also, as future versions of the product get shipped, it will be increasingly important to be able to tell which version of CCS is installed, so that setup programs can be act accordingly.

There are various "signs" that the Windows Compute Cluster Pack might be installed. Certain binaries might be in place, environment variables might be set, there are registry keys you can find. However, I discourage developers from depending on these things, not necessarily because they might change in future versions, but because looking for those things is specific to just this one product. Proper setup programs should use reusable code to detect the presence, absence, or version information for features. If you use the techniques I'm outlining here, they can easily be modified to detect dependencies on other products which use a Microsoft Installer compatible installation, which consistutes the vast majority of Windows applications. (In fact, it's a Windows Logo requirement. See https://www.microsoft.com/windowsserver2003/partners/isvs/appspec.mspx for details.)

In this posting I'm going to introduce the use of Microsoft Installer APIs that you can use get information about your CCS installation. MSI defines the concepts of "Programs", "Features", and "Components." Perhaps the best way to get started is to download the Windows SDK at https://www.microsoft.com/downloads/details.aspx?FamilyId=C2B1E300-F358-4523-B479-F53D234CDCCF&displaylang=en. This includes a VB script named "WiLstPrd.vbs" which you can use to see how MSI APIs can be called to determine what's installed. (It will get installed in C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\SysMgmt\MSI\scripts. If you just want to try the script but don't want to wait for the SDK to dowload, you can get it and the code mentioned here in the files repository from this site: https://windowshpc.net/files/17/scripting/entry1138.aspx.)

For example, if I run this on the head node in a test cluster, I get:

C:\Documents and Settings\caclark\test>cscript WiLstPrd.vbs
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

{3F7A6441-44A4-41C0-9A0A-294629D49208} = Microsoft Office Live Meeting 2005 7.9.2107
{5ADF3AE1-035F-4366-A554-27EF55449BBB} = Debugging Tools for Windows 64-bit 6.7.4
{A9CF9052-F4A0-475D-A00F-A8388C62DD63} = MSXML 4.0 SP2 (KB925672) 4.20.9839
{E95625F4-36FD-4BE0-8018-438BA5AC50AC} = SMS Advanced Client 4.0.5571
{37477865-A3F1-4772-AD43-AAFC6BCFF99F} = MSXML 4.0 SP2 (KB927978) 4.20.9841
{E09B48B5-E141-427A-AB0C-D3605127224A} = Microsoft SQL Server Desktop Engine 8.0.761
{0D8EA686-5DE3-4816-BEAE-02331D1D5DA2} = MSXML 6.0 Parser (KB927977) 6.0.3890
{E33A28C7-5017-4F83-8B19-1A3A480392DE} = F1 Profiler 8.0.0
{B6EC01E7-431D-4D29-B9D4-E1D74CAF0AB0} = Microsoft .NET Framework 2.0 (x64) 2.0.50727
{9A0ED01E-FD18-457A-AB9C-0835DCDB17BB} = Microsoft Platform SDK (R2) (3790.2075) 5.2.3790
{01493E6E-2473-4DE5-963B-BF17BACC21C3} = Microsoft Compute Cluster Pack 1.0.676
{1BBC7AAE-2DA9-40C2-B903-8E7A5EFEECF2} = CA eTrust Antivirus 7.1.192

Note that each product has a unique GUID. From this I can tell that the Microsoft Compute Cluster Pack is installed, but I know that there are many pieces to CCP, such as the binaries required for a compute node, the features for a headnode such as the MSDE database, and the client tools which include the Compute Cluster Administrator and Compute Cluster Job Scheduler UIs. With this script, it's possible to drill down further into a particluar product:

C:\Documents and Settings\caclark\test>cscript WiLstPrd.vbs /?
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

Windows Installer utility to list registered products and product information
Lists all installed and advertised products if no arguments are specified
Else 1st argument is a product name (case-insensitive) or product ID (GUID)
If 2nd argument is missing or contains 'p', then product properties are listed
If 2nd argument contains 'f', features, parents, & installed states are listed
If 2nd argument contains 'c', installed components for that product are listed
If 2nd argument contains 'd', HKLM "SharedDlls" count for key files are listed

C:\Documents and Settings\caclark\test>cscript WiLstPrd.vbs "Microsoft Compute Cluster Pack" fcd
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

---Features in product {01493E6E-2473-4DE5-963B-BF17BACC21C3}---
HeadNode = Local
ClientUtils = Local
ComputeNode = Uninstalled
---Components in product {01493E6E-2473-4DE5-963B-BF17BACC21C3}---
{7D708050-87A3-4F80-8965-EDD137C27EE0} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.Core.dll
{6763FD90-2629-4796-A273-14B1C49AFD02} = 20:\Microsoft.ComputeCluster.Cluster\
{21B17FE0-7C7E-4B63-BD86-B15C958B8BD7} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpConsole.exe
{05ED0D11-C198-4374-A814-F7BB1C5A5D54} = 02:\SOFTWARE\Microsoft\CCP\
{043E5A31-7BA6-4A35-9221-9B5000967C05} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpConfiguration.exe
{9DD2E181-54EA-4135-8DD2-4C7CBAF9028D} = C:\Program Files\Microsoft Compute Cluster Pack\LogFiles\
{4421EA91-45D2-40DF-8E5C-FDD617B905A0} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ComputerModel.dll
{FB3362D1-9E40-4522-8D86-4B72BCD4D808} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpSchedulerCore.dll
{C42CD672-C04B-417C-BF7C-B0E9BB988404} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpActivate.dll
{A7F4CF72-0F7F-4405-8BA0-84555D06713F} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.WizardFramework.dll
{EA44E123-CE4B-406C-BAD2-0DCC9079EF6A} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\mpiexec.exe
{99109423-B2E0-4B15-9C46-F2A38A69AAE4} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ManagementTasks.dll
{F105F063-18B2-430C-8C2F-FAC332F92573} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.RisModel.dll
{83B24CC3-D0F0-4504-92D2-29ABEF715C2C} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpManagement.msc
{A2447534-39F0-442F-8E43-1C15C933C6D5} = C:\Program Files\Microsoft Compute Cluster Pack\Conf\Microsoft.Ccp.ComputerModel.sdmDocument
{B18ECDB4-00CF-4896-96E2-ABAA30DF71F6} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\SdmL.exe
{DAECCA05-F483-4BED-93BA-148D3C44179F} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpSdm.exe
{0F3D19F5-D8DE-46A2-BF78-F01E1F6295DA} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.NetworkModel.dll
{5BBB32A6-C08F-490F-A4FC-42F5155AE7AF} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ClusterModel.dll
{5A7F74D9-56D4-4B61-B013-FD420754B92B} = 02:\SYSTEM\CurrentControlSet\Services\CcpScheduler\Parameters\spooldir
{8968955B-0047-42F6-9BE4-6AA453E55269} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\job.vbs
{78CE729B-3479-4BBB-ABA8-433B8D9D2C84} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\
{20DC0BCB-7DA4-4459-BAAF-4622B71345A8} =
{FEF27D3C-34C6-4BE8-BC5F-77DE20F0394B} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\
{02819C4C-6DCB-4751-A410-410C6605DEE1} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpScheduler.exe
{28E9CF5C-540A-4916-B42B-15A0F6020278} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\
{A1D0DD7C-ADEE-4993-A8D9-33C8EC832D25} = C:\Program Files\Microsoft Compute Cluster Pack\support.txt
{8C34B12D-FB2C-4A17-9C92-63BCEAC5F38F} = 22:\SOFTWARE\Microsoft\MMC\SnapIns\FX:{f0c64d10-d537-431e-bd72-8c55912a5611}\
{9362823D-E33C-4A95-91D5-9DF6888CE2FA} =
{D790FA5D-4E38-488C-B850-C255760799C5} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.SystemModel.dll
{61BD4B5D-B4E3-4DDD-92AA-A89C95AA9A7D} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.Store.dll
{E77254AD-CAE5-43BB-ADBD-ACCBA9A41EA0} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ClusterManagementInterfaces.dll
{9C8609ED-CEF4-4AD6-99ED-6AC398B5A99F} = C:\WINDOWS\assembly\GAC_MSIL\CcpAPI\1.0.2.3__31bf3856ad364e35\CcpAPI.dll
{1230911E-DF5F-4B01-AFB6-21DC9DFA1DCD} = C:\Program Files\Microsoft Compute Cluster Pack\InstallShare\RISInstall.cmd
{C338DD3E-E493-4D86-93B5-46EE5ADDE1F5} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.Manager.dll
{89061D2F-CCB5-47D3-A1A9-125979A7E1EB} = C:\Program Files\Microsoft Compute Cluster Pack\License\EULA.RTF
{F55F8B7F-34CB-4742-8909-80803A5BF052} = C:\Program Files\Microsoft Compute Cluster Pack\Bin\ToDoList.exe
---Shared DLL counts for key files of {01493E6E-2473-4DE5-963B-BF17BACC21C3}---
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.Core.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpConsole.exe
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpConfiguration.exe
0 = C:\Program Files\Microsoft Compute Cluster Pack\LogFiles\
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ComputerModel.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpSchedulerCore.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpActivate.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.WizardFramework.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\mpiexec.exe
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ManagementTasks.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.RisModel.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpManagement.msc
0 = C:\Program Files\Microsoft Compute Cluster Pack\Conf\Microsoft.Ccp.ComputerModel.sdmDocument
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\SdmL.exe
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpSdm.exe
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.NetworkModel.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ClusterModel.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\job.vbs
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\CcpScheduler.exe
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\
0 = C:\Program Files\Microsoft Compute Cluster Pack\support.txt
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.SystemModel.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.Store.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.ClusterManagementInterfaces.dll
0 = C:\WINDOWS\assembly\GAC_MSIL\CcpAPI\1.0.2.3__31bf3856ad364e35\CcpAPI.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\InstallShare\RISInstall.cmd
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\Microsoft.Ccp.Sdm.Manager.dll
0 = C:\Program Files\Microsoft Compute Cluster Pack\License\EULA.RTF
0 = C:\Program Files\Microsoft Compute Cluster Pack\Bin\ToDoList.exe

So you can see that the MSI APIs are pretty powerful, but if you have an exsiting C++ program, it can take some time to translate the appropriate pieces of code from the VBScript in WiLstPrd.vbs into C++, especially if you are not used to writing COM code on Windows. If you are only doing basic checks, you can use the MSI APIs described on

MSDN here:

https://msdn2.microsoft.com/en-us/library/aa369426.aspx

Here is a short sample in C++ which shows how you get some basic information:

// cccver.cpp: Get basic info on CCS components installed on local machine.

#define UNICODE 1

 

#include <windows.h>

#include <msi.h>

#include <stdio.h>

#include <assert.h>

 

#define CCP_PRODUCT_CODE L"{01493E6E-2473-4DE5-963B-BF17BACC21C3}" // GUID valid Microsoft Compute Cluster Pack

 

int wmain(int argc, wchar_t **argv)

{

        WCHAR wszValueBuf[BUFSIZ];

        DWORD dwBufsize = BUFSIZ;

 

        /* It it possible enumerate all of the products on the system with MsiEnumProducts() and check for those with the name

           "Microsoft Compute Cluster Pack" but this is not required. */

 

        UINT iRet = MsiGetProductInfo(CCP_PRODUCT_CODE,

               INSTALLPROPERTY_VERSIONSTRING,

               wszValueBuf,

               &dwBufsize);                  

 

        switch(iRet) {

       

        case ERROR_SUCCESS:

               wprintf(L"Microsoft Compute Cluster Pack Version %s is installed\n", wszValueBuf);

               dwBufsize = BUFSIZ;

 

               /* We now know that the current machine has at least some components installed, but which ones?

                  to find out, query the features. */

 

               WCHAR wszFeatureBuf[MAX_FEATURE_CHARS+1];

               WCHAR wszParentBuf[MAX_FEATURE_CHARS+1];

 

               for (DWORD i = 0; !MsiEnumFeatures(CCP_PRODUCT_CODE, i, wszFeatureBuf, wszParentBuf); i++) {

                       INSTALLSTATE featurestate = MsiQueryFeatureState(CCP_PRODUCT_CODE, wszFeatureBuf);

                       wprintf(L"%s:", wszFeatureBuf);

                       switch(featurestate) {

 

                       case INSTALLSTATE_ABSENT:

                               wprintf(L" absent\n");

                               break;

                       case INSTALLSTATE_ADVERTISED:

                               wprintf(L" advertised\n");

                               break;

                       case INSTALLSTATE_SOURCE:

                               wprintf(L" installed to run from source\n");

                               break;

                       case INSTALLSTATE_UNKNOWN:

                               wprintf(L" unknown\n");

                               break;

                       case INSTALLSTATE_LOCAL:

                               wprintf(L" installed locally\n");

                               break;

                       case INSTALLSTATE_INVALIDARG:

                               assert(0);

                               break;

                       }

               }

 

               break;

 

        case ERROR_UNKNOWN_PRODUCT:

               wprintf(L"Microsoft Compute Cluster Pack is not installed\n");

               break;

 

        default:

               wprintf(L"Error 0x%x\n", iRet);

               return 1;

 

 

        }

 

        /* Check for version of MSMPI.DLL component if present */

 

        WCHAR wszVersion[BUFSIZ];

        DWORD dwVersize = BUFSIZ;

        WCHAR wszSystem[MAX_PATH+1];

        WCHAR wszMSMPIPath[MAX_PATH+1];

        GetSystemDirectory(wszSystem, MAX_PATH);

        swprintf(wszMSMPIPath, L"%s\\msmpi.dll", wszSystem);

 

        if (ERROR_SUCCESS == MsiGetFileVersion(wszMSMPIPath, wszVersion, &dwVersize, 0, 0)) {

               wprintf(L"msmpi.dll version %s\n", wszVersion);

        }

                      

              

        return 0;

}

 

 

To compile this is easy. You just have to link with msi.lib. For example, you could just run the follow from an SDK build window:

C:\temp>cl /I "c:\Program Files\Microsoft SDKs\Windows\v6.0\Include" ccsver.cpp
"c:\Program Files\Microsoft SDKs\Windows\v6.0\Lib\Msi.Lib"

Here's the output if I run this program on all nodes in a cluster using "clusrun"

C:\Documents and Settings\caclark\test>clusrun /nodes:hpca3cn2001 \\hpca3hn02\test\ccsver

 

-------------------------- HPCA3CN2001 returns 0 --------------------------

Microsoft Compute Cluster Pack Version 1.0.0676.0 is installed

ComputeNode: installed locally

HeadNode: absent

ClientUtils: absent

msmpi.dll version 1.0.676.0

 

-------------------------- HPCA3CN2002 returns 0 --------------------------

Microsoft Compute Cluster Pack Version 1.0.0676.0 is installed

ComputeNode: installed locally

HeadNode: absent

ClientUtils: absent

msmpi.dll version 1.0.676.0

 

-------------------------- HPCA3CN2003 returns 0 --------------------------

Microsoft Compute Cluster Pack Version 1.0.0676.0 is installed

ComputeNode: installed locally

HeadNode: absent

ClientUtils: absent

msmpi.dll version 1.0.676.0

 

-------------------------- HPCA3CN2004 returns 0 --------------------------

Microsoft Compute Cluster Pack Version 1.0.0676.0 is installed

ComputeNode: installed locally

HeadNode: absent

ClientUtils: absent

msmpi.dll version 1.0.676.0

On the head node (which is not configured as a compute node in this cluster), the output is like this:

C:\Documents and Settings\caclark\test>ccsver
Microsoft Compute Cluster Pack Version 1.0.0676.0 is installed
HeadNode: installed locally
ClientUtils: installed locally
ComputeNode: absent

Note that in this case the headnode does not have the "ComputeNode" feature, but it does have the HeadNode feature and the ClientTools feature, whereas the compute node will only have the ComputeNode feature. If I had installed the client tools on some of the compute nodes, it would show that.

No one will this blog entry unless I mention how to find msmpi.dll. On a compute node, this will actually be installed in the system directory, so it's in the path; a normal LoadLibary() call will find it and any programs linked with the msmpi.lib import libary in the CCS SDK will work just fine.

In general, I think it's worth the trouble to add some bits of code to your setup to detect CCS correctly, because some other methods are less reliable. Also, this is perhaps the best way to insure your versions are correct.

I hope this is helpful,

-Calvin

 

Comments (2)