Использование Microsoft Virtual Server из C #: CoSetProxyBlanket ничего не делает - PullRequest
1 голос
/ 29 ноября 2008

Я пытаюсь написать пару задач NAnt для взаимодействия с Microsoft Virtual Server 2005 R2 с пакетом обновления 1 (SP1), и я поднял код, найденный в "Virtual PC Guy's WebLog", в "Управление виртуальным сервером через PowerShell " запись.

Это не работает: я всегда получаю ошибку при вызове 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 выиграла ' Я уже звонил.

У кого-нибудь это работает?

Ответы [ 2 ]

1 голос
/ 24 августа 2009

Похоже, что .NET 4.0 добавит новый метод GetObjectForIUnknownWithBlanket (в System.Runtime.InteropServices.Marshal), чтобы помочь решить эту проблему. Из статьи (бета) MSDN:

GetObjectForIUnknownWithBlanket обертывания Неизвестный в уникальном управляемом объекте и вызывает CoSetProxyBlanket функция на всех запрошенных интерфейсах. Это гарантирует, что уникальный объект вернулся вместо того, чтобы смотреть в кеш, чтобы соответствовать данному IUnknown to существующий объект.

Я еще не пробовал, но выглядит многообещающе.

И, кстати, отличный вопрос и отличный принятый ответ! Я только что столкнулся с той же проблемой, и это было единственное место, где я нашел правильное объяснение.

1 голос
/ 30 ноября 2008

Возможно, вы столкнулись с фундаментальной проблемой, связанной с использованием CoSetProxyBlanket из управляемого кода. К сожалению, нет надежного способа взаимодействия с этим методом в управляемом коде из-за того, как маршалы CLR взаимодействуют.

Вот несколько записей в блогах, описывающих эту проблему

...