Activator.CreateInstance(<guid>)在VSIDE内部工作,但不在外部工作

Mic*_*eld 6 c# interop com-interop

我有一堆COM对象都实现了相同的接口,并且需要在运行时从选项列表中创建其中一个.由于我知道每个实现COM服务器的CLSID,因此这应该很容易.但是,对于某个COM库的子集,如果我在VS2010 IDE中运行,我只能做这个工作.

这是我用来测试的整个程序:

using System;

namespace ComTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var clsid = "{E8978DA6-047F-4E3D-9C78-CDBE46041603}";
            var type = Type.GetTypeFromCLSID(new Guid(clsid));
            var obj = Activator.CreateInstance(type, true);
            Console.WriteLine("Obj is {0}", obj);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以为我迄今为止尝试的每个COM CLSID做这个工作,只要我通过VS2010.无论是否附加了调试器,无论是否附加了托管进程,我都会System.__ComObject回来CreateInstance.

当我从控制台窗口编译并运行此代码时,对于某些CLSID值,我得到:

Unhandled Exception: System.Runtime.InteropServices.COMException: Creating an instance of the COM component with CLSID {E8978DA6-047F-4E3D-9C78-CDBE46041603} from the IClassFactory failed due to the following error: 80004005.
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at ComTest.Program.Main(String[] args) in 
Run Code Online (Sandbox Code Playgroud)

这只发生在特定的CLSID上 - 例如,"{c1243ca0-bf96-11cd-b579-08002b30bfeb}"(内置文本IFilter)有效,但"{E8978DA6-047F-4E3D-9C78-CDBE46041603}"(Acrobat) Reader X的IFilter)没有.我无法弄清楚的是,通过IDE运行是如何使COM Interop调用成功的任何不同.有任何想法吗?

编辑:

我没有运行VS2010作为管理员,但我已经尝试运行通过提升PowerShell控制台输出二进制中,它仍然无法正常工作.

编辑2:

到目前为止,我用过的唯一一个重现这个"bug"的COM服务器是Acrobat Reader X的AroRdIf.dll(之前的版本工作正常).我不担心让Acrobat的特定IFilter工作了,但我非常担心我的代码在我的IDE中运行但不在其中.而且,顺便说一下,Windows SDK FILTDUMP工具加载这个COM服务器没有问题,所以我知道这是可能的,我只是不知道如何.

Dav*_*Hay 3

因此,我花了一些时间对此进行了测试,并且能够完全按照您的描述重现该问题。我重新创建了与您完全相同的控制台应用程序,并且看到了相同的行为,但我认为我至少可以添加一些新信息。

起初我和你的想法一样,认为这是 Visual Studio 让它工作的东西,但事实并非如此。如果您将其构建到控制台可执行文件中,然后从资源管理器启动它,则无需 Visual Studio 参与即可正常工作。此外,我还在开头添加了 Debugger.Launch() ,以便在从命令提示符运行时可以附加到它,即使 VS 完全附加并调试,我也会收到错误。我的结果都表明不是 VS 让它工作,而是实际上从命令提示符运行它破坏了它。

我尝试了各种方法来使命令提示符启动和 Windows 资源管理器启动之间的环境相同,但每次都得到相同的结果;在资源管理器中完美运行,在命令行中消失。

通过使用反射器进行挖掘,该设置通过了所有测试和一切。这是实际的调用:

RuntimeTypeHandle.CreateInstance(this, publicOnly, noCheck, ref canBeCached, ref ctor, ref bNeedSecurityCheck);
Run Code Online (Sandbox Code Playgroud)

在正在爆炸的 RuntimeType 类中,此时没有更多的托管代码可供深入研究。在这一点上,我的猜测是,它必须是完全包含在 Adob​​e COM Server 中的东西,当从命令提示符运行时,它会杀死它。

也许对 Windows 内部结构有更多了解的人可以谈谈从命令行执行与从资源管理器执行之间的区别?