fix(installer): release the ShellLink COM object so reading a .lnk doesn't lock it
This commit is contained in:
@@ -8,24 +8,36 @@ public static class ShortcutFactory
|
|||||||
{
|
{
|
||||||
private const int SlgpRawPath = 0x4;
|
private const int SlgpRawPath = 0x4;
|
||||||
|
|
||||||
|
// Both helpers release the ShellLink RCW explicitly. IPersistFile.Load/Save keeps a handle on
|
||||||
|
// the .lnk for as long as the COM object lives, so leaving it to the GC lets a read immediately
|
||||||
|
// followed by a write to the same path fail with "used by another process" — exactly what
|
||||||
|
// AutostartShortcut.Install does when the recorded target changed.
|
||||||
public static void CreateShortcut(string shortcutPath, string targetPath, string workingDir, string description)
|
public static void CreateShortcut(string shortcutPath, string targetPath, string workingDir, string description)
|
||||||
{
|
{
|
||||||
var link = (IShellLink)new ShellLink();
|
var link = (IShellLink)new ShellLink();
|
||||||
link.SetPath(targetPath);
|
try
|
||||||
link.SetWorkingDirectory(workingDir);
|
{
|
||||||
link.SetDescription(description);
|
link.SetPath(targetPath);
|
||||||
link.SetIconLocation(targetPath, 0);
|
link.SetWorkingDirectory(workingDir);
|
||||||
|
link.SetDescription(description);
|
||||||
|
link.SetIconLocation(targetPath, 0);
|
||||||
|
|
||||||
var file = (IPersistFile)link;
|
var file = (IPersistFile)link;
|
||||||
file.Save(shortcutPath, false);
|
file.Save(shortcutPath, false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Marshal.FinalReleaseComObject(link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Reads the target path of an existing .lnk, or null if it can't be read (missing/corrupt).</summary>
|
/// <summary>Reads the target path of an existing .lnk, or null if it can't be read (missing/corrupt).</summary>
|
||||||
public static string? TryGetTarget(string shortcutPath)
|
public static string? TryGetTarget(string shortcutPath)
|
||||||
{
|
{
|
||||||
|
IShellLink? link = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var link = (IShellLink)new ShellLink();
|
link = (IShellLink)new ShellLink();
|
||||||
((IPersistFile)link).Load(shortcutPath, 0);
|
((IPersistFile)link).Load(shortcutPath, 0);
|
||||||
var sb = new StringBuilder(260);
|
var sb = new StringBuilder(260);
|
||||||
link.GetPath(sb, sb.Capacity, IntPtr.Zero, SlgpRawPath);
|
link.GetPath(sb, sb.Capacity, IntPtr.Zero, SlgpRawPath);
|
||||||
@@ -36,6 +48,10 @@ public static class ShortcutFactory
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (link is not null) Marshal.FinalReleaseComObject(link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ComImport]
|
[ComImport]
|
||||||
|
|||||||
Reference in New Issue
Block a user