注意:この記事は、2015年8月31日時点でVisual Studio 2015 RTMを対象として書きました。今後のVisual Studio 2015のアップデート次第で、状況は変化すると考えられます。ご注意ください。

2016年4月19日追記:Visual Studio 2015 Update 1で変わりました。今後はUCRTをアプリと同じフォルダに置く (VS2015 Update 1以降)をご覧ください。

今回は、Visual C++ 2015製のデスクトップアプリケーションを配るにあたり、ユニバーサルCRT (Universal CRT, UCRT)とVC++ランタイムを同梱する方法についてです。

UCRTとVC++ランタイムのDLLは、アプリのEXEやDLLと同じフォルダに置けば動作します。「アプリ全体をZIPファイルに固めたり、MSIに固めたりしつつ、利用者にVC++ランタイムのインストールを要求しない」かつ「静的リンクは無理」を両立させるにはこの方法しかありません。

UCRTのDLLをアプリと同じフォルダに置くことは、Visual Studio 2015 RTM Now Available – Visual C++ Team Blogの2件目のコメント(James McNellis, 20 Jul 2015 8:18 AM)に書かれています。

ただし、現状ではその手順において少し注意が要るので、ここにまとめます。

手順

と言っても、難しいことはありません。適当な場所にあるDLLを集めて、アプリのEXEやDLLと同じフォルダに置くだけです。問題は、UCRTのDLLファイルがどこにあるかということだけなんです。

DLLの場所

種類別に紹介していきます。なお、この先現れるC:\Program Files (x86)は、環境に応じて適当に読み替えてください。

UCRT(リリースビルド用)

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Remote Debuggerx86またはx64にある以下のファイルです。

  • api-ms-win-core-console-l1-1-0.dll
  • api-ms-win-core-datetime-l1-1-0.dll
  • api-ms-win-core-debug-l1-1-0.dll
  • api-ms-win-core-errorhandling-l1-1-0.dll
  • api-ms-win-core-file-l1-1-0.dll
  • api-ms-win-core-file-l1-2-0.dll
  • api-ms-win-core-file-l2-1-0.dll
  • api-ms-win-core-handle-l1-1-0.dll
  • api-ms-win-core-heap-l1-1-0.dll
  • api-ms-win-core-interlocked-l1-1-0.dll
  • api-ms-win-core-libraryloader-l1-1-0.dll
  • api-ms-win-core-localization-l1-2-0.dll
  • api-ms-win-core-memory-l1-1-0.dll
  • api-ms-win-core-namedpipe-l1-1-0.dll
  • api-ms-win-core-processenvironment-l1-1-0.dll
  • api-ms-win-core-processthreads-l1-1-0.dll
  • api-ms-win-core-processthreads-l1-1-1.dll
  • api-ms-win-core-profile-l1-1-0.dll
  • api-ms-win-core-rtlsupport-l1-1-0.dll
  • api-ms-win-core-string-l1-1-0.dll
  • api-ms-win-core-synch-l1-1-0.dll
  • api-ms-win-core-synch-l1-2-0.dll
  • api-ms-win-core-sysinfo-l1-1-0.dll
  • api-ms-win-core-timezone-l1-1-0.dll
  • api-ms-win-core-util-l1-1-0.dll
  • api-ms-win-crt-conio-l1-1-0.dll
  • api-ms-win-crt-convert-l1-1-0.dll
  • api-ms-win-crt-environment-l1-1-0.dll
  • api-ms-win-crt-filesystem-l1-1-0.dll
  • api-ms-win-crt-heap-l1-1-0.dll
  • api-ms-win-crt-locale-l1-1-0.dll
  • api-ms-win-crt-math-l1-1-0.dll
  • api-ms-win-crt-multibyte-l1-1-0.dll
  • api-ms-win-crt-private-l1-1-0.dll
  • api-ms-win-crt-process-l1-1-0.dll
  • api-ms-win-crt-runtime-l1-1-0.dll
  • api-ms-win-crt-stdio-l1-1-0.dll
  • api-ms-win-crt-string-l1-1-0.dll
  • api-ms-win-crt-time-l1-1-0.dll
  • api-ms-win-crt-utility-l1-1-0.dll
  • ucrtbase.dll

UCRT(デバッグビルド用)

デバッグビルドでは、ucrtbase.dllの代わりにucrtbased.dllが必要です。これはどこにもないので、System32やSysWOW64フォルダから拝借するしかなさそうです。

Visual C++ 2015ランタイム(リリースビルド・デバッグビルド)

Visual C++ 2015のランタイムは、従来どおりC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist内にあります。いろいろあるので、適宜選び出しましょう。何が必要か分からなかったら、自分のEXEやDLLをDependency Walker (depends.exe)に食わせましょう。

DLLの場所の理由

ここから余談です。

なぜ、このリモートデバッガのフォルダにあるファイルを使うのかというと、つまりVisual Studio 2015 RTMのバグです。上記コメントによれば、「これらのファイルは本来C:\Program Files (x86)\Windows Kits\10\Redist\ucrtにあるのだが、Visual Studio 2015 RTMでは、誤って間違ったものになってしまい、使い物にならない」と書かれています。

続けて「vcredist_…を実際にインストールして取り出してね」と書かれているのですが、リモートデバッガのところに同じものがあることに気付いたのです。念のため、SHA-1の一致を確かめました。というわけで、これを使うほうが簡単だと考えました。

Visual Studio 2015をインストールしていれば、当然System32やSysWOW64にもこれらのファイルは存在します。ただ、Windows Updateなどでファイルが変化する可能性はないかなと思い避けました。過剰な心配だとは思います。おそらく、それより先にRedist\ucrtが直る更新が来る可能性のほうが高いでしょう。

UCRTのDLLはどこまで必要か?

実は、上記リモートデバッガのフォルダにあるファイルは、vcredist_x86.exeやvcredist_x64.exeでインストールされるものと比べ、少し足りません。

  • api-ms-win-core-xstate-l2-1-0.dll
  • api-ms-win-eventing-provider-l1-1-0.dll

ただ、私がいくつかビルドしてみた限り、このファイルに依存を持つものはありませんでした。もちろん、他のUCRTやVC++ランタイムからもこのファイルに依存関係があるDLLはありませんでした。そのため、今のところ私は不要そうだと判断しています。

まとめ

Visual C++ 2015でデスクトップアプリを製作した際、ユニバーサルCRT (UCRT)とDLL版VC++ランタイムをアプリに同梱するための手順を書きました。UCRTのApp-localな配置が認められ、大変ほっとしています。冒頭にも書いたように、ZIPに圧縮するだけだったり、MSIで頒布したかったりする場合には、こうするしかないからです。

なお、「静的リンクは無理」な状況には、C++/CLIやC++/CXを使う場合があります。そもそも、静的リンクは推奨されていないので、「静的リンクにする強い理由がないから」と言い換えても良いと思います。

2015年9月19日編集: uCRTをUCRTに置き換えました。


スポンサード リンク

この記事のカテゴリ

  • ⇒ UCRTをアプリと同じフォルダに置く (VS2015 RTM)