...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

VS2008のC++/CLIで作成したDLLをインストール権限のないPCでC#から使う

背景*1

開発マシンはWindows XP SP3で,VS2008と一緒に.NET 3.5 SP1が入っている.
ターゲットマシンはXP SP2の最初の状態で,.NET 2.0が入っていて,msvc*90.dll などのC++ランタイムライブラリはインストールされていない.

結論

いろいろやったけど全部ダメだった.

方法1

実行ファイルのところに,

 C:\Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.CRT

 (デバッグモードならば,C:\Program Files\Microsoft Visual Studio 8\VC\redist\Debug_NonRedist\x86\Microsoft.VC80.DebugCRT ←Debugモードで配布はしませんけど...)

を,フォルダごとコピーするという処置をとりました.

↑これでも動きますが,こちらも可能です→http://d.hatena.ne.jp/KrdLab/20070224/1172290039

C++/CLIで作成したDLLが正しくロードされない件について(お詫び編) - KrdLab's blog

こんな階層構造でいいのか?

  • cometii.exe
  • comet2clr.dll
  • Microsoft.VC90.CRT\
    • Microsoft.VC90.CRT.manifest
    • msvcr90.dll
    • msvcp90.dll
    • msvcm90.dll

C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
を実行ファイルと同じフォルダに置いたけどダメだった.

方法2

Microsoft.VC80.CRTがmsvcrt80.dllの事で、このマニフェストが無いと共有アセンブリであるmsvcrt80.dll を読み込んでくれないのです・・・て、マニフェストあるだろっ!(^^; 実は、.dllの場合、リソースとして.dllに埋め込んでやる必要があるのです。

$ mt /manifest math.dll.manifest /outputresource:math.dll;#2

最後の#2はリソースIDで、.dllの時は必ず2になります。改めてapp.exeを実行すると今度は実行されます。

2005-11-27 - 匣の向こう側 - あまりに.NETな

自分でコマンドラインからやらなくても,DLLのソリューションのプロパティで,「マニフェストツール>埋め込みマニフェスト>はい」にすればいい?
一応,「いいえ」にしてみたらこういうマニフェストファイルができた.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

「いいえ」のときと「はい」のときでDLLのファイルサイズが違うから,きっと同じマニフェストが埋め込まれているのだと思うのだが・・・.

方法3

Visual Studio 2005 のプロジェクトを利用すれば,デフォルトでマニフェストが埋め込まれます*1.

後は,ビルドに使用した Visual Studio のバージョンにあった vcredist_x86.exe をインストールすれば動作します.

C++/CLIで作成したDLLが正しくロードされない件について(追加編) - KrdLab's blog

やっぱりマニフェストは埋め込まれるらしい.
でもvcredist_x86.exeのインストール権限がないからこれじゃダメ.

方法4

作ったのがEXEではなくDLLの場合はどうすればいいのかよくわからない・・・.

方法5

1.ターゲット コンピュータで使用するフォルダ構造と同じフォルダ構造を、開発用コンピュータ上に作成します。たとえば、\bin フォルダを作成し、そこに myapplication.exe をコピーします。次に、\bin\mylibrary フォルダを作成し、そこに MyLibrary.dll をコピーします。

2.開発用コンピュータで、%PROGDIR%\Microsoft Visual Studio 8\VC\Redist\x86 から \bin および \bin\MyLibrary に Microsoft.VC90.CRT および Microsoft.VC90.MFC をインストールします。

3.ターゲット コンピュータに \bin フォルダをコピーします。ターゲット コンピュータがマニフェストベースのバインディングをサポートしている場合 (Windows XP Home Edition、Windows XP Professional、Windows Server 2003Windows Vista)、それ以上の準備は必要ありません。このサポートがないコンピュータ (Windows 98Windows 98 Second Edition、Windows Millennium EditionWindows 2000) では、Microsoft.VC90.CRT と Microsoft.VC90.MFC がパスに存在する必要があります。

方法 : XCopy を使用して配置する

DLLにマニフェストを埋め込んで,これやってみたが,動かなかった.

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembl
y 'comet2clr, Version=1.0.3165.33087, Culture=neutral, PublicKeyToken=null' or o
ne of its dependencies. このアプリケーションの構成が正しくないため、アプリケーシ
ョンを開始できませんでした。アプリケーションを再度インストールすることにより問題
が解決する場合があります。 (Exception from HRESULT: 0x800736B1)
File name: 'comet2clr, Version=1.0.3165.33087, Culture=neutral, PublicKeyToken=n
ull' ---> System.Runtime.InteropServices.COMException (0x800736B1): このアプリケ
ーションの構成が正しくないため、アプリケーションを開始できませんでした。アプリケ
ーションを再度インストールすることにより問題が解決する場合があります。 (Exceptio
n from HRESULT: 0x800736B1)
   at cometii.Form1..ctor()
   at cometii.Program.Main()

*1:あとで追加しました.