• 締切済み

VB.NetのWMIを用いたリモート端末への接続

下記の環境で作成したWinアプリからWMIを用いてリモート 端末に接続し、その端末のCPU使用率を取得しようとする と、下記ソースの30行目実行時に不定期間隔でエラーに なったりならなかったりします。どのたか解決策をご存知でし たら、お教え願います。 開発環境:VisualStudio 2005 / .NET FrameWorkバージョン:2.0 開発言語:VB.NET リモート接続端末:Windows Server 2003 R2 リモート接続ポート:135 リモートインストール済み.NET FrameWorkバージョン:1.0、2.0 エラー内容:「オブジェクト参照がオブジェクト インスタンスに設定されていません。」 以下ソース↓ Imports System.Management Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim Query As New ObjectQuery Dim Options As New ConnectionOptions Dim Scope As New ManagementScope Dim Searcher As New ManagementObjectSearcher Dim PrcCol As ManagementObjectCollection Dim sngCpu使用率 As Single = 0 Dim objPrc As ManagementBaseObject = Nothing Try Query.QueryString = "SELECT * FROM Win32_Processor" Options.Username = "接続端末名" + "\" + "ログインID" Options.Password = "ログインパスワード" Scope.Options = Options Scope.Path.Server = "接続端末名" Searcher.Query = Query Searcher.Scope = Scope Do PrcCol = Searcher.Get For Each objPrc In PrcCol 'CPU使用率取得 sngCpu使用率 = CSng(objPrc("LoadPercentage").ToString) '←ここでエラー Next Loop Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Critical) End Try End Sub End Class ここまで ↑

みんなの回答

回答No.2

>リモート端末にインストールされているFrameWorkの仕様もしくはバグで >はないかと考えています。 そこまでお調べになったのなら、開発環境の FrameWork のバージョンとサービスパックが 同じかどうかをお調べになり、開発環境と同じFrameWork のバージョンとサービスパックを インストールして見たら動作するのではないですか? 確かに、FrameWork 1.1 の SP1 では、WMI に不具合がありましたが、それ以降は問題ないように 聞いております。 因みに、私の環境では、.NET Framework 2.0 のバージョンは、2.0.50727.4016 です。

NoMusicNoLife49
質問者

お礼

ご回答ありがとうございます。 参考にさせて頂きます。

NoMusicNoLife49
質問者

補足

vbhanatyanさん 回答が遅くなり申し訳ないです。 結果、解決しました。 制約上の問題が有り、接続先ホストのFrameworkのバージョンを更新 することはできませんでした。 解決方法としては、CPU使用率を取得するWMIクラスを変更すること で対応できました。以下、修正したソースです。 Private Function Win32_PPOS_Processor() As Boolean Dim Query As New ObjectQuery Dim Options As New ConnectionOptions Dim Scope As New ManagementScope Dim Searcher As New ManagementObjectSearcher Dim PrcCol As ManagementObjectCollection Dim objPrc As ManagementBaseObject = Nothing Dim dblPT1 As Double = 0 Dim dblUT1 As Double = 0 Dim dblTS1 As Double = 0 Dim dblPT2 As Double = 0 Dim dblUT2 As Double = 0 Dim dblTS2 As Double = 0 Dim dblPT差分 As Double = 0 Dim dblUT差分 As Double = 0 Dim dblTS差分 As Double = 0 Dim dblCpu使用率 As Double = 0 Dim intCpu使用率 As Integer = 0 Try 'WQLコマンド設定 Query.QueryString = "SELECT Name" + _ ",PercentPrivilegedTime" + _ ",PercentUserTime" + _ ",Timestamp_Sys100NS " + _ "FROM Win32_PerfRawData_PerfOS_Processor " + _ "WHERE Name = '_Total'" '接続IDとパスワードを設定 Options.Username = Me.txtホスト名.Text + "\" + Me.txtID.Text Options.Password = Me.txtPass.Text '接続情報設定 Scope.Options = Options Scope.Path.Server = Me.txtホスト名.Text 'WQLコマンド実行クラスにWQLコマンド、接続情報を設定 Searcher.Query = Query Searcher.Scope = Scope 'リソースコレクション取得 PrcCol = Searcher.Get For Each objPrc In PrcCol dblPT1 = CDbl(objPrc("PercentPrivilegedTime")) dblUT1 = CDbl(objPrc("PercentUserTime")) dblTS1 = CDbl(objPrc("Timestamp_Sys100NS")) Next '5秒間停止 System.Threading.Thread.Sleep(500) 'リソースコレクション再取得 PrcCol = Searcher.Get For Each objPrc In PrcCol dblPT2 = CDbl(objPrc("PercentPrivilegedTime")) dblUT2 = CDbl(objPrc("PercentUserTime")) dblTS2 = CDbl(objPrc("Timestamp_Sys100NS")) Next '差分算出 dblPT差分 = dblPT2 - dblPT1 dblUT差分 = dblUT2 - dblUT1 dblTS差分 = dblTS2 - dblTS1 If dblTS差分 > 0 Then 'CPU使用率算出 dblCpu使用率 = (dblPT差分 + dblUT差分) / (dblTS差分) * 100 intCpu使用率 = CInt(dblCpu使用率) End If Catch ex As Exception MsgBox(ex.Message, MsgBoxStyle.Critical) End Try End Function

