Search code examples
powershellactive-directoryldapadsi

How to remotely delete an AD-Computer from Active Directory - Powershell


I am running Powershell on a remote computer that is not connected to the domain, does not have any modules and is running PS 2.0.

I want to contact the Active Directory of my domain, check if there is an entry for this computer and; if yes, delete that entry.

Checking the AD via ADSI for existance of the computer is easy. However the deleting does not work somehow.

Here is my code so far:

# Variables
$domain = "Test.com"
$Ldap = "LDAP://$domain"
$Global:AdsiSearcher = $Null

# Function to Delete PC
Function DeleteThisPc ()
{
    $CurrentSearch = $Global:AdsiSearcher
    $One = $CurrentSearch.FindOne()
    $OPath = [adsi]$One.Path
    $OPath.psbase.DeleteTree()

The Problem lies here. Even though $OPath is of type System.DirectoryServices.DirectoryEntry and the propertylist shows all properties, it does not allow me to delete the object.

Exception calling "DeleteTree" with "0" argument(s): "Logon failure: unknown user name or bad password.

At C:\TEMP\Domjoin1.1.ps1:49 char:33 $OPath.psbase.DeleteTree <<<< () CategoryInfo: NotSpecified: (:) [], MethodInvocationException FullyQualifiedErrorId : DotNetMethodException

Code:

# Function to get a ADSISearcher and set it to the global-AdsiSearcher
Function ConnectAD ()
{
    $domain = new-object DirectoryServices.DirectoryEntry($Ldap,"$domain\Bob",'1234')
    $filter = "(&(objectCategory=computer)(objectClass=computer)(cn=$ComputerName))"
    $AdsiSearch = [adsisearcher]""
    $AdsiSearch.SearchRoot = $domain
    $AdsiSearch.Filter = $filter
    $Global:AdsiSearcher = $AdsiSearch
}

# Main Function
Function Sub_Check-ADComputer()
{
    ConnectAD
    $CurSearch = $Global:AdsiSearcher.findOne()
    if($CurSearch -ne $null)
    {
       DeleteThisPc
    }
}

# Start
Sub_Check-ADComputer

Even though the issue seems to be obvious as the error states:

Logon failure: unknown user name or bad password.

The username and password is the same that I use to get the object from the AD in the first place. So it does work - do I somehow have to give the credentials again when trying to deleteTree() ? I also gave the User FullControl on the OU that the object is stored in.

Edit:

When I do it on another machine with PS 3.0 I get a different Error message:

Exception calling "DeleteTree" with "0" argument(s): "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"


Solution

  • I found the problem.

    When using invoke command the variables are not transmitted unless specified by -argumentlist. Another approach I discovered was the following, which is the one I am using now and which works like a charm.

    $domain = "DOMAINNAME"
    $AdUser = "$domain\JoinDom"
    $AdPW = "PASSWORD"
    $AdPass = convertto-securestring -string $AdPW -AsPlainText -Force
    $AdCred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdUser,$AdPass 
    $ThisComputer = $Env:COMPUTERNAME
    $RetValue = $true
    Function CheckExist ()
    {
        $ErrorActionPreference = ‘SilentlyContinue’
        $Ascriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("get-adcomputer $ThisComputer")
        $Ret = Invoke-Command -ComputerName SERVERNAME -ScriptBlock $Ascriptblock -Credential $AdCred    
        $ErrorActionPreference = ‘Continue’
        return $Ret
    }
    $ExistBefore = CheckExist
    if($ExistBefore -ne $null)
    {
            $scriptblock = $ExecutionContext.InvokeCommand.NewScriptBlock("Remove-ADComputer $ThisComputer")
            Invoke-Command -ComputerName SERVERNAME -ScriptBlock $scriptblock -Credential $AdCred
            $ExistAfter = CheckExist
            if($ExistAfter -ne $null){$RetValue = $false}
    }
    if($RetValue -ne $false)
    {
        Add-computer -domainname $domain -credential $Adcred -OUPath "OU=MyOU,DC=DOMAIN,DC=DE"
        Restart-Computer -Force
    }