Да, это проблема. Вы должны использовать COM API низкого уровня, полностью обходя DirectoryEntry
. Это, как я это сделал:
private static void SetSslCertHash(string siteId, byte[] hash)
{
using (var adminBase = TemporaryComObject.Wrap(new MSAdminBase_W()))
using (var ptrHash = new AllocHGlobal(hash))
{
using (var siteKey = new AdminBaseKey(adminBase.Com, adminBase.Com.OpenKey(METADATA_MASTER_ROOT_HANDLE, "/LM/W3SVC/" + siteId, METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE, 1000)))
{
var record = new METADATA_RECORD
{
dwMDIdentifier = SslCertHashCode,
dwMDAttributes = METADATA_INHERIT,
dwMDUserType = IIS_MD_UT_SERVER,
dwMDDataType = BINARY_METADATA,
pbMDData = ptrHash.Buffer,
dwMDDataLen = hash.Length
};
adminBase.Com.SetData(siteKey.Handle, string.Empty, ref record);
}
adminBase.Com.SaveData();
}
}
Это раздражает, что DirectoryEntry
API сломана для данного свойства. В любом случае, дополнительная помощь на низком уровне COM API находится здесь - http://support.microsoft.com/kb/313624/en-US
Конечно, вам понадобится объявление .NET класса COM MSAdminBase_W
. В то время, когда я написал этот код, я не смог найти ничего готового, поэтому я только что открыл «c: \ Program Files \ Microsoft SDKs \ Windows \ v7.1 \ Include \ Iadmw.h» и извлек все части оттуда. Здесь, для Вас, чтобы скопировать и наслаждаться:
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace MSAdminBaseLib
{
[StructLayout(LayoutKind.Sequential)]
public struct _FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
}
[ComImport, Guid("70B51430-B6CA-11D0-B9B9-00A0C922E750"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMSAdminBase_W
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void AddKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteChildKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDName, [In] int dwMDEnumObjectIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CopyKey([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int bMDOverwriteFlag, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void RenameKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDNewName);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref METADATA_RECORD pmdrMDData);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, [In] int dwMDEnumDataIndex, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, out int pdwMDNumDataEntries, out int pdwMDDataSetNumber, [In] int dwMDBufferSize, out byte pbMDBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDUserType, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CopyData([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDataPaths([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType, [In] int dwMDBufferSize, out ushort pszBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
int OpenKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAccessRequested, [In] int dwMDTimeOut);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void CloseKey([In] int hMDHandle);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void ChangePermissions([In] int hMDHandle, [In] int dwMDTimeOut, [In] int dwMDAccessRequested);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SaveData();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetHandleInfo([In] int hMDHandle, out METADATA_HANDLE_INFO pmdhiInfo);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetSystemChangeNumber(out int pdwSystemChangeNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDataSetNumber([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out int pdwMDDataSetNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
void KeyExchangePhase1();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
void KeyExchangePhase2();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Backup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Restore([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void EnumBackups([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDBackupLocation, out int pdwMDVersion, out _FILETIME pftMDBackupTime, [In] int dwMDEnumIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void DeleteBackup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void UnmarshalInterface([MarshalAs(UnmanagedType.Interface)] out MSAdminBase_W piadmbwInterface);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
void GetServerGuid();
}
[StructLayout(LayoutKind.Sequential)]
public struct METADATA_HANDLE_INFO
{
public int dwMDPermissions;
public int dwMDSystemChangeNumber;
}
[StructLayout(LayoutKind.Sequential)]
public struct METADATA_RECORD
{
public int dwMDIdentifier;
public int dwMDAttributes;
public int dwMDUserType;
public int dwMDDataType;
public int dwMDDataLen;
public IntPtr pbMDData;
public int dwMDDataTag;
}
[ComImport, Guid("70B51430-B6CA-11D0-B9B9-00A0C922E750"), CoClass(typeof(MSAdminBase_WClass))]
public interface MSAdminBase_W : IMSAdminBase_W
{
}
[ComImport, TypeLibType(TypeLibTypeFlags.FCanCreate), ClassInterface(ClassInterfaceType.None), Guid("A9E69610-B80D-11D0-B9B9-00A0C922E750")]
public class MSAdminBase_WClass : MSAdminBase_W
{
// Methods
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void AddKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void Backup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void ChangePermissions([In] int hMDHandle, [In] int dwMDTimeOut, [In] int dwMDAccessRequested);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void CloseKey([In] int hMDHandle);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void CopyData([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void CopyKey([In] int hMDSourceHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDSourcePath, [In] int hMDDestHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDDestPath, [In] int bMDOverwriteFlag, [In] int bMDCopyFlag);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDUserType, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteBackup([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteChildKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void DeleteKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void EnumBackups([In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDBackupLocation, out int pdwMDVersion, out _FILETIME pftMDBackupTime, [In] int dwMDEnumIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void EnumData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, [In] int dwMDEnumDataIndex, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void EnumKeys([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, SizeConst = 0x100)] ushort[] szMDName, [In] int dwMDEnumObjectIndex);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetAllData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAttributes, [In] int dwMDUserType, [In] int dwMDDataType, out int pdwMDNumDataEntries, out int pdwMDDataSetNumber, [In] int dwMDBufferSize, out byte pbMDBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, Out] ref METADATA_RECORD pmdrMDData, out int pdwMDRequiredDataLen);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetDataPaths([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDIdentifier, [In] int dwMDDataType, [In] int dwMDBufferSize, out ushort pszBuffer, out int pdwMDRequiredBufferSize);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetDataSetNumber([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out int pdwMDDataSetNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetHandleInfo([In] int hMDHandle, out METADATA_HANDLE_INFO pmdhiInfo);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, out _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
public virtual extern void GetServerGuid();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void GetSystemChangeNumber(out int pdwSystemChangeNumber);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
public virtual extern void KeyExchangePhase1();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), TypeLibFunc(TypeLibFuncFlags.FRestricted)]
public virtual extern void KeyExchangePhase2();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern int OpenKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] int dwMDAccessRequested, [In] int dwMDTimeOut);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void RenameKey([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDNewName);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void Restore([In, MarshalAs(UnmanagedType.LPWStr)] string pszMDBackupLocation, [In] int dwMDVersion, [In] int dwMDFlags);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void SaveData();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void SetData([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref METADATA_RECORD pmdrMDData);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void SetLastChangeTime([In] int hMDHandle, [In, MarshalAs(UnmanagedType.LPWStr)] string pszMDPath, [In] ref _FILETIME pftMDLastChangeTime, [In] int bLocalTime);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
public virtual extern void UnmarshalInterface([MarshalAs(UnmanagedType.Interface)] out MSAdminBase_W piadmbwInterface);
}
}
Далее, легкая часть - вспомогательные типы .NET реализовать C# версии RAII:
TemporaryComObject:
public class TemporaryComObject
{
public static TemporaryComObject<T> Wrap<T>(T com) where T : class
{
return new TemporaryComObject<T>(com);
}
}
public class TemporaryComObject<T> : IDisposable where T : class
{
public TemporaryComObject(T com)
{
Com = com;
}
public T Com { get; private set; }
#region IDisposable Members
public void Dispose()
{
if (Com != null)
{
Marshal.FinalReleaseComObject(Com);
Com = null;
}
}
#endregion
}
AllocHGlobal :
public class AllocHGlobal : IDisposable
{
public readonly IntPtr Buffer;
public AllocHGlobal(int len)
{
Buffer = Marshal.AllocHGlobal(len);
}
public AllocHGlobal(byte[] data) :
this(data.Length)
{
Marshal.Copy(data, 0, Buffer, data.Length);
}
#region Implementation of IDisposable
public void Dispose()
{
Marshal.FreeHGlobal(Buffer);
}
#endregion
}
AdminBaseKey:
public class AdminBaseKey : IDisposable
{
private readonly IMSAdminBase_W m_adminBase;
public readonly int Handle;
public AdminBaseKey(IMSAdminBase_W adminBase, int handle)
{
m_adminBase = adminBase;
Handle = handle;
}
#region Implementation of IDisposable
public void Dispose()
{
m_adminBase.CloseKey(Handle);
}
#endregion
}
Все. Работает на меня.
Когда вы проходите через код, вы получаете значения в 'website.Properties [" SecureBindings "]. Добавить (": 443: localhost ");'? – MethodMan
посмотрите на это сообщение, он должен дать вам представление о том, что вы можете сделать в качестве альтернативы http://stackoverflow.com/questions/10384996/nullreferenceexception-in-microsoft-web-administration-when-adding-https-binding – MethodMan
@ DJKRAZE, да, после прохождения через мы можем видеть привязку 443 в диспетчере IIS. – paxglobal