LAN ケーブルは繋がっていますか?(Part.1)

Windows 2000 以降、メディア検出機能というものが実装されています。
この機能は、ネットワークアダプターに LAN ケーブルが接続されているのか、接続されていないのかを検出する…

メディア検出

つまり、タスクトレイにあるネットワークアイコンに表示されているのは、メディア検出機能?

この機能ですが、上記 KB にあるようにレジストリで OFF にすることができます。

HKLM\System\CurrentControlSet\Services\Tcpip\Parameters

ここに、DWORD で DisableDHCPMediaSense というエントリーを作成します。
値を 1 にすると、メディア検出機能を OFF に、0 にすると ON(デフォルト)にすることができます。
(設定変更後は再起動要) もちろん、上記は Vista 以降の OS でも有効な情報です。

では、メディア検出機能を無効にしてから、LAN ケーブルを抜いてみると…
タスクトレイのアイコンにはバツマークが表示され、ケーブルが繋がっていないことがわかります。
タスクトレイのネットワークアイコンは、メディア検出機能 ON/OFF の影響は受けないようです。

実際のところ、メディア検出機能の中心はネットワークアダプターにバインドされている TCP/IP プロトコルレイヤー
自体の動作になっています。メディア検出機能 が ON になっているときに、LAN ケーブルを 抜いてしまうと、
リンク状態は OFF になり、ネットワークアダプターにバインドされている TCP/IP プロトコルレイヤーがアンロードされ、
IP アドレスが 0.0.0.0 になってしまいます。
OFF の状態だと、リンク状態はそのまま、つまり、TCP/IP プロトコルレイヤーがそのままの状態になっているので
IP アドレスもそのままの状態です。

この投稿の続きを読む

C++ で WMI クラスを使う

WMI は、普段、スクリプトで使うことがほとんどだと思いますが、C++ で使ってみようということで
コーディング方法を紹介します。VB でもなく、.NET でもなく、あえて C++ です…。
COM プログラミングなので、後処理(Release() を呼ぶのが面倒)を楽にするために、ATL のスマートポインタを使います。

今回の例は、WMI の Win32_OperatingSystem クラスを使って、コンピューター種別を調べてみようというシナリオです。
具体的には、Win32_OperatingSystem クラスの ProductType メンバーの値を参照して調べるというものです。
(一部、エラー処理を省いています)

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitialize(NULL);
    HRESULT hRes;

    hRes = CoInitializeSecurity(NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_PKT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        EOAC_NONE,
        0);
    if (SUCCEEDED(hRes))
    {
        CComPtr<IWbemLocator> pIWbemLocator = NULL;
        CComPtr<IWbemServices> pWbemServices = NULL;

        hRes = pIWbemLocator.CoCreateInstance(CLSID_WbemAdministrativeLocator,
            NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER);
        if (SUCCEEDED(hRes))
        {
            CComBSTR bstrNamespace = (L"root\\cimv2");
            hRes = pIWbemLocator->ConnectServer(
                        bstrNamespace,
                        NULL,
                        NULL,
                        NULL,
                        0,
                        NULL,
                        NULL,
                        &pWbemServices);

            CComBSTR strQuery = L"Select * from Win32_OperatingSystem";
            CComBSTR strQL = L"WQL";
            CComPtr<IEnumWbemClassObject> pEnumObject = NULL;

            hRes = pWbemServices->ExecQuery(strQL, strQuery, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumObject);

            ULONG uCount = 1, uReturned;
            CComPtr<IWbemClassObject> pClassObject = NULL;

            hRes = pEnumObject->Reset();
            hRes = pEnumObject->Next(WBEM_INFINITE, uCount, &pClassObject, &uReturned);

            CComVariant var;
            CComBSTR strClassProp = L"ProductType";
            hRes = pClassObject->Get(strClassProp, 0, &var, 0, 0);
            switch (var.intVal)
            {
            case 1: printf("This Computer is Workstation.\n"); break;
            case 2: printf("This Computer is Domain Controller.\n"); break;
            case 3: printf("This Computer is Server.\n"); break;
            default: printf("This Computer is UnKnown Type.\n"); break;
            }
        }
    }

    CoUninitialize();
    return 0;
}

C++ で WMI クラスを使う機会は少ないと思いますが、こんな方法で使うことができます。
他の WMI クラスも上記を参考にすれば、使えると思います。
こういうのを知ると、スクリプトって便利だなって思いますね。

ちなみにですが、WMI 開発の際に使えそうな便利ツールが Microsoft から提供されています。

  1. WMI Code Creator
    スクリプトで WMI を使ってみようなんて思ったら、ぜひ、これを使ってみてください。
    スクリプトコードのサンプルを出力してくれますし、C# や VB.NET のコードも生成できちゃったりします。
  2. WMI Administrative Tools
    この中にある WMI CIM Studio が有益なツールです。WMI の名前空間やクラス構造を調べるのに使うと便利です。

なお、これらのツールは、Windows Vista/Windows 7 でも動きます。