VB.NET:ADからフルネームを取得

私はユーザーID "domain \ usarname"を与えられたユーザーの完全な名前を取得しようとしています。いくつかの異なる例を試してみましたが、うまくいかないようです。 私はVisual Basic .NETを使用しています。

私はもともとVBSで次のコードを見つけ、VBAに移植してうまくいきました。 VB.NET 2010で同じコードを使用しようとすると、複数のエラーが発生し、手動で入力してもLDAPパスが見つかりません。

Function FindUser()
 On Error GoTo Err

 Dim objRoot As Variant
 Dim LDAPdomainName As String
 Dim UserName As String
 Dim UserDomain As String

 Dim cn As Variant
 Dim cmd As Variant
 Dim rs As Variant


UserName = VBA.Environ("UserName") ' Gets Current User
UserDomain = VBA.Environ("UserDomain") 'Gets Current User's Domain


Set objRoot = GetObject("LDAP://RootDSE")
Domain= objRoot.Get("defaultNamingContext") 



 Set cn = CreateObject("ADODB.Connection")
 Set cmd = CreateObject("ADODB.Command")
 Set rs = CreateObject("ADODB.Recordset")

 cn.Open "Provider=ADsDSOObject;"

 cmd.activeconnection = cn
 'cmd.commandtext = "SELECT ADsPath FROM 'LDAP://" & Domain & "' WHERE sAMAccountName = '" & UserName & "'"
 'To see all attributes names available, connect with Active Directory Explorer and add to Select.
 cmd.commandtext = "SELECT cn, mail  FROM 'LDAP://" & Domain & "' WHERE sAMAccountName = '" & UserName & "'"
 Set rs = cmd.Execute


 Do Until rs.EOF
    Debug.Print rs("cn") & " E-mail: " & rs("mail")
    rs.MoveNext
 Loop


Exit_Err:
 If Not rs Is Nothing Then rs.Close
 If Not cn Is Nothing Then cn.Close
 Set rs = Nothing
 Set cmd = Nothing
 Set cn = Nothing
 Exit Function

Err:
 If Err <> 0 Then
    MsgBox "Error connecting to Active Directory Database: " & Err.Description
 Else
    If Not rs.BOF And Not rs.EOF Then
        rs.MoveFirst
        MsgBox rs(0)
    Else
        MsgBox "Not Found"
    End If
 End If
 Resume Exit_Err


End Function
1
これまでに何を試しましたか?これまでにテストしたコードをいくつか追加する必要があります。既に検討していることは提案しません。
追加された 著者 Matthieu,
さて、彼が試したことは働いていないので、うまくいくものは有効な提案です。
追加された 著者 Yatrix,

4 答え

.NET 3.5以降であれば、 System.DirectoryServices.AccountManagement (S.DS.AM)名前空間をチェックアウトする必要があります。ここでそれについてすべて読む:

基本的には、ドメインコンテキストを定義して、AD内のユーザーやグループを簡単に見つけることができます。

' set up domain context
Dim ctx As New PrincipalContext(ContextType.Domain)

' find a user
Dim user As UserPrincipal = UserPrincipal.FindByIdentity(ctx, "domain\username")

' do something here....     
If user IsNot Nothing Then
End If

' find the group in question
Dim group As GroupPrincipal = GroupPrincipal.FindByIdentity(ctx, "YourGroupNameHere")

' if found....
If group IsNot Nothing Then
    ' iterate over members
    For Each p As Principal In group.GetMembers()
            ' do whatever you need to do to those members
        Console.WriteLine("{0}: {1}", p.StructuralObjectClass, p.DisplayName)
    Next
End If

新しいS.DS.AMにより、ADのユーザーやグループと一緒に遊ぶのが本当に簡単になります!

3
追加された
ctxで新しいPrincipalContext(ContextType.Domain)としてLdap例外が発生しました。処理されなかったエラーメッセージ:「接続を確立できません」
追加された 著者 Rick,

何について:

Imports System.DirectoryServices.AccountManagement

     

Dim userFullName As String = UserPrincipal.Current.DisplayName

3
追加された

