Windows 秘話Windows では可能でも行わないことがある

Raymond Chen

実は、Windows では元の DLL の名前を変更し、そこに新しいファイルをコピーすることで、使用中の DLL を置き換えることができます。しかし、Windows ではこの処理が行われていません。なぜでしょう。

使用中のファイルを置き換えても、古いバーションを使用するコードがまだシステム内に存在する可能性があります。たとえば、A.DLL と B.DLL という 2 つのファイルがあり、連携しているとしましょう。両方のファイルを更新する修正プログラムを実行しますが、A.DLL は使用中です。問題ありません。ファイルを 2 つとも置き換えるだけです。この結果、A.DLL を使用中のプログラムでは引き続き古いバージョンが使用されますが、新しいプログラムでは新しいバージョンが使用されます。また、すべてのプログラムで新しいバージョンの B.DLL が使用されます。

ここで、古い A.DLL を使用中のプログラムで、関数を呼び出すことになります。当然、このプログラムでは古いバージョンの B.DLL を想定しますが、呼び出されるのは新しいバージョンの B.DLL です。B.DLL に加えた変更内容によっては、この呼び出しが成功する場合もありますが、クラッシュする場合もあります。どちらの DLL も、もう一方の DLL が同じ一致する組み合わせの DLL だと想定しています。

依存関係の無い 1 つの DLL だけを更新する場合でも、やはり問題が発生する可能性があります。なぜなら、DLL は以前のバージョンの DLL 自体と相互運用する必要があるためです。

ole32.dll を使用中に置き換えるとしましょう。その後、新しく起動されたプログラムでは新しい ole32.dll が呼び出され、ドラッグ アンド ドロップ操作が開始されるとします。ユーザーは、更新前に起動したプログラムの 1 つによって作成されたウィンドウに、オブジェクトをドラッグします。その結果、新しい ole32.dll から古い ole32.dll にメッセージが送信されることになります。

2 つのプロセス間で通信を行うコードを作成する場合、通信チャネルの両端のエンドポイントで通信方法が一致している必要があるため、通常は両方のプロセスで同じバージョンのコードが実行されると想定します。「"テキストを要求します" という意味のメッセージ 5 を送信するので、"これが要求されたテキストです" という意味のメッセージ 12 を返信して応答してもらいたい」。このような場合、両端で同じバージョンのコードを実行していないと、通信メカニズムが異なる場合があります。違いは非常に小さいこともありますが、本当に互換性がなくなるおそれもあります。

構造体にフィールドを追加し、その構造体がメッセージ 5 の一部に使用されているとしましょう。さあ、たいへんです。古い構造体を使用するメッセージと、新しい構造体を使用するメッセージという、2 つの互換性のないバージョンのメッセージ 5 が存在することになります。通信の両端で構造体が異なっていると、メッセージ 5 は機能しません。

古いバージョンと新しいバージョンのサイド バイ サイド実行をサポートする場合は、たとえば、メッセージ 52 などの新しいメッセージを作成して、新しいバージョンの DLL でメッセージ 5 とメッセージ 52 の両方をサポートする必要があります。この DLL では、最初にもう一方で実行されている DLL のバージョンを確認してから、適切なメッセージを送信する必要があります。

構造体自体を変更していなくても、構造体のフィールドの一部の意味を変更していることもあります。構造体に列挙体が含まれており、新しいバージョンでその列挙体に新しい値が追加される場合でも、古いバージョンと新しいバージョンの間の互換性がなくなります。

確かに、更新プログラムを公開するたびに新しいメッセージを定義して、2 つの競合するバージョンの DLL が同時に実行されている間は古いバージョンと新しいバージョンの間の相互運用をサポートするコードを作成することもできます。しかし、3 つ目の更新プログラムに取りかかって、4 つの異なるセットのメッセージ (元のバージョンと各更新プログラムに対して 1 つずつ) が存在するとなると、もはや手に負えなくなる可能性があります。

更新プログラムを順番にインストールするよう求めても、労力はまったく減りません。元のプログラムを実行し続けることができるのであれば、元のプログラムと相互運用し続ける必要があります。

そして、記事の執筆者たちに、更新プログラムの公開があまりにも遅くて無能だと不平を言われます。

だからといって、Windows では、使用中のファイルを置き換えた場合に再起動する必要があるわけではありません。Windows では、再起動しない場合に発生する複雑さを回避しているだけです。エンジニアリングというものは、トレードオフの集まりです。推奨している安定した構成ですらない状況のために、わざわざ古いバージョンのプログラムをサポートすることはありませんね。

Raymond Chen は自身の Web サイト「The Old New Thing」および同じタイトルの書籍で、Windows の歴史と Win32 プログラミングについて扱っています。彼は皆さんが無事に帰宅されることを願っています。