none
PowerShell and ADSI

    Question

  • I asked this question in another thread after I found a solution so i apologize if this is a repeat for some.

    Situation: Newly imaged Windows 7 PC

    We run the Part1 script to:

    - Add the PC to the Domain and specific OU based on Computer Type.  

    - Add a user to Local Administrators Group

    - Reboots the PC and adds a reg entry to start Part2 

    Part2 simply adds a 4 digit code to the Description field of the PC's Active Directory entry and then kicks off the install script for System Center Configuration Manager.  

    The problem is that when i was testing everything I forgot that Joe User whose name we would be entering as the Local Admin does not have the same rights as me.  

    I am looking for a way to add a 4 digit value to the Description Field of the PC's Active Directory entry.  here are the scripts i am using:

    Part1

    ##  ADD PC TO BLAIRNET USING SETUP ID 
    $CN = $env:COMPUTERNAME
    $type = (Get-WmiObject win32_computersystem).pcsystemtype
    $domain = "DOMAIN"
    $username = "$domain\user" 
    $password = "123PASSword" | ConvertTo-SecureString -asPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($username,$password)
    $OUPath1 = "OU=ComputersWB,DC=DOMAIN,DC=NET"
    $OUPath2 = "OU=ComputersUTIMACO,DC=DOMAIN,DC=NET"
    
    
    switch -Regex ($type)
            {
    
            "1" {Add-Computer -DomainName $domain -Credential $credential -OUPath $OUPath1}
            "2" {Add-Computer -DomainName $domain -Credential $credential -OUPath $OUPath2}
            "3" {Add-Computer -DomainName $domain -Credential $credential -OUPath $OUPath1}
           
            } 
    
    
    ##  ADD USER, Rights-PC-All AS LOCAL ADMINISTRATORS
    $domain = "DOMAIN.NET"
    $PCUser = Read-Host 'PLEASE ENTER THE USERNAME OF THE USER YOU WANT AS A LOCAL ADMINISTRATOR'
    $DomainUser = "WinNT://" + $domain + "/" + $PCUser + ",user"
    $RPA = "WinNT://DOMAIN.NET/Rights-PC-All,user"
    $group = [ADSI]("WinNT://"+$env:COMPUTERNAME+"/administrators,group") 
    $group.add($DomainUser)
    $group.add($RPA)
    
    # CHANGE DEFAULT LOGIN TO USER YOU JUST ADDED
    $domain = "DOMAIN"
    $Key1 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"
    $NewKeyValue = $domain + "\" + $PCUser
    Set-ItemProperty -path $Key1 -name LastLoggedOnSamUser $NewKeyValue 
    Set-ItemProperty -path $Key1 -name LastLoggedOnUser $NewKeyValue
    
    #Add REGISTRY KEY TO RUN NEXT STEP AFTER LOGIN
    $RunOnceKey = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce"
    $RegValue = "C:\DOMAIN\Run2.cmd"
    New-ItemProperty -Path $RunOnceKey -Name Part2 -Value $RegValue
    
    
    ## RESTART COMPUTER TO COMPLETE PROCESSES
    Restart-Computer

    Part2

    ##  ADD DEPT CODE TO AD AND START SCCM INSTALL
    
    $CN = $env:COMPUTERNAME
    $type = (Get-WmiObject win32_computersystem).pcsystemtype
    $domain = "DOMAIN"
    $OUPath1 = "OU=ComputersWB,DC=DOMAIN,DC=NET"
    $OUPath2 = "OU=ComputersUTIMACO,DC=DOMAIN,DC=NET"
    
    switch -Regex ($type)
            {
    
            "1" {$computerDN = 'LDAP://' + "CN=" + $CN + "," + $OUPath1}
            "2" {$computerDN = 'LDAP://' + "CN=" + $CN + "," + $OUPath2}
            "3" {$computerDN = 'LDAP://' + "CN=" + $CN + "," + $OUPath1}
           
            } 
    
    do
        {$DeptCode = Read-Host 'PLEASE ENTER THE 4 DIGIT DEPT. CODE FOR THIS USER'}
    
    until ($DeptCode.Length -eq 4)
    
    $computer=[adsi]$computerDN
    $computer.put("description",$DeptCode)
    $computer.SetInfo()

    I'm still a newbie with PowerShell, but trying to learn.  Can I credential or use a different session to run Part2?


     


    Matt Dillon

    Wednesday, July 24, 2013 5:47 PM

Answers

  • Assuming you run the PowerShell process as another user, you don't need to change the code to use alternate credentials.  If you do still need to use alternate credentials in the script, though, I already posted example code for it.  The key point is to change $computer=[adsi]$computerDN to $computer = New-Object System.DirectoryServices.DirectoryEntry($computerDN, $username, $password)  (assuming that you have string variables named $username and $password ).

    • Marked as answer by pugmohone Wednesday, July 24, 2013 7:16 PM
    • Unmarked as answer by pugmohone Wednesday, July 24, 2013 7:30 PM
    • Marked as answer by pugmohone Wednesday, July 24, 2013 7:50 PM
    Wednesday, July 24, 2013 7:07 PM

