I'm trying to use a version of Richard's script that I bastardized to delete
computer accounts that are disabled and haven't been modified for 30 days.
This script works fine for user accounts, but it's not running and not
throwing out any errors.

We disable the computer accounts and move them to a separate OU at the time
an employee leaves.

I'm hoping a scripting guru will see the problem right away.

Note that I have the DateDiff variable set to "h" for hours while testing.

Script begins below
===================================================

Option Explicit

Dim objConnection, objCommand, objRootDSE
Dim strDNSDomain, strFilter, strQuery, objRecordSet, strDN, strDN2, HowLong,
mail
Dim intFlag, dtmWhenChanged, objComputer, objParent, objEmail

Const ADS_UF_ACCOUNTDISABLE = &H02


' Use ADO to search the domain for all computers.
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOOBject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

' Determine the DNS domain from the RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
strFilter = "(objectCategory=computer)"
strQuery = "<LDAP://ou=gpo
testing,ou=dallas,ou=us,dc=xxxx,dc=xxxxx,dc=xxx>;" & strFilter _
& ";cn,distinguishedName,userAccountControl,whenChanged"

objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 30
objCommand.Properties("Cache Results") = False

' Enumerate all computers. Check if account disabled.
Set objRecordSet = objCommand.Execute
Do Until objRecordSet.EOF
strDN = objRecordSet.Fields("distinguishedName")
strDN2 = objRecordSet.Fields("cn")
intFlag = objRecordSet.Fields("userAccountControl")
dtmWhenChanged = objRecordSet.Fields("whenChanged")

HowLong = DateDiff("h", dtmwhenChanged, Now)

If (intFlag And ADS_UF_ACCOUNTDISABLE) <> 0 Then
If DateDiff("h", dtmWhenChanged, Now) > 1 Then
Set objComputer = GetObject("LDAP://" & strDN)
Set objParent = GetObject(objComputer.Parent)
objParent.Delete "Computer", objComputer.Name
' Wscript.Echo "Deleted " & strDN
mail = "The account for " & strDN2 & " has been deleted"

'Send Mail
Set objEmail = CreateObject("CDO.Message")
objEmail.From = "AccountDeleted@xxxxx.xxx"
objEmail.To = "networknotifications@xxxxx.xxx"
objEmail.Subject = "Deleted User Account: " & strDN2
objEmail.TextBody = mail
objEmail.Configuration.Fields.Item
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objEmail.Configuration.Fields.Item
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "172.xx.x.xx"
objEmail.Configuration.Fields.Item
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objEmail.Configuration.Fields.Update

objEmail.Send

End If
End If
objRecordSet.MoveNext

Loop

' Clean up.
Set objConnection = Nothing
Set objCommand = Nothing
Set objRootDSE = Nothing
Set objRecordSet = Nothing
Set objComputer = Nothing
Set objParent = Nothing

'Wscript.Echo "Done"
===================================================

Any suggestions or glaring obvious bad code?

Thanks

Re: Script to delete computer accounts not working by Richard

Richard
Tue Jun 13 20:38:47 CDT 2006

Hi,

First, you do not specify a scope for the ADO query, so I believe the
default is "base". Only the OU specified is searched. This is probably your
intent, but if not, use "subtree" to search the OU and all sub containers
(children).

Next, you only consider computer accounts that are disabled and skip all
others. From your description this is intended.

Finally, whenChanged is in UTC (Coordinated Universal Time, or what was once
called GMT). For example, when I tested your script, I disabled a test
computer account I created a few days ago, but your HowLong variable
became -5 because of my time zone. This may be happening to you as well.
When I corrected for this, the script deleted the objects I expected. In my
case I used:

If DateDiff("h", dtmWhenChanged, Now) > -6 Then

The value you use will depend on your time zone. Of course, this should only
matter for testing. In production when you test for inactivity more than 30
days, a few hours doesn't matter.


I hope this helps.

--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net

