'----------------------------------------------------------------------------------------------+
'               MY SMALL COLLECTION OF VB.NET FUNCTIONS THAT MAY HELP OTHERS
'----------------------------------------------------------------------------------------------+

' DIRECTLY READING THE 'member' PROPERTY HAS A LIMIT OF 1500 USERS FOR ACTIVE DIRECTORY 2003
' AND 1000 USERS FOR ACTIVE DIRECTORY 2000. THIS GETS THE FULL LIST OF GROUP MEMBERS.

Public Function LdapGroupMembers(ByVal ldapPath As String) As ArrayList

    Dim groupMembers As New ArrayList

    Dim searcher As New System.DirectoryServices.DirectorySearcher()
    searcher.SearchRoot = New System.DirectoryServices.DirectoryEntry(ldapPath)

    Dim rangeStart = 0
    Dim rangeEnd = 999
    Dim rangeFinished = False

    Do
        Dim rangeKey = "member;range=" & rangeStart & "-" & rangeEnd

        searcher.PropertiesToLoad.Clear()
        searcher.PropertiesToLoad.Add(rangeKey)

        Dim result As System.DirectoryServices.SearchResult
        result = searcher.FindOne()

        If Not result.Properties.Contains(rangeKey) Then
            rangeKey = "member;range=" & rangeStart & "-*"
            If Not result.Properties.Contains(rangeKey) Then Exit Do
            rangeFinished = True
        End If

        groupMembers.AddRange(result.Properties(rangeKey))

        rangeStart = rangeEnd + 1
        rangeEnd = rangeEnd + 1000

    Loop Until rangeFinished = True

    Return groupMembers

End Function

' CONVERT System.__ComObject AKA IADsLargeInteger TO Int64
' READ VALUES SUCH AS LastLogon LastLogoff WhenCreated WhenModified
' WITHOUT NEEDING DirectorySearcher TO DO THE CONVERSION

Public Function LdapGetInt64(ByRef attribute As Object) As Object

    Try
        Dim highPart As Int64 = attribute(0).HighPart
        Dim lowPart As Int64 = attribute(0).Lowpart
        Dim total As Int64 = (highPart * 2 ^ 32) + lowPart
        Return total
    Catch ex As Exception
        Return "LdapGetInt64: FAILED"
    End Try

End Function

' CONVERT Int64 TICKS INTO A DATE FORMATTED STRING

Public Function ConvertTicksToDate(ByVal timeTicks As Int64) As String

Try
        Return DateTime.FromFileTime(timeTicks)
    Catch ex As Exception
        Return "ConvertTicksToDate: FAILED"
    End Try

End Function

' GET THE PASSWORD MAX AGE FOR A DOMAIN

Public Function LdapGetMaxPwdAge(ByRef domain As Object) As Object

    Try
        Dim attribute = domain.Properties("maxPwdAge")
        Dim highPart As Int64 = attribute(0).HighPart
        Dim lowPart As Int64 = attribute(0).Lowpart
        Dim total As Int64 = (highPart * 2 ^ 32) + lowPart
        total = total / -864000000000
        If total < 10000 Then Return total
        Return "LdapGetMaxPwdAge: NOT SET ON DOMAIN"
    Catch ex As Exception
        Return "LdapGetMaxPwdAge: FAILED"
    End Try

End Function

' SIMILAR TO Application.StartupPath BUT ALSO WORKS FOR CONSOLE APPLICATIONS.

Public Function ApplicationPath() As String

    Return System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)

End Function

Public Function ApplicationName() As String

    Return System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location)

End Function

' SIMPLE TIME STAMPED LOG FILE

Public Sub LogEvent(ByVal output As String)

    Try
        output = Format(Date.Now, "[yyyy-MM-dd HH:mm:ss] ") & output
        IO.File.AppendAllText(System.Reflection.Assembly.GetExecutingAssembly().Location & ".LOG", output & vbCrLf)
    Catch
    End Try

End Sub

' RUN A COMMAND LINE PROGRAM AND READ IN ITS OUTPUT

Public Function ShellOutput(ByVal programPath As String, Optional ByVal programArguments As String = "") As String

    Dim process As New Process()
    process.StartInfo.FileName = programPath
    process.StartInfo.Arguments = programArguments
    process.StartInfo.UseShellExecute = False
    process.StartInfo.RedirectStandardError = True
    process.StartInfo.RedirectStandardInput = True
    process.StartInfo.RedirectStandardOutput = True
    process.StartInfo.ErrorDialog = False
    process.StartInfo.CreateNoWindow = True
    process.StartInfo.LoadUserProfile = False
    process.Start()

    Return process.StandardOutput.ReadToEnd

End Function

' SHORTCUT TO BASE64 CONVERSIONS

Public Function StringToBase64(ByVal text As String) As String

    Return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text))

End Function

Public Function Base64ToString(ByVal base64 As String) As String

    Return System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(base64))

End Function

' IPv4 ADDRESS CHECKS AND CONVERSIONS

Public Function IsIpAddress(ByVal ipAddress As String) As Boolean

    If New System.Text.RegularExpressions.Regex("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").Match(ipAddress).Success = False Then Return False
    Return System.Net.IPAddress.TryParse(ipAddress, Nothing)

End Function

Public Function IpToInt64(ByVal ipAddress As String) As Int64

    Dim ipBytes = ipAddress.Split(".")
    Return (ipBytes(0) << 24) Or (ipBytes(1) << 16) Or (ipBytes(2) << 8) Or (ipBytes(3))

End Function

Public Function Int64ToIp(ByVal ipAddress As Int64) As String

    Return System.Net.IPAddress.Parse(ipAddress.ToString).ToString

End Function

Public Function IpToScope(ByVal ipAddress As String, ByVal subnetMask As String) As String

    Return Int64ToIp(IpToInt64(ipAddress) And IpToInt64(subnetMask))

End Function

Public Function HostToIP(ByVal hostName As String) As String

    Try
        Return System.Net.Dns.GetHostAddresses(hostName)(0).ToString()
    Catch ex As Exception
        Return ""
    End Try

End Function