Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C# AD SearchResultCollection.Properties["lastLogon"][0].ToString() conversion error.

1,021 views
Skip to first unread message

Terry E Dow

unread,
Mar 18, 2003, 9:29:38 PM3/18/03
to
Howdy,

As a self assigned lesson in DirectoryServices.DirectoryEntry and
.DirectorySearcher I am writing a CSVDE like utility in C# (oh yeah,
learning that too). I have been able to dump my user account's properties in
a similar method to the LDIFDE utility. But I am having problems displaying
certain fields. Looking at the GetType() of each property the two types that
are giving me the most trouble are System.Int64 and System.Byte[]. The Int64
value is converting to a string without raising an exception, but the value
is wrong. For instance, the "lastLogon" value is a long date format
representing the number of Ticks (one hundred nanoseconds) since 1/1/1601
(also referred to as FileTime). I can handle the DateTime.FileTimeOffset
once I get the correct data and bring into DateTime type. But instead of
getting a lastLogon value of 126920647101223302, I get -973668403. I do not
know if this is a unsigned long converted to a signed long, or if I'm only
getting four of the eight bytes. But I know that the MS's LDIFDE tool knows
how to display the value.

I've tried to wrap Convert.ToInt64() around it (before the .ToString()),
and it changes nothing.

I started to do this with VB.Net and it works if I include the additional
'special' code borrowed from a VBS example:

Dim pcoll As PropertyCollection

Dim oli As Object

Dim lDate As Long

...

myDirectoryEntry = New DirectoryEntry(myResult.Path)

pcoll = myDirectoryEntry.Properties

...

oli = pcoll("lastLogon")(0)

lDate = (oli.HighPart * &H100000000) + oli.LowPart

Console.WriteLine( "{0:s}", DateTime.FromFileTime(lDate))

...

How should I being doing this in C#?

And while I have your learned attention, can you suggest a way to access the
System.Byte[] array elements? LDIFDE displays the UniCode as Base64 encoded
strings (like AAAAAQAAAAcQAAEwAAAAAA==). I'd like to get the data before
encoding, or I can put together a simple procedure to decode them.

I'll be more than happy to post the work in progress to the group upon
request.

--

Terry E Dow

David Hou [MS]

unread,
Mar 19, 2003, 11:33:24 PM3/19/03
to
The following link explains how to read/write large integer type attribute
in C#:

http://msdn.microsoft.com/library/en-us/netdir/netds/large_integer_property_type.asp?frame=true

It's pretty straightforward to read byte array type. just cast the returned
property value as a byte array and then read its elements, or directly pass
the array to your encoding function.


David
--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Terry E Dow" <res1...@verizon.neXt> wrote in message
news:9L8ea.3642$5i1...@fe07.atl2.webusenet.com...

Terry E Dow

unread,
Mar 20, 2003, 8:22:46 PM3/20/03
to
David,

Bingo. I was trying hard to stay pure .Netframework, but your link proves
I still have to use a little ADSI. Here is working sample code. Note you
have to follow the directions on this link
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netdir/netd
s/using_com_interop_to_access_adsi.asp to add the ADSI COM reference, as
well as adding System.DirectoryServices. Create a new console app and paste
this into the Class1.cs file:

using System;
using System.DirectoryServices;
using ActiveDs;

namespace csvde_ldate
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class csvde_lastlogon
{
/// <summary>
/// The main entry point for the application.
/// </summary>
///

[STAThread]
static void Main( string[] args )
{
// Hard coded Active Directory user account name.
// Please change to an active user account name (like yours).
string myUserName = "USERNAME";
string myRootDN = "";

// Find the first domain RootDSE of this forest.
DirectoryEntry myRootDSE = new DirectoryEntry( "LDAP://RootDSE" );
myRootDN = myRootDSE.Properties["defaultNamingContext"][0].ToString();
myRootDN = "LDAP://" + myRootDN;

// Build a Directory Searcher.
DirectoryEntry myDomainDirectoryEntry = new DirectoryEntry( myRootDN );
DirectorySearcher mySearcher = new DirectorySearcher(
myDomainDirectoryEntry );

// Add search filter and define object properties to retrieve.
mySearcher.Filter = "sAMAccountName=" + myUserName;
mySearcher.PropertiesToLoad.Add( "lastLogon" );

foreach ( SearchResult myResult in mySearcher.FindAll() )
{
long myInt64 = 0L;
DirectoryEntry myResultDirectoryEntry = myResult.GetDirectoryEntry();
IADsLargeInteger myLargeInteger = (IADsLargeInteger)
myResultDirectoryEntry.Properties["lastLogon"].Value;
myInt64 = ((long) myLargeInteger.HighPart << 32) +
myLargeInteger.LowPart;
Console.WriteLine( "{0}", myInt64 );
}
}
}
}

Thanks for your help!!!

--
Terry E Dow

"David Hou [MS]" <davi...@online.microsoft.com> wrote in message
news:#IXWanp7...@TK2MSFTNGP11.phx.gbl...

0 new messages