none
System.__ComObject cast to int64 (PowerShell) RRS feed

  • Question

  • I have been through 20 sites trying to understand this, but I just don't get it... How do you change System.__ComObjects. I use the [ADSI] accelerator a lot and when it comes to converting Active Dirctory Large Integer/Interval values to Int64, I just don't understand how it is suppose to work.

    For example:

    We have a custom schema attribute for our computer objects named ms-Mcs-AdmPwdExpirationTime. I know from looking in the Schema that the object is a Large Integer/Interval format.  I know it is convertible to int64, because when I use the [ADSIsearcher] accelerator it is converted for me. Knowing that it can be converted I started looking at the object to see if I could convert the attribute I get back when I use the [ADSI] accelerator. Keep in mind that I don't have a problem to resolve, I have a lack of understanding I am trying to over come...

    First I tried get-member:

    TypeName: System.__ComObject

    Name MemberType Definition
    ---- ---------- ----------
    CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type ...
    Equals Method bool Equals(System.Object obj)
    GetHashCode Method int GetHashCode()
    GetLifetimeService Method System.Object GetLifetimeService()
    GetType Method type GetType()
    InitializeLifetimeService Method System.Object InitializeLifetimeService()
    ToString Method string ToString()


    Nothing here seemed exceptionally helpful to converting the object, so I tried GetType():

    IsPublic IsSerial Name BaseType
    -------- -------- ---- --------
    TRUE FALSE __ComObject System.MarshalByRefObject


    I also tried looking at the PSObject

    BaseObject          : System.__ComObject
    Members             : {System.Object GetLifetimeService(), System.Object
                          InitializeLifetimeService(), System.Runtime.Remoting.ObjRef
                          CreateObjRef(type requestedType), string ToString()...}
    Properties          : {}
    Methods             : {System.Object GetLifetimeService(), System.Object
                          InitializeLifetimeService(), System.Runtime.Remoting.ObjRef
                          CreateObjRef(type requestedType), string ToString()...}
    ImmediateBaseObject : System.__ComObject
    TypeNames           : {System.__ComObject, System.MarshalByRefObject, System.Object}

    I see absolutely no hint on how I should convert this... I know what this object is, and I know what I need it to be. How should I be looking at Com objects to determine how to convert them to other data types (Large Integer/Interval to Int64 for example)?


    • Edited by Oldguard Thursday, May 8, 2014 2:06 PM Powershell added.
    Thursday, May 8, 2014 2:04 PM

