Powershell Script to Disable Inactive Computers

Similar to the Disable User accounts script this one disabled Computers. I considered combining the two into a single script but opted not to do so.

Purpose:
Disable Computer Objects that have been inactive for 90 days.
Not to disable newly created Computer accounts unless they are not used in 30 days.

Notes:
Must be run with an Account that has rights to disable and move User Accounts
Must have QAD Powershell cmdlets installed.

Example Email:
disableinactivecomputerexample

#=====================================================================================================#
#    Copyright 2011 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#=====================================================================================================#
# Author: David Beasley
# Updated: Robert Stacks
# Original Script URL: http://vnucleus.com/2011/07/use-powershell-to-auto-disable-inactive-active-directory-accounts/
# Updated Script URL: https://randomtechminutia.wordpress.com/2014/07/09/powershell-script-to-disable-inactive-users-v3/
# Date: 7/26/2011
# Updated: 7/9/2014
# Verson: 1.0
#
# Purpose:
# Disable Inactive Active Directory Computer Accounts
#
# Update Notes:
# 7/9/2014 - Robert Stacks 
# - Added remote domain functionality
# - Added user option to enable/disable moving of disabled accounts
# - Updated the Report with a CSS Style Sheet and overall improved formatting
# - Added Creation Date column
# - Added DN Column which shows DN prior to move to disabled OU so if someone needs to re-enable an account they can move it back to the correct OU
# 7/11/2014 - Robert
# - This version of the script looks for Computers not Users
# - Added Footer to show if Objects were moved to a disabled OU or not if so it shows what OU.
#=====================================================================================================#
 

#===========================#
#User Adjustable Variables  #
#===========================#

#Account with rights to remotely log into domain
 $AdminAcct = 'domain.local\AdminAcct'
 $Adminpwd = 'password'
 
#Domain to Log into
$domain = 'domain.local'

#Company Name 
$CompanyName = 'Company Name'

# Query Options #
$searchRoot = "domain.local/" # Where to begin your recursive search - If you use top-level (e.g. "domain.local/") make sure to have a trailing slash, otherwise do not use a slash (e.g. "domain.local/Users")
$inactiveDays = 90 # Integer for number of days of inactivity (e.q. 90)
$timeSinceCreation = 30 # Integer for number of "grace" days since the account was created (to prevent disabling of brand new accounts)
$sizeLimit = 0 # How many users do you want returned. 0 = unlimited. Without setting this the default is 1000

# Action Options #
$MovedisabledAccount = 0 # 0 = disabled or 1=enabled Defines if the script will move a disabled account
$disabledOU = "OU=Disabled Computers,DC=domain,DC=com" # Define where disabled accounts are stored (e.g. "domain.local/Users/Disabled")

# Email Settings #
$emailAlerts = 1 # Turn e-mail alerts on or off. 0 = off 1 = On
$fromAddr = "ADInactiveAccounts@domain.com" # Enter the FROM address for the e-mail alert
$toAddr = "ToAddress@domain.com" # Enter the TO address for the e-mail alert
$smtpsrv = "mail.domain.com" # Enter the FQDN or IP of a SMTP relay

# Enable Script #
$enableAction = 0 # Change to 0 if you want to "whatif" this script - It will bypass the actual account disabling (turn e-mail alerts on!)

#===========================#
#Main Script                #
#===========================#

$date = Get-Date -Format d

# Format html report with CSS
$htmlReport = @"
<style type='text/css'>
.heading {
 	color:white;
	font-size:14.0pt;
	font-weight:700;
	font-family:Verdana, sans-serif;
	text-align:left;
	vertical-align:middle;
	height:20.0pt;
	width:416pt;
	background:#1975D1

}
.footer {
 	color:white;
	font-size:10.0pt;
	font-weight:700;
	font-family:Verdana, sans-serif;
	text-align:left;
	vertical-align:middle;
	height:20.0pt;
	width:416pt;
	background:#3385FF;

}
.colnames {
 	color:white;
	font-size:10.0pt;
	font-weight:700;
	font-family:Tahoma, sans-serif;
	text-align:center;
	vertical-align:middle;
	border:.5pt solid white;
	background:#3385FF;
}
.textcolor1 {
	color:windowtext;
	font-size:9.0pt;
	font-family:Arial;
	text-align:center;
	vertical-align:middle;
	border:1pt solid windowtext;
	background:#C1D0E6;
}
.textcolor2 {
	color:windowtext;
	font-size:9.0pt;
	font-family:Arial;
    text-align:center;
	vertical-align:middle;
	border:1pt solid windowtext;
	background:white;
}
</style>
<table border=0 cellpadding=4 cellspacing=1 width=auto 
 style='border-collapse:collapse;table-layout:auto;width:auto'>
 <tr style='height:15.0pt'>
  <th rowspan=3 colspan=5 height=40 width=auto class="heading">
	<center>$CompanyName</center>
	<center>Report: $($inactiveComputers.Count) Computer Accounts Disabled Due to Inactivity</center>
    <center>Date: <i> $Date </i> Domain: <i> $domain </i></center></th>
 </tr>
 <tr></tr>
 <tr></tr>
 <tr>
  <th class="colnames">Computer Name</th>
  <th class="colnames">Description</th>
  <th class="colnames">Creation Date</th>
  <th class="colnames">Last Login</th>
  <th class="colnames">DN</th>
 </tr>