"bgilbert" <bgilbert@discussions.microsoft.com> wrote in message
news:89E655CA-82C6-4F02-B80C-C75D15F9A045@microsoft.com...
> I'm trying to use a version of Richard's script that I bastardized to
> delete
> computer accounts that are disabled and haven't been modified for 30 days.
> This script works fine for user accounts, but it's not running and not
> throwing out any errors.
>
> We disable the computer accounts and move them to a separate OU at the
> time
> an employee leaves.
>
> I'm hoping a scripting guru will see the problem right away.
>
> Note that I have the DateDiff variable set to "h" for hours while testing.
>
> Script begins below
> ===================================================
>
> Option Explicit
>
> Dim objConnection, objCommand, objRootDSE
> Dim strDNSDomain, strFilter, strQuery, objRecordSet, strDN, strDN2,
> HowLong,
> mail
> Dim intFlag, dtmWhenChanged, objComputer, objParent, objEmail
>
> Const ADS_UF_ACCOUNTDISABLE = &H02
>
>
> ' Use ADO to search the domain for all computers.
> Set objConnection = CreateObject("ADODB.Connection")
> Set objCommand = CreateObject("ADODB.Command")
> objConnection.Provider = "ADsDSOOBject"
> objConnection.Open "Active Directory Provider"
> Set objCommand.ActiveConnection = objConnection
>
> ' Determine the DNS domain from the RootDSE object.
> Set objRootDSE = GetObject("LDAP://RootDSE")
> strDNSDomain = objRootDSE.Get("DefaultNamingContext")
> strFilter = "(objectCategory=computer)"
> strQuery = "<LDAP://ou=gpo
> testing,ou=dallas,ou=us,dc=xxxx,dc=xxxxx,dc=xxx>;" & strFilter _
> & ";cn,distinguishedName,userAccountControl,whenChanged"
>
> objCommand.CommandText = strQuery
> objCommand.Properties("Page Size") = 100
> objCommand.Properties("Timeout") = 30
> objCommand.Properties("Cache Results") = False
>
> ' Enumerate all computers. Check if account disabled.
> Set objRecordSet = objCommand.Execute
> Do Until objRecordSet.EOF
> strDN = objRecordSet.Fields("distinguishedName")
> strDN2 = objRecordSet.Fields("cn")
> intFlag = objRecordSet.Fields("userAccountControl")
> dtmWhenChanged = objRecordSet.Fields("whenChanged")
>
> HowLong = DateDiff("h", dtmwhenChanged, Now)
>
> If (intFlag And ADS_UF_ACCOUNTDISABLE) <> 0 Then
> If DateDiff("h", dtmWhenChanged, Now) > 1 Then
> Set objComputer = GetObject("LDAP://" & strDN)
> Set objParent = GetObject(objComputer.Parent)
> objParent.Delete "Computer", objComputer.Name
> ' Wscript.Echo "Deleted " & strDN
> mail = "The account for " & strDN2 & " has been deleted"
>
> 'Send Mail
> Set objEmail = CreateObject("CDO.Message")
> objEmail.From = "AccountDeleted@xxxxx.xxx"
> objEmail.To = "networknotifications@xxxxx.xxx"
> objEmail.Subject = "Deleted User Account: " & strDN2
> objEmail.TextBody = mail
> objEmail.Configuration.Fields.Item
> ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
> objEmail.Configuration.Fields.Item
> ("http://schemas.microsoft.com/cdo/configuration/smtpserver") =
> "172.xx.x.xx"
> objEmail.Configuration.Fields.Item
> ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
> objEmail.Configuration.Fields.Update
>
> objEmail.Send
>
> End If
> End If
> objRecordSet.MoveNext
>
> Loop
>
> ' Clean up.
> Set objConnection = Nothing
> Set objCommand = Nothing
> Set objRootDSE = Nothing
> Set objRecordSet = Nothing
> Set objComputer = Nothing
> Set objParent = Nothing
>
> 'Wscript.Echo "Done"
> ===================================================
>
> Any suggestions or glaring obvious bad code?
>
> Thanks



Re: Script to delete computer accounts not working by bgilbert

bgilbert
Wed Jun 14 10:15:02 CDT 2006

Richard,

Excellent catch! I completely forgot about the time being UTC. I tried the
script again this morning on a test account that I deleted yesterday morning
and it worked fine.

Also, thanks for the initial script as well.

BG



"Richard Mueller" wrote:

