ラベル Visual Studio の投稿を表示しています。 すべての投稿を表示
ラベル Visual Studio の投稿を表示しています。 すべての投稿を表示

2011年9月15日木曜日

64bit環境で動かない.NETアプリ

一部の特殊なアプリを除けば、64bit環境でも従来のアプリはWow64上で普通に動作するものが多いが、たまに.NETアプリは動かないものがある。フックやシェル拡張など他のプロセスに寄生するアプリやドライバならともかく.NETでそんなの書かないのに何故? と不思議に思うだろう。

どういう訳かというと.NETアプリの実行ファイルはコンパイルした段階では純粋なマシン語ではない中間言語で、実行時にCPUのビット数に合ったマシン語に変換される仕組みになっており、同じ実行ファイルでも64bit OS上では64bit, 32bit OS上では32bitで動作する。

ここに一つの罠があって、.NETアプリにはたまにネイティブのDLLを利用しているものがあり、このDLLは始めからマシン語でありコンパイル時に指定したビット数のCPUでしか動作しない。そのため、64bit環境で動作させると.NETアプリのプロセスは64bitで起動して、32bitのDLLを読み込もうとしてエラーとなってしまう。

32bitのネイティブアプリのように始めからWow64上で32bitアプリとして起動させることができれば32bitのDLLでも読み込める。実は.NETアプリのコンパイル時にTarget CPUにx86を選んでいれば、64bit環境でも32bit CPUのマシン語に変換されるため、Wow64が発動してちゃんと動いてくれる。上に書いた罠が発動するのはコンパイル時にTarget CPUにAny CPUを選んでいる場合なのだ。

最近はこのノウハウも広まってきたので、アプリ作者の人もちゃんとコンパイルオプションを選んでくれるし、今動かなくても将来のバージョンアップで動くようになるだろうけど、もう作者の人が更新を止めちゃっている場合はどうしたら良いのか。

実はコンパイルオプションを変えても実行ファイルの大部分である中間言語の部分は全く同じで、ヘッダにあるフラグがちょっと違うだけなので、バイナリエディタで書き換えてやれば良い、というのは大変なのでちゃんとツールがある。

CorFlags.exe "対象の.exe" /32BIT+

問題はこのコマンドは単体では配っていなくて、.NET FrameworkのSDKを入手してインストールしないと使えるようにならないこと。自分はVisual Studio C#のExpress Editionを使っているので始めから入っていたけど、そうじゃない人はちょっと面倒かもしれない。

2011年8月30日火曜日

Visual Studioで外部ツールでソースを更新した時の確認ダイアログがうざい

[ツール]-[オプション]-[環境]-[ドキュメント]-[環境外でのファイルの変更を検出]-[保存する場合、変更を自動的に読み込む]にチェックを入れる。

2011年8月26日金曜日

.NET Framework 4.0でsgen.exeがエラー

Visual Studio C# 2010で対象フレームワークを.NET Framework 4.0にしてプログラムを作成し、sgen.exeを実行したら以下のエラーが発生した。

エラー: 正しくない形式: xxxxxxxx.exe のアセンブリを読み込みしようとしました。
- ファイルまたはアセンブリ 'file:///xxxxxxxx.exe'、またはその依存関係の 1 つが読み込めませんでした。このアセンブリは現在読み込まれているランタイムより新しいランタイムでビルドされているため、読み込むことができません。

3.5以下であれば特にエラーもなく実行できる。
調べたところ、バージョン4.0以降は別の場所においてあるsgen.exeを使わなければいけないらしい。

3.5まで:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\sgen.exe
4.0以降:C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\sgen.exe

2011年8月10日水曜日

インテリセンスのファイル格納場所の変更

Visual Studio C++ 2010で作ったプロジェクトをWebで配布しようとして、圧縮ファイルにするとやけにサイズが大きいことに気が付く。
これはインテリセンスという入力補完などをやってくれる機能があり、この機能がキャッシュファイルなどの一時ファイル的なもの(.sdf、.ipchなど)を作るのだが、その出力先がプロジェクトディレクトリ内であるせいだ。これをプロジェクトディレクトリ内から別の場所にする設定をメモ。

(1) メニューから[ツール]→[オプション]
(2) [テキスト エディター]→[C/C++]→[詳細]にある、[常にフォールバック位置を使用]をTrueに設定し、[フォールバック位置]に適当なディレクトリを選ぶ。