3 using System.Runtime.InteropServices;
\r
4 using System.Runtime.InteropServices.ComTypes;
\r
5 using System.Diagnostics;
\r
7 namespace NaGet.InteropServices
\r
13 public enum ShellLinkResolve : uint
\r
15 // AnyMatch = 0x02, // winMe,win2k以降無効
\r
26 /// リンク先の解決ができないときダイアログを表示しない
\r
29 NoUiWithMsgPump = 0x101,
\r
46 [Guid("000214F9-0000-0000-C000-000000000046")]
\r
47 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
\r
48 public interface IShellLinkW
\r
50 void GetPath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
\r
51 int cchMaxPath, IntPtr pfd, uint fFlags);
\r
53 void GetIDList(out IntPtr ppidl);
\r
54 void SetIDList(IntPtr pidl);
\r
56 void GetDescription([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDesc,
\r
58 void SetDescription(string pszDesc);
\r
60 void GetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
\r
62 void SetWorkingDirectory(string pszDir);
\r
64 void GetArguments([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
\r
66 void SetArguments(string pszArgs);
\r
68 void GetHotkey(out short pwHotkey);
\r
69 void SetHotkey(short pwHotkey);
\r
71 void GetShowCmd(out uint piShowCmd);
\r
72 void SetShowCmd(uint piShowCmd);
\r
74 void GetIconLocation([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
\r
75 int cchMaxPath, out int piIcon);
\r
76 void SetIconLocation(string pszIconPath, int iIcon);
\r
78 void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath,
\r
79 int cchMaxPath, uint dwReserved);
\r
81 void Resolve(IntPtr hWnd, ShellLinkResolve fFlag);
\r
83 void SetPath(string pszFile);
\r
87 /// シェルリンク(ショートカット)のカプセルクラス
\r
89 public class ShellLink : IDisposable
\r
92 /// シェルリンクのCOMオブジェクト
\r
94 protected IShellLinkW shellLink;
\r
99 public const string ShellLinkGuid = "00021401-0000-0000-C000-000000000046";
\r
101 protected const int MAX_PATH = 260;
\r
104 /// 新しいシェルリンクを作成する形のコンストラクタ
\r
108 Type shellLinkType = Type.GetTypeFromCLSID(new Guid(ShellLinkGuid));
\r
109 shellLink = (IShellLinkW) Activator.CreateInstance(shellLinkType);
\r
113 /// 既存のシェルリンクを開くコンストラクタ
\r
115 /// <param name="path">既存のシェルリンクのパス</param>
\r
116 public ShellLink(string path) : this()
\r
118 if (! System.IO.File.Exists(path)) {
\r
119 throw new System.IO.FileNotFoundException("File does not found", path);
\r
122 ToPersistFile().Load(path, 0);
\r
123 Resolve(IntPtr.Zero, ShellLinkResolve.NoUpdate | ShellLinkResolve.NoUi);
\r
129 /// <param name="hWnd">親フレームのハンドル</param>
\r
130 /// <param name="fFlags">方法</param>
\r
131 public void Resolve(IntPtr? hWnd, ShellLinkResolve fFlags)
\r
133 shellLink.Resolve(hWnd ?? IntPtr.Zero, fFlags);
\r
137 /// IPersistFileとして取り出す
\r
139 /// <returns>IPersistFileにキャストされたCOMオブジェクト</returns>
\r
140 public IPersistFile ToPersistFile()
\r
142 return (IPersistFile) shellLink;
\r
146 /// リンク先パスを得る。コマンドラインを得るためにも
\r
148 /// <param name="fFlags">パスのタイプ(1:8.3形式; 2:UNCパス; 4:環境変数変換なし)</param>
\r
149 /// <returns>パス</returns>
\r
150 public string GetPath(uint fFlags)
\r
152 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
153 shellLink.GetPath(sb, sb.Capacity, IntPtr.Zero, fFlags);
\r
154 return sb.ToString();
\r
158 /// リンク先パス(取得時には環境変数は展開されません)
\r
160 public string Path {
\r
161 get { return GetPath(0x04); }
\r
162 set { shellLink.SetPath(value); }
\r
168 public string Arguments {
\r
170 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
171 shellLink.GetArguments(sb, sb.Capacity);
\r
172 return sb.ToString();
\r
174 set { shellLink.SetArguments(value); }
\r
180 public string WorkingDirectory {
\r
182 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
183 shellLink.GetWorkingDirectory(sb, sb.Capacity);
\r
184 return sb.ToString();
\r
186 set { shellLink.SetWorkingDirectory(value); }
\r
190 /// ウィンドウスタイル(ShowCmdのワッパ)
\r
192 public ProcessWindowStyle WindowStyle
\r
196 shellLink.GetShowCmd(out showcmd);
\r
199 return ProcessWindowStyle.Maximized;
\r
201 return ProcessWindowStyle.Minimized;
\r
204 return ProcessWindowStyle.Normal;
\r
209 case ProcessWindowStyle.Normal:
\r
210 shellLink.SetShowCmd(1);
\r
212 case ProcessWindowStyle.Maximized:
\r
213 shellLink.SetShowCmd(3);
\r
215 case ProcessWindowStyle.Minimized:
\r
216 case ProcessWindowStyle.Hidden:
\r
217 shellLink.SetShowCmd(7);
\r
226 /// <param name="iconPath">アイコンを含むファイルパス</param>
\r
227 /// <param name="iconIndex">アイコンのインデックス</param>
\r
228 public void GetIconLocation(out string iconPath, out int iconIndex)
\r
230 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
231 shellLink.GetIconLocation(sb, sb.Capacity, out iconIndex);
\r
232 iconPath = sb.ToString();
\r
238 /// <param name="iconPath">アイコンを含むファイルパス</param>
\r
239 /// <param name="iconIndex">アイコンのインデックス</param>
\r
240 public void SetIconLocation(string iconPath, int iconIndex)
\r
242 shellLink.SetIconLocation(iconPath, iconIndex);
\r
248 public void Dispose()
\r
250 if (shellLink != null) {
\r
251 Marshal.ReleaseComObject(shellLink);
\r
257 /// シェルリンクの中身をプロセス情報として取得する。起動の際に利用
\r
259 /// <returns>プロセス起動情報化されたシェルリンクの情報</returns>
\r
260 public ProcessStartInfo ToProcessStartInfo()
\r
262 ProcessStartInfo procInfo = new ProcessStartInfo();
\r
263 procInfo.FileName = GetPath(0);
\r
264 procInfo.Arguments = Arguments;
\r
265 procInfo.WorkingDirectory = WorkingDirectory;
\r
266 procInfo.WindowStyle = WindowStyle;
\r
272 /// プロセス情報からシェルリンクオブジェクトを生成
\r
274 /// <param name="procInfo">プロセス情報</param>
\r
275 /// <returns>生成されたシェルリンクオブジェクト</returns>
\r
276 public static ShellLink CreateFromProcessStartInfo(ProcessStartInfo procInfo)
\r
278 ShellLink shelllink = new ShellLink();
\r
279 shelllink.Path = procInfo.FileName;
\r
280 shelllink.Arguments = procInfo.Arguments;
\r
281 shelllink.WorkingDirectory = procInfo.WorkingDirectory;
\r
282 shelllink.WindowStyle = procInfo.WindowStyle;
\r
288 /// ショートカット先のEXEファイルに対して適切な名前を生成する。
\r
290 /// 具体的には、アセンブリの製品名をまず優先的に使い、
\r
291 /// それがなければ、exeファイルのファイル名(拡張子を除いたもの)を返す。
\r
293 /// 拡張子はつかないので、lnkファイル名に使う場合は、手動で
\r
294 /// <code>".lnk"</code>を追加すること。
\r
296 /// <returns>拡張子を含まない、適切な名前</returns>
\r
297 public string GetSuitableShellLinkNameFor()
\r
299 string exeFile = GetPath(0);
\r
302 FileVersionInfo vInfo = FileVersionInfo.GetVersionInfo(exeFile);
\r
303 if (vInfo.ProductName != null && vInfo.ProductName != string.Empty
\r
304 && vInfo.ProductName.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) < 0) {
\r
306 return vInfo.ProductName;
\r
308 } catch (Exception) {}
\r
310 // そのほかの場合は、*.exeファイルの名前をそのまま使用
\r
311 return System.IO.Path.GetFileNameWithoutExtension(exeFile);
\r