IShellLinkW COM接口是否安全?

时间:2013-12-18 22:59:43

标签: c# com pinvoke windows-shell

我正在使用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);
    }

2 个答案:

答案 0 :(得分:2)

您可以自己查看,COM服务器在注册表中注册其线程要求。 IShellLinkW由ShellLink coclass实现,其中包含CLSID 00021401-0000-0000-C000-000000000046。

启动Regedit.exe并导航到HKEY_LOCAL_MACHINE \ SOFTWARE \ Classes \ CLSID {00021401-0000-0000-C000-000000000046} \ InProcServer32。你会看到:

  ThreadingModel     REG_SZ    Both

“Both”意味着您也可以从MTA中的线程使用ShellLinkW实现的接口。

是的,没关系。

答案 1 :(得分:0)

Windows shell不支持MTA,因此您只应在创建shell对象的线程中调用shell接口(无线程安全),并且必须将该线程初始化为STA。 如果您使用.Net Parallel Patterns Library,请参阅How to create a task (TPL) running a STA thread?