tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトル配列を使った記述の簡素化
記事No11636
投稿日: 2016/03/07(Mon) 18:06
投稿者食う寝る走る
開発プログラムを決まった登録PCでしか動かせなくする意味で、搭載している物理メモリの情報を取得する方法を考えております。


開発環境
 OS:Windows7(32bit)プロフェッショナル
 IDE:VS2015 コミュニティ(VB.net)
 

'System.Management 参照 必要
'=== PhysicalMemory内部情報取得===============================================================
    '物理メモリが複数枚あれば、複数行表示されます。
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim PMSet As Object
        Dim str As String

        str = "Manufacturer"
        PMSet = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("SELECT " & str & " FROM Win32_PhysicalMemory")
        For Each obj In PMSet
            Console.WriteLine("Win32_PhysicalMemory." & str & "=" & obj.Manufacturer)
        Next
End Sub
'===============================================================================================

上記では、Win32_PhysicalMemoryクラスのManufacturerプロパティで製造メーカの取得は出来ました。

(質問1)「obj.Manufacturer」を obj.str みなく書けないだろうか?


(質問2)その他もろもろの、プロパティで情報取得するのに同じように長々と記述すればいいのですが、
 下記のような配列記述で短くまとめることはできないでしょうか?

'===============================================================================================
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click

        Dim PMSet As Object
        Dim Str() As String = {"BankLabel", "Capacity", "Caption", "CreationClassName", "DataWidth", "Description", "DeviceLocator",
"FormFactor", "HotSwappable", "InstallDate", "InterleaveDataDepth", "InterleavePosition", "Manufacturer", "MemoryType", "Model",
"Name", "OtherIdentifyingInfo", "PartNumber", "PositionInRow", "PoweredOn", "Removable", "Replaceable", "SerialNumber", "SKU",
"Speed", "Status", "Tag", "TotalWidth", "TypeDetail", "Version"}

        For i = 0 To UBound(Str) '配列の要素数の上限まで繰り返す
            PMSet = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("SELECT " & Str(i) & " FROM Win32_PhysicalMemory")
            For Each obj In PMSet
                Console.WriteLine(String.Format("Win32_PhysicalMemory.{0}=obj.{0}", Str(i)))
            Next obj
        Next i
    End Sub
'===============================================================================================

上記では、
Console.WriteLine(String.Format("Win32_PhysicalMemory.{0}=obj.{0}", Str(i))) ステートメントに問題があり、obj.{0}に結果が出てこないで、

出力は、
Win32_PhysicalMemory.BankLabel=obj.BankLabel
Win32_PhysicalMemory.Capacity=obj.Capacity
Win32_PhysicalMemory.Caption=obj.Caption
Win32_PhysicalMemory.CreationClassName=obj.CreationClassName

といった、値が入っていない文字列が出力されます。
(ステートメント内でオブジェクトとして振舞っていない?)

よろしくご教授 願います。

[ツリー表示へ]
タイトルRe: 配列を使った記述の簡素化
記事No11637
投稿日: 2016/03/08(Tue) 03:25
投稿者魔界の仮面弁士
> 'System.Management 参照 必要
マネージインターフェイスの System.Management.dll を用いたコードではなく、
COM 版のインターフェイスを使ったコードになってしまっているようです。

参考にしているコードは、.NET 向けの物ではなく、
VBScript 向けのコードなのではありませんか?


'Imports System.Management

Using mc As New ManagementClass("Win32_PhysicalMemory")
 For Each p In mc.GetInstances()
  Console.WriteLine($"Win32_PhysicalMemory.{str}={p(str)}")
  p.Dispose()
 Next
End Using


> (質問1)「obj.Manufacturer」を obj.str みなく書けないだろうか?
今回は、COM版のインターフェイスを使っているので、
 obj.Properties_(str).Value
ですね。アンダーバーを忘れずに。


> (質問2)その他もろもろの、プロパティで情報取得するのに同じように長々と記述すればいいのですが、
>  下記のような配列記述で短くまとめることはできないでしょうか?
できますよ。アクセス方法は上述の通りです。


> For i = 0 To UBound(Str)
こういう時は、For Each を使いましょう。