"@

Add-PSSnapin "Quest.ActiveRoles.ADManagement"

#Set User account to be used to log into cross site domain without AD Trust
$username = $AdminAcct
$password = ConvertTo-SecureString $Adminpwd -AsPlainText -Force
$livecrd = New-Object System.Management.Automation.PSCredential $username, $password

#Connect to the specific domain
Connect-QADService -Service $domain -Credential $livecrd

#Cutoff Date
$creationCutoff = (Get-Date).AddDays(-$timeSinceCreation)

#Get list of inactive user accounts
$inactiveComputers = @(Get-QADComputer -SearchRoot $searchRoot -NotLoggedOnFor $inactiveDays -CreatedBefore $creationCutoff -SizeLimit $sizeLimit -LdapFilter '(!(userAccountControl:1.2.840.113556.1.4.803:=2))' | Select-Object Name,CreationDate,LastLogonTimeStamp,Description,DN,SamAccountName | Sort-Object Name)

# Counter for color in table
$i = 0

# Generate table
do {
if($i % 2)
{$htmlReport += "<tr class='textcolor1'><td>$($inactiveComputers[$i].Name)</td><td>$($inactiveComputers[$i].Description)</td><td>$($inactiveComputers[$i].CreationDate)</td><td>$($inactiveComputers[$i].LastLogonTimestamp)</td><td>$($inactiveComputers[$i].DN)</td></tr>";$i++}
else 
{$htmlReport += "<tr class='textcolor2'><td>$($inactiveComputers[$i].Name)</td><td>$($inactiveComputers[$i].Description)</td><td>$($inactiveComputers[$i].CreationDate)</td><td>$($inactiveComputers[$i].LastLogonTimestamp)</td><td>$($inactiveComputers[$i].DN)</td></tr>";$i++}
}
while ($inactiveComputers[$i] -ne $null)

# Finish create of Table
if($MovedisabledAccount -eq 1){
$htmlReport += @"
<th colspan=5 height=40 width=auto class="footer">
 <center>Note: Disabled Computer Objects moved to this OU: <i>$disabledOU</i></center></th>
</tr>
</table></center>
"@
}
else{
$htmlReport += @"
<th colspan=5 height=40 width=auto class="footer">
 <center>Note: Disabled Computer Objects where not moved during this operation.</center></th>
</tr>
</table></center>
"@
}

# Disable Accounts #
if ($enableAction -eq 1 -and $inactiveComputers -ne $null){
 foreach($computer in $inactiveComputers){
 Set-QADComputer $computer.SamAccountName -Description "Account Disabled on $date for Inactivity - $($user.Description)" | Disable-QADComputer
  #Move Disabled Accounts to Disabled OU
  if ($MovedisabledAccount -ne 0){
   Move-QADObject $computer.SamAccountName -NewParentContainer $disabledOU
   }
 }
}


### Email Alerts ###
if ($emailAlerts -eq 1 -and $inactiveComputers -ne $null){



Send-MailMessage -To $toAddr -From $fromAddr -Subject "AutoDisable Report for $($domain): $($inactiveComputers.Count) Computer Accounts Disabled on $date" -Body "$htmlReport" -SmtpServer $smtpsrv -BodyAsHtml
}

#Disconnect from AD Cleanly
Disconnect-QADService

exit
Advertisements

Leave a comment

Powershell Script to Disable Inactive Users v3

Purpose:
Disable users that have been inactive for 90 days.
Not to disable newly created accounts unless they are not used in 30 days.

Notes:

v1 can be found here: https://randomtechminutia.wordpress.com/2013/07/09/script-to-disable-inactive-users/
v2 can be found here: http://vnucleus.com/2011/07/use-powershell-to-auto-disable-inactive-active-directory-accounts/ (Link is now bad)
Must be run with an Account that has rights to disable and move User Accounts
Must have QAD Powershell cmdlets installed.

Example Email:

disableinactiveuserexample

Code:


#=====================================================================================================#
#    Copyright 2011 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#=====================================================================================================#
# Author: David Beasley
# Updated: Robert Stacks
# Original Script URL: http://vnucleus.com/2011/07/use-powershell-to-auto-disable-inactive-active-directory-accounts/
# Updated Script URL: https://randomtechminutia.wordpress.com/2014/07/09/powershell-script-to-disable-inactive-users-v3/
# Date: 7/26/2011
# Updated: 7/9/2014
# Verson: 0.6
#
# Purpose:
# Disable Inactive Active Directory Accounts
#
# Update Notes:
# 7/9/2014 - Robert Stacks
# - Added remote domain functionality
# - Added user option to enable/disable moving of disabled accounts
# - Updated the Report with a CSS Style Sheet and overall improved formatting
# - Added Creation Date column
# - Added DN Column which shows DN prior to move to disabled OU so if someone needs to re-enable an account they can move it back to the correct OU
#
#=====================================================================================================#

