Answered How to Pull Local Admin Members from Clients

  • Tuesday, May 15, 2012 6:59 PM
     
     

    Hello everyone!

    I see this topic a lot, and have tried what has been suggested to pull members from my local admin group into a report...with no luck.

    Here's my environment-
    ConfigMgr 2007 SP1 R2
    Mix of XP Pro and Win7 Pro x86 clients(roughly 2300 total)

    I tried Sherry's steps in her latest blog about 7 days ago, yet my Local Members Class fails to appear.

    Just to confirm whats going on here, I...
    1. Run or Distribute this vbScript to all clients(i've ran it on 4 so far)
    2. Followed the steps in creating the baseline and the Config Item.
    3. Append the below to my sms_def.mof at the bottom.
    4. Wait for Machines to cycle.
    5. Create report to pull the new data of the local admin group members

    I don't yet see the class gs_v_localmembers class within ATTRIBUTES in the reports section in order to grab ahold of this data.
    Ay ideas...or any logs that i could submit here to help?

    //=====================Local Group Members, Includes Administrators
    //Pre-requisite: recurring Advertisement, or Recurring DCM Baseline/CI
    //====================================================================
    #pragma deleteclass ("LocalGroupMembers",NOFAIL)
    [ SMS_Report     (TRUE),
      SMS_Group_Name ("LocalGroupMembers"),
      SMS_Class_ID   ("CUSTOM|LocalGroupMembers|1.0") ]
    class cm_LocalGroupMembers : SMS_Class_Template
    {
        [SMS_Report (TRUE), key ] string Account;
        [SMS_Report (TRUE)      ] string Category;
        [SMS_Report (TRUE)      ] string Domain;
        [SMS_Report (TRUE), key ] string Name;
        [SMS_Report (TRUE)      ] string Type;
    };

All Replies

  • Tuesday, May 15, 2012 7:24 PM
    Moderator
     
     Answered

    http://myitforum.com/cs2/blogs/skissinger/archive/2010/04/25/report-on-all-members-of-all-local-groups.aspx

    It's either the vbscript (as an advert) or the vbscript (as a DCM Config Item).  It doesn't need to be both.

    on the machines that ran the script (either way) if you go into...

    wbemtest
    connect...
    root\cimv2
    query...
    select * from cm_localgroupmembers
    Instances
    ARE there instances?  If not, the script didn't run correctly.

    If there are instances... then I suspect you need to "just wait"  :) 

    Re-run a hardware inventory delta (it's probably been long enough now, since adding to sms_def.mof), and monitor inventoryagent.log on that client, and make sure you see a line about ' from cm_localgroupmembers', and that the next line is NOT "does not exist out".

    Oh, and you said you are looking for gs_v_localmembers.  That's not the view it would be.  It would likely be   v_gs_localgroupmembers0.


    Standardize. Simplify. Automate.

  • Thursday, December 06, 2012 5:17 PM
     
     

    My apologies on reviving an old thread...but...

    When running the script...i get an ok box.

    I then tried what Sherry suggested...
    on the machines that ran the script (either way) if you go into...
    wbemtest
    connect...
    root\cimv2
    query...
    select * from cm_localgroupmembers
    Instances
    ARE there instances?  If not, the script didn't run correctly.

    but i only get as far as hitting Query, inputting in select * from cm_localgroupmembers into the Query field..when hitting Apply i get an error- Invalid Query.
    Apparently my script didn't run correctly(but i did recived the OK box when running it.)

    Extreme newbie when it comes to WMI/Scripting so hopefully this is an easy tweak/fix...
    thanks everyone!

    randy

  • Friday, December 07, 2012 1:37 PM
    Moderator
     
     
    I don't remember what I have posted publicly anymore <grin> but in the script, are there any commented out wscript.echo lines?  i.e., 'wscript.echo blah ?

    If so, uncomment them, and run the script interactively, from a cmd prompt as SYSTEM (not as you, not as a human, but as SYSTEM).  See if it echos "stuff" to the screen.  hopefully you can figure out where the script is failing.

    Oh, and remember--this will not ever work on a machine which is a domain controller.  because a DC simply doesn't have local groups.  so if that is your test machine... there's yer problem.  Pick on a member workstation or member server--not a DC.

    Standardize. Simplify. Automate.

  • Monday, December 10, 2012 11:17 PM
     
     

    Hey there - and thanks for replying!

    Yeah, this script will only be targeting Windows 7 Pro x86 boxes(since these are the ones that won't include the user accounts in the local admin group).

    Heres the area of the script that i think you were mentioning to me to comment out...maybe?(i underlined what i thought you meant).

    Set oWMI = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set colComputer = oWMI.ExecQuery _
    ("Select DomainRole from Win32_ComputerSystem")
    For Each oComputer in colComputer
     if (oComputer.DomainRole = 4 or oComputer.DomainRole = 5) then
       wscript.echo "DomainController, So I'm quitting!"
       'wscript.quit
     Else

    and also here...( which i think is ok, maybe)?

    Next
    wscript.echo "ok"

     end if
    Next

    wscript.quit

    I took it out of the first area(wscript.quit) and i got the same...OK box when launching.
    My problem is when using wbemtest in Querying it....i rec'd this.

    and heres the whole script...

    Fon error resume next
    'Steps
    'enumerate from win32_group where localaccount=1
    'Read in the members of each local group returned
    'Add the returned information to a custom WMI namespace
    'sms-def.mof to pull that back.
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set nwo = CreateObject("Wscript.Network")
    Set sho = CreateObject("Wscript.Shell")
    TempFolder = sho.ExpandEnvironmentStrings("%temp%")
    strWindir = sho.ExpandEnvironmentStrings("%windir%")
    strComputer = nwo.ComputerName
    Dim wbemCimtypeSint16
    Dim wbemCimtypeSint32
    Dim wbemCimtypeReal32
    Dim wbemCimtypeReal64
    Dim wbemCimtypeString
    Dim wbemCimtypeBoolean
    Dim wbemCimtypeObject
    Dim wbemCimtypeSint8
    Dim wbemCimtypeUint8
    Dim wbemCimtypeUint16
    Dim wbemCimtypeUint32
    Dim wbemCimtypeSint64
    Dim wbemCimtypeUint64
    Dim wbemCimtypeDateTime
    Dim wbemCimtypeReference
    Dim wbemCimtypeChar16

    wbemCimtypeSint16 = 2
    wbemCimtypeSint32 = 3
    wbemCimtypeReal32 = 4
    wbemCimtypeReal64 = 5
    wbemCimtypeString = 8
    wbemCimtypeBoolean = 11
    wbemCimtypeObject = 13
    wbemCimtypeSint8 = 16
    wbemCimtypeUint8 = 17
    wbemCimtypeUint16 = 18
    wbemCimtypeUint32 = 19
    wbemCimtypeSint64 = 20
    wbemCimtypeUint64 = 21
    wbemCimtypeDateTime = 101
    wbemCimtypeReference = 102
    wbemCimtypeChar16 = 103
    ' Remove classes
    Set oLocation = CreateObject("WbemScripting.SWbemLocator")
    '===================
    'If this is a Domain Controller, bail!
    '===================
    Set oWMI = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set colComputer = oWMI.ExecQuery _
    ("Select DomainRole from Win32_ComputerSystem")
    For Each oComputer in colComputer
     if (oComputer.DomainRole = 4 or oComputer.DomainRole = 5) then
       wscript.echo "DomainController, So I'm quitting!"
       'wscript.quit
     Else
    '==================
    'If it is NOT a domain controller, then continue gathering info
    'and stuff it into WMI for later easy retrieval
    '==================

    Set oServices = oLocation.ConnectServer(,"root\cimv2")
    set oNewObject = oServices.Get("CM_LocalGroupMembers")
    oNewObject.Delete_
    '==================
    'Get the local Group Names
    '==================
    Dim iGroups(300)
    i=0
    Set objWMIService = GetObject("winmgmts:" _
            & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set colGroup = objWMIService.ExecQuery("select * from win32_group where localaccount=1")
    for each obj in colGroup
      igroups(i)=obj.Name
      i=i+1
    next
    '===============
    'Get all of the names within each group
    dim strLocal(300)
    k=0
    Set oLocation = CreateObject("WbemScripting.SWbemLocator")
    Set oServices = oLocation.ConnectServer(, "root\cimv2" )

    'group name, domain name, user or group
    for j = 0 to i-1

    squery = "select partcomponent from win32_groupuser where groupcomponent = ""\\\\" &_
     strComputer & "\\root\\cimv2:Win32_Group.Domain=\""" & strComputer &_
     "\"",Name=\""" &igroups(j) & "\"""""

    Set oInstances = oServices.ExecQuery(sQuery)
     FOR EACH oObject in oInstances
      strLocal(k)=igroups(j) & "!" & oObject.PartComponent

      k=k+1

     Next
    next
    '==================
    'Drop that into a custom wmi Namespace
    '==================


    ' Create data class structure
    Set oDataObject = oServices.Get
    oDataObject.Path_.Class = "CM_LocalGroupMembers"
    oDataObject.Properties_.add "Account" , wbemCimtypeString
    oDataObject.Properties_("Account").Qualifiers_.add "key" , True
    oDataObject.Properties_.add "Domain" , wbemCimtypeString
    oDataObject.Properties_.add "Category" , wbemCimtypeString
    oDataObject.Properties_.add "Type" , wbemCimtypeString
    oDataObject.Properties_.add "Name" , wbemCimtypeString
    oDataObject.Properties_("Name").Qualifiers_.add "key" , True
    oDataObject.Put_

    for m = 0 to k-1
    Set oNewObject = oServices.Get("CM_LocalGroupMembers" ).SpawnInstance_
    str0 = Split(strLocal(m), "!", -1, 1)
    str1 = Split(str0(1), "," , -1, 1)
    str2 = Split(str1(0), "\" , -1, 1)
    str4 = Split(str2(4), Chr(34), -1, 1)


    ' The Account name or Group Name is inside the quotes after the comma
    str3 = Split(str1(1), Chr(34), -1, 1)
    ' if the wmi source name is the same as the domain name inside the quotes, it' s a local account
    ' str2(2) is the wmi source name, str4(1) is the domain name inside the quotes.
    If lcase(str2(2)) = lcase(str4(1)) Then
    oNewObject.Type = "Local"
    Else
    oNewObject.Type = "Domain"
    End If
    oNewObject.Domain = str4(1)
    oNewObject.Account = str3(1)
    oNewObject.Name = str0(0)
    Select Case lcase(str4(0))
      case "cimv2:win32_useraccount.domain="
       oNewObject.Category = "UserAccount"
      Case "cimv2:win32_group.domain="
       oNewObject.Category = "Group"
      Case "cimv2:win32_systemaccount.domain="
       oNewObject.Category = "SystemAccount"
      case else
       oNewObject.Category = "unknown"
    end select
    oNewObject.Put_
    Next
    wscript.echo "ok"

     end if
    Next

    wscript.quit


  • Tuesday, December 11, 2012 11:33 AM
    Moderator
     
     

    I must of removed most of the wscript.echo's that I use in testing / verifying.  Here's where'd I'd throw one in:

    Change this:

    Set oInstances = oServices.ExecQuery(sQuery)
     FOR EACH oObject in oInstances
      strLocal(k)=igroups(j) & "!" & oObject.PartComponent

      k=k+1

     Next
    next

    to something like this:

    Set oInstances = oServices.ExecQuery(sQuery)
     FOR EACH oObject in oInstances

      wscript.echo oObject.PartComponent

      strLocal(k)=igroups(j) & "!" & oObject.PartComponent

      k=k+1

     Next
    next

    and later in the script, change this:

    end select
    oNewObject.Put_
    Next
    wscript.echo "ok"

    to something like...

    end select
    wscript.echo "Domain  " &  str4(1)
    wscript.echo "Account  " & str3(1)
    wscript.echo "Name  " &  str0(0)

    oNewObject.Put_
    Next
    wscript.echo "ok"

    ================

    that will give a starting point of seeing whether it's failing on reading out of WMI (the first part) or parsing what was returned from WMI into logical pieces to be stored in the custom (new) cm_localgroupmembers


    Standardize. Simplify. Automate.

  • Tuesday, December 11, 2012 6:37 PM
     
     

    Awesome Sherry! That was the ticket to get the script to run correctly locally on the workstation i think.
    The script did echo every group and username within every group.

    My ultimate goal is this...

    To have a handle bar in SCCM to query/report against this data of who is in the local admin group(Administrators only).
    And to be able to create a query, select this new attribute class making this the way to have some visibiltiy on our local admins.

    So, if this script now has buzzed out the WMI namespace on any workstation that runs it...can i now -

    1.) Have SCCM be able to pull against these in queries by adding the MOF edit below so it can now inventory these local group members?
    ! MOF file addition that i have already at the bottom of my MOF.
    //=====================Local Group Members, Includes Administrators
    //Pre-requisite: recurring Advertisement, or Recurring DCM Baseline/CI
    //====================================================================
    #pragma deleteclass ("LocalGroupMembers",NOFAIL)
    [ SMS_Report     (TRUE),
      SMS_Group_Name ("LocalGroupMembers"),
      SMS_Class_ID   ("CUSTOM|LocalGroupMembers|1.0") ]
    class cm_LocalGroupMembers : SMS_Class_Template
    {
        [SMS_Report (TRUE), key ] string Account;
        [SMS_Report (TRUE)      ] string Category;
        [SMS_Report (TRUE)      ] string Domain;
        [SMS_Report (TRUE), key ] string Name;
        [SMS_Report (TRUE)      ] string Type;
    };

    2.) Deliver the script to all my clients so that they too can create this handle bar for SCCM to inventory and report/query against.

    In a blind taste test, i went ahead and built a query with this thinking and two test pc's from a few months back(still active though)...see below.
    I added the last user logged on just for kicks.

    Query Criteria(to display members of the adminstrator(s) group, yet weed out the obvious Administrato(r) user.)

    And the results tab-

    Do you think this is a good way to go about getting local admin group members via SCCM?
    Thanks a million Sherry...

    randy

  • Tuesday, December 11, 2012 6:37 PM
     
     

    Criteria Tab.