WMIを使用してディスプレイの接続方法を取得

icon 項目のみ表示/展開表示の切り替え

概要

 WMI(Windows Management Instrumentation)を使用して接続されている全部のディスプレイの接続方法を取得してコマンドプロンプトに表示します。
 以下に本プログラムを実行結果を記載します。
VideoOutputTechnology:-2147483648 INTERNAL
VideoOutputTechnology:5 HDMI
いずれかのキーを押すとプログラムを終了します。
 WMIはWindowsのシステム管理を行うためのインターフェースで主にスクリプトやプログラム言語でシステムイベント、システムの設定や状態の変更が可能である。  WMIは名前空間(このプログラムではroot¥¥WMIを指定)とクラス(このプログラムではWmiMonitorConnectionParamsを指定)を指定して情報を取得する。
 動作確認は、以下の環境で実施しました。
 lenovo YogaPro3の内臓ディスプレイ(13.3インチ 3200*1800画素)とHDMI接続で TV(JLCD32V-KW J-techno(32型 1920*1080画素 70.84㎝*39.85㎝)を使用したデュアルディスプレイ環境。
TVのサイズは以下の式で計算した。


 なお、WMIの名前空間とクラス名を調べるにはhttps://forest.watch.impress.co.jp/docs/review/702170.html SimpleWMIViewというフリーソフトが便利である。

コンパイル方法

 Visual C++ 2008 Express Edition又はVisual C++ 2013 Expressで動作確認をしている。動作OSはWindows 32bit/64bit

プログラムソースの概要

WmiMonitorConnectionParams.cpp

_tmain

 WMIはCOM(Component Object Model)サーバーであり本プログラムはサーバに接続するクライアントとなる。
 CoInitializeExによりCOMライブラリを初期化します。WMIクライアントのスレッドはマルチスレッドで動作する必要があるのでCOINIT_MULTITHREADED DCOMはRPCを引数で指定しています。
 DCOMは内部でRPC使用しておりRPCの通信はセキュリティ情報を設定する必要があるためCoInitializeSecurityによりセキュリティを設定します。
 CoCreateInstanceによりWMIクライアント用のCOMオブジェクトを作成します。
 IWbemServices::ConnectServerによりroot¥¥WMI名前空間に接続します。今回はローカルの名前空間なので第2,第3引数はNULLを指定しています。
 DCOMは内部でRPC使用しておりRPCの通信はセキュリティ情報を設定する必要があるためCoSetProxyBlanketによりセキュリティを設定します。
 IWbemServices::ExecQueryによりWMI(WmiMonitorConnectionParams)クラスを取得します。
 IEnumWbemClassObject::NextによりIWbemClassObjectインスタンス取得します。
 IWbemClassObject::GetによりVideoOutputTechnologyプロパティを検索します。
 intval型が返されるのでvideo_out_type_get関数により接続タイプを示す文字列を検索します。
 VariantClearによりGet関数で作成されたintvalを解放します。
 IWbemServices::Release,IWbemLocator::Release,EnumWbemClassObject::Releaseによりオブジェクトを解放します。
 CoUninitializeによりCOMを解放します。

ソースコード

WmiMonitorConnectionParams.cpp

// WMIを使用してroot¥WMI WmiMonitorConnectionParamsでモニターの入力形式を表示(コマンドプロンプト)
// Visual C++ 2008/2013 UNICODE専用
// 動作例
//  VideoOutputTechnology:-2147483648 INTERNAL
//  VideoOutputTechnology:5 HDMI
//	いずれかのキーを押すとプログラムを終了します。


#define _WIN32_DCOM

#include <comdef.h>
#include <wbemidl.h>
#include <locale.h>
#include <tchar.h>

# pragma comment(lib, "wbemuuid.lib")

WCHAR* WMI_NAME_SPACE=L"root¥¥WMI";

typedef enum _D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY{
	D3DKMDT_VOT_UNINITIALIZED = -2,
	D3DKMDT_VOT_OTHER = -1,
	D3DKMDT_VOT_HD15 = 0,
	D3DKMDT_VOT_SVIDEO = 1,
	D3DKMDT_VOT_COMPOSITE_VIDEO = 2,
	D3DKMDT_VOT_COMPONENT_VIDEO = 3,
	D3DKMDT_VOT_DVI = 4,
	D3DKMDT_VOT_HDMI = 5,
	D3DKMDT_VOT_LVDS = 6,
	D3DKMDT_VOT_D_JPN = 8,
	D3DKMDT_VOT_SDI = 9,
	D3DKMDT_VOT_DISPLAYPORT_EXTERNAL = 10,
	D3DKMDT_VOT_DISPLAYPORT_EMBEDDED = 11,
	D3DKMDT_VOT_UDI_EXTERNAL = 12,
	D3DKMDT_VOT_UDI_EMBEDDED = 13,
	D3DKMDT_VOT_SDTVDONGLE = 14,
	D3DKMDT_VOT_MIRACAST = 15,
	D3DKMDT_VOT_INTERNAL = 0x80000000,

	D3DKMDT_VOT_SVIDEO_4PIN = D3DKMDT_VOT_SVIDEO,
	D3DKMDT_VOT_SVIDEO_7PIN = D3DKMDT_VOT_SVIDEO,
	D3DKMDT_VOT_RF = D3DKMDT_VOT_COMPOSITE_VIDEO,
	D3DKMDT_VOT_RCA_3COMPONENT = D3DKMDT_VOT_COMPONENT_VIDEO,
	D3DKMDT_VOT_BNC = D3DKMDT_VOT_COMPONENT_VIDEO,
}
D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY;

struct VIDEO_OUT_TYPE{
	INT i;
	WCHAR* l;
};

VIDEO_OUT_TYPE video_out_type[] = {
	{ D3DKMDT_VOT_OTHER, L"OTHER" },
	{ D3DKMDT_VOT_HD15, L"HD15" },
	{ D3DKMDT_VOT_SVIDEO, L"SVIDEO" },
	{ D3DKMDT_VOT_COMPOSITE_VIDEO, L"COMPOSITE_VIDEO" },
	{ D3DKMDT_VOT_COMPONENT_VIDEO, L"COMPONENT_VIDEO" },
	{ D3DKMDT_VOT_DVI, L"DVI" },
	{ D3DKMDT_VOT_HDMI, L"HDMI" },
	{ D3DKMDT_VOT_LVDS, L"LVDS" },
	{ D3DKMDT_VOT_D_JPN, L"D_JPN" },
	{ D3DKMDT_VOT_SDI, L"SDI" },
	{ D3DKMDT_VOT_DISPLAYPORT_EXTERNAL, L"DISPLAYPORT_EXTERNAL" },
	{ D3DKMDT_VOT_DISPLAYPORT_EMBEDDED, L"DISPLAYPORT_EMBEDDED" },
	{ D3DKMDT_VOT_UDI_EXTERNAL, L"UDI_EXTERNAL" },
	{ D3DKMDT_VOT_UDI_EMBEDDED, L"UDI_EMBEDDED" },
	{ D3DKMDT_VOT_SDTVDONGLE, L"SDTVDONGLE" },
	{ D3DKMDT_VOT_MIRACAST, L"MIRACAST" },
	{ D3DKMDT_VOT_INTERNAL, L"INTERNAL" },
	{ D3DKMDT_VOT_SVIDEO_4PIN, L"SVIDEO_4PIN" },
	{ D3DKMDT_VOT_SVIDEO_7PIN, L"SVIDEO_7PIN" },
	{ D3DKMDT_VOT_RF, L"RF" },
	{ D3DKMDT_VOT_RCA_3COMPONENT, L"RCA_3COMPONENT" },
	{ D3DKMDT_VOT_BNC, L"BNC" },
	{ 0, 0 } };

WCHAR* video_out_type_get(int x){
	VIDEO_OUT_TYPE* p = video_out_type;
	int n = 0;
	while (p[n].l){
		if (x == p[n].i)
			return p[n].l;
		++n;
	}
	return 0;
}

int _tmain(int argc, TCHAR **argv){

	// UNICODE文字を標準出力に正しく表示させるためにロケールを設定
	_tsetlocale(LC_ALL, _TEXT(""));
	HRESULT hres;

	// COM の実行環境を作成
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres)){
		_tprintf(_TEXT("CoInitializeEx Error¥n"));
        return 1;
    }

    // COMのセキュリティの設定

    hres =  CoInitializeSecurity(NULL,-1,NULL,NULL,RPC_C_AUTHN_LEVEL_DEFAULT,
			RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_NONE,NULL);
    if (FAILED(hres)){
		_tprintf(_TEXT("CoInitializeSecurity Error¥n"));
        CoUninitialize();
        return 1;
    }
    
    // IWbemLocator インターフェースを取得(WMI クライアント)

    IWbemLocator *pLoc = NULL;

    hres = CoCreateInstance(CLSID_WbemLocator,0,CLSCTX_INPROC_SERVER,IID_IWbemLocator, (LPVOID *) &pLoc);
     if (FAILED(hres)){
		_tprintf(_TEXT("CoCreateInstance Error¥n"));
		CoUninitialize();
        return 1;
    }

    // 指定したnamespaceでWMIに接続

    IWbemServices *pSvc = NULL;
 
	hres = pLoc->ConnectServer(_bstr_t(WMI_NAME_SPACE), NULL, NULL, 0, NULL, 0, 0, &pSvc);
    
    if (FAILED(hres)){
		_tprintf(_TEXT("ConnectServer Error¥n"));
        pLoc->Release();     
        CoUninitialize();
        return 1;
    }

    // セキュリティの設定
    hres = CoSetProxyBlanket(pSvc,RPC_C_AUTHN_WINNT,RPC_C_AUTHZ_NONE,NULL,
		RPC_C_AUTHN_LEVEL_CALL,RPC_C_IMP_LEVEL_IMPERSONATE,NULL,EOAC_NONE);

    if (FAILED(hres)){
		_tprintf(_TEXT("CoSetProxyBlanket Error¥n"));
		pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;
    }

    // WMIクラスの取得
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery( bstr_t("WQL"),bstr_t("Select * From WmiMonitorConnectionParams"),
		WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumerator);
    if (FAILED(hres)){
		_tprintf(_TEXT("ExecQuery Error¥n"));
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;
    }

    // プロパティを検索
 
    IWbemClassObject *pclsObj = NULL;
    ULONG uReturn = 0;
   
    while (pEnumerator){
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE,1,&pclsObj, &uReturn);
        if(0 == uReturn){
            break;
        }

        VARIANT vtProp;
		TCHAR* p;
		hr = pclsObj->Get(p=L"VideoOutputTechnology", 0, &vtProp, 0, 0);
		if (hr == S_OK){
			INT b;
			if (vtProp.vt == VARENUM::VT_I4)
				b = vtProp.intVal;
			WCHAR* t = video_out_type_get(b);
			_tprintf(_TEXT("%s:%d %s¥n"), p,b,t);
		}
        VariantClear(&vtProp);

        pclsObj->Release();
    }

    // メモリの解放
    
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
    CoUninitialize();
	_tprintf(_TEXT("いずれかのキーを押すとプログラムを終了します。¥n"));
	_gettchar();
    return 0;
 }

ソースファイルと実行ファイルのダウンロード

ダウンロード wmimonitorconnectionparams.zip(62.7kByte)

ZIPファイルに含まれるファイル
WmiMonitorConnectionParams.cpp
WmiMonitorConnectionParams.exe