Solved

Enumerating User Accounts on a Remote Computer using VB.Net/WMI

Posted on 2009-06-29
3
1,342 Views
Last Modified: 2013-11-25
Hello,

I had asked this question earlier.  Please see  http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_24434446.html

The suggestion given in the above PAQ still doesn't work.  Basically what happens I think is that my Select query tries to bring back the User accounts from the entire domain.  What I need is for it to bring back the User accounts ONLY for the remote computer name that I pass in.  I have tried several different WHERE clauses, but nothing seems to work.  I am attaching my code below.  It is VB.Net console application.
Option Strict Off

Imports System.Runtime.InteropServices

Imports System.IO

Imports log4net

Imports System.Configuration

Imports System

Imports System.Management

Imports System.Net.Dns

 

 

'Imports log4net

'Private Shared ReadOnly log As ILog = LogManager.GetLogger(Type.GetType(TestPage1).Name)

 

'Private Shared ReadOnly ILog log Property LogManager.GetLogger(() As =

'End Property

'  System.Reflection.MethodBase.GetCurrentMethod().DeclaringType)

 

'----------------------------------------------------------------

' Converted from C# to VB .NET using CSharpToVBConverter(1.2).

' Developed by: Kamal Patel (http://www.KamalPatel.net) 

'----------------------------------------------------------------

