Пространство имен IADsLargeInteger
Я ищу способ конвертировать COM-объект в DateTime
и я видел много статей об этой проблеме (например, эта - https://msdn.microsoft.com/en-us/library/ms180872(v=vs.80).aspx и эта - Как читать "uSNChanged" "свойство с использованием C#)
Тем не менее, все эти статьи говорят об использовании объекта из интерфейса IADsLargeInteger
,
Я пытался найти пространство имен этого интерфейса, и я просто не мог найти никакой подсказки.
3 ответа
Вот пример кода, включающий все, что вам нужно для преобразования из типа AD в DateTime:
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using ActiveDs; // Namespace added via ref to C:\Windows\System32\activeds.tlb
private DateTime? getLastLogin(DirectoryEntry de)
{
Int64 lastLogonThisServer = new Int64();
if (de.Properties.Contains("lastLogon"))
{
if (de.Properties["lastLogon"].Value != null)
{
try
{
IADsLargeInteger lgInt =
(IADsLargeInteger) de.Properties["lastLogon"].Value;
lastLogonThisServer = ((long)lgInt.HighPart << 32) + lgInt.LowPart;
return DateTime.FromFileTime(lastLogonThisServer);
}
catch (Exception e)
{
return null;
}
}
}
return null;
}
В дополнение к предыдущему ответу, который показывает правильный код, чтобы получить значение от IADsLargeInteger
Переменная, я просто хочу сказать, что нет необходимости добавлять ссылку на библиотеку COM Types, если вам нужен только этот интерфейс.
Для работы с типом COM вы можете определить интерфейс в своем собственном коде:
[ComImport, Guid("9068270b-0939-11d1-8be1-00c04fd8d503"), InterfaceType(ComInterfaceType.InterfaceIsDual)]
internal interface IAdsLargeInteger
{
long HighPart
{
[SuppressUnmanagedCodeSecurity] get; [SuppressUnmanagedCodeSecurity] set;
}
long LowPart
{
[SuppressUnmanagedCodeSecurity] get; [SuppressUnmanagedCodeSecurity] set;
}
}
и использовать его так же:
var largeInt = (IAdsLargeInteger)directoryEntry.Properties[propertyName].Value;
var datelong = (largeInt.HighPart << 32) + largeInt.LowPart;
var dateTime = DateTime.FromFileTimeUtc(datelong);
Есть также хорошая статья, объясняющая, как интерпретировать данные ADSI
Вам НЕ нужно ссылаться на ActiveDs.dll - вместо этого вы можете это сделать.
Я убедился, что это работает в .NET Standard 2.0 и .NET 5.
...
Int64 lastLogonThisServer = ConvertADSLargeIntegerToInt64(de.Properties["lastLogon"].Value);
return DateTime.FromFileTime(lastLogonThisServer);
...
public static Int64 ConvertADSLargeIntegerToInt64(object adsLargeInteger)
{
var highPart = (Int32)adsLargeInteger.GetType().InvokeMember("HighPart", System.Reflection.BindingFlags.GetProperty, null, adsLargeInteger, null);
var lowPart = (Int32)adsLargeInteger.GetType().InvokeMember("LowPart", System.Reflection.BindingFlags.GetProperty, null, adsLargeInteger, null);
return highPart * ((Int64)UInt32.MaxValue + 1) + lowPart;
}
Заслуга Саймон Gilbee за этот ответ.