从.NET Windows服务调用的Shell32.dll(Calling Shell32.dll

2019-07-18 18:47发布

我有一个使用SHELL32和Folder.GetDetailsOf()从WTV文件获取元数据的.NET 4.0库。 我曾与控制台成功地使用它和Windows窗体应用程序没有问题。 但由于某些原因,要求从.NET 4.0的Windows服务的组件时,呼叫发起壳牌类导致COM错误。

该库中失败的代码:

Shell32.Shell壳=新壳牌();

错误:

无法投射型“系统.__ ComObject”的COM对象为接口类型“Shell32.Shell”。 此操作失败的原因是对IID“{286E6F1B-7113-4355-9562-96B7E9D64C54}”的界面处的COM组件调用QueryInterface失败,因为以下错误:不支持此接口(从HRESULT异常:0x80004002(E_NOINTERFACE)) 。

我读了我的公寓线程,COM互操作性展示,动态,PIA的,等,等,等:)但是,没有,我发现已经解决了这个问题的解决方案组合的填充。 它必须是从另一个线程不能看到互操作的呼叫。 请帮忙 :)

Answer 1:

我用命令行应用程序(控制台)刚刚有同样的问题。 原来,人们需要来注释该程序的Main()与方法[STAThread]属性。 也有人指出,如果入口点是带有加注解的惨败在完全相同的方式失败[MTAThread]代替。 我希望它能帮助。



Answer 2:

我怀疑这可能与这样的事实,在默认情况下,Windows服务没有权限与桌面交互。

为了检验这一理论,重新配置(至少是暂时性的),你的服务的权限,允许桌面交互。 下面的链接将引导您这样做

https://superuser.com/questions/415204/how-do-i-allow-interactive-services-in-windows-7

UPDATE

该SHELL32功能工作得很好以LocalSystem,即使在“允许服务与桌面交互”复选框取消选中,但似乎并没有在一个特定的用户帐户在所有的工作(无论是限制或管理员)

使用Windows服务中SHFileOperation

如果你在得到这个工作取得成功,请确保您禁止任何用户界面交互。 如何做到这一点的信息,可在这样的回答:

https://stackoverflow.com/a/202519/141172



Answer 3:

我创建了一个Windows服务,我叫SHELL32用的P / Invoke。

就我而言,这是模拟文件上点击右键:

首先,我需要创建一个过程,用户(不系统)与桌面交互:

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
 static extern bool CreateProcessAsUser(
     IntPtr hToken,
     string lpApplicationName,
     string lpCommandLine,
     ref SECURITY_ATTRIBUTES lpProcessAttributes,
     ref SECURITY_ATTRIBUTES lpThreadAttributes,
     bool bInheritHandles,
     uint dwCreationFlags,
     IntPtr lpEnvironment,
     string lpCurrentDirectory,
     ref STARTUPINFO lpStartupInfo,
     out PROCESS_INFORMATION lpProcessInformation);

并在此过程中,我使用的SHELL32库(负载然后提取的值)

[DllImport("kernel32.dll")]
private static extern IntPtr LoadLibrary(string dllName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int LoadString(IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);

我的Windows服务可以用这个发现SHELL32的型动物的价值观和与台式机类似的用户交互;-)

你可以找到这个对的P / Invoke的详细信息网站



Answer 4:

因为我发现我的方式在这里通过搜索错误,我想补充一点,如果你试图让一个新的shell()从非GUI线程的GUI应用程序同样的事情发生 - 即使主标注有[STAThread ]。 @Eric J的回答给了我足够的提示,以从那里弄明白。

所以,如果你从一个GUI应用程序要壳牌(),你需要做的,如果(mainForm.InvokeRequired){mainForm.Invoke(...)}舞蹈。



文章来源: Calling Shell32.dll from .NET Windows Service