QA@IT

C#でNW上のPCに誰がログインしているかを取得するには

8575 PV

お世話になります。
VS2008のC#で、Windowsフォームアプリケーションを作っています。

同じドメイン内のPCに対して、IPやホスト名の情報から、
「現在どのユーザがそのPCにログインしているか」
を取得する方法はないでしょうか。

「そのアプリケーションを実行しているユーザ」
のIDの取得方法はわりと載っているのですが、
ネットワーク越しに取得する方法が見つかりません。

対象PCのOSはWinXPSP3とWin7SP1が混在しています。
ご返答よろしくお願いいたします。

  • 今回は「NetEnum」というツールを使い、取得したものをテキストに書き出し、それをインポートする方法を使うことにしました。

    ただやはり手間が増えてしまうので、引き続きご意見を募集させていただきます。
    -
  • で、どうなりました? -
  • 正直なんとお答えすればいいかがわかりません。「ユーザー資格情報はローカル接続には使用できません」というエラーが出て、もちろん資格周りだろうと考えて調べた結果わからなかったのでそこまで書き込みました。
    しかし、「理解しましょう」と書かれていましたので、手の打ちようがなくなりました。
    -
  • とはいえこのように書けば決してそんなつもりはなくても「わからないことを盾に開き直った」と思われるかもしれませんし、かといって「難しすぎるので諦めます」と書くのも、ここまで色々してくださったのに諦めが早いと思われ不快になるかもしれません。と考えているうちに何も書けなくなりました。

    こういう時ってどう書けば一番失礼になりませんか?
    -
  • 「こうすれば出来ると思ったことを、このようにすると、このような結果となった。期待と実際の差異はこれこれ。この結果から、こう考える」と言うことを書いてくだされば、全く失礼ではありません。 -
  • 「つまり、これから接続するのがローカルなのかどうか、判定が必要です。」と書いていますが、それについては?(遅レス失礼。ここに書くと、私にはメールされないのね) -
  • なお、この件については、質問を見てから調べはじめました。WMI で出来ると知ってはいましたが、コードは上げた日に作ったもので、同じエラーを見ています。 -
  • 何度もご返答ありがとうございます。まず上の方で「資格周りを調べた」とさらっと書きましたが、WMIは全く使ったことがなく、そもそもどこが「資格周り」なのかさえわかっていません。 -
  • 一応ConnectionOptionsとかSelectQueryとか調べてもみましたが、難しすぎて何を言っているのか理解できませんでした。なのでとりあえず値をいろいろ変えてみたに過ぎません。 -
  • なので本当に開き直りになってしまいますが、内容が高度すぎて説明すらままならない、ということのようです。ここまでして頂いて大変申し訳ありませんが、今回は諦めます。もっとスキルがついてから挑戦することにします。 -
  • 最初に「ネットワーク越し未対応」ってのを出しましたよね?そして、「判定が必要」と書いてますよ? -

回答

再度、改訂します。
ユーザーの情報にアクセスできるようにしました。
リモート PC へのアクセスも確認しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;

