1

我正在尝试编写几个用于与 Microsoft Virtual Server 2005 R2 SP1 交互的 NAnt 任务,并且我已经在“通过 PowerShell 控制虚拟服务器”帖子中提取了“Virtual PC Guy 的 WebLog”中的代码。

它不起作用:调用 CreateVirtualMachine 时总是失败:

System.Runtime.InteropServices.COMException (0x80070542): Either a required impersonation level was not provided, or the provided impersonation level is invalid. (Exception from HRESULT: 0x80070542)

at Microsoft.VirtualServer.Interop.VMVirtualServerClass.CreateVirtualMachine(String configurationName, String configurationPath)

我的代码如下:

var virtualServer = new VMVirtualServerClass();
SetSecurity(virtualServer);
var virtualMachine = virtualServer.CreateVirtualMachine("TEST",
    @"D:\Virtual Server\TEST.vmc");

...其中 SetSecurity 定义如下:

    private static void SetSecurity(object dcomObject)
    {
        IntPtr pProxy = Marshal.GetIUnknownForObject(dcomObject);
        int hr = CoSetProxyBlanket(pProxy,
            RPC_C_AUTHN_DEFAULT,
            RPC_C_AUTHZ_DEFAULT,
            IntPtr.Zero,
            RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
            RPC_C_IMP_LEVEL_IMPERSONATE,
            IntPtr.Zero,
            EOAC_DYNAMIC_CLOAKING);
        Marshal.ThrowExceptionForHR(hr);
    }

    private const uint RPC_C_AUTHN_NONE = 0;
    private const uint RPC_C_AUTHN_WINNT = 10;
    private const uint RPC_C_AUTHN_DEFAULT = 0xFFFFFFFF;

    private const uint RPC_C_AUTHZ_NONE = 0;
    private const uint RPC_C_AUTHZ_DEFAULT = 0xFFFFFFFF;

    private const uint RPC_C_AUTHN_LEVEL_DEFAULT = 0;
    private const uint RPC_C_AUTHN_LEVEL_PKT_PRIVACY = 6;

    private const uint RPC_C_IMP_LEVEL_IDENTIFY = 2;
    private const uint RPC_C_IMP_LEVEL_IMPERSONATE = 3;

    private const uint EOAC_NONE = 0;
    private const uint EOAC_DYNAMIC_CLOAKING = 0x40;
    private const uint EOAC_DEFAULT = 0x0800;

    [DllImport("Ole32.dll")]
    public static extern int CoSetProxyBlanket(IntPtr pProxy,
            UInt32 dwAuthnSvc,
            UInt32 dwAuthzSvc,
            IntPtr pServerPrincName,
            UInt32 dwAuthnLevel,
            UInt32 dwImpLevel,
            IntPtr pAuthInfo,
            UInt32 dwCapabilities);

如果我编写一个独立程序并添加对 的调用CoInitializeSecurity,那么它可以工作。但是,我不想要一个独立的程序——我想要一组 NAnt 任务(所以是一个 DLL),并且我不想调用CoInitializeSecurity,因为无法保证其他一些 NAnt 任务不会调用它已经。

有没有人有这个工作?

4

2 回答 2

1

在从托管代码中使用 CoSetProxyBlanket 时,您可能会遇到一个基本问题。不幸的是,由于 CLR 编组接口的方式,没有可靠的方法可以在托管代码中与此方法进行互操作。

以下是一些描述此问题的博客条目

于 2008-11-30T07:49:57.063 回答
1

值得一提的是,.NET 4.0 似乎将添加一个新方法GetObjectForIUnknownWithBlanket(在 System.Runtime.InteropServices.Marshal 下)来帮助解决这个问题。来自(测试版)MSDN 文章:

GetObjectForIUnknownWithBlanket 将 IUnknown 包装在一个唯一的托管对象中,并在所有请求的接口上调用 CoSetProxyBlanket 函数。它确保返回一个唯一的对象,而不是在缓存中查找以将给定的 IUnknown 与现有对象匹配。

我还没有尝试过,但它看起来很有希望。

顺便说一句,很好的问题和很好的接受的答案!我刚刚遇到了同样的问题,这是我找到正确解释的唯一地方。

于 2009-08-23T21:14:35.443 回答