Interop.activeDS headache with Sharepoint v2 webpart

Discussion in 'ASP .Net Security' started by Fowler, Dec 8, 2004.

  1. Fowler

    Fowler Guest

    I've been working on a web part that will remind a user how many days
    they have until their password expires. I strong named it and created a
    custom security policy to allow it to live in the bin rather than the
    GAC. After many painful iterations with configuring code access levels
    and active directory and such, I was able to retrieve some public AD
    info and I was ready to add the magic code that crunches the numbers. I
    added a COM reference to the interop.activeds*. Upon compiling, it said
    that com object (not the web part) wasn't strong named.

    How do I strong name an external com object that is included as a
    reference in a web part that's already strong named? I tried adding the
    com object dll to the GAC but it won't allow it without a stong name
    either.

    *ActiveDs needed to handle 'LargeInteger' type

    Using .Net 2003 and Sharepoint v2

    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Fowler, Dec 8, 2004
    #1
    1. Advertising

  2. If you just need the large integer, you can get around this in three ways:
    Use the DirectorySearcher to get the value instead of the DirectoryEntry as
    it returns Int64
    Use reflection to get the value (sample below)
    Implement your own interop types in your assembly that just do
    IADsLargeInteger

    The first is the easiest (I think).

    The second is done like this (VB.NET sample; you can translate to C# if need
    be)

    Public Shared Function GetInt64FromLargeInteger(ByVal largeInteger
    As Object) As Long
    Dim lowPart As Integer
    Dim lBytes() As Byte
    Dim highPart As Integer
    Dim hBytes() As Byte
    Dim valBytes(7) As Byte

    Dim longVal As Long
    Dim largeIntType As Type

    largeIntType = largeInteger.GetType()

    Try
    highPart = CType(largeIntType.InvokeMember("HighPart",
    BindingFlags.GetProperty Or BindingFlags.Public, Nothing, largeInteger,
    Nothing), Integer)
    lowPart = CType(largeIntType.InvokeMember("LowPart",
    BindingFlags.GetProperty Or BindingFlags.Public, Nothing, largeInteger,
    Nothing), Integer)

    'this works
    lBytes = BitConverter.GetBytes(lowPart)
    hBytes = BitConverter.GetBytes(highPart)

    lBytes.CopyTo(valBytes, 0)
    hBytes.CopyTo(valBytes, 4)

    longVal = BitConverter.ToInt64(valBytes, 0)

    Return longVal

    Catch e As MissingMethodException
    Throw New ArgumentException("Invalid COM object passed as
    parameter. Object must be IADsLargeInteger.", e)
    End Try
    End Function


    For your own interop type, you can do this:

    <ComImport(), Guid("9068270b-0939-11D1-8be1-00c04fd8d503"),
    TypeLibType(4160), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)>
    _
    public interface IADsLargeInteger
    <DispId(2)> _
    property HighPart as int32
    <DispId(3)> _
    property LowPart as int32
    end interface

    Note that this doesn't give you a CoClass for creation, but you can read
    from it.

    HTH,

    Joe K.




    "Fowler" <> wrote in message
    news:...
    > I've been working on a web part that will remind a user how many days
    > they have until their password expires. I strong named it and created a
    > custom security policy to allow it to live in the bin rather than the
    > GAC. After many painful iterations with configuring code access levels
    > and active directory and such, I was able to retrieve some public AD
    > info and I was ready to add the magic code that crunches the numbers. I
    > added a COM reference to the interop.activeds*. Upon compiling, it said
    > that com object (not the web part) wasn't strong named.
    >
    > How do I strong name an external com object that is included as a
    > reference in a web part that's already strong named? I tried adding the
    > com object dll to the GAC but it won't allow it without a stong name
    > either.
    >
    > *ActiveDs needed to handle 'LargeInteger' type
    >
    > Using .Net 2003 and Sharepoint v2
    >
    > *** Sent via Developersdex http://www.developersdex.com ***
    > Don't just participate in USENET...get rewarded for it!
     
    Joe Kaplan \(MVP - ADSI\), Dec 8, 2004
    #2
    1. Advertising

  3. Fowler

    Fowler Guest

    Thanks for your reply. To give you a little more info for the purpose of
    asking a follow up, i am trying to take the big value that represents
    the password last set value (127433834335468750) and convert it to
    something workable.

    I understand that this active directory property is an 8 byte integer
    representing seconds since Jan 1, 1970.

    How would your code example change for an 8 byte integer rather than a
    large integer?

    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Fowler, Dec 9, 2004
    #3
  4. 8 byte integer = Int64 = Large Integer in this case. They are all the same,
    just different words for the same thing.

    The documentation is incorrect in many places in that the value is actually
    the number of 100 nanosecond intervals from 1/1/1600. It is also a FILETIME
    structure.

    In .NET, to convert to a date, you just do DateTime.FromFileTime(....) or
    DateTime.FromFileTimeUtc(....) if you want the time in UTC.

    Any of those code samples will get you the Int64. The reflection approach
    uses late binding and the interop approach is just taking that one type out
    of what is in Interop.ActiveDs and putting it in your own code so you don't
    need to drag the extra assembly around.

    The easiest way is to just use the DirectorySearcher and
    ResultPropertyValueCollection. That looks like:

    Int64 dateVal = (Int64) result.Properties["pwdLastSet"][0];
    DateTime date;
    if (dateVal > 0)
    date = DateTime.FromFileTime(dateVal);
    else
    //it is either -1 or 0 which isn't a date value, but means that the
    user's password never expires or they need to change password at next logon

    HTH,

    Joe K.

    "Fowler" <> wrote in message
    news:%...
    > Thanks for your reply. To give you a little more info for the purpose of
    > asking a follow up, i am trying to take the big value that represents
    > the password last set value (127433834335468750) and convert it to
    > something workable.
    >
    > I understand that this active directory property is an 8 byte integer
    > representing seconds since Jan 1, 1970.
    >
    > How would your code example change for an 8 byte integer rather than a
    > large integer?
    >
    > *** Sent via Developersdex http://www.developersdex.com ***
    > Don't just participate in USENET...get rewarded for it!
     
    Joe Kaplan \(MVP - ADSI\), Dec 9, 2004
    #4
  5. Fowler

    Fowler Guest

    That works! Thanks for helping me out. I now have a web part that
    queries active directory (passing in the logon_user credential as the
    search filter) and returns the password last set value that I convert to
    a date using the solution described here. Then I can do some date
    arithmetic to let the user know how long they have until they need to
    change their password.

    We have an extranet portal solution in place and our external users
    occasionally run into a hassle if they allow their password to expire.



    *** Sent via Developersdex http://www.developersdex.com ***
    Don't just participate in USENET...get rewarded for it!
     
    Fowler, Dec 10, 2004
    #5
  6. Spiffy.

    We have similar stuff as well. One thing that we do is have a batch process
    that runs on a server that sends out email messages at 15, 5, 2 and 1 days
    before expiration telling people they need to update their password on the
    web site. Now that you know the "magic" for doing the calculations, you
    might consider putting something like that together as well. For that case,
    you just need to figure out the proper date values and then do a subtree
    search in your AD for all users with pwdLastSet within that range.

    Best of luck to you.

    Joe K.

    "Fowler" <> wrote in message
    news:%...
    > That works! Thanks for helping me out. I now have a web part that
    > queries active directory (passing in the logon_user credential as the
    > search filter) and returns the password last set value that I convert to
    > a date using the solution described here. Then I can do some date
    > arithmetic to let the user know how long they have until they need to
    > change their password.
    >
    > We have an extranet portal solution in place and our external users
    > occasionally run into a hassle if they allow their password to expire.
    >
    >
    >
    > *** Sent via Developersdex http://www.developersdex.com ***
    > Don't just participate in USENET...get rewarded for it!
     
    Joe Kaplan \(MVP - ADSI\), Dec 10, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joe L via .NET 247

    Web Service timeout from Sharepoint webpart

    Joe L via .NET 247, Jun 17, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    2,947
    Joe L via .NET 247
    Jun 17, 2004
  2. susurla
    Replies:
    4
    Views:
    5,063
    Siva M
    Sep 6, 2005
  3. John
    Replies:
    2
    Views:
    740
  4. David Thielen

    ASP.NET -> Sharepoint webpart

    David Thielen, Jan 23, 2008, in forum: ASP .Net
    Replies:
    3
    Views:
    544
    Steven Cheng[MSFT]
    Jan 24, 2008
  5. yohanb

    WSS : Interop.ActiveDs missing

    yohanb, Oct 25, 2005, in forum: ASP .Net Security
    Replies:
    0
    Views:
    248
    yohanb
    Oct 25, 2005
Loading...

Share This Page