2006 年 7 月 1 日 16 時 57 分

ショートカットを読む


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


続いて、IPersistFile インタフェースだ。

C# や Java では、インタフェースを実装したクラスは、
インタフェース自身のメソッドを public として持つが、
COM では、メソッド実行は必ずインタフェース型経由となる。

理由は割愛するが、上記の制約があるため、
COM クラスに例えメソッドを定義しても直接呼び出せず、
インタフェースを全て明示してアクセスする必要がある。

さて、ShortcutClass を初期化するためには、
IPersistFile を経由してファイルを指定する必要がある。
IPersistFile は非常によく使うインタフェースなので、
.NET でも、UCOMIPersistFile と言う名前で定義されている。

ファイルを読み込むためには、Load メソッドを使う。
引数の pszFileName はファイル名、
dwMode には 0 を指定しておけばデフォルトとなる。

では、これらを使って試してみよう。
スタートメニューにある「Windows Update」を読んでみる。

ColumnProvider として登録すると大変なので、
コンソールアプリケーションとして実行し、
Main から起動してテストしてみよう。

今日も一気に書く。

========== Test.cs ==========

using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using LoaferShellEx.Interop;

namespace LoaferShellEx {

    internal class Test {

        [STAThread]
        static public void Main() {

            const string path =
                    "C:\\Documents and Settings\\All Users\\Start Menu\\Windows Update.lnk";

            // Shortcut オブジェクトを作成
            ShortcutClass obj = new ShortcutClass();

            try {

                // IPersistFile インタフェースを取得し
                UCOMIPersistFile pf = (UCOMIPersistFile)obj;

                // ショートカットファイルを読み込み
                pf.Load(path, 0);

                // IShellLinkW インタフェースを取得する
                IShellLinkW link = (IShellLinkW)obj;

                // バッファを用意
                StringBuilder target =
                        new StringBuilder(Constants.MAX_PATH);

                // ショートカット先を得る
                link.GetPath(target, target.Capacity,
                        IntPtr.Zero, SLGP.UNCPRIORITY | SLGP.RAWPATH);

                // デバッグ出力
                Debug.WriteLine(target.ToString());

            } finally {

                // COM オブジェクトを解放する
                Marshal.ReleaseComObject(obj);

            }

        }

    }

}

========== end of Test.cs ==========

順に見ていこう。

ShortcutClass の作成は、new で行う。
この時点ではインスタンスは初期化されていないので、
初期化用に、IPersistFile にキャストし、
Load メソッドを呼び出してファイルから読み込む。
続いて IShellLinkW にキャストし、GetPath を呼ぶ。

GetPath は、メソッド側が値を書き込むので、
GetPath に渡す StringBuilder には
あらかじめサイズを確保しておく必要がある。

StringBuilder の Capacity が容量となるので、
int を受け取るコンストラクタを使って、
Constants.MAX_PATH(260 文字)分確保しておく。

GetPath の最初の引数はバッファ、
第 2 引数はバッファの容量だ。
第 3 引数は NULL を渡すため、IntPtr.Zero を指定。
第 4 引数はパスの取得方法だが、
SLGP.UNCPRIORITY はとりあえず指定しておく、
SLGP.RAWPATH は環境変数なども展開されない。

最後にある Marshal.ReleaseComObject(obj) は、
COM オブジェクトを解放することを明示する。

.NET はガベッジコレクションベースのメモリ管理なので、
ShortcutClass はスコープを抜けてもすぐに解放されない。
COM では、参照カウントでインスタンスを管理しており、
使わなくなった参照はすぐに解放するのがマナーだ。

そこで、ReleaseComObject を使って、
参照カウントを直ちに減算させることで、
低水準の COM オブジェクトへの参照をすぐに解放させる。

さて、実行すると、以下のように表示された。

%SystemRoot%\system32\wupdmgr.exe

ひとまずは成功だ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.