59

ディレクトリをスキャンしていくつかの情報を収集するC#アプリケーションがあります。各ファイルのアカウント名を表示したいのですが。FileInfoオブジェクトのSIDを取得し、次の手順を実行することで、ローカルシステムでこれを行うことができます。

string GetNameFromSID( SecurityIdentifier sid )
{
    NTAccount ntAccount = (NTAccount)sid.Translate( typeof( NTAccount ) );
    return ntAccount.ToString();
}

ただし、これはネットワーク上のファイルでは機能しません。おそらく、Translate()関数はローカルユーザーアカウントでのみ機能するためです。SIDでLDAPルックアップを実行できると思ったので、次のことを試しました。

string GetNameFromSID( SecurityIdentifier sid )
{
    string str = "LDAP://<SID=" + sid.Value + ">";
    DirectoryEntry dirEntry = new DirectoryEntry( str );
    return dirEntry.Name;
}

これは、「dirEntry.Name」へのアクセスがオフになってネットワークにクエリを実行しているように数秒間ハングするという点で機能しているように見えますが、その後System.Runtime.InteropServices.COMExceptionがスローされます。

任意のファイルまたはSIDのアカウント名を取得する方法を知っている人はいますか?ネットワークやLDAPなどについてはよくわかりません。DirectorySearcherというクラスがありますが、これはおそらく私が使用することになっていますが、ドメイン名が必要であり、それを取得する方法もわかりません。スキャンしているディレクトリへのパスだけがあります。

前もって感謝します。

4

10 に答える 10

50

良い答えについては、ここを参照してください。

SID で表示ユーザー名を解決する最良の方法は?

その要点は次のとおりです。

string sid="S-1-5-21-789336058-507921405-854245398-9938";
string account = new System.Security.Principal.SecurityIdentifier(sid).Translate(typeof(System.Security.Principal.NTAccount)).ToString();

このアプローチは、アクティブ ディレクトリ上の非ローカル SID に対して有効です。

于 2009-03-11T23:36:59.803 に答える
19

SecurityReference オブジェクトの Translate メソッドは、ローカル以外の SID でも機能しますが、ドメイン アカウントに対してのみ機能します。別のマシンのローカル アカウントまたは非ドメイン セットアップのアカウントの場合は、ルックアップを実行する必要がある特定のマシン名を指定して、関数 LookupAccountSid を PInvoke する必要があります。

于 2009-02-01T23:24:28.967 に答える
7

System.DirectoryServices.AccountManagement.UserPrincipalクラス ( msdn リンクFindByIdentity) には、SID をユーザー オブジェクトに変換する静的関数があります。ローカル マシンまたは LDAP/Active Directory サーバーの両方に対して機能する必要があります。Active Directoryに対してのみ使用しました。

IIS で使用した例を次に示します。

// Set the search context to a specific domain in active directory
var searchContext = new PrincipalContext(ContextType.Domain, "YOURDOMAIN", "OU=SomeOU,DC=YourCompany,DC=com");
// get the currently logged in user from IIS
MembershipUser aspUser = Membership.GetUser();
// get the SID of the user (stored in the SecurityIdentifier class)
var sid = aspUser.ProviderUserKey as System.Security.Principal.SecurityIdentifier;
// get the ActiveDirectory user object using the SID (sid.Value returns the SID in string form)
var adUser = UserPrincipal.FindByIdentity(searchContext, IdentityType.Sid, sid.Value);
// do stuff to user, look up group membership, etc.
于 2012-07-19T23:42:11.490 に答える
2

ユーザーの言語設定に関係なく機能する次のようなコードを使用して、「Everyone」などの特別なアカウントのアカウント名を取得することもできます。

   SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
   string everyone = everyoneSid.Translate(typeof(System.Security.Principal.NTAccount)).ToString();
于 2015-12-01T05:34:57.333 に答える
1

そうですね、Active Directory環境にいない可能性があるため、LDAP呼び出しが機能していない可能性があります。この場合、各マシンは独自のIDストアを担当します。また、コードを実行しているマシンは、リモートマシンでのみ意味のあるSIDを解決する方法を知らないため、最初のコードサンプルはネットワーク全体で機能していません。

