Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
 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);
         }
     }
 }
Пример #6
0
 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;
        }
Пример #8
0
        /// <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);
                }
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
            }
        }
Пример #11
0
        /// <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);
                }
            }
        }
Пример #12
0
        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;
        }
Пример #13
0
 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);
 }
Пример #14
0
        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);
            }
        }