none
.NET Remotingのために、同一ネットワーク内にある他のPCがログイン状態にあるか否かを調べる方法 RRS feed

  • 質問

  • 同一ネットワーク内にある他のPCがログイン状態にあるか否かを調べる方法をお教えいただけないでしょうか?

    .NET Remotingでサーバー、クライアントの関係のプログラムを作成しています。

    サーバーとなるPCが起動している状態で、サーバーアプリが実行していないときにクライアントからの問い合わせの反応が非常に遅いので、少しでも早くする方法を検討しています。

     

    2012年1月27日 12:53

回答

  • 例えば、WMI を調べると、Win32_LoggedOnUser class というクラスがあります。これを使うと、わかるかもしれません。

    とりあえず、次の VBS でやってみました。

    
    Option Explicit
    
    Dim oClassSet
    Dim oClass
    Dim oLocator
    Dim oService
    Dim sMesStr
    
    Set oLocator = WScript.CreateObject("WbemScripting.SWbemLocator")
    Set oService = oLocator.ConnectServer(REMOTE-HOST, "root\cimv2", ACCOUNT-NAME, PASSWORD)
    Set oClassSet = oService.ExecQuery("Select * From Win32_LoggedOnUser")
    
    For Each oClass In oClassSet
    sMesStr = sMesStr & oClass.Antecedent & vbCrLf
    Next
    
    MsgBox "一覧" & vbCrLf & vbCrLf & sMesStr
    
    Set oClassSet = Nothing
    Set oClass = Nothing
    Set oService = Nothing
    Set oLocator = Nothing
    

    REMOTE-HOST にリモートデスクトップで接続中に実行したところ、次の結果を得ました。

    一覧
    
    
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="SYSTEM"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="LOCAL SERVICE"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="NETWORK SERVICE"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="postgres"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="ANONYMOUNS LOGON"
    

    次に、リモートデスクトップからログオフして実行しましたが、同じ結果でした。ACCOUNT-NAME は自分で、複数出てきました。なぜ複数あるのか、不明です。ファイルサーバーとして利用しているので、共有ディレクトリにアクセスしたものが残っているのかもしれません。WMI を実行するために接続したアカウントも計上されているかも。でも、Win32_Process で実行中のプロセスがわかる様なので、そちらを利用する方が良いかも。


    参考:
    Windows Management Instrumentation
    Win32_LoggedOnUser クラス - WMI Library(wmifun.net)
    SWbemLocator error '800706ba' The RPC server is unavailable.(visualbasicscript.com)
    実装メモリの確認方法(C# から WMI を呼び出す方法へのリンク)

    検索の経緯:
    WMI のページからクラスの一覧を表示し、アカウントに関係する名前(account または user)を持つクラスを探した。


    Jitta@わんくま同盟
    • 回答の候補に設定 山本春海 2012年2月15日 5:15
    • 回答としてマーク 山本春海 2012年2月20日 7:10
    2012年2月3日 12:30

すべての返信

  • ちょっと時間が経っているので見ているかわかりませんが、
    これはサーバ側で動くプログラムがログインしていないと動かないから
    「サーバ側に誰かログインした状態か」を調べたいということでしょうか。
    普通はサーバ側はサービスとして作ると思うのですが、そうできない理由があるのでしょうか。
    2012年2月2日 7:15
  • おっしゃる通りです。

    普通の考え方であれば,サービスとして登録すべきことでしょうね。

    サービスとして登録できない理由は特にありません。

    私の好みの問題で,サービスを登録せずに実現したいというだけの事なのです。

    2012年2月2日 7:47
  • # 一般的な方法でなく、個人的な好みの問題で実装方法を決定したのであれば、最後まで面倒見るのが筋だと思うのですが...

    クライアント側でタイムアウトを実装してお茶を濁すだけではダメなのでしょうか?
    一定時間帰ってこなかったら、サーバー側が起動していないとみなすような。
    2012年2月2日 7:58
  • コメントをいただきありがとうございます。

     

    ># 一般的な方法でなく、個人的な好みの問題で実装方法を決定したのであれば、最後まで面倒見るのが筋だと思うのですが...

    ごめんなさい,おっしゃる意味がよくわかりませんでした。面倒を放棄してるつもりはありませんが・・・

    >クライアント側でタイムアウトを実装してお茶を濁すだけではダメなのでしょうか?
    >一定時間帰ってこなかったら、サーバー側が起動していないとみなすような。

    現状はタイムアウトの設定でどうにか運用しております。しかし,タイムアウトを設定すると本来サーバー側でプログラムが動作しているにも関わらず,返答をもらえない事もしばしばあり,適切なタイムアウト値の見極めが難しいと感じています。

     

    私のイメージでは

    1.Pingを送ってサーバーが起動しているか確認する

    2.1がOKならば,サーバーがログイン状態か確認する

    3.2がOKならばサーバープログラムに問い合わせる

    といった手順で実装したいのですが,2の方法が不明なため1と3のみで運用しております。

     

    どうしてもサービスを登録したくないというわけではありませんが,サービスを登録せずに実現する方法はないのかなと,半分好奇心もあり検討しているところです。

     

    2012年2月2日 9:07
  • ># 一般的な方法でなく、個人的な好みの問題で実装方法を決定したのであれば、最後まで面倒見るのが筋だと思うのですが...

    ごめんなさい,おっしゃる意味がよくわかりませんでした。面倒を放棄してるつもりはありませんが・・・


    分かりにくい表現で失礼しました。
    技術的な問題がないのであれば、サーバー側は Windows サービスとして実装するのが定石なのではないかと思います。
    定石ではなく個人的な好みの問題で Windows サービス以外を選択したことによって、余計な心配ごとが増えてしまっているように見えるのです。
    個人的な好みで実装方法を選択するのであれば、今回のような余計な問題点についても考慮して、解決策を見つけておくべきではなかったかと。
    長いものには巻かれておくのが、後の苦労が少なくて済むのではないかと思います。

    Windows サービスにしても、サービスが起動していないことがないとも言えないので、それなりの考慮は必要なのですが、
    「サーバー側で誰かがログオンしていて、かつサーバー側プログラムを起動中」よりは「Windows サービスが停止している」方が確立的にははるかに低いはずですので、 今回のような余計な対処をする必要もないのに、と思います。

    それはそれとして、

    タイムアウトを設定すると本来サーバー側でプログラムが動作しているにも関わらず,返答をもらえない事もしばしばあり


    この点については問題はないんでしょうか。
    2012年2月2日 11:15
  • 色々とアドバイスをいただき、ありがとうございます。

    サービスとして動作させたほうが合理的であるという点も理解しております。が、単純に知識欲というかそのような理由で他の方法がないか検討中という事です。

    不可能という事がわかればサービス登録という手段にスッキリ移れるのですが、この辺は私の気持ちの問題ですね。わがままを言ってスミマセン。

     

    >タイムアウトを設定すると本来サーバー側でプログラムが動作しているにも関わらず,返答をもらえない事もしばしばあり
    >この点については問題はないんでしょうか。

    いいえ、問題があるのでタイムアウトを設定するという方法で解決する事が現在はできておりません。

    タイムアウトを短くすれば待ち時間は短くて済みますが、本来受け取れるはずのサーバーからの情報が時間切れで受け取れなくなるというジレンマに陥っています。

    2012年2月2日 15:02
  • タイムアウトを短くしてテスト接続し、サーバーが生きてるようならタイムアウトを適度に延ばした上で本来の呼び出しをするとかできませんか?

    # .NET Remotingはもうあまり使われていないから…そういう設定ができるかはわかりません。

    2012年2月3日 1:18
  • >タイムアウトを短くしてテスト接続し、サーバーが生きてるようならタイムアウトを適度に延ばした上で本来の呼び出しをするとかできませんか?

    タイムアウトを短くするとテスト接続の段階で、生きているのに死んでいると判断してしまうので無理ではないでしょうか?

     

    2012年2月3日 4:41
  • 例えば、WMI を調べると、Win32_LoggedOnUser class というクラスがあります。これを使うと、わかるかもしれません。

    とりあえず、次の VBS でやってみました。

    
    Option Explicit
    
    Dim oClassSet
    Dim oClass
    Dim oLocator
    Dim oService
    Dim sMesStr
    
    Set oLocator = WScript.CreateObject("WbemScripting.SWbemLocator")
    Set oService = oLocator.ConnectServer(REMOTE-HOST, "root\cimv2", ACCOUNT-NAME, PASSWORD)
    Set oClassSet = oService.ExecQuery("Select * From Win32_LoggedOnUser")
    
    For Each oClass In oClassSet
    sMesStr = sMesStr & oClass.Antecedent & vbCrLf
    Next
    
    MsgBox "一覧" & vbCrLf & vbCrLf & sMesStr
    
    Set oClassSet = Nothing
    Set oClass = Nothing
    Set oService = Nothing
    Set oLocator = Nothing
    

    REMOTE-HOST にリモートデスクトップで接続中に実行したところ、次の結果を得ました。

    一覧
    
    
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="SYSTEM"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="LOCAL SERVICE"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="NETWORK SERVICE"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name=ACCOUNT-NAME
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="postgres"
    \\.root\cimv2:Win32_Account.Domain=REMOTE-HOST,Name="ANONYMOUNS LOGON"
    

    次に、リモートデスクトップからログオフして実行しましたが、同じ結果でした。ACCOUNT-NAME は自分で、複数出てきました。なぜ複数あるのか、不明です。ファイルサーバーとして利用しているので、共有ディレクトリにアクセスしたものが残っているのかもしれません。WMI を実行するために接続したアカウントも計上されているかも。でも、Win32_Process で実行中のプロセスがわかる様なので、そちらを利用する方が良いかも。


    参考:
    Windows Management Instrumentation
    Win32_LoggedOnUser クラス - WMI Library(wmifun.net)
    SWbemLocator error '800706ba' The RPC server is unavailable.(visualbasicscript.com)
    実装メモリの確認方法(C# から WMI を呼び出す方法へのリンク)

    検索の経緯:
    WMI のページからクラスの一覧を表示し、アカウントに関係する名前(account または user)を持つクラスを探した。


    Jitta@わんくま同盟
    • 回答の候補に設定 山本春海 2012年2月15日 5:15
    • 回答としてマーク 山本春海 2012年2月20日 7:10
    2012年2月3日 12:30
  • 当然ながらVB User1さん自身が適切なタイムアウト値を決めてください。応答に1分かかるなら、タイムアウトも1分以上にする必要があります。
    2012年2月4日 4:29
  • >Jittaさん

    ありがとうございます。

    そちらの路線で調べてみようと思います。

    >佐祐理さん

    そうなのです。「適切なタイムアウト値」というのがなかなか難しいのです。

    色々と実験をして見つけ出すしかないでしょうね。

    2012年2月7日 5:22