diff --git a/Installer/PostInstaller/PostInstaller.sln b/Installer/PostInstaller/PostInstaller.sln new file mode 100644 index 0000000..0f62fb4 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2012 for Windows Desktop +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostInstaller", "PostInstaller\PostInstaller.csproj", "{05F8E270-8B47-449B-8755-4599B3B3A565}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {05F8E270-8B47-449B-8755-4599B3B3A565}.Debug|Any CPU.Build.0 = Debug|Any CPU + {05F8E270-8B47-449B-8755-4599B3B3A565}.Release|Any CPU.ActiveCfg = Release|Any CPU + {05F8E270-8B47-449B-8755-4599B3B3A565}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Installer/PostInstaller/PostInstaller/App.config b/Installer/PostInstaller/PostInstaller/App.config new file mode 100644 index 0000000..84bc420 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Installer/PostInstaller/PostInstaller/IPersistFile.cs b/Installer/PostInstaller/PostInstaller/IPersistFile.cs new file mode 100644 index 0000000..c581b2f --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/IPersistFile.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + + [ComImportAttribute] + [GuidAttribute("0000010B-0000-0000-C000-000000000046")] + [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersistFile { + + // can't get this to go if I extend IPersist, + // so put it here: + [PreserveSig] + int GetClassID(out Guid pClassID); + + //[helpstring("Checks for changes since + // last file write")] + [PreserveSig] + int IsDirty(); + + //[helpstring("Opens the specified file and + // initializes the object from its contents")] + int Load( + [MarshalAs(UnmanagedType.LPWStr)] string pszFileName, + ulong dwMode); + + //[helpstring("Saves the object into + // the specified file")] + void Save( + [MarshalAs(UnmanagedType.LPWStr)] + string pszFileName, + [MarshalAs(UnmanagedType.Bool)] + bool fRemember); + + //[helpstring("Notifies the object that save + // is completed")] + void SaveCompleted( + [MarshalAs(UnmanagedType.LPWStr)] + string pszFileName); + + //[helpstring("Gets the current name of the + // file associated with the object")] + void GetCurFile( + [MarshalAs(UnmanagedType.LPWStr)] + out string ppszFileName); + + } +} diff --git a/Installer/PostInstaller/PostInstaller/IPropertyStore.cs b/Installer/PostInstaller/PostInstaller/IPropertyStore.cs new file mode 100644 index 0000000..a4d5d8b --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/IPropertyStore.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")] + public interface IPropertyStore { + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetCount([Out] out uint cProps); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetAt([In] uint iProp, out PropertyKey pkey); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void GetValue([In] ref PropertyKey key, out object pv); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void SetValue([In] ref PropertyKey key, [In] ref object pv); + + [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] + void Commit(); + } +} diff --git a/Installer/PostInstaller/PostInstaller/IShellItem.cs b/Installer/PostInstaller/PostInstaller/IShellItem.cs new file mode 100644 index 0000000..5e33eb2 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/IShellItem.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")] + public interface IShellItem { + + } +} diff --git a/Installer/PostInstaller/PostInstaller/IShellLink.cs b/Installer/PostInstaller/PostInstaller/IShellLink.cs new file mode 100644 index 0000000..84e08cb --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/IShellLink.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("000214F9-0000-0000-C000-000000000046")] + public interface IShellLink { + + /// Retrieves the path and file name of a Shell link object + void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, int fFlags); + + /// Retrieves the list of item identifiers for a Shell link object + void GetIDList(out IntPtr ppidl); + /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. + void SetIDList(IntPtr pidl); + /// Retrieves the description string for a Shell link object + void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); + /// Sets the description for a Shell link object. The description can be any application-defined string + void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + /// Retrieves the name of the working directory for a Shell link object + void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); + /// Sets the name of the working directory for a Shell link object + void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + /// Retrieves the command-line arguments associated with a Shell link object + void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); + /// Sets the command-line arguments for a Shell link object + void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + /// Retrieves the hot key for a Shell link object + void GetHotkey(out short pwHotkey); + /// Sets a hot key for a Shell link object + void SetHotkey(short wHotkey); + /// Retrieves the show command for a Shell link object + void GetShowCmd(out int piShowCmd); + /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. + void SetShowCmd(int iShowCmd); + /// Retrieves the location (path and index) of the icon for a Shell link object + void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, + int cchIconPath, out int piIcon); + /// Sets the location (path and index) of the icon for a Shell link object + void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + /// Sets the relative path to the Shell link object + void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); + + /// Attempts to find the target of a Shell link, even if it has been moved or renamed + void Resolve(IntPtr hwnd, int fFlags); + + /// Sets the path and file name of a Shell link object + void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + + } + + [GuidAttribute("00021401-0000-0000-C000-000000000046")] + [ClassInterfaceAttribute(ClassInterfaceType.None)] + [ComImportAttribute()] + public class CShellLink { + + } + +} diff --git a/Installer/PostInstaller/PostInstaller/IUnknown.cs b/Installer/PostInstaller/PostInstaller/IUnknown.cs new file mode 100644 index 0000000..9202806 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/IUnknown.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + [ComImport] + //[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("00000000-0000-0000-C000-000000000046")] + public interface IUnknown { + + IntPtr QueryInterface(ref Guid riid); + + [PreserveSig] + ulong AddRef(); + + [PreserveSig] + ulong Release(); + + } +} diff --git a/Installer/PostInstaller/PostInstaller/PostInstaller.csproj b/Installer/PostInstaller/PostInstaller/PostInstaller.csproj new file mode 100644 index 0000000..a569dc0 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/PostInstaller.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {05F8E270-8B47-449B-8755-4599B3B3A565} + Exe + Properties + PostInstaller + PostInstaller + v4.0 + 512 + Client + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + PostInstaller.Program + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Installer/PostInstaller/PostInstaller/Program.cs b/Installer/PostInstaller/PostInstaller/Program.cs new file mode 100644 index 0000000..d6bc03d --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/Program.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace PostInstaller { + class Program { + static int Main(string[] args) { + return Run(args) ? 0 : 1; + } + + private static bool Run(string[] args) { + Console.WriteLine("Attempting to create IShellItem for file {0}...", args[0]); + IShellLink link = (IShellLink)new CShellLink(); + + //Win32Shell.SHCreateItemFromParsingName(args[0], IntPtr.Zero, Win32Shell.IShellLinkId, out link); + IPersistFile persistFileLink = (IPersistFile)link; + if (persistFileLink.Load(args[0], 0x00000002L) != 0) { + Console.WriteLine("Failed to load via IPersistFile."); + return false; + } + + link.Resolve(IntPtr.Zero, 0); + + /* + link.SetPath("C:\\Windows\\notepad.exe"); + link.SetArguments(""); + */ + + Console.WriteLine("Querying for IPropertyStore interface..."); + IPropertyStore propStore = (IPropertyStore)link; + + PropertyKey appUserModelKey = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5); + + try { + object oldValue; + propStore.GetValue(ref appUserModelKey, out oldValue); + + Console.WriteLine("AppUserModel.ID value: {0} (type {1})", oldValue, oldValue.GetType().AssemblyQualifiedName); + } + catch (Exception) { +#if DEBUG + throw; +#endif + return false; + } + + Console.WriteLine("Attempting to set property 'System.AppUserModel.ID' to {0}...", args[1]); + + propStore.SetValue(ref appUserModelKey, new BStrWrapper(args[1])); + propStore.Commit(); + + //Store + ((IPersistFile)link).Save(args[0], false); + + Console.WriteLine("Done."); + return true; + } + } +} diff --git a/Installer/PostInstaller/PostInstaller/Properties/AssemblyInfo.cs b/Installer/PostInstaller/PostInstaller/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7b01646 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/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("PostInstaller")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PostInstaller")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[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("ef62555b-7bd2-40aa-8704-874f8ce12268")] + +// 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/Installer/PostInstaller/PostInstaller/PropertyKey.cs b/Installer/PostInstaller/PostInstaller/PropertyKey.cs new file mode 100644 index 0000000..4207ca4 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/PropertyKey.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + [StructLayout(LayoutKind.Sequential)] + public struct PropertyKey { + + public PropertyKey(Guid formatId, uint propertyId) { + fmtid = formatId; + pid = propertyId; + } + + public Guid fmtid; + public uint pid; + + } +} diff --git a/Installer/PostInstaller/PostInstaller/Win32Shell.cs b/Installer/PostInstaller/PostInstaller/Win32Shell.cs new file mode 100644 index 0000000..70b6307 --- /dev/null +++ b/Installer/PostInstaller/PostInstaller/Win32Shell.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace PostInstaller { + public static class Win32Shell { + + public readonly static Guid IShellItemId = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"); + + public readonly static Guid IShellLinkId = new Guid("000214F9-0000-0000-C000-000000000046"); + + public readonly static Guid IUnknownId = new Guid("00000000-0000-0000-C000-000000000046"); + + public readonly static Guid IPropertyStoreId = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"); + + [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)] + public static extern void SHCreateItemFromParsingName( + [In][MarshalAs(UnmanagedType.LPWStr)] string pszPath, + [In] IntPtr pbc, + [In][MarshalAs(UnmanagedType.LPStruct)] Guid iIdIShellItem, + [Out][MarshalAs(UnmanagedType.Interface, IidParameterIndex = 2)] out IShellLink iShellItem + ); + + } +}