2006 年 10 月 13 日 23 時 40 分

ショートカットを作成する


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


インストーラやランチャーなどのプログラムでは、
ショートカットを作成する必要に迫られる場合がある。
今度は、ショートカットを作ってみよう。

まずはプロトタイプ宣言。

========== lnkfile.h (partial) ==========

HRESULT ShortcutCreate(const wchar_t *fileName, const wchar_t *target);

========== end of lnkfile.h (partial) ==========

ファイル名と、リンク先を指定して、
ショートカットを作成する。

次に、実装を追加する。

========== lnkfile.c (partial) ==========

HRESULT ShortcutCreate(const wchar_t *fileName,
        const wchar_t *target) {

    HRESULT       result = S_OK;
    IShellLink   *link   = NULL;
    IPersistFile *pf     = NULL;

    result = CoInitialize(NULL);
    if (FAILED(result)) return result;

    result = CoCreateInstance(&CLSID_ShellLink, NULL,
            CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (void **)&link);
    if (FAILED(result)) goto cleanup;

    /* IShellLink#SetPath を利用してリンクを設定 */
    result = IShellLinkW_SetPath(link, target);
    if (FAILED(result)) goto cleanup;

    /* IPersistFile のポインタも取得 */
    result = IUnknown_QueryInterface(link,
            &IID_IPersistFile, (void **)&pf);
    if (FAILED(result)) goto cleanup;

    /* IPersistFile#Save を利用して保存 */
    result = IPersistFile_Save(pf, fileName, TRUE);

cleanup:
    if (pf)   IUnknown_Release(pf);
    if (link) IUnknown_Release(link);

    CoUninitialize();

    return result;
}

========== end of lnkfile.c (partial) ==========

読み込みと比べても、基本的なところは変わらない。
IPersistFile#Load が IPersistFile#Save に、
IShellLinkW#GetPath が IShellLinkW#SetPath になる。

そう言えば、COM オブジェクトについて書いていなかった。

C 言語では、基本的に自分で生成したオブジェクトは、
自分で破棄しないといけないのだが、
COM オブジェクトには、少し特別な規則が存在する。

COM オブジェクトには、自動的な生存管理の仕組みがあり、
個々のオブジェクトは、自らの参照の数を管理している。
参照は、インタフェースポインタの数によって決まり、
全てのインタフェースポインタが解放されると、
COM オブジェクトのインスタンスは自動的に破棄される。

そのため、COM にはインスタンスを作成する関数はあるが、
インスタンスを破棄する関数は存在せず、
IUnknown#Release を呼び出すことで解放するのだ。

ショートカットの場合、2 つのインタフェースを使うが、
必要であればいつでも、QueryInterface を使って
任意のインタフェースポインタを取得することができる。

オブジェクトを指すインタフェースポインタが存在する限り、
インスタンスが破棄されることはないため、
インタフェースを取得するタイミングは特に制約はない。

さて、では実際に作成してみよう。
適当な wmain 関数を書いてみる。

========== program.c (partial) ==========

int wmain(int argc, wchar_t *argv[]) {

    const wchar_t *path = L"C:\\メモ帳.lnk";
    const wchar_t *target = L"C:\\WINDOWS\\system32\\notepad.exe";
    HRESULT result = S_OK;

    setlocale(LC_ALL, "Japanese");

    result = ShortcutCreate(path, target);
    if (result == S_OK) {

        wprintf(L"ファイル名      : %s\n", path);
        wprintf(L"ショートカット先: %s\n", target);

    }

    return (int)result;
}

========== end of program.c (partial) ==========

ではビルドして実行してみる。

C ドライブ直下にショートカット「メモ帳」ができた。
ダブルクリックしてみるとメモ帳が起動した。

ショートカットファイルには、リンク先だけでなく
説明や作業ディレクトリなどの色々な情報が格納されているが、
それらも IShellLinkW インタフェースで操作が可能である。



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