#===========================#
#User Adjustable Variables  #
#===========================#

#Account with rights to remotely log into domain
$AdminAcct = 'domain.local\AdminAcct'
$Adminpwd = 'password'

#Domain to Log into
$domain = 'domain.local'

#Company Name - Used for Report
$CompanyName = 'Company Name'

# Query Options #
$searchRoot = "domain.local/" # Where to begin your recursive search - If you use top-level (e.g. "domain.local/") make sure to have a trailing slash, otherwise do not use a slash (e.g. "domain.local/Users")
$inactiveDays = 90 # Integer for number of days of inactivity (e.q. 90)
$timeSinceCreation = 30 # Integer for number of "grace" days since the account was created (to prevent disabling of brand new accounts)
$sizeLimit = 0 # How many users do you want returned. 0 = unlimited. Without setting this the default is 1000

# Action Options #
$MovedisabledAccount = 0 # 0 = disabled or 1=enabled Defines if the script will move a disabled account
$disabledOU = "domain.local/Users/Disabled" # Define where disabled accounts are stored (e.g. "domain.local/Users/Disabled")

# Email Settings #
$emailAlerts = 1 # Turn e-mail alerts on or off. 0 = off 1 = On
$fromAddr = "ADInactiveAccounts@domain.COM" # Enter the FROM address for the e-mail alert
$toAddr = "sysadmins@domain.com" # Enter the TO address for the e-mail alert
$smtpsrv = "mail.domain.com" # Enter the FQDN or IP of a SMTP relay

# Enable Script #
$enableAction = 0 # Change to 0 if you want to "whatif" this script - It will bypass the actual account disabling (turn e-mail alerts on!)

#===========================#
#Main Script                #
#===========================#

$date = Get-Date -Format d

# Format html report with CSS
$htmlReport = @"
<style type='text/css'>
.heading {
color:white;
font-size:14.0pt;
font-weight:700;
font-family:Verdana, sans-serif;
text-align:left;
vertical-align:middle;
height:20.0pt;
width:416pt;
background:#1975D1

}
.colnames {
color:white;
font-size:10.0pt;
font-weight:700;
font-family:Tahoma, sans-serif;
text-align:center;
vertical-align:middle;
border:.5pt solid white;
background:#3385FF;
}
.textcolor1 {
color:windowtext;
font-size:9.0pt;
font-family:Arial;
text-align:center;
vertical-align:middle;
border:1pt solid windowtext;
background:#C1D0E6;
}
.textcolor2 {
color:windowtext;
font-size:9.0pt;
font-family:Arial;
text-align:center;
vertical-align:middle;
border:1pt solid windowtext;
background:white;
}
</style>
<table border=0 cellpadding=4 cellspacing=1 width=auto
style='border-collapse:collapse;table-layout:auto;width:auto'>
<tr style='height:15.0pt'>
<th rowspan=3 colspan=5 height=40 width=auto class="heading">
<center>$CompanyName</center>
<center>Report:$($inactiveUsers.Count) User Accounts Disabled Due to Inactivity</center>
<center>Date: <i> $date </i> Domain: <i> $domain </i></center>
</th>
</tr>
<tr></tr>
<tr>
<th class="colnames">Name</th>
<th class="colnames">Account</th>
<th class="colnames">Creation Date</th>
<th class="colnames">Last Login</th>
<th class="colnames">DN</th>
</tr>
"@

Add-PSSnapin "Quest.ActiveRoles.ADManagement"

#Set User account to be used to log into cross site domain without AD Trust
$username = $AdminAcct
$password = ConvertTo-SecureString $Adminpwd -AsPlainText -Force
$livecrd = New-Object System.Management.Automation.PSCredential $username, $password

#Connect to the specific domain
Connect-QADService -Service $domain -Credential $livecrd

#Cutoff Date
$creationCutoff = (Get-Date).AddDays(-$timeSinceCreation)

#Get list of inactive user accounts
$inactiveUsers = @(Get-QADUser -SearchRoot $searchRoot -Enabled -NotLoggedOnFor $inactiveDays -CreatedBefore $creationCutoff -SizeLimit $sizeLimit | Select-Object Name,SamAccountName,CreationDate,LastLogonTimeStamp,Description,DN | Sort-Object Name)

# Counter for color in table
$i = 0

# Generate table
do {
if($i % 2)
{$htmlReport += "<tr class='textcolor1'><td>$($inactiveUsers[$i].Name)</td><td>$($inactiveUsers[$i].SamAccountName)</td><td>$($inactiveUsers[$i].CreationDate)</td><td>$($inactiveUsers[$i].LastLogonTimestamp)</td><td>$($inactiveUsers[$i].DN)</td></tr>";$i++}
else
{$htmlReport += "<tr class='textcolor2'><td>$($inactiveUsers[$i].Name)</td><td>$($inactiveUsers[$i].SamAccountName)</td><td>$($inactiveUsers[$i].CreationDate)</td><td>$($inactiveUsers[$i].LastLogonTimestamp)</td><td>$($inactiveUsers[$i].DN)</td></tr>";$i++}
}
while ($inactiveUsers[$i] -ne $null)

