注意:この記事は、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 Debugger
のx86
または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に置き換えました。
スポンサード リンク |
この記事のカテゴリ
- VC++ ⇒ UCRTをアプリと同じフォルダに置く (VS2015 RTM)