Module Module1

   

    Public MasterDirectory As String = ConfigurationSettings.AppSettings("MasterDirectory")

    Public SubDirectory1 As String = ConfigurationSettings.AppSettings("SubDirectory1")

    Public SubDirectory2 As String = ConfigurationSettings.AppSettings("SubDirectory2")

 

    Public objOS As ManagementObjectSearcher

    Public objCS As ManagementObjectSearcher

    Public objMgmt As ManagementObject

 

 

    'Logger instance {DEBUG,INFO,WARN,ERROR,FATAL,OFF}

    Private ReadOnly log As log4net.ILog = log4net.LogManager.GetLogger("TaskRunnerAccountDiscovery")

 

    Sub Main()

        Dim strDomainName, TaskRunnerServer As String

        Dim strTextFileBldr As New System.Text.StringBuilder

        Dim strCSVBldr As New System.Text.StringBuilder

        Dim arlAccountList As New ArrayList

        Dim bolFoundTaskRunner As Boolean = False

        Dim bolNoInputServers As Boolean = True

 

        Try

            log.Info("Beginning Run")

            log.Info("MasterDirectory: " & MasterDirectory)

 

            Dim arlRuntimeServers As New ArrayList

            Dim arlTextFileServers As New ArrayList

            Dim arlFinalArray As New ArrayList

            Dim arlTotalServersSearched As New ArrayList

            Dim intTaskRunnerServersFound As Integer = 0

 

            Dim strEntry As String

            Dim intNumberOfServers As Integer

            Dim intCounter As Integer = 0

            Dim ss As Integer

 

            

            arlFinalArray.Add("Archtest201")

            arlFinalArray.Add("Archtest301")

 

            If arlFinalArray.Count <= 0 Or arlFinalArray Is Nothing Then

                log.Error("Error: Server arraylist is Empty! -Exiting Program!")

            Else

                intNumberOfServers = arlFinalArray.Count.ToString

                bolNoInputServers = False

                For Each strEntry In arlFinalArray

                    strDomainName = arlFinalArray.Item(intCounter)

                    intCounter = intCounter + 1

                    If intCounter < 26 Then

                        Dim bolIsAccessDenied As Boolean = False

                        arlAccountList = EnumerateLocalAccounts(strDomainName, bolIsAccessDenied)

                        'strAccountInfo = FindAccountsOnServer(strDomainName)

                        'If strAccountInfo <> "Not Available" Then

                        If bolIsAccessDenied Then

                            strTextFileBldr.Append((Trim(strDomainName)).ToString() & "Access is Denied - Unauthorized Access Exception" & vbCrLf)

                        Else

                            If arlAccountList.Count >= 1 Then

                                strTextFileBldr.Append((Trim(strDomainName)).ToString() & vbCrLf)

                                For Each ss In arlAccountList

                                    strTextFileBldr.Append(ss).ToString()

                                    strTextFileBldr.Append(",")

                                Next

                                strTextFileBldr.Append(" " & vbCrLf & vbCrLf)

                                arlTotalServersSearched.Add(strDomainName)

                                bolFoundTaskRunner = FindIfTaskRunnerIsUsed(arlAccountList, strDomainName)

                                If bolFoundTaskRunner Then

                                    intTaskRunnerServersFound += 1

                                    strCSVBldr.Append((Trim(strDomainName)).ToString & vbCrLf)

                                End If

                            End If

                        End If

                    End If

                Next

            End If

            If bolNoInputServers Then

                Exit Sub

            Else

                WriteUserAccountsInfoToOutputFile(strTextFileBldr, arlTotalServersSearched)

                WriteServerNameToOutputFile(strCSVBldr, intTaskRunnerServersFound)

            End If

        Catch ex As Exception

            Console.WriteLine("Error Occurred: " & ex.ToString)

            log.Error("Error: " & ex.Message)

        End Try

 

        'added so the DOS screen won't flash by.... remove this when running program outside of the debugger.

        Console.ReadLine()

 

    End Sub

 

   

    Public Function EnumerateLocalAccounts(ByVal machineName As String, ByRef bolIsAccessDenied As Boolean) As ArrayList

        ''''''bolIsAccessDenied is ByRef

 

        Dim arlArrayOfAccounts As New ArrayList

        Dim strAccount As String

        Dim strDomain As String

 

        'Dim strNumbers As String = "0,1,2,3,4,5,6,7,8,9"

        'Dim strSplitNumbers() As String = Split(strNumbers, ",")

        'Dim i As Integer = 0

 

        ''If this is an IP Address....bypass

        'For i = 0 To strSplitNumbers.GetUpperBound(0)

        '    If machineName.StartsWith(strSplitNumbers(i)) Then

        '        Return arlArrayOfAccounts

        '    End If

        'Next

 

 

              Try

 

            Dim pathMachine As New Management.ManagementPath("\\" & machineName & "\root\cimv2")

 

            Dim scopeRemoteMachine As New Management.ManagementScope(pathMachine)

 

            Dim queryAccounts As New Management.ObjectQuery("SELECT * FROM Win32_Account")

            'Dim queryAccounts As New Management.ObjectQuery("SELECT * FROM Win32_Account where LocalAccount=TRUE")

 

            'Dim queryAccounts As New Management.ObjectQuery("SELECT * FROM Win32_Account where LocalAccount=TRUE And Domain = '" & machineName & "'")

 

            '("Select * from Win32_Account WHERE Domain = '" & domain & "' AND Name = '" & username & "'")

 

            'Dim queryAccounts As New Management.ObjectQuery("SELECT * FROM Win32_Account where MachineName = '" & machineName & "'")

 

 

            Dim searcherAccounts As New Management.ManagementObjectSearcher(scopeRemoteMachine, queryAccounts)

 

            Dim objectAccount As Management.ManagementObject

 

            For Each objectAccount In searcherAccounts.Get

                strAccount = (objectAccount("Name"))

                arlArrayOfAccounts.Add(strAccount)

                'Debug.WriteLine(objectAccount("Name"))

            Next

 

            Return arlArrayOfAccounts

 

        Catch uae As UnauthorizedAccessException

            log.Error("Error occurred on machinename: " & machineName & " - " & uae.Message)

            bolIsAccessDenied = True

 

        Catch ex As Exception

            log.Error("Error occurred: " & ex.Message)

        End Try

 

 

           End Function

 

 

   

   

    Function FindIfTaskRunnerIsUsed(ByVal arlAccountList As ArrayList, ByVal strDomainName As String) As Boolean

        'Dim StringArray() As String

        Dim s As String

        Dim intCounter As Integer = 0

        Dim bolServerHasTaskRunner As Boolean = False

        Try

            '''''' Split the contents of sOutput using System.Environment.Newline as the delimeter.

            'StringArray = Split(sOutput, System.Environment.NewLine)

            Dim intLen As Integer = arlAccountList.Count()

            For Each s In arlAccountList

                intCounter += 1

                If arlAccountList(intCounter).ToUpper.ToString = "TASKRUNNER".ToString Then

                    bolServerHasTaskRunner = True

                    Exit For

                End If

            Next

            Return bolServerHasTaskRunner

        Catch ex As Exception

            log.Error("Error occurred: " & ex.Message)

        End Try

    End Function

 

    Public Function MergeBothArraylists(ByVal arlRuntimeServers, ByVal arlTextFileServers) As ArrayList

        'Private Function MergeArrayLists(ByVal L1 As ArrayList, ByVal L2 As ArrayList) As Hashtable

        'Dim ht As New Hashtable

        'Dim s As String

 

        'For Each s In arlRuntimeServers

        '    If Not ht.ContainsKey(s) Then

        '        ht.Add(s, s)

        '    End If

        'Next

        'For Each s In arlTextFileServers

        '    If Not ht.ContainsKey(s) Then

        '        ht.Add(s, s)

        '    End If

        'Next

        'Return ht

 

        Dim arl As New ArrayList

        Dim s As String

 

        For Each s In arlRuntimeServers

            If Not arl.Contains(s) Then

                arl.Add(s)

            End If

        Next

        For Each s In arlTextFileServers

            If Not arl.Contains(s) Then

                arl.Add(s)

            End If

        Next

        arl.Sort()

        Return arl

    End Function

 

    Public Function ReadTextFile() As ArrayList

 

        Dim TextFileLocation As String = ConfigurationSettings.AppSettings("TextFileLocation")

        Dim arlArray As New ArrayList

        Dim oFile As System.IO.File

        Dim oRead As System.IO.StreamReader

        'oRead = oFile.OpenText("C:\sample.txt")

        oRead = oFile.OpenText(TextFileLocation)

 

 

        While oRead.Peek <> -1

            arlArray.Add(oRead.ReadLine())

        End While

        oRead.Close()

 

        Return arlArray

 

    End Function

 

    Public Function WriteFile( _

    ByVal FileName As String, _

    ByVal SubDirectory As String, _

    ByVal strFileContent As String _

)

        Try

 

            Dim objReader As StreamWriter

            If Not Directory.Exists(MasterDirectory & "\" & SubDirectory) Then

                Directory.CreateDirectory(MasterDirectory & "\" & SubDirectory)

            End If

            Dim fullpath As String = MasterDirectory & "\" & SubDirectory & "\" & FileName

            objReader = New StreamWriter(fullpath)

            objReader.Write(strFileContent)

            objReader.Close()

 

        Catch Ex As Exception

            log.Error("Error: " & Ex.ToString)

        End Try

    End Function

 

    Public Function WriteServerNameToOutputFile(ByVal strStringBldr As System.Text.StringBuilder, ByVal intRows As Integer)

 

        '''''''' This function writes a unique file for each run (e.g. TaskRunnerServersMMDDYYYY HH MM AM/PM.CSV) in a directory called 'CSVFiles' within the

        '''''''' MasterDirectory.  

        ''''''''

 

        Try

            Dim output, filename As String

            output = output & "Total Number of  Servers Searched: " & intRows.ToString & vbCrLf

            output = output & strStringBldr.ToString()

            filename = "TaskRunnerServers" & Now.ToShortDateString & " " & Now.ToShortTimeString & ".txt"

            filename = filename.Replace(":", " ")

            filename = filename.Replace("/", "")

            WriteFile(filename, SubDirectory2, output)

        Catch ex As Exception

            log.Error("Error occurred: " & ex.Message)

        End Try

 

    End Function

 

    Public Function WriteUserAccountsInfoToOutputFile(ByVal strTextFileRowBldr As System.Text.StringBuilder, ByVal arlTotalServersSearched As ArrayList)

        ''''''''

        '''''''' This function writes a unique file for each run (e.g. UserAccountInfoMMDDYYYY HH MM AM/PM.CSV) in a directory called 'CSVFiles' within the

        '''''''' MasterDirectory.  

        ''''''''

        Dim strBldrToString As String = strTextFileRowBldr.ToString()

        Dim intRows As Integer = arlTotalServersSearched.Count()

 

        Try

            Dim output, filename As String

            output = output & "Total Number of  Servers that use TaskRunner Account: " & intRows.ToString & vbCrLf

            'output = output & strTextFileRowBldr.ToString()

            output = output & strBldrToString

            filename = "UserAccountInfo" & Now.ToShortDateString & " " & Now.ToShortTimeString & ".txt"

            filename = filename.Replace(":", " ")

            filename = filename.Replace("/", "")

            WriteFile(filename, SubDirectory1, output)

        Catch ex As Exception

            log.Error("Error occurred: " & ex.Message)

        End Try

    End Function

 

 

 

 

 

 

End Module

Open in new window

0
Comment
Question by:msyed1
3 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 24746712
If the remote machine is a domain controller, then I don't think that there is a distinction between local and domain user names...
0
 

Author Comment

by:msyed1
ID: 24757313
TheLearnedOne:  The remote machine is NOT a domain controller.  As you can see in my Sub Main, I have (for the sake of testing) hard-coded the machine names I am passing in to two test servers we have:

arlFinalArray.Add("Archtest201")
arlFinalArray.Add("Archtest301")

Is there a way I can change the query to find out if a certain user account (in my case a user account called 'taskrunner' is defined on the machine ??  That is all I am trying to do.  I have a list of machine names in an arraylist.  I need to determine which machines have the 'taskrunner' account defined on them....then what I have to do is to change the password of that user account.....but so far I haven't been able to find out which machines have 'taskrunner' account defined.  Hope you can help me. msyed1.
 
0
 
LVL 13

Accepted Solution

by:
lciprianionut earned 500 total points
ID: 24757610
Here is the code you are looking for with some modification of course.
The script is search on local computer the local admin by SID, then search id there are any services that run under that account, change the password of the account and rename it.
To fit to your needs just replace
Set colAccountItems = objWMIService.ExecQuery ("Select * From Win32_UserAccount Where Domain='" & strComputer & "'")
with
 Set colAccountItems = objWMIService.ExecQuery ("Select * From Win32_UserAccount Where Domain='" & strComputer & "' and Name='taskrunner'")

Get-User.txt
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

3 Tips For Quarter Milers: A Sprinter's Understanding of Agile Software Development Two years ago, I wrote a blog entry about Agile software development (http://www.experts-exchange.com/blogs/mwvisa1/B_1770-Agile-Software-Development.html). At th…
Agile and Scrum have almost become synonymous. Have you wondered what's the difference? Scrum is just one way to be Agile. It is the most popular which leads to the common confusion. Agile actually refers to a philosophy shared by group of developme…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now