# Finish create of Table
if($MovedisabledAccount -eq 1){
$htmlReport += @"
<th colspan=5 height=40 width=auto class="footer">
 <center>Note: Disabled Computer Objects moved to this OU: <i>$disabledOU</i></center></th>
</tr>
</table></center>
"@
}
else{
$htmlReport += @"
<th colspan=5 height=40 width=auto class="footer">
 <center>Note: Disabled Computer Objects where not moved during this operation.</center></th>
</tr>
</table></center>
"@
}

# Disable Accounts #
if ($enableAction -eq 1 -and $inactiveUsers -ne $null){
 foreach($user in $inactiveUsers){
 Set-QADUser $user.SamAccountName -Description "Account Disabled on $date for Inactivity - $($user.Description)" | Disable-QADUser
  #Move Disabled Accounts to Disabled OU
  if ($MovedisabledAccount -ne 0){
   Move-QADObject $user -NewParentContainer $disabledOU
   }
 }
}

### Email Alerts ###
if ($emailAlerts -eq 1 -and $inactiveUsers -ne $null){

Send-MailMessage -To $toAddr -From $fromAddr -Subject "AutoDisable Report for $($domain): $($inactiveUsers.Count) User Accounts Disabled on $date" -Body "$htmlReport" -SmtpServer $smtpsrv -BodyAsHtml
}

#Disconnect from AD Cleanly
Disconnect-QADService

exit

 

 

3 Comments

Step by Step – How to Update Cisco IOS/Firmware

I did this on a 3560 Switch, mileage may vary.

1: Save a Copy of the Running Config just in case.

This is just a safety net but always a good practice.

Switch#Show Running-Config

Copy the output to a text file some place.

2: Check the version of IOS in Flash

Log into the Switch and get into privilege mode by typing “enable”

Run the command “dir” or “show flash” to see what is stored in flash

Switch#dir
Directory of flash:/

500 -rwx 1048 Mar 1 1993 00:01:34 +00:00 multiple-fs
3 drwx 512 Mar 1 1993 00:10:14 +00:00 c3560e-universalk9-mz.122-55.SE5

57671680 bytes total (38020096 bytes free)

Then validate the version that is running is the same as it never hurts to check.

Run the command show version

Switch#show ver

.....................

Switch Ports Model              SW Version            SW Image
------ ----- -----              ----------            ----------
*    1 54    WS-C3560X-48P      12.2(55)SE5           C3560E-UNIVERSALK9-M

Configuration register is 0xF

3: Download the latest version from Cisco’s website

Website: http://software.cisco.com/download/navigator.html?mdfid=268438038&flowid=2622

The ISO must match the switch model and version of ISO.

Example:
We are running c3560e-universalk9-mz.122-55.SE5 as we can see from the version command or more specific 12.2 on a 3560e Switch in this case. The upgrade file is c3560e-universalk9-mz.152-1.E1 or version 15.2.

4: Place the IOS file some place it can be fetched by the switch

I installed Solarwinds free tftp server on a server at 192.168.200.100. You could use ssh or ftp if you want commands will be similar. You would have to do some other work and tftp is the simplest.

5: From the Cisco Switch Download ISO from TFTP Server

Make sure your TFTP Server is running. On the Cisco device run the following command from enable (exec) mode. Where c3560e-universalk9-mz.152-1.E1.bin is the upgrade image you downloaded from Cisco.

230Net-4#copy tftp flash
Address or name of remote host []? 192.168.200.100
Source filename []? c3560e-universalk9-mz.152-1.E1.bin
Destination filename [c3560e-universalk9-mz.152-1.E1.bin]?

After a series of ”!” the file should show up under flash, you can check with another “dir” or “show flash” command test. To see the file is now in Flash, but not used yet.

Switch#show flash
Directory of flash:/

....
    5  drwx         512   Mar 1 1993 00:10:33 +00:00  c3560e-universalk9-mz.122-55.SE3
  444  -rwx    23152768  Feb 10 2014 05:12:47 +00:00  c3560e-universalk9-mz.152-1.E1.bin

57671680 bytes total (15296000 bytes free)

6: Validate Image

Do this just to make sure the file is what it should be.
Note: I discovered on the cisco site I link below they did not include the /md5 part of the command but I couldn’t get it to work without it.

230Net-4#verify /md5 flash:c3560e-universalk9-mz.152-1.E1.bin
......................................Done!
verify /md5 (flash:c3560e-universalk9-mz.152-1.E1.bin) = 8d8332134837780940f2672db566697d

7: Verify The Configuration Register

Use the show version command to check the value. The last line item will show the Register you are booting from.

Switches should be 0xF
Routers should be 0x2102

