2013-12-18 89 views
0

我使用C#中的PInvoke進行了一些對IShellLinkW.GetPath(...)的調用。我希望在多個異步任務中同時執行這些操作。IShellLinkW COM接口線程安全嗎?

這些調用是否線程安全?我可以這樣做嗎?

更新:

什麼我做的是解決快捷方式作爲一個更大的任務的一部分。下面是代碼:

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

您可以看看自己,COM服務器在註冊表中註冊它們的線程要求。 IShellLinkW由具有CLSID 00021401-0000-0000-C000-000000000046的ShellLink coclass實現。

啓動Regedit.exe並導航到HKEY_LOCAL_MACHINE \ SOFTWARE \ Classes \ CLSID {00021401-0000-0000-C000-000000000046} \ InProcServer32。您會看到:

ThreadingModel  REG_SZ Both 

「Both」表示您可以使用ShellLinkW從MTA中的線程實現的接口。

所以,沒關係。

+0

我看到註冊表中的條目。但是,我聲明的IShellLinkW具有000214F9-0000-0000-C000-000000000046的CLSID,並且在註冊表中找不到此條目。當我嘗試使用您注意到的CLSID時,我沒有收到對象(它們返回null)。我用源代碼更新了我的問題。 – Elan

+0

不,這是IID,IShellLinkW的接口ID。與ShellLink的CLSID(類ID)不同。不要只是任意改變[Guid]屬性。 –

0

Windows外殼程序不支持MTA,所以你應該只調用殼接口的殼對象中(沒有線程安全)創建線程,線程必須初始化爲STA 。 如果您使用.Net並行模式庫,請參閱How to create a task (TPL) running a STA thread?