私はこれを.Net 2.0から.Net 4.0に至るまで手助けしてくれた2つの機能を持っています MSDNを一見した後、これは.Netランタイムのすべてのバージョンで動作するはずです。

2つの機能は次のとおりです。


'Determines your domain name
Private Function DomainName() As String
    Dim objRootDSE As New System.DirectoryServices.DirectoryEntry("LDAP://RootDSE")
    DomainName = objRootDSE.Properties("defaultNamingContext")(0)
End Function

'Will output user first name and last name. 
Public Sub ReturnUserName(ByVal UserAccountName As String)
    ' add a reference to System.DirectoryServices.dll
    Dim srch As System.DirectoryServices.DirectorySearcher
    Dim result As System.DirectoryServices.SearchResult
    Dim de, dir As System.DirectoryServices.DirectoryEntry

    de = New System.DirectoryServices.DirectoryEntry("LDAP://" & DomainName())
    srch = New System.DirectoryServices.DirectorySearcher(de)

    srch.SearchScope = SearchScope.Subtree
    srch.PropertiesToLoad.Add("givenName")
    srch.PropertiesToLoad.Add("sn")

    'Other field examples:
    'srch.PropertiesToLoad.Add("distinguishedName")
    'srch.PropertiesToLoad.Add("uid")

    ' users require both "user" and "person" filters
    ' and we also add the sAMAccountName to get the user passed.
    ' If you want to return all users in the domain remove the (sAMAccountName=" & UserAccountName & ")
    ' from the filter below.
    srch.Filter = "(&(objectClass=user)(objectCategory=person)(sAMAccountName=" & UserAccountName & "))"

    For Each result In srch.FindAll()
        dir = result.GetDirectoryEntry
        ' Properties are case sensitive!
        Debug.WriteLine(dir.Properties("givenname").Value & " " & dir.Properties("cn").Value)
    Next
End Sub

この例の呼び出しは次のようになります。


Public Sub TestUserCall()
    'Returns the current logged in user.
    Call ReturnUserName(System.Security.Principal.WindowsIdentity.GetCurrent.Name)
End Sub

この例の呼び出しは、ランタイムバージョン2.0から4.0で確実に動作し、これまでにリリースされたすべてのバージョンで動作するはずです 。

関連するMSDNページは次のとおりです。

http:///msdn.microsoft.com/en-us/library/system.security.principal.windowsidentity.name(v=VS.100).aspx

http://msdn.microsoft.com/en -us/library/94se97ay(v = VS.80).aspx

http://hdc.co.jp com/ja-ja/library/system.directoryservices.directoryentry(v = VS.80).aspx

http://msdn.microsoft。 com/ja-ja/library/system.directoryservices.searchresult(v = VS.80).aspx

1
追加された
"DomainName = objRootDSE.Properties(" defaultNamingContext ")(0)" COMExceptionが発生しました。処理できなかったエラーが発生しました: "ネットワークパスが見つかりませんでした。
追加された 著者 Rick,
完全なホスト名、さらにはIPアドレスでネットワーク上のすべての異なるDNSサーバーに変更しようとしましたが、同じエラーが発生します。
追加された 著者 Rick,
私はWindows Server 2008上で動作するメインのドメインコントローラを指していました。
追加された 著者 Rick,
あなたのマシンがドメインサーバーを返さないかもしれない何らかの理由しか考えられません。 "LDAP:// RootDSE"をドメインサーバーのDNSである "LDAP://server.com/RootDSE" server.comに置き換えてみてください。
追加された 著者 Mako Steel,
これは、DomainName()サブミットの最初の行をDim objRootDSEとして新しいSystem.DirectoryServices.DirectoryEntry( "LDAP://server.com/R‌ ootDSE")server.comに置き換える必要があります。
追加された 著者 Mako Steel,
ドメインコントローラはどのバージョンのOSで動作していますか? Windows Server 2003の疑いがありますか?
追加された 著者 Mako Steel,
ちょうどあなたがDNSサーバを見ようとしていることに気づいただけです。コマンドプロンプトを開いて「set logonserver」と入力すると、DCのUNC名が表示され、server.comの代わりにそのアドレスを指定することで、アドレスを見つけることができます"\\"のない文字列
追加された 著者 Mako Steel,
これまでにこのようなことが起こることはありませんでした。答えを提供する他の投稿だけが悲しいことに、悲しいことに、むしろうつ病です。 social.msdn.microsoft.com/Forums/en/netfxnetcom/thread/…
追加された 著者 Mako Steel,

