<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Multifunctioning DBA &#187; AD</title>
	<atom:link href="http://itknowledgeexchange.techtarget.com/dba/tag/ad/feed/" rel="self" type="application/rss+xml" />
	<link>http://itknowledgeexchange.techtarget.com/dba</link>
	<description></description>
	<lastBuildDate>Wed, 06 Feb 2013 01:01:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>PS script to check SQL Server Groups</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ps-script-to-check-sql-server-groups/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ps-script-to-check-sql-server-groups/#comments</comments>
		<pubDate>Sat, 14 Jan 2012 08:00:04 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[Groups]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/ps-script-to-check-sql-server-groups/</guid>
		<description><![CDATA[This is the script that I threw together to check and see if a user is in multiple AD Groups that are logins to the SQL Server instance. This helped me resolve an issue and it may help you look for things like explicit deny or some other reason why a user does not have [...]]]></description>
				<content:encoded><![CDATA[<p>This is the script that I threw together to check and see if a user is in multiple AD Groups that are logins to the SQL Server instance. This helped me resolve an issue and it may help you look for things like explicit deny or some other reason why a user does not have the access they need or perhaps they have too much.</p>
<p>connect-sql &#8220;sql server name&#8221;<br />
$groups = $s.Logins | where {$_.LoginType -eq &#8220;windowsgroup&#8221;} | where {$_.Name -like &#8220;ssg\*&#8221;}<br />
##$groups | select name</p>
<p>foreach ($group in $groups)<br />
{<br />
$gname = $group.Name<br />
##$gname<br />
$ingroup = $null<br />
$ingroup=Get-QADGroupMember $gname | where {$_.samaccountname -eq &#8220;usersamname&#8221;}</p>
<p>if ($ingroup -ne $null)<br />
{<br />
$gname<br />
}<br />
}</p>
<p>Hope that will help</p>
<p>Look for the connect-sql function in tomorrows post</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ps-script-to-check-sql-server-groups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Create Random Password and update AD account</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/create-random-password-and-update-ad-account/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/create-random-password-and-update-ad-account/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 10:00:07 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/create-random-password-and-update-ad-account/</guid>
		<description><![CDATA[Not to long ago I was asked to write a script that would create a random password and change an AD account to use that new password. The requirements were that the password be 3 uppercase letters 2 numbers and 3 lowercase letters. Here is what I did. /* Style Definitions */ table.MsoNormalTable {mso-style-name:&#8221;Table Normal&#8221;; [...]]]></description>
				<content:encoded><![CDATA[<p>Not to long ago I was asked to write a script that would create a random password and change an AD account to use that new password. The requirements were that the password be 3 uppercase letters 2 numbers and 3 lowercase letters. Here is what I did.</p>
<p><!--[if gte mso 9]&gt;  Normal 0     false false false  EN-US X-NONE X-NONE              MicrosoftInternetExplorer4              &lt;![endif]--><!--[if gte mso 9]&gt;                                                                                                                                            &lt;![endif]--><!--[if gte mso 10]&gt;--><br />
 /* Style Definitions */<br />
 table.MsoNormalTable<br />
	{mso-style-name:&#8221;Table Normal&#8221;;<br />
	mso-tstyle-rowband-size:0;<br />
	mso-tstyle-colband-size:0;<br />
	mso-style-noshow:yes;<br />
	mso-style-priority:99;<br />
	mso-style-qformat:yes;<br />
	mso-style-parent:&#8221;";<br />
	mso-padding-alt:0in 5.4pt 0in 5.4pt;<br />
	mso-para-margin:0in;<br />
	mso-para-margin-bottom:.0001pt;<br />
	mso-pagination:widow-orphan;<br />
	font-size:11.0pt;<br />
	font-family:&#8221;Calibri&#8221;,&#8221;sans-serif&#8221;;<br />
	mso-ascii-font-family:Calibri;<br />
	mso-ascii-theme-font:minor-latin;<br />
	mso-fareast-font-family:&#8221;Times New Roman&#8221;;<br />
	mso-fareast-theme-font:minor-fareast;<br />
	mso-hansi-font-family:Calibri;<br />
	mso-hansi-theme-font:minor-latin;<br />
	mso-bidi-font-family:&#8221;Times New Roman&#8221;;<br />
	mso-bidi-theme-font:minor-bidi;}</p>
<p class="MsoNormal">#Clear out all variables from last run</p>
<p class="MsoNormal">$newpassword = $NULL</p>
<p class="MsoNormal">$loops = 1..3</p>
<p class="MsoNormal">## Set up Random Generator</p>
<p class="MsoNormal">$rand = New-Object System.Random</p>
<p class="MsoNormal">$i = 1</p>
<p class="MsoNormal">$n = 1</p>
<p class="MsoNormal">#set up loop to generate each section of $NewPassword</p>
<p class="MsoNormal">foreach($number in $loops)</p>
<p class="MsoNormal">{</p>
<p class="MsoNormal">if ($i -eq 1)</p>
<p class="MsoNormal">{</p>
<p class="MsoNormal">$part = $NULL</p>
<p class="MsoNormal">$m = 3</p>
<p class="MsoNormal">$s = 65</p>
<p class="MsoNormal">$e = 90</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal">if ($i -eq 2)</p>
<p class="MsoNormal">{</p>
<p class="MsoNormal">$part = $NULL</p>
<p class="MsoNormal">$m = 2</p>
<p class="MsoNormal">$s = 48</p>
<p class="MsoNormal">$e = 57</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal">if ($i -eq 3)</p>
<p class="MsoNormal">{</p>
<p class="MsoNormal">$part = $NULL</p>
<p class="MsoNormal">$m = 3</p>
<p class="MsoNormal">$s = 97</p>
<p class="MsoNormal">$e = 122</p>
<p class="MsoNormal">}</p>
<p class="MsoNormal">$n..$m | foreach { $part = $part + [char]$rand.next($s,$e) }</p>
<p class="MsoNormal">$newpassword = $newpassword + $part</p>
<p class="MsoNormal">
<p class="MsoNormal">$i = $i + 1</p>
<p class="MsoNormal"><!--[if gte mso 9]&gt;  Normal 0     false false false  EN-US X-NONE X-NONE              MicrosoftInternetExplorer4              &lt;![endif]--><!--[if gte mso 9]&gt;                                                                                                                                            &lt;![endif]--><!--[if gte mso 10]&gt;--><br />
 /* Style Definitions */<br />
 table.MsoNormalTable<br />
	{mso-style-name:&#8221;Table Normal&#8221;;<br />
	mso-tstyle-rowband-size:0;<br />
	mso-tstyle-colband-size:0;<br />
	mso-style-noshow:yes;<br />
	mso-style-priority:99;<br />
	mso-style-qformat:yes;<br />
	mso-style-parent:&#8221;";<br />
	mso-padding-alt:0in 5.4pt 0in 5.4pt;<br />
	mso-para-margin:0in;<br />
	mso-para-margin-bottom:.0001pt;<br />
	mso-pagination:widow-orphan;<br />
	font-size:11.0pt;<br />
	font-family:&#8221;Calibri&#8221;,&#8221;sans-serif&#8221;;<br />
	mso-ascii-font-family:Calibri;<br />
	mso-ascii-theme-font:minor-latin;<br />
	mso-fareast-font-family:&#8221;Times New Roman&#8221;;<br />
	mso-fareast-theme-font:minor-fareast;<br />
	mso-hansi-font-family:Calibri;<br />
	mso-hansi-theme-font:minor-latin;<br />
	mso-bidi-font-family:&#8221;Times New Roman&#8221;;<br />
	mso-bidi-theme-font:minor-bidi;}</p>
<p class="MsoNormal">Set-QADUser PNI-GUEST -UserPassword $newpassword</p>
<p class="MsoNormal">
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/create-random-password-and-update-ad-account/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell to get unique login count from SQL Server</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/powershell-to-get-unique-login-count-from-sql-server/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/powershell-to-get-unique-login-count-from-sql-server/#comments</comments>
		<pubDate>Wed, 26 May 2010 07:00:50 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[Administration]]></category>
		<category><![CDATA[DBA]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Reporting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/powershell-to-get-unique-login-count-from-sql-server/</guid>
		<description><![CDATA[Just like I needed to get a count of unique logins to an application on one of our Sybase instances I also needed to get these values for a few of our SQL Servers. Since SQL Server uses mixed mode authentication and we are using AD groups to aid in the security of the SQL [...]]]></description>
				<content:encoded><![CDATA[<p>Just like I needed to get a count of unique logins to an application on one of our Sybase instances I also needed to get these values for a few of our SQL Servers. Since SQL Server uses mixed mode authentication and we are using AD groups to aid in the security of the SQL Server, I could not just write a query against the instance to get a list of unique logins. I could have but it would have returned the groups and not the individuals that are members of the groups. So I wrote a PS Script to go out and connect to the SQL Server, get a list of logins and then parse the AD Groups to get me a listing of all the members of those groups. Then it takes that list and gets unique logins, since a user may be a member of more than one group, and then counted the number of users. First I made a connection to the SQL Server using SMO, then I find all the logins and filter them based on whether they are a user or a group. If it is a group then I query the domain to find the group members and output all those users as well as the local sql users to a file. Once I have looped thru all groups then I get the contents of the file and sort and get unique and then I select a count of the new object. That is it. If you have any questions or would like to see the code then just let me know.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/powershell-to-get-unique-login-count-from-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell: AD Groups</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/powershell-ad-groups/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/powershell-ad-groups/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 17:00:16 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[Groups]]></category>
		<category><![CDATA[Powershell]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/powershell-ad-groups/</guid>
		<description><![CDATA[Two weeks ago was part of implementing a large upgrade in one of our Sybase environments. In order for this upgrade to be succesful we had to do some work in some AD groups. We needed to find all the users that would need to be a member of the new group that we were [...]]]></description>
				<content:encoded><![CDATA[<p>Two weeks ago was part of implementing a large upgrade in one of our Sybase environments. In order for this upgrade to be succesful we had to do some work in some AD groups. We needed to find all the users that would need to be a member of the new group that we were creating and take them out of the old group. The old group still needed to be around though, for users that were not affected by the upgrade. I knew that I would we had one group, that all the affected users were already a member of, so I could copy that groups members into the new group. However, if I did not also take these users out of the old group, then nothing would work. So here is what I did.</p>
<pre><code>
</code>
<div style="font-size: 10px;width: 700px;color: #000000;font-family: arial black;height: 150px;text-align: left;padding: 4px">

$users = Get-QADGroupMember "GroupA"

foreach ($user in $users){

$user | Remove-QADGroupMember "GroupB"

$user | Add-QADGroupMember "GroupC"</div></pre>
<p>Keep in mind that you will need the <a title="AD cmdlets" href="http://www.quest.com/powershell/activeroles-server.aspx">Quest AD cmdlets </a>installed in order for this to work.</p>
<p> </p>
<p>Let me know if you have any questions.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/powershell-ad-groups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AD Audit all together</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ad-audit-all-together/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ad-audit-all-together/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 10:00:24 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[AD Administration]]></category>
		<category><![CDATA[AD Managment]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/ad-audit-all-together/</guid>
		<description><![CDATA[Here is the full script so you can copy and paste it. Remember that you will need to make some modifications to the script to fit your environment. Let me know if you have any questions at all. Thanks ########################################################################### ## Script Name: 90-180.ps1 ## Written by: Colin Smith ## Date: 9/15/09 ########################################################################### ## ChangeLog [...]]]></description>
				<content:encoded><![CDATA[<p>Here is the full script so you can copy and paste it. Remember that you will need to make some modifications to the script to fit your environment. Let me know if you have any questions at all.</p>
<p>Thanks</p>
<pre><code>
</code>

###########################################################################
## Script Name: 90-180.ps1
## Written by: Colin Smith
## Date: 9/15/09
###########################################################################
## ChangeLog
###########################################################################
###########################################################################
## This Script will enumerate all accounts in the your domain
## and disable all accounts that have not been logged in with in 
## over 90 days, unless the account is one of the Protected OU's.
## This script will also delete all accounts that are disabled
## and have not been loged in with in over 180 Days.
## This script will not search accounts that reside in defined 
## exception containers. This will also find the users H: Drive 
## folder and move it to \\someserver\_term to await deletion.
## This script will also remove all group memberships from accounts
## before deletion of the account. This will avoid Hashes in Groups
## this replaces the 90-180 Visual Basic Script.
###########################################################################
###########################################################################
## Requirments for this script are Powershell V1 installed as well as
## Quest Active Directory Management Snapin
###########################################################################



#######################################################
## This Function Gets a listing of all user account
## and last logon times and created dates for 
## all users on the your domain that are not in
## Excluded OU's
#######################################################
function get_users
{
	foreach($company in $companies)
		{
#Echo "Company is $company"
			Clear-Content "c:\90-180\$company.csv"
			Clear-Content "c:\90-180\$company.disabled.txt"
			echo "enabled, LogonName, firstname, lastname, dn, lastlogon, createddate" &gt;&gt; "c:\90-180\$company.csv"

			$dcs = Get-QADComputer -ComputerRole DomainController
	
			$users = Get-QADUser -SizeLimit 0 -searchroot "Some.root.com/$company/Users" | where{(($_.dn -notlike "*disabled*") -and ($_.dn -notlike "*Generic*") -and ($_.dn -notlike "*Vendors*") -and ($_.dn -notlike "*mail-in*") -and ($_.dn -notlike "*shared calendars*"))}

	
			foreach($user in $users)
				{
					$lastlogon = $null
					foreach($dc in $dcs)
					{
						$dclogon = Get-QADUser -Service $dc.Name -SamAccountName $user.samaccountname | select lastlogon
						$dclogon = $dclogon.lastlogon.value

						if ($dclogon -ne $null)
							{
								if($lastlogon -lt $dclogon)
									{
										$lastlogon = $dclogon
									}
							}
					}
					if ($lastlogon -eq $Null) 
						{ 
							$lastlogon = [datetime]::Now.AddDays(-500000)
						}

					$o = New-Object PSObject
					$o | Add-Member NoteProperty "User" $user.Name
					$o | Add-Member NoteProperty "LastLogin" $lastlogon
					$o | Add-Member NoteProperty "DisplayName" $user.DisplayName
					$o | Add-Member NoteProperty "Disabled" $user.accountisdisabled 
					$o | Add-Member NoteProperty "DistinguishedName" $user.DN
					$o | Add-Member NoteProperty "Created" $user.CreationDate
					$o | Add-Member NoteProperty "SamAccountName" $user.SamAccountName
					$o | Add-Member NoteProperty "LastName" $user.LastName
					$o | Add-Member NoteProperty "FirstName" $user.FirstName

		
					if($o.disabled -eq "False")
						{			$enabled = "DISABLED"}
					else
						{			$enabled = "ENABLED"}
					$Fname = $o.FirstName
					$lname = $o.LastName
					$lastlogon = $o.LastLogin
					$created = $o.Created
					$samname = $o.samaccountname
					$dn = $o.DistinguishedName
					$dn = $dn.replace(",", ":")
			
					echo "$enabled, $samname, $fname, $lname, $DN, $lastlogon, $created" &gt;&gt; "c:\90-180\$company.csv"
			
				}
	

		}
}


##########################################################
## Function Disable_Accounts
## Find all accounts that need to be disabled
## Disable the account
## Move the account to the appropriate disabled OU
## Log the account that has been disabled and moved
##########################################################
function Disable_Accounts
{
	foreach($company in $companies)
		{
			$listedusers = Import-Csv "c:\90-180\$company.csv"
			foreach($listeduser in $listedusers)
			{
				$fname = $listeduser.Firstname
				$lname = $listeduser.LastName
				$dn = $listeduser.dn
				$dn = $dn.replace(":", ",")
				$enabled = $listeduser.enabled
				$logon = $listeduser.lastlogon
				$logonname = $listeduser.logonname
				$created = $listeduser.createddate
			
##########################################################
## Check for accounts in Holding OU that are still 
## disabled and beyond the 30 holding limit and
## move them to the disabled OU
##########################################################
				if(($enabled -eq "DISABLED") -and ($created -lt $holdingdate) -and ($dn -like "*holding*"))
					{
						$logonname | Move-QADObject -NewParentContainer "pni.us.ad.gannett.com/$company/Users/Disabled" -WhatIf
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.disabled.txt"
					}
					
##########################################################
## Find any accounts that are disabled and not in the 
## Holding OU and move them to the disabled OU
## This cleans up any accounts that have been disabled
## by hand and not moved to the disabled OU.
##########################################################
				if(($enabled -eq "DISABLED")-and ($dn -notlike "*holding*"))
					{
						$logonname | Move-QADObject -NewParentContainer 'some.root.com/$company/Users/Disabled' -WhatIf
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.disabled.txt"
					}
			
##########################################################
## Check for accounts not in holding OU that are beyond 
## the 90 day limit for login and create date
## and disable them and move them to the disabled OU.
##########################################################			
				if(($enabled -eq "ENABLED") -and ($logon -lt $disabledate) -and ($created -lt $disabledate) -and ($dn -notlike "*Holding*"))
					{
						$logonname | Disable-QADUser -WhatIf
						$logonname | Move-QADObject -NewParentContainer "some.root.com/$company/Users/Disabled" -WhatIf
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.disabled.txt"
					}
							
				
			}
		}
}

##########################################################
## function Get_Disabled_Accounts
## Search only the disabled OU for all disabled accounts
## Get the Last Login time and the Created Date so we 
## can determine if the account should be removed from 
## the domain.
##########################################################
function Get_Disabled_Accounts
{

foreach($company in $companies)
{
Clear-Content "c:\90-180\$company.disabledou.csv"
echo "enabled, LogonName, firstname, lastname, dn, lastlogon, createddate" &gt;&gt; "c:\90-180\$company.disabledou.csv"

			$dcs = Get-QADComputer -ComputerRole DomainController
	
			$users = Get-QADUser -SizeLimit 0 -searchroot "some.root.com/$company/Users/Disabled"

			foreach($user in $users)
				{
					$lastlogon = $null
					foreach($dc in $dcs)
					{
						$dclogon = Get-QADUser -Service $dc.Name -SamAccountName $user.samaccountname | select lastlogon
						$dclogon = $dclogon.lastlogon.value

						if ($dclogon -ne $null)
							{
								if($lastlogon -lt $dclogon)
									{
										$lastlogon = $dclogon
									}
							}
					}
					if ($lastlogon -eq $Null) 
						{ 
							$lastlogon = [datetime]::Now.AddDays(-500000)
						}

					$o = New-Object PSObject
					$o | Add-Member NoteProperty "User" $user.Name
					$o | Add-Member NoteProperty "LastLogin" $lastlogon
					$o | Add-Member NoteProperty "DisplayName" $user.DisplayName
					$o | Add-Member NoteProperty "Disabled" $user.accountisdisabled 
					$o | Add-Member NoteProperty "DistinguishedName" $user.DN
					$o | Add-Member NoteProperty "Created" $user.CreationDate
					$o | Add-Member NoteProperty "SamAccountName" $user.SamAccountName
					$o | Add-Member NoteProperty "LastName" $user.LastName
					$o | Add-Member NoteProperty "FirstName" $user.FirstName
					$o | Add-Member NoteProperty "Groups" $user.MemberOf

		
					if($o.disabled -eq "False")
						{			$enabled = "DISABLED"}
					else
						{			$enabled = "ENABLED"}
					$Fname = $o.FirstName
					$lname = $o.LastName
					$lastlogon = $o.LastLogin
					$created = $o.Created
					$samname = $o.samaccountname
					$dn = $o.DistinguishedName
					$dn = $dn.replace(",", ":")
					$groups = $o.groups
			
					echo "$enabled, $samname, $fname, $lname, $DN, $lastlogon, $created" &gt;&gt; "c:\90-180\$company.disabledou.csv"
					if($groups -ne $null)
						{
							if(($lastlogon -lt $deletedate) -and ($created -lt $deletedate))
								{
									echo $groups &gt;&gt; "c:\90-180\$samname.groups.txt"
								}
						}
			
				}
	

		}
}
##########################################################
## Function Delete_Accounts
## Find all acounts that are in the disabled OU's and
## determine what accounts have not been loged in with
## in over 180 days and also were created over 180 days
## ago. Once the accounts have been identified capture 
## Users login name so that we can remove all groups 
## from that user as well as move the users H: Drive 
## folder to the K drive to await deletion.
##########################################################
function Delete_Accounts
{
	foreach($company in $companies)
		{
		Echo "Delete accounts for $company"
			$listedusers = Import-Csv "c:\90-180\$company.disabledou.csv"
			Clear-Content "c:\90-18\$company.deleted.txt"
			foreach($listeduser in $listedusers)
			{
				$fname = $listeduser.Firstname
				$lname = $listeduser.LastName
				$dn = $listeduser.dn
				$dn = $dn.replace(":", ",")
				$enabled = $listeduser.enabled
				$logon = $listeduser.lastlogon
				$logonname = $listeduser.logonname
				$created = $listeduser.createddate
			
			
##########################################################
## Check for accounts that have not been used and were
## created more than 180 days ago. If found then remove
## all groups, remove from domain, log removal from 
## domain and move H: Drive to holding area.
##########################################################
				if(($created -lt $deletedate) -and ($logon -lt $deletedate))
					{
##########################################################
## Gather all groups that the user is a member of
## and loop thru all groups to remove the user.
##########################################################									
						if(Test-Path "c:\90-180\$logonname.groups.txt")
						{
							$groups = Get-Content "c:\90-180\$logonname.groups.txt"
							foreach($group in $groups)
							{	
								Remove-QADGroupMember -Identity $group -Member $logonname -whatif	
							}
							#rm "c:\90-180\$logonname.groups.txt"
						}
						
##########################################################
## Remove the User Object and log the removal
##########################################################
						Remove-QADObject $logonname -whatif
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.deleted.txt"

##########################################################
## Check to see if the user has an H: Drive
## If the folder exists then move it to the K: Drive
## to hold until the time limit to delete the folder
##########################################################
						if(Test-Path "\\someserver\yourhomedrives\$logonname")
						{
							move-item -literalPath "\\someserver\yourhomedrives\$logonname" -destination "\\someserver\_term\$logonname" -whatIf
							Echo "Moved \\someserver\yourhomedrives\$logonname to \\pni-pcfs01\data\common\_term\$logonname" &gt;&gt; "c:\90-180\homedirs.txt"
						}
						else
						{
							Echo "NO H Drive found for $logonname" &gt;&gt; "c:\90-180\homedirs.txt"
						}
					}

				}
			}
}
##########################################################
## Email all Log files about disabled and deleted 
## accounts to someaccount@domain.com
##########################################################
function Mail
{
$file1 = "c:\90-180\file1.Disabled.txt"
$file2 = "c:\90-180\file2.Disabled.txt"
$file3 = "c:\90-180\file3.Disabled.txt"
$file4 = "c:\90-180\file1.Deleted.txt"
$file5 = "c:\90-180\file2.Deleted.txt"
$file6 = "c:\90-180\file3.Deleted.txt"

$smtpServer = "somemailhost"
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$msg = New-Object Net.Mail.MailMessage

##########################################################
## Test for Attachment files. If the file is not 
## available then do not create the attachment object
##########################################################
if(Test-Path $file1)
{$att1 = New-Object Net.Mail.Attachment($file1)}
if(Test-Path $file2)
{$att2 = New-Object Net.Mail.Attachment($file2)}
if(Test-Path $file3)
{$att3 = New-Object Net.Mail.Attachment($file3)}
if(Test-Path $file4)
{$att4 = New-Object Net.Mail.Attachment($file4)}
if(Test-Path $file5)
{$att5 = New-Object Net.Mail.Attachment($file5)}
if(Test-Path $file6)
{$att6 = New-Object Net.Mail.Attachment($file6)}


$msg.From = "90-180Audit@pni.com"
$msg.To.Add("somemail@domain.com")
$msg.Subject = "Disabled and Deleted Domain Accounts"
$msg.Body = "Attached are files with names of disabled and deleted accounts."

##########################################################
## Test if the file is available again. If so then
## create the attachment.
##########################################################
if(Test-Path $file1)
{$msg.Attachments.Add($att1)}
if(Test-Path $file2)
{$msg.Attachments.Add($att2)}
if(Test-Path $file3)
{$msg.Attachments.Add($att3)}
if(Test-Path $file4)
{$msg.Attachments.Add($att4)}
if(Test-Path $file5)
{$msg.Attachments.Add($att5)}
if(Test-Path $file6)
{$msg.Attachments.Add($att6)}

$smtp.Send($msg)
$att1.Dispose()
$att2.Dispose()
$att3.Dispose()
$att4.Dispose()
$att5.Dispose()
$att6.Dispose()
}

##########################################################
## Main
## Set up variables and call functions of script.
##########################################################
$ErrorActionPreference = "SilentlyContinue"
$starttime = [datetime]::Now
echo "Start 90-180 Script run at $starttime" &gt;&gt; "c:\90-180\90-180.log"
$holdingdays = -30
$disabledays = -90
$deletedays = -180
$disabledate = [datetime]::Now.AddDays($disabledays)
$deletedate = [datetime]::Now.AddDays($deletedays)
$holdingdate = [datetime]::Now.AddDays($holdingdays)
$companies = "PNI", "AMG", "GPP"
clear-content "c:\90-180\homedirs.txt"
#echo "calling Get_Users"
Get_Users
#echo "calling Disable_Acconts"
Disable_Accounts
#Echo "Calling Get Disabled Accounts"
Get_Disabled_Accounts
#Echo "Calling Delete_Accounts"
Delete_Accounts
#Echo "Calling Mail"
Mail
$endtime = [datetime]::Now
echo "End 90-180 Script run at $endtime" &gt;&gt; "c:\90-180\90-180.log"
echo "#################################`n" &gt;&gt; "c:\90-180\90-180.log"
</div></pre>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ad-audit-all-together/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AD Audit Script Q and A</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ad-audit-script-q-and-a/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ad-audit-script-q-and-a/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 18:48:03 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[AD Administration]]></category>
		<category><![CDATA[AD Managment]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Q and A]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/ad-audit-script-q-and-a/</guid>
		<description><![CDATA[I got the following comment on Part 3 of the script. RobDolfijn Hi Colin, This is just what I need so I’m looking forward to the whole script! I’m getting stuc on Get_Users because it is not recognized as a cmdlet, please help me? So I am not sure how you have it set up [...]]]></description>
				<content:encoded><![CDATA[<p>
I got the following comment on <a href="http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-3/">Part 3</a> of the script.<br />
RobDolfijn</p>
<p>Hi Colin,</p>
<p>This is just what I need so I’m looking forward to the whole script!<br />
I’m getting stuc on Get_Users because it is not recognized as a cmdlet, please help me?</p>
<p>So I am not sure how you have it set up but I think I have an idea of what is going on. One of two things.</p>
<p>1. You have the function below the main part of the script that calls the function. The function has to be before the main part of the script so that Powershell knows about the function.</p>
<p>2. The other thing is that you do not have the function defined in the {} brackets.</p>
<p>My assumption here is that the first thing is the issue. The Powershell &#8216;Engine&#8217; looks for the function definitions before the function is called. It seems strange but that is how it works in many languages. So just make sure that you put all the functions above the function call and you should be good. Hope that this helps. Please let me know if you have any issues.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ad-audit-script-q-and-a/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AD Audit in Powershell Script Part 6</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-6/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-6/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 16:45:23 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[AD Administration]]></category>
		<category><![CDATA[AD Managment]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-6/</guid>
		<description><![CDATA[As i recall, in Part 5 we had gathered all the account information, parsed that, disabled accounts that needed to be disabled, gathered information on all the disabled accounts, and removed the accounts from the domain that needed to be as well as documented that we did so. Now that leaves me with needing to [...]]]></description>
				<content:encoded><![CDATA[<p>As i recall, in <a href="http://itknowledgeexchange.techtarget.com/dba/">Part 5</a> we had gathered all the account information, parsed that, disabled accounts that needed to be disabled, gathered information on all the disabled accounts, and removed the accounts from the domain that needed to be as well as documented that we did so. Now that leaves me with needing to accomplish one more thing. My business would like to have certain people notified about the account changes that have taken place. This is where the Mail function comes into play. Below is the code that I execute to send email when needed.</p>
<pre><code>
</code>
<div style="padding: 4px;width: 700px;height: 150px;color: #000000;font-family: arial black;font-size: 10px;text-align: left">
function Mail
{
$file1 = "c:\90-180\file1.Disabled.txt"
$file2 = "c:\90-180\file2.Disabled.txt"
$file3 = "c:\90-180\file3.Disabled.txt"
$file4 = "c:\90-180\file1.Deleted.txt"
$file5 = "c:\90-180\file2.Deleted.txt"
$file6 = "c:\90-180\file3.Deleted.txt"

$smtpServer = "mailhost"
$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$msg = New-Object Net.Mail.MailMessage

##########################################################
## Test for Attachment files. If the file is not 
## available then do not create the attachment object
##########################################################
if(Test-Path $file1)
{$att1 = New-Object Net.Mail.Attachment($file1)}
if(Test-Path $file2)
{$att2 = New-Object Net.Mail.Attachment($file2)}
if(Test-Path $file3)
{$att3 = New-Object Net.Mail.Attachment($file3)}
if(Test-Path $file4)
{$att4 = New-Object Net.Mail.Attachment($file4)}
if(Test-Path $file5)
{$att5 = New-Object Net.Mail.Attachment($file5)}
if(Test-Path $file6)
{$att6 = New-Object Net.Mail.Attachment($file6)}


$msg.From = "90-180Audit@pni.com"
$msg.To.Add("somemail@host.com")
$msg.Subject = "Disabled and Deleted Domain Accounts"
$msg.Body = "Attached are files with names of disabled and deleted accounts."

##########################################################
## Test if the file is available again. If so then
## create the attachment.
##########################################################
if(Test-Path $file1)
{$msg.Attachments.Add($att1)}
if(Test-Path $file2)
{$msg.Attachments.Add($att2)}
if(Test-Path $file3)
{$msg.Attachments.Add($att3)}
if(Test-Path $file4)
{$msg.Attachments.Add($att4)}
if(Test-Path $file5)
{$msg.Attachments.Add($att5)}
if(Test-Path $file6)
{$msg.Attachments.Add($att6)}

$smtp.Send($msg)
$att1.Dispose()
$att2.Dispose()
$att3.Dispose()
$att4.Dispose()
$att5.Dispose()
$att6.Dispose()
}

</div></pre>
<p>first I define all 6 of the files that I may or may not want to attach to the email. Then I set up the SMTPserver and the mail objects. Now I test for each of the files that I may or may not want to attach. I only want to attach the file if the file exists. This way I do not get errors about files not being on the filesystem and I am not sending blank files to the people that need the information.<br />
I then define who the message is from, who it is to, subject, and the body. Now that we have that I have to start attaching the files. After attaching the files that are needed I send the message and then close all the attachments just to make sure that no handles keep the files open. I want to be able to delete the files later. </p>
<p>Well that is it. Next post will have the script in its entirety so that you do not have to cut and paste so much. Hope all this helps you out. Let me know if you have any questions about any part of this script.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AD Audit in Powershell Script Part 5</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-5/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-5/#comments</comments>
		<pubDate>Sun, 27 Sep 2009 09:00:24 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[AD Administration]]></category>
		<category><![CDATA[AD Managment]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-5/</guid>
		<description><![CDATA[Now that we have disabled and moved all the disabled accounts to the Disabled OU I am going to get all the user object information from just the disabled OU this time. I need this since objects have been moved around. This scan of AD does go much faster as I am only scanning the [...]]]></description>
				<content:encoded><![CDATA[<p>Now that we have disabled and moved all the disabled accounts to the Disabled OU I am going to get all the user object information from just the disabled OU this time. I need this since objects have been moved around. This scan of AD does go much faster as I am only scanning the one OU. I have this is the Delete_Users function. I chose not to have the gathering disabled users as a function but you certainly could break that out if you like.<br />
In this function I create a csv file for all the objects in the disabled OU and now I determine if they meet the criteria for delection. If they do then I have a few things that I want to do with them.<br />
First I want to get a list of all the groups that the user is a member of so I can remove them from the groups before deleting the user object. This will prevent us from getting hashes of UID&#8217;s in groups. I hate that&#8230;<br />
Then I remove the user object and make note that I did so, again so paperwork can be done for this action. Then I need to go check and see if they have a home directory. I go out and look and if they do I move it to another chunk of disk that managers have access to so they can look through the data in that folder for anything that they may need. Those folders are removed at regular intervals by another clean up script. </p>
<pre><code>
</code>
<div style="padding: 4px;width: 700px;height: 150px;color: #000000;font-family: arial black;font-size: 10px;text-align: left">
##########################################################
## Function Delete_Accounts
## Find all acounts that are in the disabled OU's and
## determine what accounts have not been loged in with
## in over 180 days and also were created over 180 days
## ago. Once the accounts have been identified capture 
## Users login name so that we can remove all groups 
## from that user as well as move the users Home Drive 
## folder to anothe location to await deletion.
##########################################################
function Delete_Accounts
{
	foreach($company in $companies)
		{
		Echo "Delete accounts for $company"
			$listedusers = Import-Csv "c:\90-180\$company.disabledou.csv"
			Clear-Content "c:\90-18\$company.deleted.txt"
			foreach($listeduser in $listedusers)
			{
				$fname = $listeduser.Firstname
				$lname = $listeduser.LastName
				$dn = $listeduser.dn
				$dn = $dn.replace(":", ",")
				$enabled = $listeduser.enabled
				$logon = $listeduser.lastlogon
				$logonname = $listeduser.logonname
				$created = $listeduser.createddate
			
			
##########################################################
## Check for accounts that have not been used and were
## created more than 180 days ago. If found then remove
## all groups, remove from domain, log removal from 
## domain and move H: Drive to holding area.
##########################################################
				if(($created -lt $deletedate) -and ($logon -lt $deletedate))
					{
##########################################################
## Gather all groups that the user is a member of
## and loop thru all groups to remove the user.
##########################################################									
						if(Test-Path "c:\90-180\$logonname.groups.txt")
						{
							$groups = Get-Content "c:\90-180\$logonname.groups.txt"
							foreach($group in $groups)
							{	
								Remove-QADGroupMember -Identity $group -Member $logonname -whatif	
							}
							#rm "c:\90-180\$logonname.groups.txt"
						}
						
##########################################################
## Remove the User Object and log the removal
##########################################################
						Remove-QADObject $logonname -whatif
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.deleted.txt"

##########################################################
## Check to see if the user has an H: Drive
## If the folder exists then move it to the K: Drive
## to hold until the time limit to delete the folder
##########################################################
						if(Test-Path "\\servername\users$\$logonname")
						{
							move-item -literalPath "\\servername\users$\$logonname" -destination "\\servername\data\common\_term\$logonname" -whatIf
							Echo "Moved \\servername\users$\$logonname to \\servername\data\common\_term\$logonname" &gt;&gt; "c:\90-180\homedirs.txt"
						}
						else
						{
							Echo "NO H Drive found for $logonname" &gt;&gt; "c:\90-180\homedirs.txt"
						}
					}

				}
			}
}

</div></pre>
<p>Well that does it for taking action on the AD Objects. Now I just need to send out the notifications of the actions that the script took. That will be next time. Let me know if you have any questions about this function.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AD Audit in Powershell Script Part 4</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-4/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-4/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 16:57:23 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[AD Administration]]></category>
		<category><![CDATA[AD Managment]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/?p=264</guid>
		<description><![CDATA[Now that we have all of the users information into a csv file it is time to start sorting through all of that data and determining what objects need to be disabled and moved to the disabled OU that I have set up for all disabled accounts to go and await deletion. Lets do that [...]]]></description>
				<content:encoded><![CDATA[<p>Now that we have all of the users information into a csv file it is time to start sorting through all of that data and determining what objects need to be disabled and moved to the disabled OU that I have set up for all disabled accounts to go and await deletion. Lets do that with the Disable_Accounts function. This is a pretty basic function but I have a do a few different things here. First we have a Holding OU and that is available for our new account provisioning system. It creates accounts and places them in this OU in a disabled state. I am going to look in this OU to see if the account has been there for 30 days or more and if so I will move the user object. I am also going to go scan for any accounts that are disabled but not in the Disabled or Holding OU&#8217;s and then move them. This keeps things clean just in case a person disables an account and does not move it. Lastly I will disable and move all accounts that meet my criteria. I am also logging the accounts that I disable so that paperwork can also be done for these accounts.</p>
<pre><code>
</code>
<div style="padding: 4px;width: 700px;height: 150px;color: #000000;font-family: arial black;font-size: 10px;text-align: left">

##########################################################
## Function Disable_Accounts
## Find all accounts that need to be disabled
## Disable the account
## Move the account to the appropriate disabled OU
## Log the account that has been disabled and moved
##########################################################
function Disable_Accounts
{
	foreach($company in $companies)
		{
			$listedusers = Import-Csv "c:\90-180\$company.csv"
			foreach($listeduser in $listedusers)
			{
				$fname = $listeduser.Firstname
				$lname = $listeduser.LastName
				$dn = $listeduser.dn
				$dn = $dn.replace(":", ",")
				$enabled = $listeduser.enabled
				$logon = $listeduser.lastlogon
				$logonname = $listeduser.logonname
				$created = $listeduser.createddate
			
##########################################################
## Check for accounts in Holding OU that are still 
## disabled and beyond the 30 holding limit and
## move them to the disabled OU
##########################################################
				if(($enabled -eq "DISABLED") -and ($created -lt $holdingdate) -and ($dn -like "*holding*"))
					{
						$logonname | Move-QADObject -NewParentContainer "pni.us.ad.gannett.com/$company/Users/Disabled" -WhatIf
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.disabled.txt"
					}
					
##########################################################
## Find any accounts that are disabled and not in the 
## Holding OU and move them to the disabled OU
## This cleans up any accounts that have been disabled
## by hand and not moved to the disabled OU.
##########################################################
				if(($enabled -eq "DISABLED")-and ($dn -notlike "*holding*"))
					{
						$logonname | Move-QADObject -NewParentContainer 'pni.us.ad.gannett.com/$company/Users/Disabled' -WhatIf
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.disabled.txt"
					}
			
##########################################################
## Check for accounts not in holding OU that are beyond 
## the 90 day limit for login and create date
## and disable them and move them to the disabled OU.
##########################################################			
				if(($enabled -eq "ENABLED") -and ($logon -lt $disabledate) -and ($created -lt $disabledate) -and ($dn -notlike "*Holding*"))
					{
						$logonname | Disable-QADUser -WhatIf
						$logonname | Move-QADObject -NewParentContainer "pni.us.ad.gannett.com/$company/Users/Disabled" -WhatIf
						echo "$fname $lname $logonname" &gt;&gt; "c:\90-180\$company.disabled.txt"
					}
							
				
			}
		}
}

</div></pre>
<p>Nothing to complex here. Let me know if you have any questions about this function.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AD Audit in Powershell Script Part 3</title>
		<link>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-3/</link>
		<comments>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-3/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 20:30:16 +0000</pubDate>
		<dc:creator>Colin Smith</dc:creator>
				<category><![CDATA[AD]]></category>
		<category><![CDATA[AD Administration]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://itknowledgeexchange.techtarget.com/dba/?p=260</guid>
		<description><![CDATA[Now that we have the main part of the script setup it is time to look at the first function that we call. This is the Get_users function. Now this function gets a listing of all the DC&#8217;s and does a get-qaduser on all of them looking at the lastlogon property to determine what DC [...]]]></description>
				<content:encoded><![CDATA[<p>Now that we have the main part of the script setup it is time to look at the first function that we call. This is the Get_users function. Now this function gets a listing of all the DC&#8217;s and does a get-qaduser on all of them looking at the lastlogon property to determine what DC has the latest information on that user object. It will then use that DC to write that users information out the the file for me.</p>
<pre><code>
</code>
<div style="padding: 4px;width: 700px;height: 150px;color: #000000;font-family: arial black;font-size: 10px;text-align: left">

function get_users
{
	foreach($company in $companies)
		{
#Echo "Company is $company"
			Clear-Content "c:\90-180\$company.csv"
			Clear-Content "c:\90-180\$company.disabled.txt"
			echo "enabled, LogonName, firstname, lastname, dn, lastlogon, createddate" &gt;&gt; "c:\90-180\$company.csv"

			$dcs = Get-QADComputer -ComputerRole DomainController

			$users = Get-QADUser -SizeLimit 0 -searchroot "somecomapny.com/$company/Users" | where{(($_.dn -notlike "*disabled*") -and ($_.dn -notlike "*Generic*") -and ($_.dn -notlike "*Vendors*") -and ($_.dn -notlike "*mail-in*") -and ($_.dn -notlike "*shared calendars*"))}

			foreach($user in $users)
				{
					$lastlogon = $null
					foreach($dc in $dcs)
					{
						$dclogon = Get-QADUser -Service $dc.Name -SamAccountName $user.samaccountname | select lastlogon
						$dclogon = $dclogon.lastlogon.value

						if ($dclogon -ne $null)
							{
								if($lastlogon -lt $dclogon)
									{
										$lastlogon = $dclogon
									}
							}
					}
					if ($lastlogon -eq $Null)
						{
							$lastlogon = [datetime]::Now.AddDays(-500000)
						}

					$o = New-Object PSObject
					$o | Add-Member NoteProperty "User" $user.Name
					$o | Add-Member NoteProperty "LastLogin" $lastlogon
					$o | Add-Member NoteProperty "DisplayName" $user.DisplayName
					$o | Add-Member NoteProperty "Disabled" $user.accountisdisabled
					$o | Add-Member NoteProperty "DistinguishedName" $user.DN
					$o | Add-Member NoteProperty "Created" $user.CreationDate
					$o | Add-Member NoteProperty "SamAccountName" $user.SamAccountName
					$o | Add-Member NoteProperty "LastName" $user.LastName
					$o | Add-Member NoteProperty "FirstName" $user.FirstName

					if($o.disabled -eq "False")
						{			$enabled = "DISABLED"}
					else
						{			$enabled = "ENABLED"}
					$Fname = $o.FirstName
					$lname = $o.LastName
					$lastlogon = $o.LastLogin
					$created = $o.Created
					$samname = $o.samaccountname
					$dn = $o.DistinguishedName
					$dn = $dn.replace(",", ":")

					echo "$enabled, $samname, $fname, $lname, $DN, $lastlogon, $created" &gt;&gt; "c:\90-180\$company.csv"

				}

		}
}</div></pre>
<p>So lets break this down a bit and if you need more explanation just let me know.<br />
Like I said in Part 2 I have multiple companies that are designated by OU&#8217;s in the forest. That is why you see the foreach loop. I am breaking it down by company. You do not have to do this if you do not need to.<br />
Now I loop thru and get user info from all DC&#8217;s and determine what info to use. You will also notice that I have a<br />
if ($lastlogon -eq $null){$lastlogon = [datetime]::now.adddays(-50000)}<br />
That is so that when I compare to the lastlogon time if the user has never logged on I still get a date but it is a date that will always be less than my 90 or 180 day criteria.<br />
Then I create a new-psobject and define all the fields that I want each object to have. Then I write that out to a csv file. You will notice that I am doing a replace on the DN field. That is because I want to use a csv file and if that field has items separated by commas it will mess things up when I import-csv that file later.</p>
<p>Well that is it for now. Until next time&#8230;.</p>
<!-- wpms-network-global-inserts -->]]></content:encoded>
			<wfw:commentRss>http://itknowledgeexchange.techtarget.com/dba/ad-audit-in-powershell-script-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
