private static JumpItem GetJumpItemForShellObject(object shellObject) { var shellItem = shellObject as IShellItem2; var shellLink = shellObject as IShellLinkW; if (shellItem != null) { JumpPath path = new JumpPath { Path = shellItem.GetDisplayName(SIGDN.DESKTOPABSOLUTEPARSING), }; return(path); } if (shellLink != null) { var pathBuilder = new StringBuilder((int)Win32Value.MAX_PATH); shellLink.GetPath(pathBuilder, pathBuilder.Capacity, null, SLGP.RAWPATH); var argsBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE); shellLink.GetArguments(argsBuilder, argsBuilder.Capacity); var descBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE); shellLink.GetDescription(descBuilder, descBuilder.Capacity); var iconBuilder = new StringBuilder((int)Win32Value.MAX_PATH); int iconIndex; shellLink.GetIconLocation(iconBuilder, iconBuilder.Capacity, out iconIndex); var dirBuilder = new StringBuilder((int)Win32Value.MAX_PATH); shellLink.GetWorkingDirectory(dirBuilder, dirBuilder.Capacity); JumpTask task = new JumpTask { // Set ApplicationPath and IconResources, even if they're from the current application. // This means that equivalent JumpTasks won't necessarily compare property-for-property. ApplicationPath = pathBuilder.ToString(), Arguments = argsBuilder.ToString(), Description = descBuilder.ToString(), IconResourceIndex = iconIndex, IconResourcePath = iconBuilder.ToString(), WorkingDirectory = dirBuilder.ToString(), }; using (PROPVARIANT pv = new PROPVARIANT()) { var propStore = (IPropertyStore)shellLink; PKEY pkeyTitle = PKEY.Title; propStore.GetValue(ref pkeyTitle, pv); // PKEY_Title should be an LPWSTR if it's not empty. task.Title = pv.GetValue() ?? ""; } return(task); } // Unsupported type? Debug.Assert(false); return(null); }
private static JumpItem GetJumpItemForShellObject(object shellObject) { int num; Standard.IShellItem2 item = shellObject as Standard.IShellItem2; Standard.IShellLinkW kw = shellObject as Standard.IShellLinkW; if (item != null) { return(new JumpPath { Path = item.GetDisplayName(unchecked ((Standard.SIGDN)(-2147319808))) }); } if (kw == null) { return(null); } StringBuilder pszFile = new StringBuilder(260); kw.GetPath(pszFile, pszFile.Capacity, null, Standard.SLGP.RAWPATH); StringBuilder pszArgs = new StringBuilder(0x400); kw.GetArguments(pszArgs, pszArgs.Capacity); StringBuilder builder3 = new StringBuilder(0x400); kw.GetDescription(builder3, builder3.Capacity); StringBuilder pszIconPath = new StringBuilder(260); kw.GetIconLocation(pszIconPath, pszIconPath.Capacity, out num); StringBuilder pszDir = new StringBuilder(260); kw.GetWorkingDirectory(pszDir, pszDir.Capacity); JumpTask task = new JumpTask { ApplicationPath = pszFile.ToString(), Arguments = pszArgs.ToString(), Description = builder3.ToString(), IconResourceIndex = num, IconResourcePath = pszIconPath.ToString(), WorkingDirectory = pszDir.ToString() }; using (PROPVARIANT propvariant = new PROPVARIANT()) { Standard.IPropertyStore store = (Standard.IPropertyStore)kw; Standard.PKEY title = Standard.PKEY.Title; store.GetValue(ref title, propvariant); task.Title = propvariant.GetValue() ?? ""; } return(task); }
private static object GetShellObjectForJumpItem(JumpItem jumpItem) { JumpPath jumpPath = jumpItem as JumpPath; JumpTask jumpTask = jumpItem as JumpTask; if (jumpPath != null) { return(JumpList.CreateItemFromJumpPath(jumpPath)); } if (jumpTask != null) { return(JumpList.CreateLinkFromJumpTask(jumpTask, true)); } return(null); }
private static JumpItem GetJumpItemForShellObject(object shellObject) { IShellItem2 shellItem = shellObject as IShellItem2; IShellLinkW shellLinkW = shellObject as IShellLinkW; if (shellItem != null) { return(new JumpPath { Path = shellItem.GetDisplayName((SIGDN)2147647488u) }); } if (shellLinkW != null) { StringBuilder stringBuilder = new StringBuilder(260); shellLinkW.GetPath(stringBuilder, stringBuilder.Capacity, null, SLGP.RAWPATH); StringBuilder stringBuilder2 = new StringBuilder(1024); shellLinkW.GetArguments(stringBuilder2, stringBuilder2.Capacity); StringBuilder stringBuilder3 = new StringBuilder(1024); shellLinkW.GetDescription(stringBuilder3, stringBuilder3.Capacity); StringBuilder stringBuilder4 = new StringBuilder(260); int iconResourceIndex; shellLinkW.GetIconLocation(stringBuilder4, stringBuilder4.Capacity, out iconResourceIndex); StringBuilder stringBuilder5 = new StringBuilder(260); shellLinkW.GetWorkingDirectory(stringBuilder5, stringBuilder5.Capacity); JumpTask jumpTask = new JumpTask { ApplicationPath = stringBuilder.ToString(), Arguments = stringBuilder2.ToString(), Description = stringBuilder3.ToString(), IconResourceIndex = iconResourceIndex, IconResourcePath = stringBuilder4.ToString(), WorkingDirectory = stringBuilder5.ToString() }; using (PROPVARIANT propvariant = new PROPVARIANT()) { IPropertyStore propertyStore = (IPropertyStore)shellLinkW; PKEY title = PKEY.Title; propertyStore.GetValue(ref title, propvariant); jumpTask.Title = (propvariant.GetValue() ?? ""); } return(jumpTask); } return(null); }
public static void AddToRecentCategory(JumpTask jumpTask) { Verify.IsNotNull <JumpTask>(jumpTask, "jumpTask"); if (Utility.IsOSWindows7OrNewer) { IShellLinkW shellLinkW = JumpList.CreateLinkFromJumpTask(jumpTask, false); try { if (shellLinkW != null) { NativeMethods.SHAddToRecentDocs(shellLinkW); } } finally { Utility.SafeRelease <IShellLinkW>(ref shellLinkW); } } }
public static void AddToRecentCategory(JumpTask jumpTask) { Standard.Verify.IsNotNull <JumpTask>(jumpTask, "jumpTask"); if (Standard.Utility.IsOSWindows7OrNewer) { Standard.IShellLinkW shellLink = CreateLinkFromJumpTask(jumpTask, false); try { if (shellLink != null) { Standard.NativeMethods.SHAddToRecentDocs(shellLink); } } finally { Standard.Utility.SafeRelease <Standard.IShellLinkW>(ref shellLink); } } }
private JumpTask GenerateJumpTask() { var jt = new JumpTask { ApplicationPath = _jumpTaskAppPathBox.Text, IconResourcePath = _jumpTaskIconResourcePathBox.Text, Arguments = _jumpTaskArgsBox.Text, Title = _jumpTaskTitleBox.Text, Description = _jumpTaskDescriptionBox.Text, WorkingDirectory = _jumpTaskWorkingDirBox.Text, CustomCategory = _jumpTaskCategoryBox.Text, }; int i; if (int.TryParse(_jumpTaskIconResourceIndexBox.Text, out i)) { jt.IconResourceIndex = i; } return jt; }
/// <summary> /// Add the task at the specified file path to the application's JumpList's recent items. /// </summary> /// <remarks> /// This makes the item eligible for inclusion in the special Recent and Frequent categories. /// </remarks> public static void AddToRecentCategory(JumpTask jumpTask) { Verify.IsNotNull(jumpTask, "jumpTask"); // SHAddToRecentDocs only allows IShellLinks in Windows 7 and later. // Silently fail this if that's not the case. // We don't give feedback on success here, so this is okay. if (Utility.IsOSWindows7OrNewer) { IShellLinkW shellLink = CreateLinkFromJumpTask(jumpTask, false); try { if (shellLink != null) { NativeMethods.SHAddToRecentDocs(shellLink); } } finally { Utility.SafeRelease(ref shellLink); } } }
private static IShellLinkW CreateLinkFromJumpTask(JumpTask jumpTask, bool allowSeparators) { if (string.IsNullOrEmpty(jumpTask.Title) && (!allowSeparators || !string.IsNullOrEmpty(jumpTask.CustomCategory))) { return(null); } IShellLinkW shellLinkW = (IShellLinkW)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("00021401-0000-0000-C000-000000000046"))); IShellLinkW result; try { string path = JumpList._FullName; if (!string.IsNullOrEmpty(jumpTask.ApplicationPath)) { path = jumpTask.ApplicationPath; } shellLinkW.SetPath(path); if (!string.IsNullOrEmpty(jumpTask.WorkingDirectory)) { shellLinkW.SetWorkingDirectory(jumpTask.WorkingDirectory); } if (!string.IsNullOrEmpty(jumpTask.Arguments)) { shellLinkW.SetArguments(jumpTask.Arguments); } if (jumpTask.IconResourceIndex != -1) { string pszIconPath = JumpList._FullName; if (!string.IsNullOrEmpty(jumpTask.IconResourcePath)) { if ((long)jumpTask.IconResourcePath.Length >= 260L) { return(null); } pszIconPath = jumpTask.IconResourcePath; } shellLinkW.SetIconLocation(pszIconPath, jumpTask.IconResourceIndex); } if (!string.IsNullOrEmpty(jumpTask.Description)) { shellLinkW.SetDescription(jumpTask.Description); } IPropertyStore propertyStore = (IPropertyStore)shellLinkW; using (PROPVARIANT propvariant = new PROPVARIANT()) { PKEY pkey = default(PKEY); if (!string.IsNullOrEmpty(jumpTask.Title)) { propvariant.SetValue(jumpTask.Title); pkey = PKEY.Title; } else { propvariant.SetValue(true); pkey = PKEY.AppUserModel_IsDestListSeparator; } propertyStore.SetValue(ref pkey, propvariant); } propertyStore.Commit(); IShellLinkW shellLinkW2 = shellLinkW; shellLinkW = null; result = shellLinkW2; } catch (Exception) { result = null; } finally { Utility.SafeRelease <IShellLinkW>(ref shellLinkW); } return(result); }
private static IShellLinkW CreateLinkFromJumpTask(JumpTask jumpTask, bool allowSeparators) { Debug.Assert(jumpTask != null); // Title is generally required. If it's missing we need to treat this like a separator. // Everything else can still appear on separator elements, // but separators can only exist in the Tasks category. if (string.IsNullOrEmpty(jumpTask.Title)) { if (!allowSeparators || !string.IsNullOrEmpty(jumpTask.CustomCategory)) { // Just treat this situation as an InvalidItem. return null; } } var link = (IShellLinkW)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.ShellLink))); try { string appPath = _FullName; if (!string.IsNullOrEmpty(jumpTask.ApplicationPath)) { appPath = jumpTask.ApplicationPath; } link.SetPath(appPath); // This is optional. Don't set it if the app hasn't explicitly requested it. if (!string.IsNullOrEmpty(jumpTask.WorkingDirectory)) { // Don't verify this. It's possible that the directory doesn't exist now, but it will later. // Shell handles this fine when we try to set an improperly formatted path. link.SetWorkingDirectory(jumpTask.WorkingDirectory); } if (!string.IsNullOrEmpty(jumpTask.Arguments)) { link.SetArguments(jumpTask.Arguments); } // -1 is a sentinel value indicating not to use the icon. if (jumpTask.IconResourceIndex != -1) { string resourcePath = _FullName; if (!string.IsNullOrEmpty(jumpTask.IconResourcePath)) { // Shell bug (Windows 7 595770): IShellLink doesn't correctly limit icon location path to MAX_PATH. // It's really too bad we have to enforce this here. When the shortcut gets // serialized it streams the full string. On deserialization it only retrieves // MAX_PATH for this field leaving junk behind for subsequent gets, leading to data corruption. // Because we don't want to allow the app to do create something that we know may // be corrupt we have to enforce this ourselves. If Shell fixes this later then // we need to remove this check to let them handle this as they see fit. // If they fix it by supporting longer paths, then we're artificially constraining this value... if (jumpTask.IconResourcePath.Length >= Win32Value.MAX_PATH) { // we could throw the exception here, but we're already globally catching everything. return null; } resourcePath = jumpTask.IconResourcePath; } link.SetIconLocation(resourcePath, jumpTask.IconResourceIndex); } if (!string.IsNullOrEmpty(jumpTask.Description)) { link.SetDescription(jumpTask.Description); } IPropertyStore propStore = (IPropertyStore)link; using (var pv = new PROPVARIANT()) { PKEY pkey = default(PKEY); if (!string.IsNullOrEmpty(jumpTask.Title)) { pv.SetValue(jumpTask.Title); pkey = PKEY.Title; } else { pv.SetValue(true); pkey = PKEY.AppUserModel_IsDestListSeparator; } propStore.SetValue(ref pkey, pv); } propStore.Commit(); IShellLinkW retLink = link; link = null; return retLink; } catch (Exception) { // IShellLinkW::Set* methods tend to return E_FAIL when trying to set invalid data. // The create methods don't explicitly check for these kinds of errors. // If we aren't able to create the item for any reason just return null to indicate an invalid item. return null; } finally { Utility.SafeRelease(ref link); } }
private static JumpItem GetJumpItemForShellObject(object shellObject) { var shellItem = shellObject as IShellItem2; var shellLink = shellObject as IShellLinkW; if (shellItem != null) { JumpPath path = new JumpPath { Path = shellItem.GetDisplayName(SIGDN.DESKTOPABSOLUTEPARSING), }; return path; } if (shellLink != null) { var pathBuilder = new StringBuilder((int)Win32Value.MAX_PATH); shellLink.GetPath(pathBuilder, pathBuilder.Capacity, null, SLGP.RAWPATH); var argsBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE); shellLink.GetArguments(argsBuilder, argsBuilder.Capacity); var descBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE); shellLink.GetDescription(descBuilder, descBuilder.Capacity); var iconBuilder = new StringBuilder((int)Win32Value.MAX_PATH); int iconIndex; shellLink.GetIconLocation(iconBuilder, iconBuilder.Capacity, out iconIndex); var dirBuilder = new StringBuilder((int)Win32Value.MAX_PATH); shellLink.GetWorkingDirectory(dirBuilder, dirBuilder.Capacity); JumpTask task = new JumpTask { // Set ApplicationPath and IconResources, even if they're from the current application. // This means that equivalent JumpTasks won't necessarily compare property-for-property. ApplicationPath = pathBuilder.ToString(), Arguments = argsBuilder.ToString(), Description = descBuilder.ToString(), IconResourceIndex = iconIndex, IconResourcePath = iconBuilder.ToString(), WorkingDirectory = dirBuilder.ToString(), }; using (PROPVARIANT pv = new PROPVARIANT()) { var propStore = (IPropertyStore)shellLink; PKEY pkeyTitle = PKEY.Title; propStore.GetValue(ref pkeyTitle, pv); // PKEY_Title should be an LPWSTR if it's not empty. task.Title = pv.GetValue() ?? ""; } return task; } // Unsupported type? Debug.Assert(false); return null; }
private static Standard.IShellLinkW CreateLinkFromJumpTask(JumpTask jumpTask, bool allowSeparators) { Standard.IShellLinkW kw3; if (string.IsNullOrEmpty(jumpTask.Title) && (!allowSeparators || !string.IsNullOrEmpty(jumpTask.CustomCategory))) { return(null); } Standard.IShellLinkW comObject = (Standard.IShellLinkW)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("00021401-0000-0000-C000-000000000046"))); try { string pszFile = _FullName; if (!string.IsNullOrEmpty(jumpTask.ApplicationPath)) { pszFile = jumpTask.ApplicationPath; } comObject.SetPath(pszFile); if (!string.IsNullOrEmpty(jumpTask.WorkingDirectory)) { comObject.SetWorkingDirectory(jumpTask.WorkingDirectory); } if (!string.IsNullOrEmpty(jumpTask.Arguments)) { comObject.SetArguments(jumpTask.Arguments); } if (jumpTask.IconResourceIndex != -1) { string pszIconPath = _FullName; if (!string.IsNullOrEmpty(jumpTask.IconResourcePath)) { if (jumpTask.IconResourcePath.Length >= 260L) { return(null); } pszIconPath = jumpTask.IconResourcePath; } comObject.SetIconLocation(pszIconPath, jumpTask.IconResourceIndex); } if (!string.IsNullOrEmpty(jumpTask.Description)) { comObject.SetDescription(jumpTask.Description); } Standard.IPropertyStore store = (Standard.IPropertyStore)comObject; using (PROPVARIANT propvariant = new PROPVARIANT()) { Standard.PKEY title = new Standard.PKEY(); if (!string.IsNullOrEmpty(jumpTask.Title)) { propvariant.SetValue(jumpTask.Title); title = Standard.PKEY.Title; } else { propvariant.SetValue(true); title = Standard.PKEY.AppUserModel_IsDestListSeparator; } store.SetValue(ref title, propvariant); } store.Commit(); Standard.IShellLinkW kw2 = comObject; comObject = null; kw3 = kw2; } catch (Exception) { kw3 = null; } finally { Standard.Utility.SafeRelease <Standard.IShellLinkW>(ref comObject); } return(kw3); }
private static IShellLinkW CreateLinkFromJumpTask(JumpTask jumpTask, bool allowSeparators) { Debug.Assert(jumpTask != null); // Title is generally required. If it's missing we need to treat this like a separator. // Everything else can still appear on separator elements, // but separators can only exist in the Tasks category. if (string.IsNullOrEmpty(jumpTask.Title)) { if (!allowSeparators || !string.IsNullOrEmpty(jumpTask.CustomCategory)) { // Just treat this situation as an InvalidItem. return(null); } } var link = (IShellLinkW)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.ShellLink))); try { string appPath = _FullName; if (!string.IsNullOrEmpty(jumpTask.ApplicationPath)) { appPath = jumpTask.ApplicationPath; } link.SetPath(appPath); // This is optional. Don't set it if the app hasn't explicitly requested it. if (!string.IsNullOrEmpty(jumpTask.WorkingDirectory)) { // Don't verify this. It's possible that the directory doesn't exist now, but it will later. // Shell handles this fine when we try to set an improperly formatted path. link.SetWorkingDirectory(jumpTask.WorkingDirectory); } if (!string.IsNullOrEmpty(jumpTask.Arguments)) { link.SetArguments(jumpTask.Arguments); } // -1 is a sentinel value indicating not to use the icon. if (jumpTask.IconResourceIndex != -1) { string resourcePath = _FullName; if (!string.IsNullOrEmpty(jumpTask.IconResourcePath)) { // Shell bug (Windows 7 595770): IShellLink doesn't correctly limit icon location path to MAX_PATH. // It's really too bad we have to enforce this here. When the shortcut gets // serialized it streams the full string. On deserialization it only retrieves // MAX_PATH for this field leaving junk behind for subsequent gets, leading to data corruption. // Because we don't want to allow the app to do create something that we know may // be corrupt we have to enforce this ourselves. If Shell fixes this later then // we need to remove this check to let them handle this as they see fit. // If they fix it by supporting longer paths, then we're artificially constraining this value... if (jumpTask.IconResourcePath.Length >= Win32Value.MAX_PATH) { // we could throw the exception here, but we're already globally catching everything. return(null); } resourcePath = jumpTask.IconResourcePath; } link.SetIconLocation(resourcePath, jumpTask.IconResourceIndex); } if (!string.IsNullOrEmpty(jumpTask.Description)) { link.SetDescription(jumpTask.Description); } IPropertyStore propStore = (IPropertyStore)link; using (var pv = new PROPVARIANT()) { PKEY pkey = default(PKEY); if (!string.IsNullOrEmpty(jumpTask.Title)) { pv.SetValue(jumpTask.Title); pkey = PKEY.Title; } else { pv.SetValue(true); pkey = PKEY.AppUserModel_IsDestListSeparator; } propStore.SetValue(ref pkey, pv); } propStore.Commit(); IShellLinkW retLink = link; link = null; return(retLink); } catch (Exception) { // IShellLinkW::Set* methods tend to return E_FAIL when trying to set invalid data. // The create methods don't explicitly check for these kinds of errors. // If we aren't able to create the item for any reason just return null to indicate an invalid item. return(null); } finally { Utility.SafeRelease(ref link); } }