3 using System.Runtime.InteropServices;
\r
4 using System.Runtime.InteropServices.ComTypes;
\r
5 using System.Diagnostics;
\r
7 namespace NaGet.InteropServices
\r
12 public enum ShellLinkResolve : uint
\r
14 // AnyMatch = 0x02, // winMe,win2k以降無効
\r
25 /// リンク先の解決ができないときダイアログを表示しない
\r
28 NoUiWithMsgPump = 0x101,
\r
45 [Guid("000214F9-0000-0000-C000-000000000046")]
\r
46 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
\r
47 public interface IShellLinkW
\r
49 void GetPath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
\r
50 int cchMaxPath, IntPtr pfd, uint fFlags);
\r
52 void GetIDList(out IntPtr ppidl);
\r
53 void SetIDList(IntPtr pidl);
\r
55 void GetDescription([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDesc,
\r
57 void SetDescription(string pszDesc);
\r
59 void GetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
\r
61 void SetWorkingDirectory(string pszDir);
\r
63 void GetArguments([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
\r
65 void SetArguments(string pszArgs);
\r
67 void GetHotkey(out short pwHotkey);
\r
68 void SetHotkey(short pwHotkey);
\r
70 void GetShowCmd(out uint piShowCmd);
\r
71 void SetShowCmd(uint piShowCmd);
\r
73 void GetIconLocation([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
\r
74 int cchMaxPath, out int piIcon);
\r
75 void SetIconLocation(string pszIconPath, int iIcon);
\r
77 void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszPath,
\r
78 int cchMaxPath, uint dwReserved);
\r
80 void Resolve(IntPtr hWnd, ShellLinkResolve fFlag);
\r
82 void SetPath(string pszFile);
\r
86 /// シェルリンク(ショートカット)のカプセルクラス
\r
88 public class ShellLink : IDisposable
\r
91 /// シェルリンクのCOMオブジェクト
\r
93 protected IShellLinkW shellLink;
\r
98 public const string ShellLinkGuid = "00021401-0000-0000-C000-000000000046";
\r
100 protected const int MAX_PATH = 260;
\r
103 /// 新しいシェルリンクを作成する形のコンストラクタ
\r
107 Type shellLinkType = Type.GetTypeFromCLSID(new Guid(ShellLinkGuid));
\r
108 shellLink = (IShellLinkW) Activator.CreateInstance(shellLinkType);
\r
112 /// 既存のシェルリンクを開くコンストラクタ
\r
114 /// <param name="path">既存のシェルリンクのパス</param>
\r
115 public ShellLink(string path) : this()
\r
117 if (! System.IO.File.Exists(path)) {
\r
118 throw new System.IO.FileNotFoundException("File does not found", path);
\r
121 ToPersistFile().Load(path, 0);
\r
122 Resolve(IntPtr.Zero, ShellLinkResolve.NoUpdate | ShellLinkResolve.NoUi);
\r
128 /// <param name="hWnd">親フレームのハンドル</param>
\r
129 /// <param name="fFlags">方法</param>
\r
130 public void Resolve(IntPtr? hWnd, ShellLinkResolve fFlags)
\r
132 shellLink.Resolve(hWnd ?? IntPtr.Zero, fFlags);
\r
136 /// IPersistFileとして取り出す
\r
138 /// <returns>IPersistFileにキャストされたCOMオブジェクト</returns>
\r
139 public IPersistFile ToPersistFile()
\r
141 return (IPersistFile) shellLink;
\r
145 /// リンク先パスを得る。コマンドラインを得るためにも
\r
147 /// <param name="fFlags">パスのタイプ(1:8.3形式; 2:UNCパス; 4:環境変数変換なし)</param>
\r
148 /// <returns>パス</returns>
\r
149 public string GetPath(uint fFlags)
\r
151 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
152 shellLink.GetPath(sb, sb.Capacity, IntPtr.Zero, fFlags);
\r
153 return sb.ToString();
\r
157 /// リンク先パス(取得時には環境変数は展開されません)
\r
159 public string Path {
\r
160 get { return GetPath(0x04); }
\r
161 set { shellLink.SetPath(value); }
\r
167 public string Arguments {
\r
169 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
170 shellLink.GetArguments(sb, sb.Capacity);
\r
171 return sb.ToString();
\r
173 set { shellLink.SetArguments(value); }
\r
179 public string WorkingDirectory {
\r
181 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
182 shellLink.GetWorkingDirectory(sb, sb.Capacity);
\r
183 return sb.ToString();
\r
185 set { shellLink.SetWorkingDirectory(value); }
\r
189 /// ウィンドウスタイル(ShowCmdのワッパ)
\r
191 public ProcessWindowStyle WindowStyle
\r
195 shellLink.GetShowCmd(out showcmd);
\r
198 return ProcessWindowStyle.Maximized;
\r
200 return ProcessWindowStyle.Minimized;
\r
203 return ProcessWindowStyle.Normal;
\r
208 case ProcessWindowStyle.Normal:
\r
209 shellLink.SetShowCmd(1);
\r
211 case ProcessWindowStyle.Maximized:
\r
212 shellLink.SetShowCmd(3);
\r
214 case ProcessWindowStyle.Minimized:
\r
215 case ProcessWindowStyle.Hidden:
\r
216 shellLink.SetShowCmd(7);
\r
225 /// <param name="iconPath">アイコンを含むファイルパス</param>
\r
226 /// <param name="iconIndex">アイコンのインデックス</param>
\r
227 public void GetIconLocation(out string iconPath, out int iconIndex)
\r
229 StringBuilder sb = new StringBuilder(MAX_PATH);
\r
230 shellLink.GetIconLocation(sb, sb.Capacity, out iconIndex);
\r
231 iconPath = sb.ToString();
\r
237 /// <param name="iconPath">アイコンを含むファイルパス</param>
\r
238 /// <param name="iconIndex">アイコンのインデックス</param>
\r
239 public void SetIconLocation(string iconPath, int iconIndex)
\r
241 shellLink.SetIconLocation(iconPath, iconIndex);
\r
247 public void Dispose()
\r
249 if (shellLink != null) {
\r
250 Marshal.ReleaseComObject(shellLink);
\r
253 GC.SuppressFinalize(this);
\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 ( (!string.IsNullOrEmpty(vInfo.ProductName))
\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