mirror of
https://github.com/QL-Win/QuickLook.git
synced 2026-05-06 02:06:44 +08:00
Try to fix #311: use new shortcut interface
This commit is contained in:
@@ -17,7 +17,9 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using QuickLook.Common.Helpers;
|
||||
using QuickLook.NativeMethods;
|
||||
|
||||
namespace QuickLook.Helpers
|
||||
{
|
||||
@@ -34,16 +36,15 @@ namespace QuickLook.Helpers
|
||||
|
||||
try
|
||||
{
|
||||
File.Create(StartupFullPath).Close();
|
||||
RemoveAutorunShortcut();
|
||||
|
||||
var lnk = ShellLinkHelper.OpenShellLink(StartupFullPath);
|
||||
var lnk = (IShellLinkW) new ShellLink();
|
||||
|
||||
lnk.Path = App.AppFullPath;
|
||||
lnk.Arguments = "/autorun"; // silent
|
||||
lnk.SetPath(App.AppFullPath);
|
||||
lnk.SetArguments("/autorun"); // silent
|
||||
lnk.SetIconLocation(App.AppFullPath, 0);
|
||||
lnk.WorkingDirectory = App.AppPath;
|
||||
|
||||
lnk.Save(StartupFullPath);
|
||||
lnk.SetWorkingDirectory(App.AppPath);
|
||||
((IPersistFile) lnk).Save(StartupFullPath, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -57,7 +58,15 @@ namespace QuickLook.Helpers
|
||||
if (App.IsUWP)
|
||||
return;
|
||||
|
||||
File.Delete(StartupFullPath);
|
||||
try
|
||||
{
|
||||
File.Delete(StartupFullPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ProcessHelper.WriteLog(e.ToString());
|
||||
TrayIconManager.ShowNotification("", "Failed to delete QuickLook startup shortcut.");
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsAutorun()
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
// Copyright © 2018 Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Shell32;
|
||||
|
||||
namespace QuickLook.Helpers
|
||||
{
|
||||
public class ShellLinkHelper
|
||||
{
|
||||
public static ShellLinkObject OpenShellLink(string path)
|
||||
{
|
||||
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
|
||||
return StartSTATask(() => OpenShellLink(path)).Result;
|
||||
|
||||
var shl = new Shell();
|
||||
var dir = shl.NameSpace(Path.GetDirectoryName(path));
|
||||
var itm = dir.Items().Item(Path.GetFileName(path));
|
||||
var lnk = (ShellLinkObject) itm.GetLink;
|
||||
return lnk;
|
||||
}
|
||||
|
||||
public static string GetTarget(string path)
|
||||
{
|
||||
if (Path.GetExtension(path).ToLower() != ".lnk")
|
||||
return path;
|
||||
|
||||
try
|
||||
{
|
||||
return Thread.CurrentThread.GetApartmentState() != ApartmentState.STA
|
||||
? StartSTATask(() => GetTarget(path)).Result
|
||||
: OpenShellLink(path).Target.Path;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
private static Task<T> StartSTATask<T>(Func<T> func)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<T>();
|
||||
var thread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
tcs.SetResult(func());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
tcs.SetException(e);
|
||||
}
|
||||
});
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
thread.Start();
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
// Copyright © 2018 Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace QuickLook.NativeMethods
|
||||
{
|
||||
[Flags]
|
||||
internal enum SLGP_FLAGS
|
||||
{
|
||||
/// <summary>Retrieves the standard short (8.3 format) file name</summary>
|
||||
SLGP_SHORTPATH = 0x1,
|
||||
/// <summary>Retrieves the Universal Naming Convention (UNC) path name of the file</summary>
|
||||
SLGP_UNCPRIORITY = 0x2,
|
||||
/// <summary>
|
||||
/// Retrieves the raw path name. A raw path is something that might not exist and may include environment
|
||||
/// variables that need to be expanded
|
||||
/// </summary>
|
||||
SLGP_RAWPATH = 0x4
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
internal struct WIN32_FIND_DATAW
|
||||
{
|
||||
public uint dwFileAttributes;
|
||||
public long ftCreationTime;
|
||||
public long ftLastAccessTime;
|
||||
public long 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;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum SLR_FLAGS
|
||||
{
|
||||
/// <summary>
|
||||
/// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set,
|
||||
/// the high-order word of fFlags can be set to a time-out value that specifies the
|
||||
/// maximum amount of time to be spent resolving the link. The function returns if the
|
||||
/// link cannot be resolved within the time-out duration. If the high-order word is set
|
||||
/// to zero, the time-out duration will be set to the default value of 3,000 milliseconds
|
||||
/// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out
|
||||
/// duration, in milliseconds.
|
||||
/// </summary>
|
||||
SLR_NO_UI = 0x1,
|
||||
/// <summary>Obsolete and no longer used</summary>
|
||||
SLR_ANY_MATCH = 0x2,
|
||||
/// <summary>
|
||||
/// If the link object has changed, update its path and list of identifiers.
|
||||
/// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine
|
||||
/// whether or not the link object has changed.
|
||||
/// </summary>
|
||||
SLR_UPDATE = 0x4,
|
||||
/// <summary>Do not update the link information</summary>
|
||||
SLR_NOUPDATE = 0x8,
|
||||
/// <summary>Do not execute the search heuristics</summary>
|
||||
SLR_NOSEARCH = 0x10,
|
||||
/// <summary>Do not use distributed link tracking</summary>
|
||||
SLR_NOTRACK = 0x20,
|
||||
/// <summary>
|
||||
/// Disable distributed link tracking. By default, distributed link tracking tracks
|
||||
/// removable media across multiple devices based on the volume name. It also uses the
|
||||
/// Universal Naming Convention (UNC) path to track remote file systems whose drive letter
|
||||
/// has changed. Setting SLR_NOLINKINFO disables both types of tracking.
|
||||
/// </summary>
|
||||
SLR_NOLINKINFO = 0x40,
|
||||
/// <summary>Call the Microsoft Windows Installer</summary>
|
||||
SLR_INVOKE_MSI = 0x80
|
||||
}
|
||||
|
||||
|
||||
/// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary>
|
||||
[ComImport]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
[Guid("000214F9-0000-0000-C000-000000000046")]
|
||||
internal interface IShellLinkW
|
||||
{
|
||||
/// <summary>Retrieves the path and file name of a Shell link object</summary>
|
||||
void GetPath([Out] [MarshalAs(UnmanagedType.LPWStr)]
|
||||
StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
|
||||
|
||||
/// <summary>Retrieves the list of item identifiers for a Shell link object</summary>
|
||||
void GetIDList(out IntPtr ppidl);
|
||||
|
||||
/// <summary>Sets the pointer to an item identifier list (PIDL) for a Shell link object.</summary>
|
||||
void SetIDList(IntPtr pidl);
|
||||
|
||||
/// <summary>Retrieves the description string for a Shell link object</summary>
|
||||
void GetDescription([Out] [MarshalAs(UnmanagedType.LPWStr)]
|
||||
StringBuilder pszName, int cchMaxName);
|
||||
|
||||
/// <summary>Sets the description for a Shell link object. The description can be any application-defined string</summary>
|
||||
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
|
||||
|
||||
/// <summary>Retrieves the name of the working directory for a Shell link object</summary>
|
||||
void GetWorkingDirectory([Out] [MarshalAs(UnmanagedType.LPWStr)]
|
||||
StringBuilder pszDir, int cchMaxPath);
|
||||
|
||||
/// <summary>Sets the name of the working directory for a Shell link object</summary>
|
||||
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
|
||||
|
||||
/// <summary>Retrieves the command-line arguments associated with a Shell link object</summary>
|
||||
void GetArguments([Out] [MarshalAs(UnmanagedType.LPWStr)]
|
||||
StringBuilder pszArgs, int cchMaxPath);
|
||||
|
||||
/// <summary>Sets the command-line arguments for a Shell link object</summary>
|
||||
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
|
||||
|
||||
/// <summary>Retrieves the hot key for a Shell link object</summary>
|
||||
void GetHotkey(out short pwHotkey);
|
||||
|
||||
/// <summary>Sets a hot key for a Shell link object</summary>
|
||||
void SetHotkey(short wHotkey);
|
||||
|
||||
/// <summary>Retrieves the show command for a Shell link object</summary>
|
||||
void GetShowCmd(out int piShowCmd);
|
||||
|
||||
/// <summary>Sets the show command for a Shell link object. The show command sets the initial show state of the window.</summary>
|
||||
void SetShowCmd(int iShowCmd);
|
||||
|
||||
/// <summary>Retrieves the location (path and index) of the icon for a Shell link object</summary>
|
||||
void GetIconLocation([Out] [MarshalAs(UnmanagedType.LPWStr)]
|
||||
StringBuilder pszIconPath,
|
||||
int cchIconPath, out int piIcon);
|
||||
|
||||
/// <summary>Sets the location (path and index) of the icon for a Shell link object</summary>
|
||||
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
|
||||
|
||||
/// <summary>Sets the relative path to the Shell link object</summary>
|
||||
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
|
||||
|
||||
/// <summary>Attempts to find the target of a Shell link, even if it has been moved or renamed</summary>
|
||||
void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
|
||||
|
||||
/// <summary>Sets the path and file name of a Shell link object</summary>
|
||||
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
|
||||
}
|
||||
|
||||
// CLSID_ShellLink from ShlGuid.h
|
||||
[ComImport]
|
||||
[Guid("00021401-0000-0000-C000-000000000046")]
|
||||
public class ShellLink
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,13 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Threading;
|
||||
using QuickLook.Helpers;
|
||||
using QuickLook.NativeMethods;
|
||||
|
||||
namespace QuickLook
|
||||
{
|
||||
@@ -123,7 +125,8 @@ namespace QuickLook
|
||||
var wParam = msg.Substring(0, split);
|
||||
var lParam = msg.Substring(split + 1, msg.Length - split - 1);
|
||||
|
||||
lParam = ShellLinkHelper.GetTarget(lParam);
|
||||
if (!string.IsNullOrEmpty(lParam))
|
||||
lParam = ResolveShortcut(lParam);
|
||||
|
||||
switch (wParam)
|
||||
{
|
||||
@@ -168,5 +171,17 @@ namespace QuickLook
|
||||
{
|
||||
return _instance ?? (_instance = new PipeServerManager());
|
||||
}
|
||||
|
||||
public static string ResolveShortcut(string filename)
|
||||
{
|
||||
if (Path.GetExtension(filename).ToLower() != ".lnk")
|
||||
return filename;
|
||||
|
||||
var link = new ShellLink();
|
||||
((IPersistFile) link).Load(filename, 0);
|
||||
var sb = new StringBuilder(260);
|
||||
((IShellLinkW) link).GetPath(sb, sb.Capacity, out _, 0);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@
|
||||
<Compile Include="Controls\BusyDecorator\BusyDecorator.cs" />
|
||||
<Compile Include="Controls\BusyDecorator\VisualTargetPresentationSource.cs" />
|
||||
<Compile Include="Helpers\ShareHelper.cs" />
|
||||
<Compile Include="Helpers\ShellLinkHelper.cs" />
|
||||
<Compile Include="NativeMethods\ShellLink.cs" />
|
||||
<Compile Include="PipeServerManager.cs" />
|
||||
<Compile Include="PluginManager.cs" />
|
||||
<Compile Include="Plugin\InfoPanel\FileHelper.cs" />
|
||||
@@ -245,17 +245,6 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="Shell32">
|
||||
<Guid>{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}</Guid>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<Lcid>0</Lcid>
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<Isolated>False</Isolated>
|
||||
<EmbedInteropTypes>True</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Translations.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
|
||||
Reference in New Issue
Block a user