230Net-4#show version
Cisco IOS Software, C3560E Software (C3560E-UNIVERSALK9-M), Version 15.2(1)E1, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2013 by Cisco Systems, Inc.
Compiled Fri 22-Nov-13 10:28 by prod_rel_team
.....

CLEI Code Number                : COMJP00ARB
Hardware Board Revision Number  : 0x03


Switch Ports Model              SW Version            SW Image
------ ----- -----              ----------            ----------
*    1 54    WS-C3560X-48P      15.2(1)E1             C3560E-UNIVERSALK9-M


Configuration register is 0xF

8: Set the next boot to be the new Image

Configure the system to boot from the new image after the next reboot.

Show current boot image
The second line shows the Image we are booting from in this case the old one.

230Net-4#show boot
BOOT path-list      : flash:c3560e-universalk9-mz.122-55.SE3
Config file         : flash:/config.text
Private Config file : flash:/private-config.text
Enable Break        : no
Manual Boot         : no
Allow Dev Key         : yes
HELPER path-list    :
Auto upgrade        : yes
Auto upgrade path   :
NVRAM/Config file
      buffer size:   524288
Timeout for Config
          Download:    0 seconds
Config Download
       via DHCP:       disabled (next boot: disabled)

Change the boot image to the new one.
Run the following command from config mode.

230Net-4(config)#boot system flash:c3560e-universalk9-mz.152-1.E1.bin

Validate Change

230Net-4#show boot
BOOT path-list      : flash:c3560e-universalk9-mz.152-1.E1.bin
Config file         : flash:/config.text
Private Config file : flash:/private-config.text
Enable Break        : no
Manual Boot         : no
Allow Dev Key         : yes
HELPER path-list    :
Auto upgrade        : yes
Auto upgrade path   :
NVRAM/Config file
      buffer size:   524288
Timeout for Config
          Download:    0 seconds
Config Download
       via DHCP:       disabled (next boot: disabled)

Save Config

230Net-4#Write

9: Reload/Reboot device

230Net-4#reload

Note:This can take a while, on my switch it took between 20 and 30 minutes in this case.

Show Version
After the reboot log back in and check to make sure the new version is running.

230Net-4#Sh Ver
..
Switch Ports Model              SW Version            SW Image
------ ----- -----              ----------            ----------
*    1 54    WS-C3560X-48P      15.2(1)E1             C3560E-UNIVERSALK9-M

Delete the old IOS Image

230Net-4#delete /f /r flash:c3560e-universalk9-mz.122-55.SE3

That’s it.

References:

How to upgrade the IOS http://www.cisco.com/en/US/products/ps5855/products_tech_note09186a00801fc986.shtml

Register Values http://www.cisco.com/en/US/products/hw/routers/ps133/products_tech_note09186a008022493f.shtml

Leave a comment

Powershell Script to Copy Files from One Server to Another in the same Domain.

Purpose:
Simple script to copy files from one computer or server to another in the same domain. Example can
also email a simple report of files copied. Created to move some files hourly and only email when
something was moved.

Notes:
Will not work across different domains. Account used to run task from task manager must be a domain
user with enough rights on both systems to read and write.

#=====================================================================================================#
#    Copyright 2014 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see .
#
#=====================================================================================================#
# Original Author: Robert Stacks
# Original Script URL: https://randomtechminutia.wordpress.com/2014/02/03/copy-files-from-one-server-to-another-in-the-same-domain/
# Date: 2/3/2014
# Updated: 
# Version: 1.0
#
# Purpose:
# Simple script to copy files from one computer or server to another in the same domain.  Example can 
# also email a simple report of files copied.  Created to move some files hourly and only email when 
# something was moved.
# 
# Many of the user variables are set with $TRUE or $FALSE for on or off.
#
# Will not work across different domains.  Account used to run task from task manager must be a domain 
# user with enough rights on both systems to read and write.
#
# Update Notes:
# 
#=====================================================================================================#

# Email Settings
$fromAddr = "From@domain.com" # Enter the FROM address for the e-mail alert
$toAddr = "To@domain.com" # Enter the TO address for the e-mail alert
$smtpsrv = "mail.domain.com" # Enter the FQDN or IP of a SMTP relay

# Files to Copy and where they are going
# Local Files should be in the formate of C:\Folder\* for Files only or C:\Folder to copy the folder as well
$Localfiles = "C:\Folder\*"
# Remote Path should be UNC path with admin share example \\hostname\c$\pathtocopyto
$Remotefiles = "\\hostname\c$\pathtocopyto"

#Enable or Disable Script functions
$EmailAlerts = $TRUE # Turn e-mail alerts on or off. $FALSE or 0 = off
$TestfromPrompt = $FALSE # Turn on output from command line.  $FALSE or 0 = no output
$RemoveFilesafterCopy = $TRUE # Remove files after files have been copied over?

#===========================#
#Main Script                #
#===========================#

#Get the names of the files we want to transfer
$files = Get-childitem "$Localfiles" |foreach { $_.Name}