[ツリー表示へ]
タイトルRe^2: 配列を使った記述の簡素化
記事No11638
投稿日: 2016/03/08(Tue) 11:23
投稿者食う寝る走る
魔界の仮面弁士 さま アドバイスありがとうございます。
教えていただいたUsing ブロックによるインスタンス作成コードで無事、簡素化が出来ました。
参照元のサンプルコードを確認したら、ご指摘のようにScriptの説明サイトでした。
先に作った、CPU,BIOS,HDD等の情報取得コードにも展開して修正したいと思います。

以下、まとめとして コードを貼っておきます。

'------------------------------------------------------------------------------------------
'(質問1)「obj.Manufacturer」を obj.str みなく書けないだろうか?

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
  Dim PMSet As Object
        Dim Str() As String = {"BankLabel", "Capacity", "Caption", "CreationClassName", "DataWidth", "Description", "DeviceLocator",
"FormFactor", "HotSwappable", "InstallDate", "InterleaveDataDepth", "InterleavePosition", "Manufacturer", "MemoryType", "Model",
"Name", "OtherIdentifyingInfo", "PartNumber", "PositionInRow", "PoweredOn", "Removable", "Replaceable", "SerialNumber", "SKU",
"Speed", "Status", "Tag", "TotalWidth", "TypeDetail", "Version"}

        For Each i In Str
            PMSet = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("SELECT " & i & " FROM Win32_PhysicalMemory")
            For Each obj In PMSet
                Console.WriteLine("Win32_PhysicalMemory." & i & "=" & obj.Properties_(i).Value)
        Next obj, i
    End Sub
'------------------------------------------------------------------------------------------


'------------------------------------------------------------------------------------------
'(質問2)その他もろもろの、プロパティで情報取得するのに同じように長々と記述すればいいのですが、
'  下記のような配列記述で短くまとめることはできないでしょうか?

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        'Imports System.Management
        Dim Str() As String = {"BankLabel", "Capacity", "Caption", "CreationClassName", "DataWidth", "Description", "DeviceLocator",
"FormFactor", "HotSwappable", "InstallDate", "InterleaveDataDepth", "InterleavePosition", "Manufacturer", "MemoryType", "Model",
"Name", "OtherIdentifyingInfo", "PartNumber", "PositionInRow", "PoweredOn", "Removable", "Replaceable", "SerialNumber", "SKU",
"Speed", "Status", "Tag", "TotalWidth", "TypeDetail", "Version"}

        Using mc As New ManagementClass("Win32_PhysicalMemory")
            For Each i In Str
                For Each p In mc.GetInstances()
                    'Console.WriteLine($"Win32_PhysicalMemory.{str}={p(str)}")
                    Console.WriteLine($"Win32_PhysicalMemory.{i}={p(i)}")
                    p.Dispose()
            Next p, i
        End Using
    End Sub
'------------------------------------------------------------------------------------------

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

[ツリー表示へ]
タイトルRe^3: 配列を使った記述の簡素化
記事No11639
投稿日: 2016/03/08(Tue) 14:33
投稿者魔界の仮面弁士
> PMSet = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("SELECT " & i & " FROM Win32_PhysicalMemory")

GetObject の COM 版インターフェイスは使わないでください。
(質問2)のコードのように、System.Management 名前空間を用いた記述に書き直すべきです。


もしも COM 版インターフェイスを使うのであれば、各オブジェクトの利用後には
Marshal.ReleaseComObject の呼び出しが必要となります。そしてその場合、
For Each を使うべきではありません(オブジェクトの明示的な解放手段が失われるため)。

マネージ版であれば、それぞれに IDisposable が実装されているため、
列挙子も For Each ループ後に自動処分されますが、COM 版の場合は
ReleaseComObject を自前で呼ばねばなりません。

以下、ReleaseComObject の使用例。WMI ではなく Excel の場合ですけど。
http://hanatyan.sakura.ne.jp/dotnet/Excel08.htm
http://bbs.wankuma.com/index.cgi?mode=red&namber=54149&KLOG=91

[ツリー表示へ]
タイトルRe^4: 配列を使った記述の簡素化 (解決)
記事No11640
投稿日: 2016/03/09(Wed) 10:21
投稿者食う寝る走る
魔界の仮面弁士さま、アドバイスありがとうございます。
GetObject の COM 版インターフェイスは、手続きが煩雑になるように思えますので
ご指摘のように(質問2)のSystem.Management 名前空間を用いた記述に書き直します。

おかげさまで 記述の簡素化も出来ました。

[ツリー表示へ]