> Hi,
>
> First, you do not specify a scope for the ADO query, so I believe the
> default is "base". Only the OU specified is searched. This is probably your
> intent, but if not, use "subtree" to search the OU and all sub containers
> (children).
>
> Next, you only consider computer accounts that are disabled and skip all
> others. From your description this is intended.
>
> Finally, whenChanged is in UTC (Coordinated Universal Time, or what was once
> called GMT). For example, when I tested your script, I disabled a test
> computer account I created a few days ago, but your HowLong variable
> became -5 because of my time zone. This may be happening to you as well.
> When I corrected for this, the script deleted the objects I expected. In my
> case I used:
>
> If DateDiff("h", dtmWhenChanged, Now) > -6 Then
>
> The value you use will depend on your time zone. Of course, this should only
> matter for testing. In production when you test for inactivity more than 30
> days, a few hours doesn't matter.
>
>
> I hope this helps.
>
> --
> Richard
> Microsoft MVP Scripting and ADSI
> Hilltop Lab - http://www.rlmueller.net
>
> "bgilbert" <bgilbert@discussions.microsoft.com> wrote in message
> news:89E655CA-82C6-4F02-B80C-C75D15F9A045@microsoft.com...
> > I'm trying to use a version of Richard's script that I bastardized to
> > delete
> > computer accounts that are disabled and haven't been modified for 30 days.
> > This script works fine for user accounts, but it's not running and not
> > throwing out any errors.
> >
> > We disable the computer accounts and move them to a separate OU at the
> > time
> > an employee leaves.
> >
> > I'm hoping a scripting guru will see the problem right away.
> >
> > Note that I have the DateDiff variable set to "h" for hours while testing.
> >
> > Script begins below
> > ===================================================
> >
> > Option Explicit
> >
> > Dim objConnection, objCommand, objRootDSE
> > Dim strDNSDomain, strFilter, strQuery, objRecordSet, strDN, strDN2,
> > HowLong,
> > mail
> > Dim intFlag, dtmWhenChanged, objComputer, objParent, objEmail
> >
> > Const ADS_UF_ACCOUNTDISABLE = &H02
> >
> >
> > ' Use ADO to search the domain for all computers.
> > Set objConnection = CreateObject("ADODB.Connection")
> > Set objCommand = CreateObject("ADODB.Command")
> > objConnection.Provider = "ADsDSOOBject"
> > objConnection.Open "Active Directory Provider"
> > Set objCommand.ActiveConnection = objConnection
> >
> > ' Determine the DNS domain from the RootDSE object.
> > Set objRootDSE = GetObject("LDAP://RootDSE")
> > strDNSDomain = objRootDSE.Get("DefaultNamingContext")
> > strFilter = "(objectCategory=computer)"
> > strQuery = "<LDAP://ou=gpo
> > testing,ou=dallas,ou=us,dc=xxxx,dc=xxxxx,dc=xxx>;" & strFilter _
> > & ";cn,distinguishedName,userAccountControl,whenChanged"
> >
> > objCommand.CommandText = strQuery
> > objCommand.Properties("Page Size") = 100
> > objCommand.Properties("Timeout") = 30
> > objCommand.Properties("Cache Results") = False
> >
> > ' Enumerate all computers. Check if account disabled.
> > Set objRecordSet = objCommand.Execute
> > Do Until objRecordSet.EOF
> > strDN = objRecordSet.Fields("distinguishedName")
> > strDN2 = objRecordSet.Fields("cn")
> > intFlag = objRecordSet.Fields("userAccountControl")
> > dtmWhenChanged = objRecordSet.Fields("whenChanged")
> >
> > HowLong = DateDiff("h", dtmwhenChanged, Now)
> >
> > If (intFlag And ADS_UF_ACCOUNTDISABLE) <> 0 Then
> > If DateDiff("h", dtmWhenChanged, Now) > 1 Then
> > Set objComputer = GetObject("LDAP://" & strDN)
> > Set objParent = GetObject(objComputer.Parent)
> > objParent.Delete "Computer", objComputer.Name
> > ' Wscript.Echo "Deleted " & strDN
> > mail = "The account for " & strDN2 & " has been deleted"
> >
> > 'Send Mail
> > Set objEmail = CreateObject("CDO.Message")
> > objEmail.From = "AccountDeleted@xxxxx.xxx"
> > objEmail.To = "networknotifications@xxxxx.xxx"
> > objEmail.Subject = "Deleted User Account: " & strDN2
> > objEmail.TextBody = mail
> > objEmail.Configuration.Fields.Item
> > ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
> > objEmail.Configuration.Fields.Item
> > ("http://schemas.microsoft.com/cdo/configuration/smtpserver") =
> > "172.xx.x.xx"
> > objEmail.Configuration.Fields.Item
> > ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
> > objEmail.Configuration.Fields.Update
> >
> > objEmail.Send
> >
> > End If
> > End If
> > objRecordSet.MoveNext
> >
> > Loop
> >
> > ' Clean up.
> > Set objConnection = Nothing
> > Set objCommand = Nothing
> > Set objRootDSE = Nothing
> > Set objRecordSet = Nothing
> > Set objComputer = Nothing
> > Set objParent = Nothing
> >
> > 'Wscript.Echo "Done"
> > ===================================================
> >
> > Any suggestions or glaring obvious bad code?
> >
> > Thanks
>
>
>

Re: Script to delete computer accounts not working by Dr

Dr
Thu Jun 15 10:41:11 CDT 2006

JRS: In article <uTwAKN1jGHA.1272@TK2MSFTNGP03.phx.gbl>, dated Tue, 13
Jun 2006 20:38:47 remote, seen in news:microsoft.public.scripting.vbscri
pt, Richard Mueller <rlmueller-NOSPAM@ameritech.NOSPAM.net> posted :
>
>Finally, whenChanged is in UTC (Coordinated Universal Time, or what was once
>called GMT).


Inaccurate. Microsoft uses UTC to refer to time behaving like
traditional GMT, but in the real outside world UTC and GMT are quite
distinct concepts (though the difference should never exceed 0.9
seconds).

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm
Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.