マシンがActiveDirectoryの一部であるかどうかを実際に確認する必要があります。ログオンプロセス中にこれを知っているでしょう。または、[マイコンピュータ]を右クリックして[プロパティ]、[コンピュータ名]タブを選択し、コンピュータがドメインの一部であるかどうかを確認することもできます。

于 2009-02-01T05:50:43.850 に答える
1

偉大な。ここからいくつかの LookupAccountSid() コードを引用しました。

http://www.pinvoke.net/default.aspx/advapi32.LookupAccountSid

ホスト名を自分で指定する必要がありましたが、それはうまくいきました。UNC パスの場合は、その最初のコンポーネントだけを使用できます。マップされたドライブの場合、次のコードを使用してパスを UNC に変換します。

http://www.wiredprarie.us/blog/index.php/archives/22

うまくいくように見えるので、誰かが UNC パスの最初のコンポーネントがホスト名ではないという状況に遭遇しない限り、それが私のやり方です...

ご協力ありがとうございました。

于 2009-02-02T02:15:09.730 に答える
0

これはスタンパーです。あなたはActiveDirectory環境にいますよね?チェックしてるだけ:)

とにかく、sid.Valueでバインドする代わりに、

string str = "LDAP://<SID=" + sid.Value + ">";

SIDのバイト配列をオクテット文字列に変換して、代わりにバインドしてみます。

ここに78ページの良い例があります。これはあなたを近づけるでしょう。正直なところ、私はこれまでSIDでバインドしようとしたことがありません。しかし、私はユーザーのGUIDとのバインドに成功しました:)

頑張って、どうなるか教えてください。

于 2009-01-31T19:08:38.267 に答える
0

現在のドメインを取得します。

System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain();

LDAP とドメイン名からディレクトリ エントリを取得します。

DirectoryEntry de = new DirectoryEntry(string.Format("LDAP://{0}", domain));

ActiveDirectoryMembershipProvider ActiveDirectoryMembershipUser から sid を取得します。

ActiveDirectoryMembershipUser user = (ActiveDirectoryMembershipUser)Membership.GetUser();
var sid = (SecurityIdentifier)user.ProviderUserKey;

SecurityIdentifier からユーザー名を取得します。

(NTAccount)sid.Translate(typeof(NTAccount));

ドメイン ディレクトリ エントリとユーザー名を使用して、アクティブ ディレクトリでディレクトリ検索を実行します。

DirectorySearcher search = new DirectorySearcher(entry);
        search.Filter = string.Format("(SAMAccountName={0})", username);
        search.PropertiesToLoad.Add("Name");
        search.PropertiesToLoad.Add("displayName");
        search.PropertiesToLoad.Add("company");
        search.PropertiesToLoad.Add("homePhone");
        search.PropertiesToLoad.Add("mail");
        search.PropertiesToLoad.Add("givenName");
        search.PropertiesToLoad.Add("lastLogon");
        search.PropertiesToLoad.Add("userPrincipalName");
        search.PropertiesToLoad.Add("st");
        search.PropertiesToLoad.Add("sn");
        search.PropertiesToLoad.Add("telephoneNumber");
        search.PropertiesToLoad.Add("postalCode");
        SearchResult result = search.FindOne();
        if (result != null)
        {
            foreach (string key in result.Properties.PropertyNames)
            {
                // Each property contains a collection of its own
                // that may contain multiple values
                foreach (Object propValue in result.Properties[key])
                {
                    outputString += key + " = " + propValue + ".<br/>";
                }
            }
        }

Active Directory 内のデータに応じて、出力でさまざまな応答が得られます。

必要なすべてのユーザー プロパティを備えたサイトを次に示します。

于 2009-05-17T22:27:25.073 に答える
-4

ここから受け入れられた回答を使用できると確信しています: C# を使用して LocalSystem アカウント名を決定する

基本的に、SecurityIdentifier クラスのインスタンスを NTAccount 型に変換し、そこからユーザー名を取得できます。コード内:

using System.Security.Principal;

SecurityIdentifier sid = new SecurityIdentifier("S-1-5-18");
NTAccount acct = (NTAccount)sid.Translate(typeof(NTAccount));
Console.WriteLine(acct.Value);
于 2009-02-01T10:02:31.333 に答える