Answers

  • Looks like I over thought the problem:

    I was doing this:

    $TestValue = (([adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=Contoso,DC=Com")."ms-Mcs-AdmPwdExpirationTime"[0])

    When I did get-member, I would get no option to convert the _ComObject.

    This worked a lot better:

    $TestValue = [adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=contoso,DC=Com"
    $TestValue.ConvertLargeIntegerToInt64($Testvalue."ms-Mcs-AdmPwdExpirationTime"[0])

    • Marked as answer by Oldguard Thursday, May 8, 2014 2:29 PM
    Thursday, May 8, 2014 2:26 PM

All replies

  • What?  That is not a custom schema object.  Try asking a simple question like I am trying to get the password expiration time..

    You are making a lot of statements that show you are lost.  Try not using technical language and just ask the question.  Almost nothing in WIndows is this difficult.

    Here is a backgrounder on large integer type: http://bsonposh.com/archives/226


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 2:24 PM
  • Looks like I over thought the problem:

    I was doing this:

    $TestValue = (([adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=Contoso,DC=Com")."ms-Mcs-AdmPwdExpirationTime"[0])

    When I did get-member, I would get no option to convert the _ComObject.

    This worked a lot better:

    $TestValue = [adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=contoso,DC=Com"
    $TestValue.ConvertLargeIntegerToInt64($Testvalue."ms-Mcs-AdmPwdExpirationTime"[0])

    • Marked as answer by Oldguard Thursday, May 8, 2014 2:29 PM
    Thursday, May 8, 2014 2:26 PM
  • Some times you just have to ask a stupid question so you can figure out the question was stupid...

    Thursday, May 8, 2014 2:29 PM
  • I recommend learning about AD.  You are guessing at it and guessing wrong.

    There is no password expiration time on an object.  There is a password age since last changed.  You have to computer the expiration time.  The global time is what we use to calculate the actual time.

    Is this what you are trying to do?


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 2:30 PM
  • Here is how to analyze an objecy:

    $TestValue = [adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=contoso,DC=Com"
    $testvalue | select *

    The value you need is:

    $TestValue.pwdLastSet

     

    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 2:35 PM
  • No, I know plenty about AD, I just did a terrible job of explaining my issue... We have a custom attribute provided by A developer as part of a password management solution. The name of that computer attribute is:

    Mcs-AdmPwdExpirationTime

    I just got tired of using the [ADSISEARCHER] to convert it to an INT64 and wanted to understand how I could have converted it from a COM object to a INT64 without using the searcher to do it.

    Some of my confusion came because I am spoiled by using Get-ADComputer which handles this for me most of the time, but since I often need to work from systems that do not have the ActiveDirectory RSAT tools on them, I have been working to become more proficient with the [ADSI] accelerator. Often times I can evaluate a network with nothing but the [ADSI] accelerator, and the .Net components for Active Directory (System.DirectoryServices.ActiveDirectory).

    Sorry I made myself look stupid, but I will never forget the lesson I just learned. Off to lick my wounds and learn how active directory works...

    Thursday, May 8, 2014 2:48 PM
  • Looks like I over thought the problem:

    I was doing this:

    $TestValue = (([adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=Contoso,DC=Com")."ms-Mcs-AdmPwdExpirationTime"[0])

    When I did get-member, I would get no option to convert the _ComObject.

    This worked a lot better:

    $TestValue = [adsi]"LDAP://CN=SomeComputer,OU=SomeOU,DC=contoso,DC=Com"
    $TestValue.ConvertLargeIntegerToInt64($Testvalue."ms-Mcs-AdmPwdExpirationTime"[0])

    That won't work and there is no such value on that object.  That attribute exists on the domain object.  You first have to get the pwdLastset but you have to check to be sure that password never expires is not set.

    Passwords on computer objects are handled automatically by AD.  You should not bother with those.  They get changed frequently.  If there is a failure to change you will het event log entries.

    That is what I mean about asking  a simple question.  I still have no idea what task you are trying to accomplish.


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 2:52 PM
  • We are not talking about the same thing... I thought I was pretty clear that we have a custom schema attribute for computer objects. I will try to be more clear on that in the future.
    Thursday, May 8, 2014 3:00 PM
  • No, I know plenty about AD, I just did a terrible job of explaining my issue... We have a custom attribute provided by A developer as part of a password management solution. The name of that computer attribute is:

    Mcs-AdmPwdExpirationTime

    I just got tired of using the [ADSISEARCHER] to convert it to an INT64 and wanted to understand how I could have converted it from a COM object to a INT64 without using the searcher to do it.

    Some of my confusion came because I am spoiled by using Get-ADComputer which handles this for me most of the time, but since I often need to work from systems that do not have the ActiveDirectory RSAT tools on them, I have been working to become more proficient with the [ADSI] accelerator. Often times I can evaluate a network with nothing but the [ADSI] accelerator, and the .Net components for Active Directory (System.DirectoryServices.ActiveDirectory).

    Sorry I made myself look stupid, but I will never forget the lesson I just learned. Off to lick my wounds and learn how active directory works...

    No - that attribute is not custom.  It is an ms-MCS-* attribute which belongs to Microsoft.  The attribute is the schema identifier for the global password expiration time.  You can getit from the domain object.  It is a time interval.  It is usually set at 90 days.

    Use the adsi type to get the domain configuration object an that is where you will find that value. THe user and account objects just carry pwdLastSet as a large integer value which is converted as you have done.  Next we can turn it into a real datatime object:

    It looks like this:
    $pwdLastSet64=$TestValue.ConvertLargeIntegerToInt64($TestValue.pwdLastSet[0])
    [datetime]::FromFileTime($pwdLastSet64)

    THis works with all large integers on the account objects. 

    The expiration time is obtained:

    $pwdLastSet + $PasswordExpirationTime

    where $passwordExpirationTime is a tImespan object converted from the domain value.
    On WS2008R2 and later we can also use granular password rules.


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 3:02 PM
  • Oops - I got that wrong by thinking ahead too much.  The ADM got me or I missed it.

    You are trying to get the admin password management values.  This is also a MIcrosoft solution and is just a simple extension to allow central administration of admin passwords.

    The rest of the rules are the same.

    I believe these are the schema extensions you are using:\

    ms-MCS-AdmPwdExpirationTime and ms-MCS-AdmPwd


    ¯\_(ツ)_/¯


    • Edited by jrv Thursday, May 8, 2014 3:09 PM
    Thursday, May 8, 2014 3:08 PM
  • I also just discovered that it is the actual expiration time that is shown in the GUI but I believe it is still the set time in the variable exactly like the account password.  Check this carefully to be sure it works as desired.  If it is the target date then it is just easier to use.


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 3:14 PM
  • You got it Jim... We are having a problem where some of our systems are failing to read the ms-MCS-AdmPwdExpirationTime correctly and I have been trying to troubleshoot it with the developer. I needed to ensure that I could read the same value that the computer is failing to read. I know I could determine when the password gets changed through other attributes, but in this case I needed to read a specific value, because it is the value that the application is failing to read. I needed to do without RSAT tools because I want to try the query on the impacted computer so I can verify there is not something host specific preventing the attribute from being read...

    I was trying to avoid getting into all of that because I just wanted to understand the COM conversion process better. I already had a means of getting my answer, but I was frustrated that I didn't understand how the conversion of COM objects occurs. Sorry to send you in circles.

    Thursday, May 8, 2014 3:23 PM
  • We are not talking about the same thing... I thought I was pretty clear that we have a custom schema attribute for computer objects. I will try to be more clear on that in the future.

    You are talking about the Microsoft local admin password setting tool/wizard for ADUC. The schema extension is optional in 2008 but I believe it is standard in WS2012.  The clue is the leading ms- which is what X.500 has specified that vendors should use when altering the schema.  'ms' owns that prefix.

    So your real question was just how to use the converter. It is on all iADS objects in ADSI I believe. There is one way that does not require any object that is not readily available:

    ([adsi]'WinNT://.').ConvertLargeIntegerToInt64($largeInteger)

    This is always available.


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 3:26 PM
  • The application is created by a Microsoft Dev (which is why I guess he is using the Microsoft format for attributes).

    You do need to extend the schema.

    http://code.msdn.microsoft.com/windowsdesktop/Solution-for-management-of-ae44e789

    It's a password reset tool for the local admin account.

    Uses a client side extension and the following attributes.  ms-MCS-AdmPwdExpirationTime & ms-MCS-AdmPwd

    The solution checks the current timestamp against ms-MCS-AdmPwdExpirationTime, and if appropriate updates the ms-MCS-AdmPwd attribute with the new password and then extends the expiration time by whatever is set in the Client Side Extension.



    • Edited by Newbie Jones Thursday, May 8, 2014 4:37 PM corrected web address
    Thursday, May 8, 2014 3:33 PM
  • Exactly... Works great for us except for two systems. Just trying to figure out why... I was able to use a powershell script run as the Network Service account to verify that the computer account could access the attribute properly (verification that the delegation of rights to SELF worked correctly)... Looks like my delegation is fine... Looks like the developer will need to figure it out from here...
    Thursday, May 8, 2014 4:15 PM
  • Bit strange as the application has inbuilt tests to ensure that AD is written to before the password is actually changed.

    The application documentation does have a pretty extensive listing of errors that should be written to the Event Log on the affected machines.

    Thursday, May 8, 2014 4:40 PM
  • You got it Jim... We are having a problem where some of our systems are failing to read the ms-MCS-AdmPwdExpirationTime correctly and I have been trying to troubleshoot it with the developer. I needed to ensure that I could read the same value that the computer is failing to read. I know I could determine when the password gets changed through other attributes, but in this case I needed to read a specific value, because it is the value that the application is failing to read. I needed to do without RSAT tools because I want to try the query on the impacted computer so I can verify there is not something host specific preventing the attribute from being read...

    I was trying to avoid getting into all of that because I just wanted to understand the COM conversion process better. I already had a means of getting my answer, but I was frustrated that I didn't understand how the conversion of COM objects occurs. Sorry to send you in circles.

    Check all versions of Net Framework.  You must have the latest version for the Convert to work.

    The password sync runs on the AD system.  The MS code alters the admin password set in AD then it is synced to the remote by a demon from what I can see.  I can't see how that can get it wrong. 


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 4:52 PM
  • Exactly... Works great for us except for two systems. Just trying to figure out why... I was able to use a powershell script run as the Network Service account to verify that the computer account could access the attribute properly (verification that the delegation of rights to SELF worked correctly)... Looks like my delegation is fine... Looks like the developer will need to figure it out from here...

    Can you force a manual change from the DC?  Is it just failing to sync?


    ¯\_(ツ)_/¯

    Thursday, May 8, 2014 4:54 PM
  • Replicates fine... If I clear the value completely then password change process will reset the password, successfully write to the ms-MCS-AdmPwdExpirationTime attribute, and will never be able to read the attribute again unless I clear it. The value it sets is correct, so it isn't even that it writes bad data... If I set the value to zero (which works for most other systems), the application still fails to read the attribute...

    I know the Network Service account has access because I can run the Powershell script as the Network Service and it returns the correct value.

    Thursday, May 8, 2014 6:45 PM