如何获取快捷方式文件夹的目录路径?我已经到处搜索,只找到了快捷方式文件的目标路径。
我认为你需要使用COM并添加对“Microsoft Shell Control And Automation”的引用,如这篇博客文章所述:
以下是使用该代码提供的示例:
namespace Shortcut
{
using System;
using System.Diagnostics;
using System.IO;
using Shell32;
class Program
{
public static string GetShortcutTargetFile(string shortcutFilename)
{
string pathOnly = System.IO.Path.GetDirectoryName(shortcutFilename);
string filenameOnly = System.IO.Path.GetFileName(shortcutFilename);
Shell shell = new Shell();
Folder folder = shell.NameSpace(pathOnly);
FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
return link.Path;
}
return string.Empty;
}
static void Main(string[] args)
{
const string path = @"C:\link to foobar.lnk";
Console.WriteLine(GetShortcutTargetFile(path));
}
}
}
C:\Program Files\Oracle\VirtualBoxOSX
的 VirtualBox 快捷方式时失败了。它一直返回目标位置为 C:\Program Files (x86)\Oracle\VirtualBoxOSX\VirtualBox.exe
。对此行为有何解释? - swdev// new way for windows 10
string targetname;
string pathOnly = System.IO.Path.GetDirectoryName(LnkFileName);
string filenameOnly = System.IO.Path.GetFileName(LnkFileName);
Shell shell = new Shell();
Shell32.Folder folder = shell.NameSpace(pathOnly);
FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null) {
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
targetname = link.Target.Path; // <-- main difference
if (targetname.StartsWith("{")) { // it is prefixed with {54A35DE2-guid-for-program-files-x86-QZ32BP4}
int endguid = targetname.IndexOf("}");
if (endguid > 0) {
targetname = "C:\\program files (x86)" + targetname.Substring(endguid + 1);
}
}
如果您不想使用依赖项,可以使用https://blez.wordpress.com/2013/02/18/get-file-shortcuts-target-with-c/。
但是lnk格式是未经记录的,因此只有在您理解风险的情况下才能这样做。
public static string GetLnkTarget(string lnkPath)
{
var shl = new Shell();
var dir = shl.NameSpace(Path.GetDirectoryName(lnkPath));
var itm = dir.Items().Item(Path.GetFileName(lnkPath));
var lnk = (ShellLinkObject)itm.GetLink;
if (!File.Exists(lnk.Path)){
return lnk.Path.Replace("Program Files (x86)", "Program Files");
}
else{
return lnk.Path;
}
}
获取链接路径的更简单的方法是:
private static string LnkToFile(string fileLink)
{
string link = File.ReadAllText(fileLink);
int i1 = link.IndexOf("DATA\0");
if (i1 < 0)
return null;
i1 += 5;
int i2 = link.IndexOf("\0", i1);
if (i2 < 0)
return link.Substring(i1);
else
return link.Substring(i1, i2 - i1);
}
但是如果lnk文件格式发生变化,它肯定会出现故障。
*.lnk
文件 - 它不适用于由 Windows Installer 创建的 *.lnk
文件(它们无论如何都不指向文件),以及某些其他类型的 *.lnk
文件,这些文件不将路径存储为单个字符串 - 不幸的是,二进制文件格式有点复杂:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/16cb4ca1-9339-4d0c-a68d-bf1d6cc0f943 - Dai public static string GetLnkTarget(string lnkPath)
{
if (!System.IO.File.Exists(lnkPath))
throw new FileNotFoundException();
Type shlType;
object shl = null;
object dir = null;
object items = null;
object itm = null;
object lnk = null;
try
{
//var shl = new Shell();
shlType = Type.GetTypeFromProgID("Shell.Application");
shl = Activator.CreateInstance(shlType);
string dirName = Path.GetDirectoryName(lnkPath);
string lnkFile = Path.GetFileName(lnkPath);
//var dir = shl.NameSpace(dirName);
dir = shlType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shl, new object[] { dirName });
//var itm = dir.Items().Item(lnkFile);
items = dir.GetType().InvokeMember("Items", System.Reflection.BindingFlags.InvokeMethod, null, dir, null);
itm = items.GetType().InvokeMember("Item", System.Reflection.BindingFlags.InvokeMethod, null, items, new object[] { lnkFile });
//var lnk = (ShellLinkObject)itm.GetLink;
lnk = itm.GetType().InvokeMember("GetLink", System.Reflection.BindingFlags.GetProperty, null, itm, null);
//return lnk.Path;
object path = lnk.GetType().InvokeMember("Path", System.Reflection.BindingFlags.GetProperty, null, lnk, null);
return (string)path;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (lnk != null) Marshal.ReleaseComObject(lnk);
if (itm != null) Marshal.ReleaseComObject(itm);
if (items != null) Marshal.ReleaseComObject(items);
if (dir != null) Marshal.ReleaseComObject(dir);
if (shl != null) Marshal.ReleaseComObject(shl);
}
}
感谢Mohsen.Sharify的回答,我得到了更整洁的代码:
var fileName = Process.GetCurrentProcess().MainModule.FileName;
var folderName = Path.Combine(fileName, ".."); //origin folder
Process.GetCurrentProcess().MainModule.FileName.Substring(0, Process.GetCurrentProcess().MainModule.FileName.LastIndexOf("\\")
这段代码返回正在运行的任何exe路径,不管是谁请求的文件