All replies

  • I'm assuming, for now, that you're intentionally using the [adsi] instead of the PowerShell ActiveDirectory module's cmdlets (maybe due to not meeting the requirements for using the AD Module).

    [adsi] is a PowerShell accelerator that refers to the System.DirectoryServices.DirectoryEntry class.  That class has a few different constructors, a couple of which allow you to specify alternate credentials (though hard-coding passwords like this in a script does represent a security risk).

    $username = "$domain\user" 
    $password = "123PASSword"
    
    # ....
    
    $computer = New-Object System.DirectoryServices.DirectoryEntry($computerDN, $username, $password)
    

    Wednesday, July 24, 2013 6:14 PM
  • Yes.  I used that code in Part1.  i guess my question is how can I run part2 using the same credentials.  What do i need to add to my script?  I am logging in as Joe User and need to run the script as the credentialed user.  

    Is this staring me right in the face and i don't see it?  i cannot figure out how to run the code as the user I need it run as.  

    Thanks.  


    Matt Dillon

    Wednesday, July 24, 2013 6:21 PM
  • I recommend not trying to store credentials in a script (this is a HUGE security hole) and simply start PowerShell using the needed credentials, then run your script(s).

    Bill

    Wednesday, July 24, 2013 6:28 PM
    Moderator
  • How do I start Powershell as someone else is the question then?  or even run this with a prompt.  Put the security hole to the side.  it is not a concern at the moment.  I need to know if this can be done.  

    Thanks.  


    Matt Dillon

    Wednesday, July 24, 2013 6:31 PM
  • Hi Matt,

    You can launch PowerShell as another user by using RunAs:

    runas /user:domain\username powershell


    Don't retire TechNet!

    Wednesday, July 24, 2013 6:40 PM
  • Hold shift key, right-click PowerShell shortcut, click "Run as different user."

    Bill

    Wednesday, July 24, 2013 6:40 PM
    Moderator
  • Assuming you run the PowerShell process as another user, you don't need to change the code to use alternate credentials.  If you do still need to use alternate credentials in the script, though, I already posted example code for it.  The key point is to change $computer=[adsi]$computerDN to $computer = New-Object System.DirectoryServices.DirectoryEntry($computerDN, $username, $password)  (assuming that you have string variables named $username and $password ).

    • Marked as answer by pugmohone Wednesday, July 24, 2013 7:16 PM
    • Unmarked as answer by pugmohone Wednesday, July 24, 2013 7:30 PM
    • Marked as answer by pugmohone Wednesday, July 24, 2013 7:50 PM
    Wednesday, July 24, 2013 7:07 PM
  • You da man Dave Wyatt!!  Thanks.  Not sure why it works, but it does.  One day it will be crystal clear.  Thanks !

    Matt Dillon

    Wednesday, July 24, 2013 7:52 PM
  • Casting a string to [adsi] in PowerShell is a shortcut for calling New-Object System.DirectoryServices.DirectoryEntry() with the one-argument constructor.  To get at the other constructors (such as the one we're using that takes three strings), you have to call New-Object explicitly.

    Technically, you can still use the "adsi" accelerator as the class name instead of typing out System.DirectoryServices.DirectoryEntry , but I like to see full .NET class names in my code most of the time.  Makes it easy for people to look things up on MSDN if needed.

    $computer = New-Object System.DirectoryServices.DirectoryEntry($computerDN, $username, $password)
    
    # is the same as
    
    $computer = New-Object adsi($computerDN, $username, $password)
    


    Wednesday, July 24, 2013 8:48 PM
  • Thank you so much for the explanation. Now I actually understand what I was missing.  

    Matt Dillon

    Thursday, July 25, 2013 1:20 PM
  • Shouldn't most of this, and especially making the computer description be a department code, be done remotely by a user with administrator privileges, so there is no need for alternate credentials. Adding a domain user to a local group should also be done remotely by an admin. In fact, perhaps most of this can be one in bulk for all computers in an OU at once.


    Richard Mueller - MVP Directory Services

    Thursday, July 25, 2013 3:27 PM
    Moderator
  • Assuming the script to update the computer description is run on the actual computer by someone with sufficient permissions, I would suggest the following:

    $SysInfo = New-Object -ComObject "ADSystemInfo"
    $ComputerDN = $SysInfo.GetType().InvokeMember("ComputerName", "GetProperty", $Null, $SysInfo, $Null)
    $Computer = [ADSI]"LDAP://$ComputerDN"

    Do{$DeptCode = Read-Host "Please enter the 4 digit department code for this user"}
    Until ($DeptCode.Length -eq 4)

    $Computer.Put("description", $DeptCode)
    $Computer.SetInfo()

    -----

    This retrieves the DN of the local computer directly, so there is no need to use WMI to retrieve anything, or modify the code later for new OU's, or risk cases where the NetBIOS name of the machine does not match the Common Name, etc. Of course, this still correlates the computer with the department code of one user, which may need to be modified in the future.


    Richard Mueller - MVP Directory Services

    Thursday, July 25, 2013 4:16 PM
    Moderator