2013-12-18 4 views
0

Я делаю несколько вызовов IShellLinkW.GetPath (...), используя PInvoke из C#. Я хотел бы, чтобы они выполнялись одновременно с несколькими задачами async.Являются ли IShellLinkW COM интерфейсами потокобезопасными?

Являются ли эти потоки безопасными? Я могу сделать это?

Update:

То, что я делаю, решения ярлыки как часть более крупной задачи. Ниже приведен код:

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 реализуется с помощью класса ShellLink, который имеет CLSID 00021401-0000-0000-C000-000000000046.

Запустите Regedit.exe и перейдите к HKEY_LOCAL_MACHINE \ SOFTWARE \ Classes \ CLSID {00021401-0000-0000-C000-000000000046} \ InProcServer32. Вы увидите:

ThreadingModel  REG_SZ Both 

«И» означает, что вы можете использовать интерфейсы, реализованные ShellLinkW из потока в MTA, а также.

Итак, да, все в порядке.

+0

Я вижу запись в реестре. Однако IShellLinkW, который я объявил, имеет CLSID 000214F9-0000-0000-C000-000000000046, и я не нашел запись для этого в реестре. Когда я попытался использовать CLSID, который вы отметили, я не получаю объекты (они возвращаются в нуль). Я обновил свой вопрос с помощью исходного кода. – Elan

+0

Нет, это IID, идентификатор интерфейса для IShellLinkW. Не то же самое, что CLSID для ShellLink, идентификатор класса. Не просто произвольно изменяйте атрибуты [Guid]. –

0

окон оболочка не поддерживает MTA, поэтому вы должны вызывать только интерфейсы оболочки в потоке объект оболочки создаются в (не потокобезопасности), и поток должен быть инициализирован как STA , Если вы используете библиотеку параллельных шаблонов .Net, см. How to create a task (TPL) running a STA thread?

Смежные вопросы