回答No.1

Do PrcCol = Searcher.Get For Each objPrc In PrcCol 'CPU使用率取得 sngCpu使用率 = CSng(objPrc("LoadPercentage").ToString) '←ここでエラー Next Loop このように永遠と超高速に取得しているからではないですか? ループの部分をタイマーコントロールを使って 500 ミリ秒間隔位で取得してどうなりますか?

NoMusicNoLife49
質問者

お礼

ご回答ありがとうございます。 ご参考にさせて頂きます。

NoMusicNoLife49
質問者

補足

vbhanatyanさん ご回答ありがとうございます。 ご指摘頂いたように、タイマーコントロールを用いて 500ミリ秒間隔で取得するように修正しましたが、 エラーになります。ちなみに10000ミリ秒間隔でも エラーになるため、WMIの実行間隔とエラーの関係 性は低いと考えられます。 エラーになる理由を詳細に説明しますとWMI実行時に リモート端末のリソースコレクションが取得できず、参照型 の変数(objPrc)の参照先がNothingのため、ToStringメッソ ド呼出時にエラーなっしまいます。なので原因はリモート端末 側に有ると考えています。 いろいろと調査しましたが、現在把握している状況は 1.エラーになるリモート端末とならないリモート端末が有る。 2.エラーにならないリモート端末のみ、FrameWork4.0が  インストールされている。 3.FrameWorkを用いないWMI接続(VB6.0)ではエラーにな  らない。 4.リモート端末、監視端末共にWMIのサービスは起動して  いる。 5.リモート端末、監視端末共にCPUパワーやメモリの消費  に余裕がある。 上記の把握状況から、今回のエラー(現象)はリモート端末 にインストールされているFrameWorkの仕様もしくはバグで はないかと考えています。

