615 lines
21 KiB
C#
615 lines
21 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
|
|
namespace VSoft.Prams
|
|
{
|
|
public class ShellLink : IDisposable
|
|
{
|
|
// Fields
|
|
private IShellLinkW linkW;
|
|
private IShellLinkA linkA;
|
|
private string shortcutFile;
|
|
|
|
// Methods
|
|
public ShellLink()
|
|
{
|
|
this.shortcutFile = "";
|
|
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
|
|
{
|
|
this.linkW = (IShellLinkW)new CShellLink();
|
|
}
|
|
else
|
|
{
|
|
this.linkA = (IShellLinkA)new CShellLink();
|
|
}
|
|
}
|
|
|
|
public ShellLink(string linkFile) : this()
|
|
{
|
|
this.Open(linkFile);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
private bool disposed = false;
|
|
// Dispose(bool disposing) executes in two distinct scenarios.
|
|
// If disposing equals true, the method has been called directly
|
|
// or indirectly by a user's code. Managed and unmanaged resources
|
|
// can be disposed.
|
|
// If disposing equals false, the method has been called by the
|
|
// runtime from inside the finalizer and you should not reference
|
|
// other objects. Only unmanaged resources can be disposed.
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
// Check to see if Dispose has already been called.
|
|
if (!this.disposed)
|
|
{
|
|
// If disposing equals true, dispose all managed
|
|
// and unmanaged resources.
|
|
if (disposing)
|
|
{
|
|
if (this.linkW != null)
|
|
{
|
|
Marshal.ReleaseComObject(this.linkW);
|
|
this.linkW = null;
|
|
}
|
|
if (this.linkA != null)
|
|
{
|
|
Marshal.ReleaseComObject(this.linkA);
|
|
this.linkA = null;
|
|
}
|
|
// Dispose managed resources.
|
|
this.Dispose();
|
|
}
|
|
|
|
// Call the appropriate methods to clean up
|
|
// unmanaged resources here.
|
|
// If disposing is false,
|
|
// only the following code is executed.
|
|
|
|
// Note disposing has been done.
|
|
disposed = true;
|
|
|
|
}
|
|
}
|
|
~ShellLink()
|
|
{
|
|
this.Dispose(false);
|
|
}
|
|
|
|
private Icon getIcon(bool large)
|
|
{
|
|
int piIcon = 0;
|
|
StringBuilder pszIconPath = new StringBuilder(260, 260);
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
string lpszFile = pszIconPath.ToString();
|
|
if (lpszFile.Length == 0)
|
|
{
|
|
FileIcon.SHGetFileInfoConstants flags = FileIcon.SHGetFileInfoConstants.SHGFI_ATTRIBUTES | FileIcon.SHGetFileInfoConstants.SHGFI_ICON;
|
|
if (large)
|
|
{
|
|
//flags = flags;
|
|
}
|
|
else
|
|
{
|
|
flags |= FileIcon.SHGetFileInfoConstants.SHGFI_SMALLICON;
|
|
}
|
|
FileIcon icon = new FileIcon(this.Target, flags);
|
|
return icon.ShellIcon;
|
|
}
|
|
IntPtr[] phIconLarge = new IntPtr[] { IntPtr.Zero };
|
|
if (large)
|
|
{
|
|
UnManagedMethods.ExtractIconEx(lpszFile, piIcon, phIconLarge, null, 1);
|
|
}
|
|
else
|
|
{
|
|
UnManagedMethods.ExtractIconEx(lpszFile, piIcon, null, phIconLarge, 1);
|
|
}
|
|
Icon icon2 = null;
|
|
if (phIconLarge[0] != IntPtr.Zero)
|
|
{
|
|
icon2 = Icon.FromHandle(phIconLarge[0]);
|
|
}
|
|
return icon2;
|
|
}
|
|
|
|
public void Open(string linkFile)
|
|
{
|
|
this.Open(linkFile, IntPtr.Zero, EShellLinkResolveFlags.SLR_ANY_MATCH | EShellLinkResolveFlags.SLR_NO_UI, 1);
|
|
}
|
|
|
|
public void Open(string linkFile, IntPtr hWnd, EShellLinkResolveFlags resolveFlags)
|
|
{
|
|
this.Open(linkFile, hWnd, resolveFlags, 1);
|
|
}
|
|
|
|
public void Open(string linkFile, IntPtr hWnd, EShellLinkResolveFlags resolveFlags, ushort timeOut)
|
|
{
|
|
uint num;
|
|
if ((resolveFlags & EShellLinkResolveFlags.SLR_NO_UI) == EShellLinkResolveFlags.SLR_NO_UI)
|
|
{
|
|
num = (uint)(resolveFlags | ((EShellLinkResolveFlags)(timeOut << 0x10)));
|
|
}
|
|
else
|
|
{
|
|
num = (uint)resolveFlags;
|
|
}
|
|
if (this.linkA == null)
|
|
{
|
|
((IPersistFile)this.linkW).Load(linkFile, 0);
|
|
this.linkW.Resolve(hWnd, num);
|
|
this.shortcutFile = linkFile;
|
|
}
|
|
else
|
|
{
|
|
((IPersistFile)this.linkA).Load(linkFile, 0);
|
|
this.linkA.Resolve(hWnd, num);
|
|
this.shortcutFile = linkFile;
|
|
}
|
|
}
|
|
|
|
public void Save()
|
|
{
|
|
this.Save(this.shortcutFile);
|
|
}
|
|
|
|
public void Save(string linkFile)
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
((IPersistFile)this.linkW).Save(linkFile, true);
|
|
this.shortcutFile = linkFile;
|
|
}
|
|
else
|
|
{
|
|
((IPersistFile)this.linkA).Save(linkFile, true);
|
|
this.shortcutFile = linkFile;
|
|
}
|
|
}
|
|
|
|
// Properties
|
|
public string ShortCutFile
|
|
{
|
|
get =>
|
|
this.shortcutFile;
|
|
set =>
|
|
this.shortcutFile = value;
|
|
}
|
|
|
|
public Icon LargeIcon =>
|
|
this.getIcon(true);
|
|
|
|
public Icon SmallIcon =>
|
|
this.getIcon(false);
|
|
|
|
public string IconPath
|
|
{
|
|
get
|
|
{
|
|
StringBuilder pszIconPath = new StringBuilder(260, 260);
|
|
int piIcon = 0;
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
return pszIconPath.ToString();
|
|
}
|
|
set
|
|
{
|
|
StringBuilder pszIconPath = new StringBuilder(260, 260);
|
|
int piIcon = 0;
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetIconLocation(value, piIcon);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetIconLocation(value, piIcon);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int IconIndex
|
|
{
|
|
get
|
|
{
|
|
StringBuilder pszIconPath = new StringBuilder(260, 260);
|
|
int piIcon = 0;
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
return piIcon;
|
|
}
|
|
this.linkA.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
return piIcon;
|
|
}
|
|
set
|
|
{
|
|
StringBuilder pszIconPath = new StringBuilder(260, 260);
|
|
int piIcon = 0;
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetIconLocation(pszIconPath, pszIconPath.Capacity, out piIcon);
|
|
}
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetIconLocation(pszIconPath.ToString(), value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetIconLocation(pszIconPath.ToString(), value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Target
|
|
{
|
|
get
|
|
{
|
|
StringBuilder pszFile = new StringBuilder(260, 260);
|
|
if (this.linkA == null)
|
|
{
|
|
_WIN32_FIND_DATAW pfd = new _WIN32_FIND_DATAW();
|
|
this.linkW.GetPath(pszFile, pszFile.Capacity, ref pfd, 2);
|
|
}
|
|
else
|
|
{
|
|
_WIN32_FIND_DATAA pfd = new _WIN32_FIND_DATAA();
|
|
this.linkA.GetPath(pszFile, pszFile.Capacity, ref pfd, 2);
|
|
}
|
|
return pszFile.ToString();
|
|
}
|
|
set
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetPath(value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetPath(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string WorkingDirectory
|
|
{
|
|
get
|
|
{
|
|
StringBuilder pszDir = new StringBuilder(260, 260);
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetWorkingDirectory(pszDir, pszDir.Capacity);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetWorkingDirectory(pszDir, pszDir.Capacity);
|
|
}
|
|
return pszDir.ToString();
|
|
}
|
|
set
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetWorkingDirectory(value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetWorkingDirectory(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Description
|
|
{
|
|
get
|
|
{
|
|
StringBuilder pszFile = new StringBuilder(0x400, 0x400);
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetDescription(pszFile, pszFile.Capacity);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetDescription(pszFile, pszFile.Capacity);
|
|
}
|
|
return pszFile.ToString();
|
|
}
|
|
set
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetDescription(value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetDescription(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Arguments
|
|
{
|
|
get
|
|
{
|
|
StringBuilder pszArgs = new StringBuilder(260, 260);
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetArguments(pszArgs, pszArgs.Capacity);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetArguments(pszArgs, pszArgs.Capacity);
|
|
}
|
|
return pszArgs.ToString();
|
|
}
|
|
set
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetArguments(value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetArguments(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public LinkDisplayMode DisplayMode
|
|
{
|
|
get
|
|
{
|
|
uint piShowCmd = 0;
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetShowCmd(out piShowCmd);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetShowCmd(out piShowCmd);
|
|
}
|
|
return (LinkDisplayMode)piShowCmd;
|
|
}
|
|
set
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetShowCmd((uint)value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetShowCmd((uint)value);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Keys HotKey
|
|
{
|
|
get
|
|
{
|
|
short pwHotkey = 0;
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.GetHotkey(out pwHotkey);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.GetHotkey(out pwHotkey);
|
|
}
|
|
return (Keys)pwHotkey;
|
|
}
|
|
set
|
|
{
|
|
if (this.linkA == null)
|
|
{
|
|
this.linkW.SetHotkey((short)value);
|
|
}
|
|
else
|
|
{
|
|
this.linkA.SetHotkey((short)value);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Nested Types
|
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
|
private struct _FILETIME
|
|
{
|
|
public uint dwLowDateTime;
|
|
public uint dwHighDateTime;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
|
private struct _WIN32_FIND_DATAA
|
|
{
|
|
public uint dwFileAttributes;
|
|
public ShellLink._FILETIME ftCreationTime;
|
|
public ShellLink._FILETIME ftLastAccessTime;
|
|
public ShellLink._FILETIME ftLastWriteTime;
|
|
public uint nFileSizeHigh;
|
|
public uint nFileSizeLow;
|
|
public uint dwReserved0;
|
|
public uint dwReserved1;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
|
public string cFileName;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
|
|
public string cAlternateFileName;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
|
|
private struct _WIN32_FIND_DATAW
|
|
{
|
|
public uint dwFileAttributes;
|
|
public ShellLink._FILETIME ftCreationTime;
|
|
public ShellLink._FILETIME ftLastAccessTime;
|
|
public ShellLink._FILETIME ftLastWriteTime;
|
|
public uint nFileSizeHigh;
|
|
public uint nFileSizeLow;
|
|
public uint dwReserved0;
|
|
public uint dwReserved1;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
|
public string cFileName;
|
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
|
|
public string cAlternateFileName;
|
|
}
|
|
|
|
[ComImport, ClassInterface(ClassInterfaceType.None), Guid("00021401-0000-0000-C000-000000000046")]
|
|
private class CShellLink
|
|
{
|
|
}
|
|
|
|
private enum EShellLinkGP : uint
|
|
{
|
|
SLGP_SHORTPATH = 1,
|
|
SLGP_UNCPRIORITY = 2
|
|
}
|
|
|
|
[Flags]
|
|
public enum EShellLinkResolveFlags : uint
|
|
{
|
|
SLR_ANY_MATCH = 2,
|
|
SLR_INVOKE_MSI = 0x80,
|
|
SLR_NOLINKINFO = 0x40,
|
|
SLR_NO_UI = 1,
|
|
SLR_NO_UI_WITH_MSG_PUMP = 0x101,
|
|
SLR_NOUPDATE = 8,
|
|
SLR_NOSEARCH = 0x10,
|
|
SLR_NOTRACK = 0x20,
|
|
SLR_UPDATE = 4
|
|
}
|
|
|
|
[Flags]
|
|
private enum EShowWindowFlags : uint
|
|
{
|
|
SW_HIDE = 0,
|
|
SW_SHOWNORMAL = 1,
|
|
SW_NORMAL = 1,
|
|
SW_SHOWMINIMIZED = 2,
|
|
SW_SHOWMAXIMIZED = 3,
|
|
SW_MAXIMIZE = 3,
|
|
SW_SHOWNOACTIVATE = 4,
|
|
SW_SHOW = 5,
|
|
SW_MINIMIZE = 6,
|
|
SW_SHOWMINNOACTIVE = 7,
|
|
SW_SHOWNA = 8,
|
|
SW_RESTORE = 9,
|
|
SW_SHOWDEFAULT = 10,
|
|
SW_MAX = 10
|
|
}
|
|
|
|
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000010C-0000-0000-C000-000000000046")]
|
|
private interface IPersist
|
|
{
|
|
[PreserveSig]
|
|
void GetClassID(out Guid pClassID);
|
|
}
|
|
|
|
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000010B-0000-0000-C000-000000000046")]
|
|
private interface IPersistFile
|
|
{
|
|
[PreserveSig]
|
|
void GetClassID(out Guid pClassID);
|
|
void IsDirty();
|
|
void Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode);
|
|
void Save([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember);
|
|
void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
|
|
void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out string ppszFileName);
|
|
}
|
|
|
|
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214EE-0000-0000-C000-000000000046")]
|
|
private interface IShellLinkA
|
|
{
|
|
void GetPath([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszFile, int cchMaxPath, ref ShellLink._WIN32_FIND_DATAA pfd, uint fFlags);
|
|
void GetIDList(out IntPtr ppidl);
|
|
void SetIDList(IntPtr pidl);
|
|
void GetDescription([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszFile, int cchMaxName);
|
|
void SetDescription([MarshalAs(UnmanagedType.LPStr)] string pszName);
|
|
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszDir, int cchMaxPath);
|
|
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPStr)] string pszDir);
|
|
void GetArguments([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszArgs, int cchMaxPath);
|
|
void SetArguments([MarshalAs(UnmanagedType.LPStr)] string pszArgs);
|
|
void GetHotkey(out short pwHotkey);
|
|
void SetHotkey(short pwHotkey);
|
|
void GetShowCmd(out uint piShowCmd);
|
|
void SetShowCmd(uint piShowCmd);
|
|
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
|
|
void SetIconLocation([MarshalAs(UnmanagedType.LPStr)] string pszIconPath, int iIcon);
|
|
void SetRelativePath([MarshalAs(UnmanagedType.LPStr)] string pszPathRel, uint dwReserved);
|
|
void Resolve(IntPtr hWnd, uint fFlags);
|
|
void SetPath([MarshalAs(UnmanagedType.LPStr)] string pszFile);
|
|
}
|
|
|
|
[ComImport, Guid("000214F9-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
private interface IShellLinkW
|
|
{
|
|
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, ref ShellLink._WIN32_FIND_DATAW pfd, uint fFlags);
|
|
void GetIDList(out IntPtr ppidl);
|
|
void SetIDList(IntPtr pidl);
|
|
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName);
|
|
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
|
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
|
|
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
|
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
|
|
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
|
void GetHotkey(out short pwHotkey);
|
|
void SetHotkey(short pwHotkey);
|
|
void GetShowCmd(out uint piShowCmd);
|
|
void SetShowCmd(uint piShowCmd);
|
|
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
|
|
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
|
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
|
|
void Resolve(IntPtr hWnd, uint fFlags);
|
|
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
|
}
|
|
|
|
public enum LinkDisplayMode : uint
|
|
{
|
|
edmNormal = 1,
|
|
edmMinimized = 7,
|
|
edmMaximized = 3
|
|
}
|
|
|
|
private class UnManagedMethods
|
|
{
|
|
// Methods
|
|
[DllImport("user32")]
|
|
internal static extern int DestroyIcon(IntPtr hIcon);
|
|
[DllImport("shell32", CharSet = CharSet.Auto)]
|
|
internal static extern int ExtractIconEx([MarshalAs(UnmanagedType.LPWStr)] string lpszFile, int nIconIndex, IntPtr[] phIconLarge, IntPtr[] phIconSmall, int nIcons);
|
|
}
|
|
}
|
|
}
|