namespace ConsoleApplication1
{
    internal static class WmiTest
    {
        public static void Test()
        {
            // locale と authority は要注意
            ConnectionOptions opt = new ConnectionOptions(
                "MS_1033",
                **USER NAME**,
                **PASSWORD**,
                "ntlmdomain:**DOMAIN NAME**",
                ImpersonationLevel.Impersonate,
                AuthenticationLevel.Default,
                false,
                null,
                TimeSpan.MaxValue);
            try
            {
                // スコープ構築
                ManagementScope scope = new ManagementScope(@"\\**COMPUTER NAME**\root\cimv2", opt);
                // ログオン中のセッション情報から、タイプを指定して問い合わせる
                SelectQuery query = new SelectQuery(
                    "select * from Win32_LogonSession where LogonType = **TYPE**");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                ManagementObjectCollection queryCollection = searcher.Get();
                foreach (ManagementObject m in queryCollection)
                {
                    // Id 情報とユーザー情報をつなぐ情報からユーザー情報を取り出す
                    string q = string.Format(
                        "ASSOCIATORS OF {{Win32_LogonSession.LogonId='{0}'}} WHERE AssocClass = Win32_LoggedOnUser Role=Dependent",
                        m["LogonId"].ToString());
                    RelatedObjectQuery relatedQuery = new RelatedObjectQuery(q);
                    ManagementObjectSearcher related = new ManagementObjectSearcher(scope, relatedQuery);
                    // ユーザー情報のプロパティを列挙
                    foreach (ManagementObject m2 in related.Get())
                    {
                        foreach (var p in m2.Properties)
                        {
                            Console.WriteLine(string.Format("{0}->{1}", p.Name, p.Value));
                        }
                    }
                }
            }
            catch (ManagementException ex)
            {
                System.Diagnostics.Trace.WriteLine(ex);
                System.Console.WriteLine(ex);
            }
        }
    }
}
編集 履歴 (3)
  • http://msdn.microsoft.com/en-us/library/windows/desktop/aa394582(v=vs.85).aspx
    http://msdn.microsoft.com/ja-jp/library/ms257340(VS.90).aspx
    -
  • ご返答ありがとうございます。会社でしか確認ができないので、結果は来週以降になると思いますが、ひとまずお礼まで。 -
  • ``` の手前に改行を入れたらちゃんと等幅フォントになると思いますよ :) -
  • 早速上記コードをビルドしてみました。
    参照設定を追加して、ビルドも成功したのですが、実行すると

    ```
    foreach (ManagementObject m in queryCollection)
    ```

    のところでforeach文を抜け出してしまいます。
    中身が空っぽということみたいなのですが、どこがいけないのかがわかりません。
    -
  • あ、改行もコードもダメなんですね。やったことといえば、 new ManagementScope(@"\.\root\cimv2"); の項目を new ManagementScope(@"\\192.168.100.200\root\cimv2"); のように自PCのIPに変えたことだけです。お手数ですがご返答いただけますでしょうか。 -
  •  まず、対象が「.」、つまり自 PC の時は、期待通りの結果を得られたでしょうか。まず、そこからではないでしょうか。 -
  •  プログラムを実行したアカウントは、接続先 PC でコマンドを実行する権限があるでしょうか。例えば、スタート メニューの「コンピューター」を右クリックして「管理」を選択してコンピュータの管理を表示し、「操作」メニューから「別のコンピュータへ接続」を選択します。 -
  • 適当に接続先を選んだときに、そのコンピュータの管理を行う事ができますか?できない場合、ConnectionOptions クラスで接続先 PC の管理を行えるアカウントを指定しなければなりません?→ http://msdn.microsoft.com/ja-jp/library/vstudio/system.management.connectionoptions.aspx -
  • ノートは200字以内だって(--; コード中の「**~**」が、強調表示されませんでした。LogonType は、Win32_Account のページにあります。 -
  • お忙しい中ご返答ありがとうございます。アカウントはDomain Administratorsの権利があります。また、自PCのIPを指定した際も他のIP指定時も、同じ個所でforeachを抜けてしまいます。 -
  • あ、すみません、コードを書き直してくださってたんですね。もう一度やってみます。 -
  • 上記コードで実行したところ、再び「queryCollection = searcher.Get()」の個所でCatchに行ってしまい、「ユーザー資格情報はローカル接続には使用できません」というエラーが出ました。ドメインのAdminやローカルのAdminでもやってみましたが同じ結果でした。LogonTypeは2・3・8などで試してみましたが、やはり結果は変わりませんでした。 -
  • メッセージの通りです。せっかく何がいけないか情報をくれているのですから、理解しましょう。 ローカル PC に接続するときは、資格情報をつけてはいけません。つまり、これから接続するのがローカルなのかどうか、判定が必要です。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。