if ($files -ne $null)
{

   #Generates output to command line if Value = True
   if ($TestfromPrompt -eq $TRUE)
   {
	Write-Host "These are the files being copied" 
	$files
   }

#Copy files to remote computer
copy-item -path "$Localfiles" -Destination "$Remotefiles" -Recurse

   #Remove Files if Value = True
   if ($RemoveFilesafterCopy -eq $TRUE)
   {
	#Remove Files after they have been moved
	Remove-Item "$Localfiles"
   }
   
   #Send Email Alert if Value = True
   if ($EmailAlerts -eq $TRUE)
   {
    $date = Get-Date -Format g
    Send-MailMessage -To $toAddr -From $fromAddr -Subject "$date Files Copied" -Body "The Following Files were moved: " + $files -SmtpServer $smtpsrv 
   }
}

6 Comments

Powershell Script to Encrypt a Password for Another Script to Use.

Simple Script that will create a text file that another scheduled script can then use to as the password for some account.  Example, you want a script to auto run and remote into some domain, machine, etc but you want to secure the password used by the script.  So it will not be stored in plain text on a server in a script file.  This will get that done.

You call this script from commandline once and then put the text file “securestring.txt” in a call in the automated script.

1. Create a file called encryptpassword.ps1 and put the following in it.

write-host "Enter password to encrypt "
$secure = read-host -assecurestring
$encrypted = convertfrom-securestring -secureString $secure | set-content securestring.txt
$secure2 = get-content securestring.txt | convertto-securestring
write-host "password decrypted is " $secure2
exit

2. Open a powershell command prompt and launch .\encryptpassword.ps1

  • Type your password when prompted
  • Look in the directory you launched powershell from and you should see a securestring.txt

3. Then in your script call the securestring.txt

$username = "domain\user"
$password = get-content d:\powershellScripts\securestring.txt | convertto-securestring
$livecrd = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password

Leave a comment

Powershell Script to Disable inactive Users

Purpose:
Disable users that have been inactive for 90 days.

Notes:
Have not improved format yet.

Must be run on a DC with Domain Admin rights.

# Get today's date
$date = get-date

# Set variable LLTSlimit to today's date minus 90 days
$LLTSlimit = (Get-Date).AddDays(-90).ToFileTimeUTC().ToString()

# Set variable LDAPfilter as a LDAP filter to only find ACTIVE user accounts (useraccountcontrol piece) that have a lastlogontimestamp of older than 90 days
$LDAPFilter = "(&(objectCategory=Person)(objectClass=User)(lastlogontimestamp<=$LLTSlimit)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" #output LDAPfilter to txt file for loop dsquery * domainroot -filter $LDAPFilter -limit 0 > D:\scripts\AD Auto Disable\ADUserstoDisable.txt

