7以降で利用されるAppUserModelIDを含んだショートカットをC#から操作するコードを書いてみた。8のWindowsストアアプリでは常駐型アプリは難しいので、常駐型の監視アプリを使おうとする場合、(x86版であれば)デスクトップアプリを動かしておいて何かあればWindowsストアアプリの画面にトースト通知を出すのが一つの解になると思うが、このトースト通知をデスクトップアプリから送るにはAppUserModelIDを含んだショートカットがスタートメニューにあることが条件になっている。このAppUserModelIDは普通に張ったショートカットには含まれないもので、これを含むショートカットの作成はアプリのインストーラにやらせることをMicrosoftは推奨している。言ってもインストーラの作ったショートカットをユーザーが消してしまう可能性もあるので確実性に欠けるし、常にインストーラを必要とするのはあまり便利ではない。Frameworkでは提供されておらず、ショートカットでよく使われるWSHのWshShortcutオブジェクトでもAppUserModelIDは対象に入っていない。一応C++での方法は示されているので、であればと、これに沿ってC#からWin32とCOMを使って操作するコード(ラッパークラス)を書いた次第。コーディングC#あるいはVBからCOMのIShellLinkインターフェイスを使ってショートカットを読み書きする例は既に幾つかあって、これをベースにさせていただいた。ShellLinkまた、C++でAppUserModelIDを読み書きする例は以下のとおり。System.ApplicationUserModel.IDwin7appid方針としては、IShellLinkを使う例を基本的に踏襲しつつ(IPersistFileインターフェイスはSystem.Runtime.InteropServices.ComTypes.IPersistFileの方を使う)、IShellLinkはAppUserModelIDに対応してないので、さらに下のIPropertyStoreインターフェイスを使って直にプロパティをいじるというもの。Packに)答えがあった。FrameworkこれにあるPROPVARIANTを扱うクラスは長いものだが、出し入れする値の内容を文字列に限定してしまえば(AppUserModelIDは文字列)、さほどでもない。IPropertyStoreに必要なコードを整理すると、まずIPropertyStore自体は以下のとおり。Commit();}この中でプロパティのキーを格納するPropertyKey構造体。#endregion}で、プロパティの値を格納するPropVariantクラス(とそれに必要な関数)。pvar);また、AppUserModelIDのキーはFormatIDとPropIDからPropertyKeyを使って以下のように定義できる。5);これらを使ってAppUserModelIDをShellLinkクラスのプロパティとして加えた。VerifySucceededは戻り値を見て失敗なら例外を出すメソッド。ショートカットにAppUserModelIDのプロパティが存在しない場合、Valueはnullとなる。}}このShellLinkクラスを使うアプリも合わせた全体のコードはこちらに載せた。IShellLink自体の機能は本題ではないので、最低限必要なものに絞ってある。アプリの見た目は以下のようなもので、ショートカット先のターゲットファイルのパス、実行時のオプション、AppUserModelIDの読み書きが可能。実際に使うには作り込みの必要があると思うが、叩き台としてはこんなものかと。Overview)にしたがってNyaRuRuさんがC++のコードを書かれていたので(SSDなら動作を変えるアプリケーションを作る)、同じことをC#からWin32を使って行うコードを書いてみた。内容的にはほぼNyaRuRuさんのコードのままで、以下の方法の2本立て。penalty」を利用する。rate」を利用する。Win32の宣言は以下のとおり。使用するWin32の関数はCreateFileとDeviceIoControlで、後はそれに必要な定数と構造体。penalty」を利用する「HasNoSeekPenalty」で、物理ドライブ名を「\\\\.\\PhysicalDrive0」の形にした文字列を引数に取る。QA@ITで質問させていただいたもの(SSDかどうかをC#から判別する方法)と基本的に同じ。似た例がなかったので、ほぼスクラッチ。}}(注)GetErrorMessageはエラーメッセージを得るためのメソッド。rate」を利用する「HasNominalMediaRotationRate」で、引数は同じ。DeviceIOControl)、かなり参考にさせていただいた。}}全体を通したコードはこちらに載せた。G2)とHDDを判別できることを確認している。まあC++のライブラリを作ってそれを利用する形でもいいが、.NETから直接使える方法があってもいいかな、ということで。論理ドライブ名から物理ドライブ名を取得するコードも書いてみた。WMIを使う方法もあるが、折角なのでWin32で。lpOverlapped);これを受けたメソッド。論理ドライブ名の文字を引数とし、始めにリムーバブルディスクなどではない固定ディスクかどうかのチェックを通す。SafeFileHandleの解放ドライブへのハンドルの解放にCloseHandle関数を使っていたが、SafeFileHandleにCloseHandleを使うと、その後にガベージコレクタがメモリを解放するときにエラーを起こすらしいと気づいたので、SafeHandle.Closeメソッドを使うように修正した。MSDNなどでソースは見つけられなかったが、問題の状況によく合うし、修正してからは起こらなくなったので、当たっていたのだと思う。Communitywww.flickr.comコメントについてコメントは承認制です。承認まで時間がかかるときがあります。感想、間違いの指摘など歓迎します。間違いについては、その場所と内容を明記してください。エントリと関係がないもの、不適当と思われるものは承認しません。プロフィールEMOGitHub詳しくないプロフィール当てにならないカスタマイズ。