関連するQ&A

  • VB.NET2005からoracle92へ接続するには?

    IDとパスワードを入力し、オラクルのDBにあるIDとパスワードだったら次の画面を開くというプログラムを作りたいです。 オラクルへの接続がうまく行ってないようで画面が固まってしまいます。 プログラムの不具合を教えていただけないでしょうか? よろしくお願いします。 Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cn As New OleDb.OleDbConnection() Dim cmd As New OleDb.OleDbCommand() Dim rs As OleDb.OleDbDataReader cn.ConnectionString = "Provider=OraOLEDB.Oracle;Data Source=*;User ID=*;Password=*;" cn.Open() '←ここで、エラーになります。 cmd = cn.CreateCommand() cmd.CommandText = "Select ID from abc" rs = cmd.ExecuteReader() While rs.Read() If TextBox1.Text = cmd.CommandText Then MessageBox.Show("パスワードを受付けました。") Dim frm2 As New Form2 frm2.Show() TextBox1.Clear() TextBox2.Clear() Else MessageBox.Show("パスワードが違います。") TextBox1.Text = "" TextBox1.Focus() TextBox1.Clear() TextBox2.Clear() End if     End While cn.Close() rs.Close() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.Close() End Sub End Class

  • VB.netでSQLserverに接続したい

    VB2008express で SQLserver2000に接続しようとしています フォーム上で ボタンを2つ作成し button1の記述では接続できるのですが button2では接続できず タイムオーバーになります。 SqlConnectionの使い方など基本的な理解不足かと思いますが お気づきの点あればお願いします。 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim DATACNN As String Dim DATAADO As ADODB.Connection DATACNN = "DRIVER={SQL SERVER};" & "SERVER=TESTSERVER;UID=sa;PWD=123;DATABASE=BD" DATAADO = New ADODB.Connection DATAADO.Open(DATACNN) MsgBox("接続1OK") End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim stConnectionString As String = String.Empty stConnectionString &= "Data Source =TESTSERVER;" stConnectionString &= "persist security info=True;" stConnectionString &= "Database=BD;" stConnectionString &= "user id=sa;" stConnectionString &= "password=123;"  Dim cSqlConnection As New System.Data.SqlClient.SqlConnection(stConnectionString) cSqlConnection.Open()  ’←タイムオーバーになります MsgBox("接続2OK") cSqlConnection.Close() cSqlConnection.Dispose() End Sub

  • VB.NET2005からoracle92へ接続する方法。

    IDとパスワードを入力し、オラクルのDBにあるIDとパスワードだったら次の画面を開くというプログラムを作りたいです。 オラクルへの接続がうまく行ってないようで画面が固まってしまいます。 プログラムの不具合を教えていただけないでしょうか? よろしくお願いします。 Public Class Form1 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim cn As New OleDb.OleDbConnection() Dim cmd As New OleDb.OleDbCommand() Dim rs As OleDb.OleDbDataReader cn.ConnectionString = "Provider=OraOLEDB.Oracle;Data Source=*;User ID=*;Password=*;" cn.Open() '←ここで、エラーになります。 cmd = cn.CreateCommand() cmd.CommandText = "Select ID from abc" rs = cmd.ExecuteReader() While rs.Read() If TextBox1.Text = cmd.CommandText Then MessageBox.Show("パスワードを受付けました。") Dim frm2 As New Form2 frm2.Show() TextBox1.Clear() TextBox2.Clear() Else MessageBox.Show("パスワードが違います。") TextBox1.Text = "" TextBox1.Focus() TextBox1.Clear() TextBox2.Clear() End if     End While cn.Close() rs.Close() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.Close() End Sub End Class

  • VB初心者です。コードの書き方が分かりません。

    VB初心者です。 VBで(zのn乗)-(xのn乗+yのn乗)の計算が出来るようにしたいのですが、答えが必ず-1になってしまいます。 Option Explicit On Public Class Form1 Dim x As Long Dim y As Long Dim z As Long Dim n As Long Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Me.Close() End Sub Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged End Sub Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged End Sub Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged End Sub Private Sub TextBox4_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox4.TextChanged End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click TextBox5.Text = (z ^ n) - (x ^ n + y ^ n) End Sub End Class 正しいコードの書き方を教えて下さい。 また特定の答えのときにメッセージを表示したいのですが、どうすればいいですか?

  • VB.NETのデリゲートについて

    VB.NETのデリゲートについて質問です。 以下のプログラムなのですが、 デリゲート型をインスタンス化しているところで、コンストラクタにパラメータを渡していますが、 そのコンストラクタはどこに定義されているのでしょうか。 (AddressOf t1.Ohayou)というパラメータが渡されていますが、このパラメータを受け取っているコンストラクタがどれなのかが分かりません。 ご教示よろしくお願いいたします。 Delegate Sub Myprint(ByVal s As String) Module Module1 Sub Main() Dim t1 As Test1 = New Test1() Dim t2 As TEst2 = New Test2() Dim d As Myprint = New Myprint(AddressOf t1.Ohayou) d.Invoke("VB太郎") d = New Myprint(AddressOf t2.Konbanwa) d.Invoke("VB太郎") End Sub End Module Class Test1 Sub Ohayou(ByVal s As String) Console.WriteLine("おはようございます。{0}です。", s) End Sub End Class Class Test2 Sub Konbanwa(ByVal s As String) Console.WriteLine("こんばんわ。{0}です。", s) End Sub End Class

  • VB.NETでのデータベース書き込みについて

    リストレビューに表示されているデータをデータベースに書き込む処理を追加したいのですが、データセットにメモリ上のテーブルを作成してデータベースへ書き込む方が良いのでしょうか? それとも直接データベースに書き込む方が良いのでしょうか? 前者のテーブル作成のコードは書きの通りです。 Public Function AddDataSetTable(ByVal kojo_cd() As String, ByVal kojo_name() As String, ByVal kojo_date() As String)   Dim dtSet As New DataSet("DataSetTable")   Dim dtTable As New DataTable("CalDatTable")   Dim fmain As New FrmMain   Dim i As Integer   'テーブルに列を追加    With dtTable.Columns     .Add("コード")     .Add("名称")     .Add("日にち")    End With   'テーブルに行を追加   With dtTable.Rows    For i = 0 To UBound(kojo_cd)     .Add(New Object() {kojo_cd(i), kojo_name(i), kojo_date(i)})    Next i   End With   'データセットにテーブルを追加   dtSet.Tables.Add(dtTable) End Function

  • マルチスレッド[ VB.NET 2005 ]

    VB.NET 2005 VC++で作成した通信DLLをマルチスレッドで呼び出すプログラムを作成しています。 マルチスレッドについてご質問です。 ---------------------------------------------------------------- Private Sub ThreadMethod(ByVal aiIndex As UInt32) fSockInit() ← スレッドスタートなので別スレッドで動く End Sub '************************************************** ' フォームロード '************************************************** Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load wkThread(Index) = New Thread(New ThreadStart(AddressOf ThreadMethod)) wkThread(Index).Start() End Sub '************************************************** ' 接続ボタン押下 '************************************************** Private Sub btConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btConnect.Click fConnect() ← スレッドを指定して動かしたい End Sub '************************************************** ' パラメータ設定ボタン押下 '************************************************** Private Sub btParm_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btParm.Click fParmSet() ← スレッドを指定して動かしたい End Sub ---------------------------------------------------------------- 上記の例では、fSockInitはスレッド別に動作しますが、fConnect、fParmSetはメインスレッドで動作するようになっています。 frmMain_Loadで作成したスレッドを指定(※1)して関数を呼び出すことは出来ないのでしょうか? ※1.「クリックイベント(メインスレッド)→実行するスレッドを指定→関数呼び出し→メインスレッドに戻す」の様に。。。

  • VB.NETのSendMessageを教えてください

    SendMessageというAPIを試しているのですが、まず試しに Button2.Text = "test" と同じ結果をSendMessageでやってみたいのですが 下のようにしてみたのですが、変更になりませんでした。 どのようにすれば良いかご教授頂ければ幸いです。よろしくお願致します。 Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer Private Const WM_SETTEXT As Integer = &HC Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim h As Integer h = Me.Button2.Handle.ToInt32 SendMessage(h, WM_SETTEXT, 0&, "test") End Sub VB.NET2003 FrameWork1.1 WindowsXP-PRO(SP2) です。

  • VB.netで印刷

    プリンターにA4サイズより5mm内側に四角形を書いて印刷したいのですが ずれてしまいます。おそらく余白の設定ではないかとおもうのですが 用紙を横向き、余白0,指定はどう指定すればよいでしょうか あるいは、参考になるサイトをお教えください。 Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage Dim f As New Font("MS 明朝", 64, FontStyle.Bold) e.Graphics.PageUnit = GraphicsUnit.Millimeter e.Graphics.DrawRectangle(New Pen(Color.Red), 5, 5, 287, 200) End Sub

  • C#でリモートPC(win2000)シャットダウン

    C#でリモートPC(win2000)シャットダウンさせたいのですが、 ************************************ string svr = "コンピュータ名"; string usr = "ユーザー名"; string pass = ""; ConnectionOptions options = new ConnectionOptions(); options.Username = usr; options.Password = pass; string mPath = @"\\" + svr + @"\root\cimv2"; ManagementScope scope = new ManagementScope(mPath, options); scope.Connect(); System.Management.ObjectQuery oq = new System.Management.ObjectQuery("SELECT * FROM Win32_OperatingSystem"); anagementObjectSearcher searcher = new ManagementObjectSearcher(scope, oq); ManagementObjectCollection collection = searcher.Get(); foreach( ManagementObject mo in collection ) { string[] ss={""}; mo.InvokeMethod("Shutdown",ss); } *********************************************** とやっても2000で『電源がきることができます』の画面で完全にシャットダウンしないのです。完全にシャットダウンする方法はありますでしょうか?

専門家に質問してみよう