#if LDaPfilter is not null, we will disable some accounts and send a email else do nothing.
if (($ldapcontent = get-content "D:\scripts\AD Auto Disable\ADUserstoDisable.txt") -ne $NULL)
{

    # Pre-create file to store query results
ECHO "Summary of Users Disabled Due To Inactivity" >  D:\scripts\AD Auto Disable\AutoDisableResults.txt
ECHO "*--------------------------------------------------------*" >> D:\scripts\AD Auto Disable\AutoDisableResults.txt

#Loop through the users that need to be disabled one at a time
FOREACH ($f in get-content D:\scripts\AD Auto Disable\ADUserstoDisable.txt)
{
#Add the user to be disabled to txt file to be emailed out.
$f>>D:\scripts\AD Auto Disable\AutoDisableResults.txt

#get the old description so it can be appended
$olddesc = dsget user $f -desc
$olddesc > D:\scripts\AD Auto Disable\olddesc.txt
$processolddesc = get-content "D:\scripts\AD Auto Disable\olddesc.txt"
$processolddesc = $processolddesc[1]

Update:
There is a better version of this script over at vNucleus.com that David wrote:
http://vnucleus.com/2011/07/use-powershell-to-auto-disable-inactive-active-directory-accounts/

David recently sold his domain and this link no longer works.  As soon as he republishes his site I’ll update the link.

A newer version can now be found here: http://wp.me/p1VY3A-7R

Leave a comment

Simple Powershell Script to Disable PCs that have been inactive in AD for 90 Days.

Purpose:
Find PC’s that have been inactive for more than 90 days

Notes:
I haven’t formated this script in the typical fashion I normally do.

Must be run on a DC with Domain Rights.

# Get today's date
$date = get-date

# Set variable LLTSlimit to today's date minus 90 days
$LLTSlimit = (Get-Date).AddDays(-90).ToFileTimeUTC().ToString()

# Set variable LDAPfilter as a LDAP filter to only find ACTIVE user accounts (useraccountcontrol piece) that have a lastlogontimestamp of older than 90 days
$LDAPFilter = "(&(objectCategory=Computer)(objectClass=User)(lastlogontimestamp<=$LLTSlimit)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"

#output LDAPfilter to txt file for loop
dsquery * domainroot -filter $LDAPFilter -limit 0 > D:\scripts\test.txt

#Loop through the computers that need to be disabled one at a time
FOREACH ($f in get-content D:\scripts\test.txt)
{

#disable computer and append to the old description the note about disabling account
dsmod computer $f -disabled yes -desc "$processolddesc - Disabled due to inactivity on $date"

}

exit

Leave a comment

Powershell script to generate and email a DFS Health Report.

Purpose:
This script was used to generate a DFS Health Report and email it to the admin team on a daily basis.

Comments:
I attempted to push the report into the body of the email but Outlook did not like the formatting so instead it was added as an attachment.
This is on a Windows 2008 R2 Server using the old commandline version of DFS and its reporting. The Report does not work in some of the newer version of IE.
To view the report you have to hit F12 and then change the Document Mode: IE quirks to IE5 Quirks

#=====================================================================================================#
#    Copyright 2011 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#=====================================================================================================#
# Author: Robert Stacks
# URL: RandomTechMinutia.wordpress.com
# Date: 11/30/2012
# Updated: 11/30/2012
# Version: 0.1
#
# Purpose:
# Generate a DFS Admin Report and Email it to the admin team it must be viewed with IE due to HTML/Java formatting
#=====================================================================================================#

#Get todays Date
$date = Get-Date

#===========================#
#User Adjustable Variables  #
#===========================#

#Mail Server Variables
$SMTPserver = "mail.domain.com"
$from = "DFSReplicationReport@domain.com"
$to = "Youremail@domain.com"
$subject = "DFS Replication Health Report " + $date
$emailbody = "Attached is the Report"

#DFS Info
#Note: $ReplicationGroup=`"Corp Office to Phoenix`", if your group name has no spaces you can remove the `"
#the dfsadmin command can be a little unforgiving about quotes you may have to adjust your values accordingly.

$ReplicationGroup=`"Your Replication Group`"
$MemeberServer="ServerName"
$SaveReportLocation="C:\DFSReports"

#===========================#
#Main Script                #
#===========================#

#Generate DFS Report

dfsradmin health new /RgName:$ReplicationGroup /RefMemName:$MemeberServer /repname:$SaveReportLocation

# Send email
Send-MailMessage -From $from -To $to -SmtpServer $SMTPserver -Subject $subject -Body "Attached is the DFS Health Report. It must be viewed in IE" -Attachments ("C:\DFSReports\Health-Corp Office to Phoenix.html")

3 Comments

Tweak registry to make Windows always prefer IPv4 over IPv6

One of those basic things that Microsoft changed for us, when logged into a Windows 7 or Server 2008 R2 server and you ping itself you get a IP6 address.  Few shops have converted to IP6 yet so this is how you change that address back to IP4.  I do this in my Windows Templates in VMware.

  • Open RegEdit, navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\tcpip6\Parameters
  • Create DisabledComponents DWORD registry value, set its value to 20 (Hexadecimal).
  • Reboot.

See Microsoft KB 929852 for more info.

2 Comments

Powershell Script to Report on Drive Space Usage in another domain.

This is something I worked up to scan a list of servers, determine their drive space usage, and then calculate a cost to charge a customer.  The script obviously was written with a client-customer, hosted solution in mind.  All that said I scrubbed the code of anything that was actually used by the client/customer but the script has some pretty interesting features that took me a while to put together using hints from others on the web.

The most interesting aspect of this script is the ability to remote into a remote domain and then function as if you were a member of that domain.

This script has a specific purpose where I used it but it could be modified to do something else, so I’m posing it here if nothing else as a reference/example.  Also keep in mind this script was chopped up a good bit to publish to the web so it might be a little buggy now.

Purpose:
Report on remote server hard drive usage when said server is in another domain and alert when usage hits a ceiling in GB.

Requirements:
Quest.ActiveRoles.ADManagement on the system running the script
Domain admin or at least rights to log onto the servers to be scanned
The PC or Server running the script must be able to resolve the foreign domains DNS and Servers FQDN

Other:
The script can also be used with some minor modifications to generate a cost based on Storage usage, this is how I used it.
Line 183 “Some Cost” is the line I used to input a bit of math to determine a cost.  That line along with 133 could be removed if so desired.
The script is designed to log into a remote domain or work group, if this wasn’t the case it could be converted into a much simpler/smaller script.


#=====================================================================================================#
#    Copyright 2011 Robert Stacks
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#=====================================================================================================#
# Author: Robert Stacks
# URL: RandomTechMinutia.wordpress.com
# Date: 7/31/2012
# Updated: 7/31/2011
# Version: 0.1
#
# Purpose:
# Scan and report on storage used on a list of servers.  Can also be used to calculate costs if the
# Drive usage goes over a given amount.  I used 20GB in this example.
#=====================================================================================================#

#Add Snapins
Add-PSSnapin "Quest.ActiveRoles.ADManagement" -ErrorAction SilentlyContinue

#Get todays Date
$date = Get-Date

#===========================#
#User Adjustable Variables  #
#===========================#

#Mail Server Variables
$SMTPserver = "mail.yourdomain.com"
$from = "ScriptReporter@Yourdomain.com"
$to = "adminteam@yourdomain.com"
$EmailSubject = "Drive Space Report"

#Account with rights to remotely log into domain
$AdminAcct = 'domain\admin'
$Adminpwd = 'password'

#Domain to Log into
$domain = 'Remotedomain'

#OU container to get list of Servers to check
$OUStoSearch= 'Yourremotedomain/OU'

#Alert if Drive Space Goes over this amount figured in GB
$DriveCeiling = 20

#===========================#
#Main Script                #
#===========================#

#Set User account to be used to log into cross site domain without AD Trust
$username = $AdminAcct
$password = ConvertTo-SecureString $Adminpwd -AsPlainText -Force
$livecrd = New-Object System.Management.Automation.PSCredential $username, $password

# Format html report
$htmlReport = @"
<style type='text/css'>
.heading {
color:#0B1ABF;
font-size:14.0pt;
font-weight:700;
font-family:Verdana, sans-serif;
text-align:left;
vertical-align:middle;
height:20.0pt;
width:416pt;
}
.colnames {
color:white;
font-size:10.0pt;
font-weight:700;
font-family:Tahoma, sans-serif;
text-align:center;
vertical-align:middle;
border:.5pt solid windowtext;
background:#730000;
}
.lblueback {
color:windowtext;
font-size:10.0pt;
font-family:Arial;
text-align:center;
vertical-align:middle;
border:.5pt solid windowtext;
background:#B2E6FF;
}
.greyback {
color:windowtext;
font-size:10.0pt;
font-family:Arial;
text-align:center;
vertical-align:middle;
border:.5pt solid windowtext;
background:#EAEAEA;
}
.charge {
color:#730000;
font-size:10.0pt;
font-family:Arial;
font-weight:bold;
text-align:center;
vertical-align:middle;
border:.5pt solid windowtext;
background:#FFFF00;
}

</style>
<table border=.5 cellpadding=.5 cellspacing=.5 width=556
style='border-collapse:collapse;table-layout:auto;width:600pt'>
<tr style='height:15.0pt'>
<th colspan=6 height=40 width=600>
<center>Drive Space Report</center></th>
</tr>
<tr>
<th>Server Name</th>
<th>Drive</th>
<th>Size(GB)</th>
<th>Used(GB)</th>
<th>Freespace(GB)</th>
<th>Over Amount (15GB)</th>
<th>Amount to Charge</th>
</tr>
"@

#Connect to the specific domain
Connect-QADService -Service $domain -Credential $livecrd

#Get a LIst of Servers from a OU
$servers=get-qadcomputer -SearchRoot $OUStoSearch | foreach { $_.Name} | Sort

#counter to manage alternating row color
$colorcounter = 0

foreach ($server in $servers)
{

#If loop to determine color of Rows related each system.
if ($colorcounter%2 -eq 0){
$tablecell = @"
<td class='lblueback'>
"@
}
else {
$tablecell = @"
<td class='greyback'>
"@
}
#format the server name with its FQDN
$server=$server + '.' + $domain
# Get a list of Hard Drives
$DISKS=Get-WmiObject Win32_LogicalDisk -computerName $server -Credential $livecrd -Filter "DriveType = 3"

# For each disk print out its stats
foreach ($DISK in $DISKS)
{
$htmlReport=$htmlReport +
"<tr>" + $tablecell + $server + "</td>" +
$tablecell + ($DISK.DeviceID) + "</td>" +
$tablecell + [Math]::round(($DISK.size/1gb),2) + "</td>" +
$tablecell + [Math]::round((($DISK.size-$DISK.freespace)/1gb),2) + "</td>" +
$tablecell + [Math]::round(($DISK.freespace/1gb),2) + "</td>"

#Determine if more that X GB is being used.
$GBOver = (($DISK.size-$DISK.freespace)/1gb) - $DriveCeiling

#If more than X GB is being used we change the color of the table and calulate the cost
if($GBOver -gt 0 )
{
#You can change the item "Some Cost" to a actual formual to determine a cost if you so desire.
$htmlReport=$htmlReport +
"<td class='charge'>" + [Math]::round($GBOver,2) + "</td>" +
"<td class='charge'>" + "$" + "Some Cost" + "</td></tr>"
}

#If they are not using more than X GB then we just report a zero and no charge
else
{
$htmlReport=$htmlReport +
$tablecell + "0" + "</td>" +
$tablecell + "No Charge" + "</td></tr>"

}

}
# value used in conjuction with if loop to rotate color in table
$colorcounter = $colorcounter + 1
}

$htmlReport = $htmlReport + "</table>"

# Send email
$subject = $EmailSubject + $date
$emailbody = $htmlReport
$mailer = New-Object Net.Mail.SMTPclient($SMTPserver)
$msg = New-Object Net.Mail.MailMessage($from, $to, $subject, $emailbody)
$msg.IsBodyHTML = $true
$mailer.send($msg)

Leave a comment