Roger Zander at myITforum.com

August 2008 - Posts

How to create a C# WMI-Provider

Creating a WMIProvider in C# using the WMI Provider Extension from .NET Framework 3.5 is not a big thing and it requires only a few additional lines of code.
A lot of SMS/SCCM administrators do have the requirement to inventory the members of the local administrators group, that’s why I will do an example for this scenario, but it can be easy adapted to report whatever you want….

First at all: If you do not have .NET 3.5 SP1, you should first register the “System.Management.Instrumentation.dll” as described in How to: Fix Provider Load Failure Error.

1.  Create a new Class Library Project in VS2008 and verify the project is using the .NET Framework 3.5.

2.  Add the “System.Management.Instrumentation” namespace to the references and to the using directives:
using System.Management.Instrumentation;

3.  Above the Namespace keyword, you have to declare the WMI Namespace which should contain our new dynamic WMI Class:
[assembly: WmiConfiguration(@"root\cimv2", HostingModel = ManagementHostingModel.LocalService)]
In our case, the provider must be able to enumerate all local administrators, that’s why I'm using the “Local Service” security context.

4.   You have to tag the C# Class to provide WMI informations and you have to specify the WMI Class Name:
[ManagementEntity(Name = "Win32_LocalAdmins")]

The complete code looks now like this:
using System;

using System.Collections.Generic;

using System.Text;

using System.Management.Instrumentation;

 

[assembly: WmiConfiguration(@"root\cimv2", HostingModel = ManagementHostingModel.LocalService)]

namespace ClassLibrary1

{

    [ManagementEntity(Name = "Win32_LocalAdmins")]

    public class Class1

    {

    }

}

5.  Now, you have to declare the attributes of our “Win32_LocalAdmins” WMI Class. Let’s create three Attributes:  the Name of the local admin group members, the Type (User or Group) and the SID. The “Member” attribute will become a Key property:
 [ManagementEntity(Name = "Win32_LocalAdmins")]
    public class Class1
    {
        [ManagementKey]
        public string Member { get; set; }
        [ManagementProbe]
        public string Type { get; set; }
        [ManagementProbe]
        public string SID { get; set; }
    }

6.  To fill up the class with values, we need to define a Constructor:
     public Class1(string sMember, string sGUID, string sType)
        {
            Member = sMember;
            SID = sGUID;
            Type = sType;
        }

7.   The missing part now is the code which will be executed if the WMI Class is enumerated. So you have to declare a function of the type IEnumerable:
[ManagementEnumerator]
static public IEnumerable GetAdmins()
{ // GetAdmin Code }
The code should create new instances of Class1 for each member of the local adming group by using the Constructor of Class1:
return new Class1(Name, SID, Type)

Note: Download the attached VS2008 Project to see the complete code behind "GetAdmins()".
 
That’s all you need to create a dynamic WMI Class ... But how to Install the WMIProvider ?  
You have to create an Installer class and it would make sense to provide a way to uninstall the „Win32_LocalAdmins“ class:

    [System.ComponentModel.RunInstaller(true)]
    public class MyInstall : DefaultManagementInstaller
    {
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            System.Runtime.InteropServices.RegistrationServices RS = 
                new System.Runtime.InteropServices.RegistrationServices();
        }

        public override void Uninstall(IDictionary savedState)
        {
            try
            {
                ManagementClass MC = 
                    new ManagementClass(@"root\cimv2:Win32_LocalAdmins");
                MC.Delete();
            }
            catch { }
            try
            {
                base.Uninstall(savedState);
            }
            catch { }
        }
    }

Now, you have to copy the library to the Global Assembly Cache by using the Command:
gacutil.exe /i „<Path>\classlibrary1.dll“

The WMIProvider can now be installed with the command:
InstallUtil.exe /i “<Path>\classlibrary1.dll”

Both last manual actions can be easy integrated in a Windows Installer Setup Project.

 

Done... If you start "wmic.exe path win32_LocalAdmins" you should get a list with all the members of your local administrators group:
wmic:root\cli>path Win32_LocalAdmins
Member         SID                                            Type
Administrator  S-1-5-21-3333231195-3254942849-1953328938-500  User

 

The complete VS2008 Project can be downloaded at:

http://myitforum.com/cs2/blogs/rzander/LocalAdminWMIProvider.zip

Posted: Aug 12 2008, 02:25 PM by rzander | with 2 comment(s)
Filed under: , ,
SMS/SCCM Command-line Actions

WMIC is a very powerful but rarely used tool to manage WMI from Command-line and it's part of the Operating-system since WindowsXP.... !

