我正在寻找将COM 对象转换为的方法DateTime
,我看到了很多关于这个问题的文章(比如这个 - https://msdn.microsoft.com/en-us/library/ms180872(v=vs.80).aspx
还有这个 -
如何使用 C# 读取“uSNChanged”属性)
但是,所有这些文章都在谈论使用 interface 中的对象IADsLargeInteger
。
我试图寻找这个接口的命名空间,但我找不到任何线索。
我正在寻找将COM 对象转换为的方法DateTime
,我看到了很多关于这个问题的文章(比如这个 - https://msdn.microsoft.com/en-us/library/ms180872(v=vs.80).aspx
还有这个 -
如何使用 C# 读取“uSNChanged”属性)
但是,所有这些文章都在谈论使用 interface 中的对象IADsLargeInteger
。
我试图寻找这个接口的命名空间,但我找不到任何线索。
这是一个代码示例,其中包括您需要从 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 类型库的引用。
要使用 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;
}
这个答案归功于 Simon Gilbee 。