この種のタスクを実行するには、 System.DirectoryServices 名前空間を使用します( DirectoryServicesはLDAP用の管理されたラッパーです)。

Try
   ' Bind to the users container.
    Dim entry As New 
          DirectoryEntry("LDAP://CN=users,DC=fabrikam,DC=com")

    ' Create a DirectorySearcher object.
    Dim mySearcher As New DirectorySearcher(entry)

    ' Create a SearchResultCollection object to hold a collection
    ' of SearchResults returned by the FindAll method.
    Dim result As SearchResultCollection = mySearcher.FindAll()

    ' Create an object to hold a single result from the 
    ' result collection.
    Dim resEnt1 As SearchResult

    ' Get search results. For more information, 
    ' see Getting Search Results.
    ' 
    ' This sample uses Try...Catch to catch errors.
    ' Create an Exception object. For more information, 
    ' see System.Exception.

Catch Exception1 As System.Runtime.InteropServices.COMException
    Console.WriteLine(Exception1.Message)

Catch Exception2 As InvalidOperationException
    Console.WriteLine(Exception2.Message)

Catch Exception3 As NotSupportedException
    Console.WriteLine(Exception3.Message)

End Try 

You can use a search string such as "(&(objectCategory=user)(objectClass=person)(sAMAccountName=" + userId + "))" to search for a user (userID would need to be replaced with the User's ID).

すべてをまとめて結合するには、以下のスニペットを修正してユーザーのすべてのプロパティを表示します。ユーザー名にのみフォーカスするように調整できます。

Dim results As SearchResultCollection = Nothing

Try
    ' Bind to the users container.
    Dim path As String = "LDAP://CN=users,DC=fabrikam,DC=com"
    path = "LDAP://CN=Users,DC=strohmadom,DC=nttest,DC=microsoft,DC=com"
    Dim entry As New DirectoryEntry(path)

    ' Create a DirectorySearcher object.
    Dim mySearcher As New DirectorySearcher(entry)

    ' Set a filter for users with the name test.
    mySearcher.Filter = "(&(objectClass=user)(anr=test*))"

    ' Use the FindAll method to return objects to a SearchResultCollection.
    results = mySearcher.FindAll()

    ' Iterate through each SearchResult in the SearchResultCollection.
    Dim searchResult As SearchResult
    For Each searchResult In results
        ' Display the path of the object found.
        Console.WriteLine("Search properties for {0}", _
            searchResult.Path)

        ' Iterate through each property name in each SearchResult.
        Dim propertyKey As String
        For Each propertyKey In searchResult.Properties.PropertyNames
            ' Retrieve the value assigned to that property name 
            ' in the ResultPropertyValueCollection.
            Dim valueCollection As ResultPropertyValueCollection = searchResult.Properties(propertyKey)

            ' Iterate through values for each property name in each SearchResult.
            Dim propertyValue As Object
            For Each propertyValue In valueCollection
                ' Handle results. Be aware that the following 
                ' WriteLine() only returns readable results for 
                ' properties that are strings.
                Console.WriteLine("{0}:{1}", _
                    propertyKey, _
                    propertyValue.ToString())
            Next propertyValue
        Next propertyKey
    Next searchResult
Finally
    ' To prevent memory leaks, always call 
    ' SearchResultCollection.Dispose() manually.
    If Not results Is Nothing Then
        results.Dispose()
        results = Nothing
    End If
End Try
0
追加された
"results = mySearcher.FindAll()"の行で "ネットワークパスが見つかりませんでした"というエラーが表示されます。私はLDAPパス文字列をLDAPサーバーに置き換えました。
追加された 著者 Rick,