Some examples to trigger SMS/SCCM Client Actions from command line:

Disable Software-Distribution:
WMIC /namespace:\\root\ccm\policy\machine\requestedconfig path ccm_SoftwareDistributionClientConfig  CREATE ComponentName="Disable SWDist",Enabled="false",LockSettings="TRUE",PolicySource="local",PolicyVersion="1.0" ,SiteSettingsKey="1" /NOINTERACTIVE

Re-Activate Software-Distribution:
WMIC /namespace:\\root\ccm\policy\machine\requestedconfig path ccm_SoftwareDistributionClientConfig  WHERE ComponentName="Disable SWDist" delete /NOINTERACTIVE

Trigger Hardware Inventory:
WMIC /namespace:\\root\ccm path sms_client CALL TriggerSchedule "{00000000-0000-0000-0000-000000000001}" /NOINTERACTIVE

Trigger Software Inventory:
WMIC /namespace:\\root\ccm path sms_client CALL TriggerSchedule "{00000000-0000-0000-0000-000000000002}" /NOINTERACTIVE

Trigger DataDiscoverRecord (DDR) update:
WMIC /namespace:\\root\ccm path sms_client CALL TriggerSchedule "{00000000-0000-0000-0000-000000000003}" /NOINTERACTIVE

Force a FULL HW Inventory on next HW-Inv Schedule:
WMIC /namespace:\\root\ccm\invagt path inventoryActionStatus where InventoryActionID="{00000000-0000-0000-0000-000000000001}" DELETE /NOINTERACTIVE

Repair SMS/SCCM Agent on a remote client:
WMIC /node:%MACHINE% /namespace:\\root\ccm path sms_client CALL RepairClient

Repair a list (all clients listed in clients.txt) of remote SMS/SCCM Agents:
WMIC /node:@clients.txt /namespace:\\root\ccm path sms_client CALL RepairClient

Posted: Aug 11 2008, 01:37 PM by rzander | with 1 comment(s)
Filed under: ,
SCCM2007 DCM Reporting Issue in Multi-Language environments

In SCCM2007, the Configuration Baselines or Items do store the LocaleID (Language Code) from the System where they are created.
If you have the SCCM Admin Console installed on a System with a different OS Language than the language of SCCM on the Primary Server, be aware that Configuration Baselines and Items created on that System will not work properly (mainly Web-Reporting)...

Most of the DCM Reports are linked with the View "v_LocalizedCIProperties_SiteLoc" which does lookup for ConfigItems with the same LocaleID as on the SCCM Server.
SQL statement of v_LocalizedCIProperties_SiteLoc:
select loc.*
from SMSData sms
cross apply fn_LocalizedCIProperties(sms.LocaleID) loc

The View will not report instances if the CI's do have a different LocaleID.

 Workaround1:
Change the Queries of the DCM reports to use the view "v_LocalizedCIProperties" instead of "v_LocalizedCIProperties_SiteLoc"...

Workaround2:
Change the LocaleID of the CI's by editing the SQL table "CI_LocalizedProperties" to the same LocaleID as in dbo.SMSData.LocaleID....

Workaround3:
Modify the CI's (like changing the name) with the Admin Console on the SCCM Server (this will create an additional object in dbo.CI_LocalizedProperties)...

Posted: Aug 05 2008, 06:17 PM by rzander | with no comments
Filed under:
(SCCM2007) Move SMSPKGSIG Directory to another drive

SCCM2007 creates a folder "SMSPKGSIG" on the drive where the SCCM ProgramFiles are installed.
To move the folder to another drive, you have to do the following actions:

  • Stop all SCCM related services (SMS_EXECUTIVE, SMS_SITE_COMPONENT_MANAGER, SMS_SITE_VSS_WRITER)
  • Edit the registry key: HKLM\SOFTWARE\Microsoft\SMS\Components\SMS_DISTRIBUTION_MANAGER\Signature Manager\SignatureRepository = <NewDrive>:\SMSPKGSIG
  • Move the folder SMSPKGSIG to the new drive
  • Start the SCCM services (SMS_SITE_VSS_WRITER, SMS_SITE_COMPONENT_MANAGER, SMS_EXECUTIVE, SMS_SITE_VSS_WRITER)

Note: Do not move the "SMSSIG$" folder, this procedure is only for the "SMSPKGSIG" folder...
Caution: This is not an official/supported procedure... implementation at your own risk !!!

Posted: Aug 05 2008, 03:32 PM by rzander | with no comments
Filed under: