Windows XP がもたらす Visual Basic デベロッパーへの福音

~ 第 2 回: 新しいサイド バイ サイド技術 ~

Shozo Arai (荒井 省三)
マイクロソフト株式会社
デベロッパー・マーケティング本部

February 7, 2002

目次

はじめに
COMCTL32.DLL バージョン 6
ActiveX DLL でのサイド バイ サイドの利用
まとめ
次回について


はじめに

前回は Windows XP の視覚スタイルの概要と Visual Basic 6.0 を使って 視覚スタイルを利用した Visual Basic アプリケーションの作成方法と問題点を説明しました。今回は、視覚スタイルの裏側で活躍している COMCTL32.DLL バージョン 6 や Windows 2000 から更に進化したサイド バイ サイド技術の説明と Visual Basic で作成する ActiveX DLL において、どのような恩恵があるかを説明いたします。

COMCTL32.DLL バージョン 6

Windows XP では、COMCTL32.DLL のバージョン 6 が新しく導入されています。この COMCTL32.DLL を使って 視覚スタイルを表示しています。テーマの切り替えは、テーマ マネージャ Uxtheme.dll を通じて COMCTL32.DLL のバージョン 6 とバージョン 5 を切り替えることで行っているのです。COMCTL32.DLL のバージョン 5 (図 1 ) とバージョン 6 (図 2 ) について説明します。Windows 2000 のコントロールでは、

図1. Windows 2000 のコントロール

 

図 2. Windows XP のコントロール

USER32.DLL、WIN32.SYS や COMCTL32.DLL バージョン 5 にコントロールが組み込まれています。Windows XP では、USER32.DLL、WIN32.SYS や COMCTL32.DLL バージョン 5 に含まれているコントロールを統合した COMCTL32.DLL バージョン 6 が存在します。Windows XP では、明示的に COMCTL32.DLL バージョン 6 を使用すると宣言しない限り、COMCTL32.DLL バージョン 5 が使用されます。このように、COMCTL32.DLL の複数バージョンがサイド バイ サイド技術を使って共有されています (Windows 2000 では、EXE 名 .local というファイルを配置することでサイド バイ サイドを実現していました。詳しくは 「アプリケーションで共有するサイド バイ サイドコンポーネントの実装 (拡張)」 をご参照ください)。この技術は、.NET Framework をフルサポートすることを目標に DLL Hell の解消、バージョン競合の解消、容易な配置、容易な環境設定 (NoMore リブート) をサポートすることを前提にしています。この目標を達成するために Windows XP では、COMCTL32.DLL バージョン 6 や GDI + 等を共有アセンブリとして組み込んでいます。共有アセンブリのインストール場所は「%SYSTEMROOT%\WinSxS」です (通常は、C:\Winnt\ WinSxS です)。共有アセンブリと従前の %SYSTEMROOT%\SYSTEM32 にインストールされる共有 DLL の主要なものを表1に抜粋します。

配置場所 サブディレクトリー又はファイル名 説 明
WinSxS Manifests 共有コンポーネントのマニフェスト
x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.0.0_x-ww_1382d70a COMCTL32.DLL V6コンポーネント
x86_Microsoft.Windows.GdiPlus_6595b64144ccf1df_1.0.0.0_x-ww_8d353f13 GDI+コンポーネント
x86_Microsoft.Windows.CPlusPlusRuntime_6595b64144ccf1df_7.0.0.0_x-ww_2726e76a VC++のランタイム
x86_Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries_6595b64144ccf1df_6.0.0.0_x-ww_ff9986d7
x86_Microsoft.Tools.VisualCPlusPlus.Runtime-Libraries.Resources_6595b64144ccf1df_6.0.0.0_ja-JP_8a84acaa
System32 COMCTL32.DLL COMCTL32.DLL V5コンポーネント
MSVCRT.DLL VC++のランタイム

表1.共有アセンブリの抜粋

 

共有アセンブリが導入されたことにより、VC++ のランタイムや COMCTL32.DLL を原因とする DLL の競合は解決されます (思い起こせば、IE3.X がリリースされたときの問題が解消されるのです)。このサイド バイ サイドの仕組みをご覧になられた方は、「あれ?」と思われたかもしれません。「マニフェスト」「アセンブリ」という用語をどこかでお聞きになられた方達も多いことと思います。そうです、.NET Framework の配布単位がアセンブリと呼ばれ、アプリケーションの自己記述情報 (バージョン情報や関連モジュール情報等) がマニフェストと呼ばれていたのです。この サイド バイ サイド技術は、Windows 2000 と Windows 98 Second Edition に始まり、.NET Framework 向けに進化し、Windows XP で Platform 向けに最適化されて進化してきたのです。

WinSxS にインストールされる共有アセンブリは、.NET Framework と同様にストロングネームを必要とします。インストールするには、Windows Installer でインストールを行う必要があります。このように共有アセンブリは厳密に管理されますので、DLL の競合が発生する可能性を低くすることが可能になるのです。後は、皆さんが配布されるアプリケーションのインストールフォルダに共有コンポーネントも一緒に配布して、アプリケーション マニフェストを配置すれば DLL Hell から脱出することが可能になります。今後は、%SYSTEMROOT%\SYSTEM32 フォルダに共有コンポーネントを配布しないようにすれば良いのです。ここまで読まれた方たちは、「関数をエキスポートできるダイナミックリンクライブラリは Windows 2000 でも実現されていたし、COM に関してはどうなんだ?」 という疑問を持たれたことと思います。Windows 2000 では DLL/COM リダイレクションがありましたが、Windows XP では更に進化した COM のサポートがあります。

ActiveX DLL でのサイド バイ サイドの利用

これから Visual Basic で作成する ActiveX DLL のサポート (COM のサポート) がどうなったのかについて説明していきたいと思います。手始めに、簡単な ActiveX DLL (リスト 1 ) と利用する Visual Basic アプリケーション (リスト 2 ) を作成してみます。このアプリケーション (Project1.exe) を実行した様子を図 3 に示し、レジストリの情報を図 4 に示します。

Public Function Add(ByVal lngA As Long, ByVal lngB As Long) As Long

'   ActiveX DLLの例

'   加算結果を戻すメソッド

'

    Dim lngResult As Long

    lngResult = lngA + lngB

    MsgBox "結果=" & CStr(lngResult), vbOKOnly, "Side-by-Side Comへようこそ"

    Add = lngResult

End Function

リスト 1. ActiveX DLL (プロジェクト名: ComTest、クラス名 : SideBySide)

 

Private Sub Command1_Click()

'   ActiveX DLLを利用するアプリケーション

'   ProgId=ComTest.SideBySide を使用する

'

    Dim objComTest As ComTest.SideBySide

    Dim lngResult As Long

    Set objComTest = New ComTest.SideBySide

    lngResult = objComTest.Add(CLng(txtA.Text), CLng(txtB.Text))

    txtResult.Text = CStr(lngResult)

    Set objComTest = Nothing

End Sub

リスト 2. ActiveX DLL を利用する Visual Basic アプリケーション (プロジェクト名 : Project 1 )

 

図3. Visual Basic の ActiveX DLL を実行したところ

図4. ComTest.SideBySide のレジストリ登録情報

図 3 と図 4 を見れば、VB で作成した ActiveX DLL の動作としては当たり前の動作をしていることをご理解いただけることと思います。それでは、コマンドプロンプトで 「Regsvr32.exe /u ComTest.dll」 を実行し、その結果のレジストリ登録情報を図 5 に示します。

図5. ActiveX DLL を削除した状態のレジストリ情報

図 5 を見ると、きれいにレジストリの登録情報が削除されていることがわかると思います (Windows 2000 までは、レジストリにキーのみのゴミが残っていたことをご存知の方も多いかと思います)。これで、さきほどの 「Project1.exe」 を実行しても、実行することはできなくなります (図 6)。この動作は、レジストリに ActiveX DLL の登録情報がありませんので当然のこととご理解いただけると思います。

図6. Project1.exe の実行時エラー

次に、アプリケーション マニフェストをリスト 3 のように記述します。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 

    <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" 

                      name="Microsoft.SidebySide.Test" type="win32" /> 

    <description>サイドbyサイドのテスト(XP)</description> 

    <file name="ComTest.dll"> 

        <comClass  

            clsid="{12A129C3-E5E5-4635-894F-BE4EAB24CA68}" 

            progid="ComTest.SideBySide" /> 

    </file> 

</assembly>

リスト 3. ActiveX DLL で使用するアプリケーション マニフェスト

マニフェストに記述したクラス ID は、レジストリエディタか OLE VIEW (Visual Studio6.0 に付属) で調べることができます (筆者の環境では、OLE VIEW で調査しました。レジストリエディタでは、HKEY_CLASSROOT\Prog Id\CLSID キーで調査します)。これで、ActiveX DLL を使用するアプリケーション 「Project1.exe」 を実行してみます (図 7)。

図7. マニフェスト記述後の実行例

図 3 と同じように実行できたことが確認できたと思います。この時のレジストリ情報を検索しても、図 5 と同様にレジストリに登録情報を発見することはできませんでした。Windows 2000 の COM リダイレクションでは、.local を配置していましたがレジストリ登録情報を必要としていました。明らかに、Windows 2000 のサイド バイ サイド技術より進化しているのが伺えることと思います。

では、ダイナミックリンクライブラリを明示的にマニフェストで指定するにはどうすれば良いのでしょうか。マニフェストの具体例をリスト 4 に示します。このように指定すれば、アプリケーションのインストール

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 

    <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" 

                      name="Microsoft.SidebySide.Test" type="win32" /> 

    <description>サイドbyサイドのテスト(XP)</description> 

    <file name="msvcrt.dll"/> 

    <file name="msvcrt40.dll"/> 

</assembly>

リスト 4. プライベートダイナミックリンクライブラリの指定

フォルダにインストールしたダイナミックリンクライブラリを明示的に指定することが可能となるのです。ここまで説明してきたマニフェストに記述するノードを表 2 で説明します。

ノード/アトリビュート名 備 考
AssemblyIdentity アプリケーション毎に一つ。 dependencyAssembly ノードのノードしては、サイド バイ サイド使用のアセンブリを指定します。
  version アプリケーションやサイド バイ サイドアセンブリのバージョンで、メジャー.マイナー.ビルド.リビジョンを指定します。
peocessorArchitecture 「x86」か「ia64」を記入します。
name 一意になるアプリケーション名 (組織.部門.アプリケーション名) かアセンブリ名を指定します。
type アプリケーションタイプを指定します。「win32」
publicKeyToken 16 文字の SHA-1 ハッシュ値を指定します。
language 言語識別子を指定します (DHTML の言語コードです)。「*」
dependencyAssembly サイド バイ サイド使用するアセンブリを dependencyAssembly ノードを使って指定します。
file COM やプライベートアセンブリ (MSVCRT.DLL 等) を指定するノードです。
  name ファイル名を指定します。
comClass COM の場合に、file ノードの子ノードとして COM 関係の情報を以下のアトリビュートで指定します。
  description 説明。例えば、「Font Property Page」など。
clsid クラス ID を指定します。
progid プログラムID (COM のフレンドリー名)を指定します。
thredingModel スレッドモデルを指定します。例えば、「Both」など。
tlbid タイプライブラリ ID を指定します。
version バージョンを指定します。
helpdir ヘルプファイルのフォルダを指定します。

表 2. マニフェストの記述内容の説明 (抜粋)

表 2 で説明したアトリビュートは全てが必須ということではありません。リスト 3 のように省略も可能です。マニフェストの XML のエンコード (<?xml version="1.0" encoding="UTF-8"?>) には UTF-8 が指定されていますが、Windows XP では UTF-8 と UTF-16 がサポートされています (お勧めは UTF-8 ですが)。ここで説明した以外に、COM のサポートがマニフェストにあります。それは、ProxyStub を使用する COM コンポーネントです。ProxyStub を使用する COM コンポーネントの場合には、「comInterfaceExternalProxyStub」 ノードを記述することで対応することができます。更に、COMCTL32.DLL のようなコントロールであれば 「windowClass」 アトリビュートを指定して、特定のウインドウクラスのみを使用させることもできます。これらの指定方法は、ここでは説明を割愛させていただきますので、ご興味のあるかたは MSDN オンラインの記事 「How To Build and Service Isolated Applications and Side-by-Side Assemblies for Windows XP」をご参照下さい。

今回のまとめ

如何でしたでしょうか。VB で作成した ActiveX DLL がレジストリを使わないで動作したことをご理解いただけたことと思います。Windows XP のサイド バイ サイド技術は、Windows 2000 を第一世代とするならば格段に向上しているのがご理解いただけたと思います。完成した ActiveX DLL と Visual Basic アプリケーションの配布ですが、アプリケーション マニフェストと一緒にインストールフォルダにコピーするだけで動作します (但し、「VB6.0 のランタイムが配布されていれば」との条件がつきますが)。つまり、.NET Framework が提唱する XCOPY ライクな配布が限定的ながら実現されているのが、ご理解いただけることと思います。つまり、COM や DLL のバージョン毎の整合性の確認の工数を格段に減らす手段ができたということです。

最後になりましたが、XCOPY ライクな配布が限定的と申し上げましたのは、Windows XP で採用されたサイド バイ サイド技術で XCOPY ライクな配布が実現できるアプリケーションは、スタンドアロン形式の実行モジュール (EXE) だけになります。Active Server Pages などの世界には、まだ適用することができません。ですが、読者の皆様が作成された過去の Visual Basic アプリケーションを Windows XP へ安全に移行する手段が存在することを本コラムを通じて、ご理解頂けたのではないかと思います。Windows XP へ移行される場合は、アプリケーション マニフェストを記述して、十分なテストを行うことだけです。本コラムは 「Windows XP がもたらす Visual Basic プログラマーへの福音」と題してお届けしています。もう皆様には、お解かりのことと思いますが、「福音」とは、視覚スタイルを Visual Basic の生産性を活かして活用する方法とサイド バイ サイドを利用しての容易な配布が実現できることを指して名付けました。つまり、DLL Hell の解消が一歩進んだことを皆さんに、お知らせしたかったのです。

次回について

次回で本コラムは最終回になります。第 1 回で 視覚スタイルを取り上げ、第 2 回でサイド バイ サイドを取り上げました。次回は、.NET Framework を含めて新しい開発環境である Visual Studio.NET とサイド バイ サイドの将来性についても触れていきたいと考えております。それでは、次回まで、しばしのお別れです。


Shozo Arai: マイクロソフトのテクニカルエバンジェリストとして、デベロッパー向けに .NET Framework 技術を中心とした啓蒙活動をしています。現在注目しているのは .NET におけるスケーラビリティの向上技術や互換性技術です。


 

ページのトップへ