IShellLinkW COM 接口线程安全吗?
本文关键字:安全 线程 COM 接口 IShellLinkW | 更新日期: 2024-10-30 10:37:08
我正在使用来自 C# 的 PInvoke 对 IShellLinkW.GetPath(...) 进行多次调用。我想在多个异步任务上同时执行这些任务。
这些调用线程安全吗?我可以这样做吗?
更新:
我正在做的是解决快捷方式作为更大任务的一部分。下面是代码:
const uint STGM_READ = 0;
public static string ResolveShortcut(string filename)
{
ShellLink link = new ShellLink();
((IPersistFile)link).Load(filename, STGM_READ);
StringBuilder buff = new StringBuilder(260);
WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
IShellLinkW linkW = link as IShellLinkW;
linkW.GetPath(buff, buff.Capacity, out data, SLGP_FLAGS.SLGP_UNCPRIORITY);
return buff.ToString();
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
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;
}
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("000214F9-0000-0000-C000-000000000046")]
{
/// <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);
}
[ComImport, Guid("0000010b-0000-0000-C000-000000000046"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistFile : IPersist
{
new void GetClassID(out Guid pClassID);
[PreserveSig]
int IsDirty();
[PreserveSig]
void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode);
[PreserveSig]
void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
[In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
[PreserveSig]
void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
[PreserveSig]
void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
}
您可以自己看看,COM 服务器在注册表中注册其线程要求。 IShellLinkW 由 CLSID 00021401-0000-0000-C000-00000000046 的 ShellLink 子类实现。
启动 Regedit.exe 并导航到 HKEY_LOCAL_MACHINE''SOFTWARE''Classes''CLSID{00021401-0000-0000-C000-000000000046}''InProcServer32。 你会知道的:
ThreadingModel REG_SZ Both
"两者"意味着您也可以从MTA中的线程使用ShellLinkW实现的接口。
所以是的,没关系。
Windows shell
不支持 MTA,因此您应该只在创建 shell 对象的线程中调用 shell 接口(无线程安全),并且线程必须初始化为 STA。如果使用 .Net 并行模式库,请参阅如何创建运行 STA 线程的任务 (TPL)?