diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Properties/Settings.Designer.cs b/SetLnkApp/Properties/Settings.Designer.cs new file mode 100755 index 0000000..0b6b6e1 --- /dev/null +++ b/SetLnkApp/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Properties/Settings.Designer.cs b/SetLnkApp/Properties/Settings.Designer.cs new file mode 100755 index 0000000..0b6b6e1 --- /dev/null +++ b/SetLnkApp/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/SetLnkApp/Properties/Settings.settings b/SetLnkApp/Properties/Settings.settings new file mode 100755 index 0000000..abf36c5 --- /dev/null +++ b/SetLnkApp/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Properties/Settings.Designer.cs b/SetLnkApp/Properties/Settings.Designer.cs new file mode 100755 index 0000000..0b6b6e1 --- /dev/null +++ b/SetLnkApp/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/SetLnkApp/Properties/Settings.settings b/SetLnkApp/Properties/Settings.settings new file mode 100755 index 0000000..abf36c5 --- /dev/null +++ b/SetLnkApp/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json deleted file mode 100755 index 420478a..0000000 --- a/SetLnkApp/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "SetLnkApp": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Properties/Settings.Designer.cs b/SetLnkApp/Properties/Settings.Designer.cs new file mode 100755 index 0000000..0b6b6e1 --- /dev/null +++ b/SetLnkApp/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/SetLnkApp/Properties/Settings.settings b/SetLnkApp/Properties/Settings.settings new file mode 100755 index 0000000..abf36c5 --- /dev/null +++ b/SetLnkApp/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json deleted file mode 100755 index 420478a..0000000 --- a/SetLnkApp/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "SetLnkApp": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/SetLnkApp/SetLnkApp.csproj b/SetLnkApp/SetLnkApp.csproj index d453e9a..ec4d625 100755 --- a/SetLnkApp/SetLnkApp.csproj +++ b/SetLnkApp/SetLnkApp.csproj @@ -1,8 +1,86 @@ - - + + + - Exe - netcoreapp3.1 + Debug + AnyCPU + {443B8959-7F3D-4199-838C-7A805427CE42} + WinExe + SetLnkApp + SetLnkApp + v4.7.2 + 512 + true + true - - + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + ShellLink.cs + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Properties/Settings.Designer.cs b/SetLnkApp/Properties/Settings.Designer.cs new file mode 100755 index 0000000..0b6b6e1 --- /dev/null +++ b/SetLnkApp/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/SetLnkApp/Properties/Settings.settings b/SetLnkApp/Properties/Settings.settings new file mode 100755 index 0000000..abf36c5 --- /dev/null +++ b/SetLnkApp/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json deleted file mode 100755 index 420478a..0000000 --- a/SetLnkApp/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "SetLnkApp": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/SetLnkApp/SetLnkApp.csproj b/SetLnkApp/SetLnkApp.csproj index d453e9a..ec4d625 100755 --- a/SetLnkApp/SetLnkApp.csproj +++ b/SetLnkApp/SetLnkApp.csproj @@ -1,8 +1,86 @@ - - + + + - Exe - netcoreapp3.1 + Debug + AnyCPU + {443B8959-7F3D-4199-838C-7A805427CE42} + WinExe + SetLnkApp + SetLnkApp + v4.7.2 + 512 + true + true - - + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + ShellLink.cs + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/SetLnkApp/ShellLink.cs b/SetLnkApp/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/SetLnkApp/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/JumpListUtil.sln b/JumpListUtil.sln index c91e4de..4219963 100755 --- a/JumpListUtil.sln +++ b/JumpListUtil.sln @@ -5,7 +5,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{443B8959-7F3D-4199-838C-7A805427CE42}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -17,10 +17,10 @@ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {443B8959-7F3D-4199-838C-7A805427CE42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj index 5f31de9..935dc6f 100755 --- a/JumpListUtil/JumpListUtil.csproj +++ b/JumpListUtil/JumpListUtil.csproj @@ -75,9 +75,11 @@ + + ShellLink.cs + - ResXFileCodeGenerator Resources.Designer.cs diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/JumpListUtil/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/SetLnkApp/App.config b/SetLnkApp/App.config new file mode 100755 index 0000000..5754728 --- /dev/null +++ b/SetLnkApp/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SetLnkApp/MainForm.Designer.cs b/SetLnkApp/MainForm.Designer.cs new file mode 100755 index 0000000..304b462 --- /dev/null +++ b/SetLnkApp/MainForm.Designer.cs @@ -0,0 +1,47 @@ +namespace SetLnkApp +{ + partial class MainForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.SuspendLayout(); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(830, 144); + this.Name = "MainForm"; + this.Text = "SetLnkApp"; + this.ResumeLayout(false); + + } + + #endregion + } +} + diff --git a/SetLnkApp/MainForm.cs b/SetLnkApp/MainForm.cs new file mode 100755 index 0000000..3a63c06 --- /dev/null +++ b/SetLnkApp/MainForm.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SetLnkApp +{ + public partial class MainForm : Form + { + public MainForm() + { + InitializeComponent(); + } + } +} diff --git a/SetLnkApp/MainForm.resx b/SetLnkApp/MainForm.resx new file mode 100755 index 0000000..29dcb1b --- /dev/null +++ b/SetLnkApp/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs index 08a160a..a583108 100755 --- a/SetLnkApp/Program.cs +++ b/SetLnkApp/Program.cs @@ -1,34 +1,22 @@ -using ShellLinkPlus; -using System; -using System.IO; +using System; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; namespace SetLnkApp { - class Program + static class Program { - static void Main(string[] args) + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() { - bool existing = File.Exists(args[0]); - using (ShellLink shortcut = new ShellLink(existing ? args[0] : null)) - { - if (existing) - { - if (args.Length > 2) - { - throw new Exception("For an existing shortcut, only pass AppUserModelId"); - } - } - else - { - shortcut.TargetPath = args[2]; - //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : ""; - shortcut.Arguments = string.Join(" ", args.Skip(3)); - } - shortcut.AppUserModelID = args[1]; - - shortcut.Save(args[0]); - } + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); } } } diff --git a/SetLnkApp/Properties/AssemblyInfo.cs b/SetLnkApp/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..b05592c --- /dev/null +++ b/SetLnkApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SetLnkApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SetLnkApp")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("443b8959-7f3d-4199-838c-7a805427ce42")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SetLnkApp/Properties/Resources.Designer.cs b/SetLnkApp/Properties/Resources.Designer.cs new file mode 100755 index 0000000..fbae7bb --- /dev/null +++ b/SetLnkApp/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SetLnkApp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/SetLnkApp/Properties/Resources.resx b/SetLnkApp/Properties/Resources.resx new file mode 100755 index 0000000..ffecec8 --- /dev/null +++ b/SetLnkApp/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SetLnkApp/Properties/Settings.Designer.cs b/SetLnkApp/Properties/Settings.Designer.cs new file mode 100755 index 0000000..0b6b6e1 --- /dev/null +++ b/SetLnkApp/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SetLnkApp.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/SetLnkApp/Properties/Settings.settings b/SetLnkApp/Properties/Settings.settings new file mode 100755 index 0000000..abf36c5 --- /dev/null +++ b/SetLnkApp/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json deleted file mode 100755 index 420478a..0000000 --- a/SetLnkApp/Properties/launchSettings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "profiles": { - "SetLnkApp": { - "commandName": "Project" - } - } -} \ No newline at end of file diff --git a/SetLnkApp/SetLnkApp.csproj b/SetLnkApp/SetLnkApp.csproj index d453e9a..ec4d625 100755 --- a/SetLnkApp/SetLnkApp.csproj +++ b/SetLnkApp/SetLnkApp.csproj @@ -1,8 +1,86 @@ - - + + + - Exe - netcoreapp3.1 + Debug + AnyCPU + {443B8959-7F3D-4199-838C-7A805427CE42} + WinExe + SetLnkApp + SetLnkApp + v4.7.2 + 512 + true + true - - + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + ShellLink.cs + + + Form + + + MainForm.cs + + + + + MainForm.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/SetLnkApp/ShellLink.cs b/SetLnkApp/ShellLink.cs deleted file mode 100755 index 6d13f4e..0000000 --- a/SetLnkApp/ShellLink.cs +++ /dev/null @@ -1,486 +0,0 @@ -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using System.Text; -using ComTypes = System.Runtime.InteropServices.ComTypes; - -/**************************************************************************** - * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ - ***************************************************************************/ - -namespace ShellLinkPlus -{ - // Modified from http://smdn.jp/programming/tips/createlnk/ - // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects - // /Creating_and_Modifying_Shortcuts/article.asp - // Partly based on Sending toast notifications from desktop apps sample - public class ShellLink : IDisposable - { - #region Win32 and COM - - // IShellLink Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("000214F9-0000-0000-C000-000000000046")] - private interface IShellLinkW - { - uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, - int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); - uint GetIDList(out IntPtr ppidl); - uint SetIDList(IntPtr pidl); - uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, - int cchMaxName); - uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); - uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, - int cchMaxPath); - uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); - uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, - int cchMaxPath); - uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); - uint GetHotKey(out ushort pwHotkey); - uint SetHotKey(ushort wHotKey); - uint GetShowCmd(out int piShowCmd); - uint SetShowCmd(int iShowCmd); - uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, - int cchIconPath, out int piIcon); - uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); - uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, - uint dwReserved); - uint Resolve(IntPtr hwnd, uint fFlags); - uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); - } - - // ShellLink CoClass (ShellLink object) - [ComImport, - ClassInterface(ClassInterfaceType.None), - Guid("00021401-0000-0000-C000-000000000046")] - private class CShellLink { } - - // WIN32_FIND_DATAW Structure - [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] - private struct WIN32_FIND_DATAW - { - public uint dwFileAttributes; - public ComTypes.FILETIME ftCreationTime; - public ComTypes.FILETIME ftLastAccessTime; - public ComTypes.FILETIME ftLastWriteTime; - public uint nFileSizeHigh; - public uint nFileSizeLow; - public uint dwReserved0; - public uint dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] - public string cFileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string cAlternateFileName; - } - - // IPropertyStore Interface - [ComImport, - InterfaceType(ComInterfaceType.InterfaceIsIUnknown), - Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] - private interface IPropertyStore - { - uint GetCount([Out] out uint cProps); - uint GetAt([In] uint iProp, out PropertyKey pkey); - uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); - uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); - uint Commit(); - } - - // PropertyKey Structure - // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 - [StructLayout(LayoutKind.Sequential, Pack = 4)] - private struct PropertyKey - { - #region Fields - - private Guid formatId; // Unique GUID for property - private Int32 propertyId; // Property identifier (PID) - - #endregion - - #region Public Properties - - public Guid FormatId - { - get - { - return formatId; - } - } - - public Int32 PropertyId - { - get - { - return propertyId; - } - } - - #endregion - - #region Constructor - - public PropertyKey(Guid formatId, Int32 propertyId) - { - this.formatId = formatId; - this.propertyId = propertyId; - } - - public PropertyKey(string formatId, Int32 propertyId) - { - this.formatId = new Guid(formatId); - this.propertyId = propertyId; - } - - #endregion - } - - // PropVariant Class (only for string value) - // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 - // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 - // /interop-with-propvariants-in-net.aspx - [StructLayout(LayoutKind.Explicit)] - private sealed class PropVariant : IDisposable - { - #region Fields - - [FieldOffset(0)] - ushort valueType; // Value type - - // [FieldOffset(2)] - // ushort wReserved1; // Reserved field - // [FieldOffset(4)] - // ushort wReserved2; // Reserved field - // [FieldOffset(6)] - // ushort wReserved3; // Reserved field - - [FieldOffset(8)] - IntPtr ptr; // Value - - #endregion - - #region Public Properties - - // Value type (System.Runtime.InteropServices.VarEnum) - public VarEnum VarType - { - get { return (VarEnum)valueType; } - set { valueType = (ushort)value; } - } - - // Whether value is empty or null - public bool IsNullOrEmpty - { - get - { - return (valueType == (ushort)VarEnum.VT_EMPTY || - valueType == (ushort)VarEnum.VT_NULL); - } - } - - // Value (only for string value) - public string Value - { - get - { - return Marshal.PtrToStringUni(ptr); - } - } - - #endregion - - #region Constructor - - public PropVariant() - { } - - // Construct with string value - public PropVariant(string value) - { - if (value == null) - throw new ArgumentException("Failed to set value."); - - valueType = (ushort)VarEnum.VT_LPWSTR; - ptr = Marshal.StringToCoTaskMemUni(value); - } - - #endregion - - #region Destructor - - ~PropVariant() - { - Dispose(); - } - - public void Dispose() - { - PropVariantClear(this); - GC.SuppressFinalize(this); - } - - #endregion - } - - [DllImport("Ole32.dll", PreserveSig = false)] - private extern static void PropVariantClear([In, Out] PropVariant pvar); - - #endregion - - #region Fields - - private IShellLinkW shellLinkW = null; - - // Name = System.AppUserModel.ID - // ShellPKey = PKEY_AppUserModel_ID - // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 - // PropID = 5 - // Type = String (VT_LPWSTR) - private readonly PropertyKey AppUserModelIDKey = - new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); - - private const int MAX_PATH = 260; - private const int INFOTIPSIZE = 1024; - - private const int STGM_READ = 0x00000000; // STGM constants - private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags - - #endregion - - #region Private Properties (Interfaces) - - private IPersistFile PersistFile - { - get - { - IPersistFile PersistFile = shellLinkW as IPersistFile; - - if (PersistFile == null) - throw new COMException("Failed to create IPersistFile."); - else - return PersistFile; - } - } - - private IPropertyStore PropertyStore - { - get - { - IPropertyStore PropertyStore = shellLinkW as IPropertyStore; - - if (PropertyStore == null) - throw new COMException("Failed to create IPropertyStore."); - else - return PropertyStore; - } - } - - #endregion - - #region Public Properties (Minimal) - - // Path of loaded shortcut file - public string ShortcutFile - { - get - { - string shortcutFile; - - PersistFile.GetCurFile(out shortcutFile); - - return shortcutFile; - } - } - - // Path of target file - public string TargetPath - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder targetPath = new StringBuilder(MAX_PATH); - - WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); - - VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, - SLGP_UNCPRIORITY)); - - return targetPath.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetPath(value)); - } - } - - public string Arguments - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder arguments = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); - - return arguments.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetArguments(value)); - } - } - - public string Description - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder description = new StringBuilder(INFOTIPSIZE); - - VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); - - return description.ToString(); - } - set - { - VerifySucceeded(shellLinkW.SetDescription(value)); - } - } - - public Tuple IconLocation - { - get - { - // No limitation to length of buffer string in the case of Unicode though. - StringBuilder icon = new StringBuilder(INFOTIPSIZE); - - int index; - VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); - - return new Tuple(icon.ToString(), index); - } - set - { - VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); - } - } - - // AppUserModelID to be used for Windows 7 or later. - public string AppUserModelID - { - get - { - using (PropVariant pv = new PropVariant()) - { - VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); - - if (pv.Value == null) - return "Null"; - else - return pv.Value; - } - } - set - { - using (PropVariant pv = new PropVariant(value)) - { - VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); - VerifySucceeded(PropertyStore.Commit()); - } - } - } - - #endregion - - #region Constructor - - public ShellLink() - : this(null) - { } - - // Construct with loading shortcut file. - public ShellLink(string file) - { - try - { - shellLinkW = (IShellLinkW)new CShellLink(); - } - catch - { - throw new COMException("Failed to create ShellLink object."); - } - - if (file != null) - Load(file); - } - - #endregion - - #region Destructor - - ~ShellLink() - { - Dispose(false); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (shellLinkW != null) - { - // Release all references. - Marshal.FinalReleaseComObject(shellLinkW); - shellLinkW = null; - } - } - - #endregion - - #region Methods - - // Save shortcut file. - public void Save() - { - string file = ShortcutFile; - - if (file == null) - throw new InvalidOperationException("File name is not given."); - else - Save(file); - } - - public void Save(string file) - { - if (file == null) - throw new ArgumentNullException("File name is required."); - else - PersistFile.Save(file, true); - } - - // Load shortcut file. - public void Load(string file) - { - if (!File.Exists(file)) - throw new FileNotFoundException("File is not found.", file); - else - PersistFile.Load(file, STGM_READ); - } - - // Verify if operation succeeded. - public static void VerifySucceeded(uint hresult) - { - if (hresult > 1) - throw new InvalidOperationException("Failed with HRESULT: " + - hresult.ToString("X")); - } - - #endregion - } -} diff --git a/ShellLink.cs b/ShellLink.cs new file mode 100755 index 0000000..6d13f4e --- /dev/null +++ b/ShellLink.cs @@ -0,0 +1,486 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using ComTypes = System.Runtime.InteropServices.ComTypes; + +/**************************************************************************** + * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/ + ***************************************************************************/ + +namespace ShellLinkPlus +{ + // Modified from http://smdn.jp/programming/tips/createlnk/ + // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects + // /Creating_and_Modifying_Shortcuts/article.asp + // Partly based on Sending toast notifications from desktop apps sample + public class ShellLink : IDisposable + { + #region Win32 and COM + + // IShellLink Interface + [ComImport, + InterfaceType(ComInterfaceType.InterfaceIsIUnknown), + Guid("000214F9-0000-0000-C000-000000000046")] + private interface IShellLinkW + { + uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, + int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags); + uint GetIDList(out IntPtr ppidl); + uint SetIDList(IntPtr pidl); + uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, + int cchMaxName); + uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, + int cchMaxPath); + uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, + int cchMaxPath); + uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + uint GetHotKey(out ushort pwHotkey); + uint SetHotKey(ushort wHotKey); + uint GetShowCmd(out int piShowCmd); + uint SetShowCmd(int iShowCmd); + uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, + int cchIconPath, out int piIcon); + uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, + uint dwReserved); + uint Resolve(IntPtr hwnd, uint fFlags); + uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + } + + // ShellLink CoClass (ShellLink object) + [ComImport, + ClassInterface(ClassInterfaceType.None), + Guid("00021401-0000-0000-C000-000000000046")] + private class CShellLink { } + + // WIN32_FIND_DATAW Structure + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] + private struct WIN32_FIND_DATAW + { + public uint dwFileAttributes; + public ComTypes.FILETIME ftCreationTime; + public ComTypes.FILETIME ftLastAccessTime; + public ComTypes.FILETIME ftLastWriteTime; + public uint nFileSizeHigh; + public uint nFileSizeLow; + public uint dwReserved0; + public uint dwReserved1; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] + public string cFileName; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] + public string cAlternateFileName; + } + + // IPropertyStore Interface + [ComImport, + InterfaceType(ComInterfaceType.InterfaceIsIUnknown), + Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] + private interface IPropertyStore + { + uint GetCount([Out] out uint cProps); + uint GetAt([In] uint iProp, out PropertyKey pkey); + uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv); + uint SetValue([In] ref PropertyKey key, [In] PropVariant pv); + uint Commit(); + } + + // PropertyKey Structure + // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1 + [StructLayout(LayoutKind.Sequential, Pack = 4)] + private struct PropertyKey + { + #region Fields + + private Guid formatId; // Unique GUID for property + private Int32 propertyId; // Property identifier (PID) + + #endregion + + #region Public Properties + + public Guid FormatId + { + get + { + return formatId; + } + } + + public Int32 PropertyId + { + get + { + return propertyId; + } + } + + #endregion + + #region Constructor + + public PropertyKey(Guid formatId, Int32 propertyId) + { + this.formatId = formatId; + this.propertyId = propertyId; + } + + public PropertyKey(string formatId, Int32 propertyId) + { + this.formatId = new Guid(formatId); + this.propertyId = propertyId; + } + + #endregion + } + + // PropVariant Class (only for string value) + // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1 + // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11 + // /interop-with-propvariants-in-net.aspx + [StructLayout(LayoutKind.Explicit)] + private sealed class PropVariant : IDisposable + { + #region Fields + + [FieldOffset(0)] + ushort valueType; // Value type + + // [FieldOffset(2)] + // ushort wReserved1; // Reserved field + // [FieldOffset(4)] + // ushort wReserved2; // Reserved field + // [FieldOffset(6)] + // ushort wReserved3; // Reserved field + + [FieldOffset(8)] + IntPtr ptr; // Value + + #endregion + + #region Public Properties + + // Value type (System.Runtime.InteropServices.VarEnum) + public VarEnum VarType + { + get { return (VarEnum)valueType; } + set { valueType = (ushort)value; } + } + + // Whether value is empty or null + public bool IsNullOrEmpty + { + get + { + return (valueType == (ushort)VarEnum.VT_EMPTY || + valueType == (ushort)VarEnum.VT_NULL); + } + } + + // Value (only for string value) + public string Value + { + get + { + return Marshal.PtrToStringUni(ptr); + } + } + + #endregion + + #region Constructor + + public PropVariant() + { } + + // Construct with string value + public PropVariant(string value) + { + if (value == null) + throw new ArgumentException("Failed to set value."); + + valueType = (ushort)VarEnum.VT_LPWSTR; + ptr = Marshal.StringToCoTaskMemUni(value); + } + + #endregion + + #region Destructor + + ~PropVariant() + { + Dispose(); + } + + public void Dispose() + { + PropVariantClear(this); + GC.SuppressFinalize(this); + } + + #endregion + } + + [DllImport("Ole32.dll", PreserveSig = false)] + private extern static void PropVariantClear([In, Out] PropVariant pvar); + + #endregion + + #region Fields + + private IShellLinkW shellLinkW = null; + + // Name = System.AppUserModel.ID + // ShellPKey = PKEY_AppUserModel_ID + // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3 + // PropID = 5 + // Type = String (VT_LPWSTR) + private readonly PropertyKey AppUserModelIDKey = + new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5); + + private const int MAX_PATH = 260; + private const int INFOTIPSIZE = 1024; + + private const int STGM_READ = 0x00000000; // STGM constants + private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags + + #endregion + + #region Private Properties (Interfaces) + + private IPersistFile PersistFile + { + get + { + IPersistFile PersistFile = shellLinkW as IPersistFile; + + if (PersistFile == null) + throw new COMException("Failed to create IPersistFile."); + else + return PersistFile; + } + } + + private IPropertyStore PropertyStore + { + get + { + IPropertyStore PropertyStore = shellLinkW as IPropertyStore; + + if (PropertyStore == null) + throw new COMException("Failed to create IPropertyStore."); + else + return PropertyStore; + } + } + + #endregion + + #region Public Properties (Minimal) + + // Path of loaded shortcut file + public string ShortcutFile + { + get + { + string shortcutFile; + + PersistFile.GetCurFile(out shortcutFile); + + return shortcutFile; + } + } + + // Path of target file + public string TargetPath + { + get + { + // No limitation to length of buffer string in the case of Unicode though. + StringBuilder targetPath = new StringBuilder(MAX_PATH); + + WIN32_FIND_DATAW data = new WIN32_FIND_DATAW(); + + VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, + SLGP_UNCPRIORITY)); + + return targetPath.ToString(); + } + set + { + VerifySucceeded(shellLinkW.SetPath(value)); + } + } + + public string Arguments + { + get + { + // No limitation to length of buffer string in the case of Unicode though. + StringBuilder arguments = new StringBuilder(INFOTIPSIZE); + + VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity)); + + return arguments.ToString(); + } + set + { + VerifySucceeded(shellLinkW.SetArguments(value)); + } + } + + public string Description + { + get + { + // No limitation to length of buffer string in the case of Unicode though. + StringBuilder description = new StringBuilder(INFOTIPSIZE); + + VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity)); + + return description.ToString(); + } + set + { + VerifySucceeded(shellLinkW.SetDescription(value)); + } + } + + public Tuple IconLocation + { + get + { + // No limitation to length of buffer string in the case of Unicode though. + StringBuilder icon = new StringBuilder(INFOTIPSIZE); + + int index; + VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index)); + + return new Tuple(icon.ToString(), index); + } + set + { + VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2)); + } + } + + // AppUserModelID to be used for Windows 7 or later. + public string AppUserModelID + { + get + { + using (PropVariant pv = new PropVariant()) + { + VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv)); + + if (pv.Value == null) + return "Null"; + else + return pv.Value; + } + } + set + { + using (PropVariant pv = new PropVariant(value)) + { + VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv)); + VerifySucceeded(PropertyStore.Commit()); + } + } + } + + #endregion + + #region Constructor + + public ShellLink() + : this(null) + { } + + // Construct with loading shortcut file. + public ShellLink(string file) + { + try + { + shellLinkW = (IShellLinkW)new CShellLink(); + } + catch + { + throw new COMException("Failed to create ShellLink object."); + } + + if (file != null) + Load(file); + } + + #endregion + + #region Destructor + + ~ShellLink() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (shellLinkW != null) + { + // Release all references. + Marshal.FinalReleaseComObject(shellLinkW); + shellLinkW = null; + } + } + + #endregion + + #region Methods + + // Save shortcut file. + public void Save() + { + string file = ShortcutFile; + + if (file == null) + throw new InvalidOperationException("File name is not given."); + else + Save(file); + } + + public void Save(string file) + { + if (file == null) + throw new ArgumentNullException("File name is required."); + else + PersistFile.Save(file, true); + } + + // Load shortcut file. + public void Load(string file) + { + if (!File.Exists(file)) + throw new FileNotFoundException("File is not found.", file); + else + PersistFile.Load(file, STGM_READ); + } + + // Verify if operation succeeded. + public static void VerifySucceeded(uint hresult) + { + if (hresult > 1) + throw new InvalidOperationException("Failed with HRESULT: " + + hresult.ToString("X")); + } + + #endregion + } +}