Visual Studio2013(VC++)でVisual Studio2010以前に作成したDirectShowを含んだプログラムをビルドするときの対応

2019年6月20日

Visual C++プロパティページ全般

はじめに

DirectShowを使ったプログラムはVisual C++6.0の頃から脈々と作り続けているわけだが、SDKのバージョンを最新のものにするなどの必要はあったものの、コンパイラーのバーションを変更しただけでビルドがエラーになることは少なくともなかった。

今回、Visual Studio2010からVisual Studio2013へ開発環境を上げたときに遭遇した時に発生したエラーとその対処方法をまとめた。

開発環境のOSはWindows7なのでWindows8以降の場合にどのようになるかは未検証である。また、DirectShowに限らずDirectX SDKを使用している場合にも発生するようだが(他にも発生するライブラリがあるかもしれない)、DirectShow以外のDirectXを使用したプログラムを書いていないので真偽のほどは確かめていない。

Visual Studio2013で2010以前のプロジェクトの読み込み

これまでVisual Studio2010以前で正常にビルドできていたプロジェクトをVisual Studio2013で読み込む。

そのままビルドするとVisual Studio2010が併存している環境ではVisual Studio2010のコンパイラを呼び出してビルドしてしまうので、普通にビルドできてしまうので、以下の手順でVisual Studio2013のコンパイラを使ってビルドするように設定し直す。

ソリューションエクスプローラーで対象となるプロジェクトを選択した上で、メニューの[プロジェクト]からプルダウンの一番下にある[プロパティ]を選択する。

Visual C++プロパティページ全般

構成プロパティ[全般]にあるプラットフォームツールセットが「Visual Studio2010(v100)」となっているので、プルダウンメニューを表示させて「Visual Studio2013(v120)」を選択する。

Visual C++プロパティページ全般_プラットフォームツールセットプルダウンメニュー(V120)

これで設定終了でメニューの[ビルド]から[ソリューションのビルド]を選択するとビルドが実行される。

ビルドエラーの状況

通常であればこれで何事もなくビルドは完了するのだが、次のようなエラーが出てビルトが失敗する。

stdafx.cpp
c:\program files\microsoft sdks\windows\v7.1\include\sal_supp.h(57): warning C4005: __useHeader : マクロが再定義されました。
 c:\program files (x86)\microsoft visual studio 12.0\vc\include\sal.h(2886) : __useHeader の前の定義を確認してください
c:\program files\microsoft sdks\windows\v7.1\include\specstrings_supp.h(77): warning C4005: __on_failure : マクロが再定義されました。
 c:\program files (x86)\microsoft visual studio 12.0\vc\include\sal.h(2896) : __on_failure の前の定義を確認してください
c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlcore.h(633): error C2039: SetDefaultDllDirectories : `global namespace のメンバーではありません。
c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlcore.h(633): error C2065: SetDefaultDllDirectories : 定義されていない識別子です。
c:\program files (x86)\microsoft visual studio 12.0\vc\atlmfc\include\atlcore.h(635): error C2065: LOAD_LIBRARY_SEARCH_SYSTEM32 : 定義されていない識別子です。

========== すべてリビルド: 0 正常終了、1 失敗、0 スキップ ==========

「error C2039: 'SetDefaultDllDirectories’ : '`global namespace" のメンバーではありません。」の部分をダブルクリックしてatlcore.hを表示すると下記のようなコードが出てくる。

#ifndef _USING_V110_SDK71_
	// the LOAD_LIBRARY_SEARCH_SYSTEM32 flag for LoadLibraryExW is only supported if the DLL-preload fixes are installed, so
	// use LoadLibraryExW only if SetDefaultDllDirectories is available (only on Win8, or with KB2533623 on Vista and Win7)...
	IFDYNAMICGETCACHEDFUNCTION(L"kernel32.dll", SetDefaultDllDirectories, pfSetDefaultDllDirectories)
	{
		return(::LoadLibraryExW(pszLibrary, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32));
	}

	// ...otherwise fall back to using LoadLibrary from the SYSTEM32 folder explicitly.
#endif

「#ifndef _USING_V110_SDK71_」ということで _USING_V110_SDK71_が定義されていないとSetDefaultDllDirectoriesの存在をチェックしにいくようだ。

ならばと「#define _USING_V110_SDK71_」を「stdafx.h」で記述すると無事ビルド完了した。

これで本当に解決なのか?

本件ネットで検索しても「#define _USING_V110_SDK71_」を各ソースコードの先頭に記述するという解決方法が主流である。Visual Studio2010以前の環境とクロスコンパイルするようなときは「#define _USING_V110_SDK71_」がなんらかしらの影響を与えないか気になったが、私が書いたプログラムの範囲内では特段の影響は確認されなかった。

調べた中で他の解決方法もあった。というかこちらの方がむしろ正当な解決方法のようである。

1つめがプロジェクトのプロパティダイヤログにあるプラットフォームツールセットの設定値を「Visual Studio 2013 – Windows XP (v120_xp)」にするという方法。

Visual C++プロパティページ全般_プラットフォームツールセットプルダウンメニュー(V120_xp)

2つめがプロジェクトのプロパティダイヤログの構成プロパティ[C/C++]-[プリプロセッサ]にある「プリプロセッサの定義」に「 _USING_V110_SDK71_」を追加する方法

Visual C++プロパティページ_C++_プリプロセッサ

プリプロセッサの定義_プルダウンメニュー

プリプロセッサの定義

1つめの方法を行ったときのプリプロセッサの定義を見ると継承の値に _USING_V110_SDK71_」が追加されているのがわかる。

プリプロセッサの定義

プラットフォームツールセットの設定値を「Visual Studio 2013 – Windows XP (v120_xp)」にすることはWindows XPでも動作するバイナリファイルをビルドすることなのでここの設定以外にもWindows XPでの動作に必要な設定がされている。

この二つの方法のいずれかを用いるとソースコードに手を加えなくてもビルドできるようになる。

「 _USING_V110_SDK71_」からもわかる様にVisual Studio2012(VC++2012のバージョンナンバーがv11)からこの仕様になった。

Wikipediaによると「Windows SDK バージョン 8.0 以降は、DirectX SDK は Windows SDK に統合された。DirectX 関連ツール類もリニューアルされたものが Visual Studio 2012 以降に統合されている」となっている。

開発環境のOSがWindows7であるためVisual Studio2012以降の場合標準ではSDK内部にDirectX関連が含まれている仕様になり、これらを呼び出すために「_USING_V110_SDK71_」を明示的に示さなければならないのではないかと推測している。

そのことはWindows 8以上のOSでビルドするときに検証してみたいと思う。