Powershell script is sending 3 emails instead of 1 - email

I have a script that pings ip addresses and sends an email if one or more do not succeed. The script is working except, when it sends the email, it sends 3 copies instead of just the one. Any help would be appreciated.
param($alert)
# Create the variables
$global:GArgs = $Args
$TimeStop = "23:55"
$errorCount = 0
$urlsToTest = #{}
$urlsToTest["HCC Brandon"] = "ip address"
$urlsToTest["HCC Dale Mabry"] = "ip address"
$urlsToTest["HCC Plant City"] = "ip address"
$urlsToTest["HCC South Shore"] = "ip address"
$urlsToTest["HCC Ybor"] = "ip address"
$urlsToTest["HCC Admin"] = "ip address"
$errorTime =#{}
$errorTime["HCC Brandon"] = "5/7/2015 02:00:00 AM"
$errorTime["HCC Dale Mabry"] = "5/7/2015 02:00:00 AM"
$errorTime["HCC Plant City"] = "5/7/2015 02:00:00 AM"
$errorTime["HCC South Shore"] = "5/7/2015 02:00:00 AM"
$errorTime["HCC Ybor"] = "5/7/2015 02:00:00 AM"
$errorTime["HCC Admin"] = "5/7/2015 02:00:00 AM"
$ping = new-object System.Net.NetworkInformation.Ping
Do {
foreach ($key in $urlsToTest.Keys) {
$output = ""
$startTime = get-date
$output = $ping.send($urlsToTest[$key])
$endTime = get-date
if (((New-TimeSpan -Start $errorTime[$key]).hours) -ge "1") {
if ($output.status.tostring() –eq "Success") {
$key + "`t`tSuccess`t`t" + $startTime.DateTime + "`t`t" + ($endTime - $startTime).TotalSeconds + " seconds"
if ($GArgs -eq "-log") {
$key + "`t`tSuccess`t`t" + $startTime.DateTime + "`t`t" + ($endTime - $startTime).TotalSeconds + " seconds" >> BACboneSiteTest.log
}
} else {
$errorCount++
$key + "`t`tFail`t`t" + $startTime.DateTime + "`t`t" + ($endTime - $startTime).TotalSeconds + " seconds"
$errorTime[$key] = Get-Date
if ($GArgs -eq "-log") {
$key + "`t`tFail`t`t" + $startTime.DateTime + "`t`t" + ($endTime - $startTime).TotalSeconds + " seconds" >> BACboneSiteTest.log
}
}
} else {
$key + "`t`tSkipping`t`t"
}
}
if ($errorCount -ge 1) {
if ($alert) {
$EmailFrom = "emailfrom"
$EmailTo = "emailto"
$Subject = "BACbone Test Failure - " + $startTime
$body = "BACbone Test Failure: " + $startTime
$smtpServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("username", "password");
$SMTPClient.Send($EmailFrom,$EmailTo,$Subject,$body)
}
}
$errorCount = 0
start-sleep -seconds 30
}Until ((get-date).Hour -eq $TimeStop.Hour -and (get.date).Minute -eq $TimeStop.Minute)
$ping = $null

Related

Powershell Email body formatting not showing as expected

The code gathers ping and traceroute info and send it in an email. The output of ping result comes out fine in the email's body but tracert info is not formatted correctly. Please see the example below as seen in the email body. The information must be passed on from variable to the body of email as its done below and not attached as a logfile.
The code is as below:
$TimeSpan = New-TimeSpan -Minutes 1
$EndTime = (Get-Date).AddMinutes($TimeSpan.TotalMinutes).ToString("HH:mm")
# $log_file='c:\timee.log'
cls
do
{
write-host 'Gathering logs..wait 2 mins'
$1+=ping google.com |Select-String "Reply"| foreach $_ { $a = Get-Date;
$a.ToString() + " " + $_ } #|
Out-File -Append -Encoding UTF8 -FilePath $log_file
$2+= tracert google.com
}
until ($EndTime -eq (Get-Date -Format HH:mm))
$EmailFrom = "from#gmail.com"
$EmailTo = "to#hotmail.com"
$Subject = "Notification from yy"
$Body = $1+$2
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587)
$SMTPClient.EnableSsl = $true
$SMTPClient.Credentials = New-Object
System.Net.NetworkCredential("from#gmail.com",
"passwd");
$SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body)
#Clear-Variable -name '1'
Write-Host "All done" -ForegroundColor Green

Creating a Powershell Script to get disk info of remote machines

I have been playing with a script i found online that gives you a breakdown of your disks and a lovely pie chart after.
I was wondering this; we currently have VPN running to all our customer sites where there the servers are.
I can get to them all using the local IP for administration purposes via RDCM or Web Browser. I was wondering if there is anyway for me to be able to run the shell command directly from my machine and listing the ip's of the machines i want checked.
I tried using a list file of the ip's but it just returns nothing.
It would save a lot of time rather than clicking through all 100 servers to get the info every month.
Things to bare in mind:
Each site has it's own domain and admin account/password to access.
Here is the script which is direct from the technet script centre (I havent placed any details in.) It works fine when i run it directly on the machine):
#### Spreadsheet Location
$DirectoryToSaveTo = "c:\"
$date=Get-Date -format "yyyy-MM-d"
$Filename="serverinfo-$($date)"
$FromEmail="<ToEmail>"
$ToEmail="<FromEmail>"
$SMTPMail="<SMTP MAIL>"
###InputLocation
$Computers = Get-Content "c:\server.txt"
# before we do anything else, are we likely to be able to save the file?
# if the directory doesn't exist, then create it
if (!(Test-Path -path "$DirectoryToSaveTo")) #create it if not existing
{
New-Item "$DirectoryToSaveTo" -type directory | out-null
}
#Create a new Excel object using COM
$Excel = New-Object -ComObject Excel.Application
$Excel.visible = $True
$Excel = $Excel.Workbooks.Add()
$Sheet = $Excel.Worksheets.Item(1)
$sheet.Name = 'Server Inventory'
#Create a Title for the first worksheet
$row = 1
$Column = 1
$Sheet.Cells.Item($row,$column)= 'Server Inventory'
$range = $Sheet.Range("a1","s2")
$range.Merge() | Out-Null
$range.VerticalAlignment = -4160
#Give it a nice Style so it stands out
$range.Style = 'Title'
#Increment row for next set of data
$row++;$row++
#Save the initial row so it can be used later to create a border
#Counter variable for rows
$intRow = $row
$xlOpenXMLWorkbook=[int]51
#Read thru the contents of the SQL_Servers.txt file
$Sheet.Cells.Item($intRow,1) ="Name"
$Sheet.Cells.Item($intRow,2) ="status"
$Sheet.Cells.Item($intRow,3) ="OS"
$Sheet.Cells.Item($intRow,4) ="Domain Role"
$Sheet.Cells.Item($intRow,5) ="ProcessorName"
$Sheet.Cells.Item($intRow,6) ="Manufacturer"
$Sheet.Cells.Item($intRow,7) ="Model"
$Sheet.Cells.Item($intRow,8) ="SystemType"
$Sheet.Cells.Item($intRow,9) ="Last Boot Time"
$Sheet.Cells.Item($intRow,10) ="Bios Version"
$Sheet.Cells.Item($intRow,11) ="CPU Info"
$Sheet.Cells.Item($intRow,12) ="NoOfProcessors"
$Sheet.Cells.Item($intRow,13) ="Total Physical Memory"
$Sheet.Cells.Item($intRow,14) ="Total Free Physical Memory"
$Sheet.Cells.Item($intRow,15) ="Total Virtual Memory"
$Sheet.Cells.Item($intRow,16) ="Total Free Virtual Memory"
$Sheet.Cells.Item($intRow,17) ="Disk Info"
$Sheet.Cells.Item($intRow,18) ="FQDN"
$Sheet.Cells.Item($intRow,19) ="IPAddress"
for ($col = 1; $col –le 19; $col++)
{
$Sheet.Cells.Item($intRow,$col).Font.Bold = $True
$Sheet.Cells.Item($intRow,$col).Interior.ColorIndex = 48
$Sheet.Cells.Item($intRow,$col).Font.ColorIndex = 34
}
$intRow++
Function GetStatusCode
{
Param([int] $StatusCode)
switch($StatusCode)
{
0 {"Success"}
11001 {"Buffer Too Small"}
11002 {"Destination Net Unreachable"}
11003 {"Destination Host Unreachable"}
11004 {"Destination Protocol Unreachable"}
11005 {"Destination Port Unreachable"}
11006 {"No Resources"}
11007 {"Bad Option"}
11008 {"Hardware Error"}
11009 {"Packet Too Big"}
11010 {"Request Timed Out"}
11011 {"Bad Request"}
11012 {"Bad Route"}
11013 {"TimeToLive Expired Transit"}
11014 {"TimeToLive Expired Reassembly"}
11015 {"Parameter Problem"}
11016 {"Source Quench"}
11017 {"Option Too Big"}
11018 {"Bad Destination"}
11032 {"Negotiating IPSEC"}
11050 {"General Failure"}
default {"Failed"}
}
}
Function GetUpTime
{
param([string] $LastBootTime)
$Uptime = (Get-Date) - [System.Management.ManagementDateTimeconverter]::ToDateTime($LastBootTime)
"Days: $($Uptime.Days); Hours: $($Uptime.Hours); Minutes: $($Uptime.Minutes); Seconds: $($Uptime.Seconds)"
}
foreach ($Computer in $Computers)
{
TRY {
$OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer
$Bios = Get-WmiObject -Class Win32_BIOS -ComputerName $Computer
$sheetS = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Computer
$sheetPU = Get-WmiObject -Class Win32_Processor -ComputerName $Computer
$drives = Get-WmiObject -ComputerName $Computer Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}
$pingStatus = Get-WmiObject -Query "Select * from win32_PingStatus where Address='$Computer'"
$IPAddress=(Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computer | ? {$_.IPEnabled}).ipaddress
$FQDN=[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name
$OSRunning = $OS.caption + " " + $OS.OSArchitecture + " SP " + $OS.ServicePackMajorVersion
$NoOfProcessors=$sheetS.numberofProcessors
$name=$SheetPU|select name -First 1
$Manufacturer=$sheetS.Manufacturer
$Model=$sheetS.Model
$systemType=$sheetS.SystemType
$ProcessorName=$SheetPU|select name -First 1
$DomainRole = $sheetS.DomainRole
$TotalAvailMemory = $OS.totalvisiblememorysize/1kb
$TotalVirtualMemory = $OS.totalvirtualmemorysize/1kb
$TotalFreeMemory = $OS.FreePhysicalMemory/1kb
$TotalFreeVirtualMemory = $OS.FreeVirtualMemory/1kb
$TotalMem = "{0:N2}" -f $TotalAvailMemory
$TotalVirt = "{0:N2}" -f $TotalVirtualMemory
$FreeMem = "{0:N2}" -f $TotalFreeMemory
$FreeVirtMem = "{0:N2}" -f $TotalFreeVirtualMemory
$date = Get-Date
$uptime = $OS.ConvertToDateTime($OS.lastbootuptime)
$BiosVersion = $Bios.Manufacturer + " " + $Bios.SMBIOSBIOSVERSION + " " + $Bios.ConvertToDateTime($Bios.Releasedate)
$sheetPUInfo = $name.Name + " & has " + $sheetPU.NumberOfCores + " Cores & the FSB is " + $sheetPU.ExtClock + " Mhz"
$sheetPULOAD = $sheetPU.LoadPercentage
if($pingStatus.StatusCode -eq 0)
{
$Status = GetStatusCode( $pingStatus.StatusCode )
}
else
{
$Status = GetStatusCode( $pingStatus.StatusCode )
}
if (($DomainRole -eq "0") -or ($DomainRole -eq "1"))
{
$Role = "Work Station"
}
elseif (($DomainRole -eq "2") -or ($DomainRole -eq "3"))
{
$Role = "Member Server"
}
elseif (($DomainRole -eq "4") -or ($DomainRole -eq "5"))
{
$Role = "Domain Controller"
}
else
{
$Role = "Unknown"
}
}
CATCH
{
$pcnotfound = "true"
}
#### Pump Data to Excel
if ($pcnotfound -eq "true")
{
$sheet.Cells.Item($intRow, 1) = "PC Not Found"
}
else
{
$sheet.Cells.Item($intRow, 1) = $computer
$sheet.Cells.Item($intRow, 2) = $status
$sheet.Cells.Item($intRow, 3) = $OSRunning
$sheet.Cells.Item($intRow, 4) = $Role
$sheet.Cells.Item($intRow, 5) = $name.name
$Sheet.Cells.Item($intRow, 6) = $Manufacturer
$Sheet.Cells.Item($intRow, 7) = $Model
$Sheet.Cells.Item($intRow, 8) = $SystemType
$sheet.Cells.Item($intRow, 9) = $uptime
$sheet.Cells.Item($intRow, 10)= $BiosVersion
$sheet.Cells.Item($intRow, 11)= $sheetPUInfo
$sheet.Cells.Item($intRow, 12)=$NoOfProcessors
$sheet.Cells.Item($intRow, 13)= "$TotalMem MB"
$sheet.Cells.Item($intRow, 14)= "$FreeMem MB"
$sheet.Cells.Item($intRow, 15)= "$TotalVirt MB"
$sheet.Cells.Item($intRow, 16)= "$FreeVirtMem MB"
$sheet.Cells.Item($intRow, 19)=$IPAddress
$sheet.Cells.Item($intRow, 18)=$FQDN
$driveStr = ""
foreach($drive in $drives)
{
$size1 = $drive.size / 1GB
$size = "{0:N2}" -f $size1
$free1 = $drive.freespace / 1GB
$free = "{0:N2}" -f $free1
$freea = $free1 / $size1 * 100
$freeb = "{0:N2}" -f $freea
$ID = $drive.DeviceID
$driveStr += "$ID = Total Space: $size GB / Free Space: $free GB / Free (Percent): $freeb % ` "
}
$sheet.Cells.Item($intRow, 17) = $driveStr
}
$intRow = $intRow + 1
$pcnotfound = "false"
}
$erroractionpreference = “SilentlyContinue”
$Sheet.UsedRange.EntireColumn.AutoFit()
########################################333
$Sheet = $Excel.Worksheets.Item(2)
$sheet.Name = 'DiskSpace'
$Sheet.Activate() | Out-Null
#Create a Title for the first worksheet
$row = 1
$Column = 1
$Sheet.Cells.Item($row,$column)= 'Disk Space Information'
$range = $Sheet.Range("a1","h2")
$range.Merge() | Out-Null
$range.VerticalAlignment = -4160
#Give it a nice Style so it stands out
$range.Style = 'Title'
#Increment row for next set of data
$row++;$row++
#Save the initial row so it can be used later to create a border
$initalRow = $row
#Create a header for Disk Space Report; set each cell to Bold and add a background color
$Sheet.Cells.Item($row,$column)= 'Computername'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= 'DeviceID'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= 'VolumeName'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= 'TotalSizeGB'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= 'UsedSpaceGB'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= 'FreeSpaceGB'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= '%Free'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
$Column++
$Sheet.Cells.Item($row,$column)= 'State'
$Sheet.Cells.Item($row,$column).Interior.ColorIndex =48
$Sheet.Cells.Item($row,$column).Font.Bold=$True
#Set up a header filter
$headerRange = $Sheet.Range("a3","h3")
$headerRange.AutoFilter() | Out-Null
#Increment Row and reset Column back to first column
$row++
$Column = 1
$critical=0
$warning=0
$good=0
#Get the drives and filter out CD/DVD drives
foreach ($computer in $Computers)
{
$diskDrives = Get-WmiObject win32_LogicalDisk -Filter "DriveType='3'" -ComputerName $computer
#Process each disk in the collection and write to spreadsheet
ForEach ($disk in $diskDrives) {
$Sheet.Cells.Item($row,1)= $disk.__Server
$Sheet.Cells.Item($row,2)= $disk.DeviceID
$Sheet.Cells.Item($row,3)= $disk.VolumeName
$Sheet.Cells.Item($row,4)= [math]::Round(($disk.Size /1GB),2)
$Sheet.Cells.Item($row,5)= [math]::Round((($disk.Size - $disk.FreeSpace)/1GB),2)
$Sheet.Cells.Item($row,6)= [math]::Round(($disk.FreeSpace / 1GB),2)
$Sheet.Cells.Item($row,7)= ("{0:P}" -f ($disk.FreeSpace / $disk.Size))
#Determine if disk needs to be flagged for warning or critical alert
If ($disk.FreeSpace -lt 5GB -AND ("{0:P}" -f ($disk.FreeSpace / $disk.Size)) -lt 40) {
$Sheet.Cells.Item($row,8) = "Critical"
$critical++
#Check to see if space is near empty and use appropriate background colors
$range = $Sheet.Range(("A{0}" -f $row),("H{0}" -f $row))
$range.Select() | Out-Null
#Critical threshold
$range.Interior.ColorIndex = 3
} ElseIf ($disk.FreeSpace -lt 10GB -AND ("{0:P}" -f ($disk.FreeSpace / $disk.Size)) -lt 60) {
$Sheet.Cells.Item($row,8) = "Warning"
$range = $Sheet.Range(("A{0}" -f $row),("H{0}" -f $row))
$range.Select() | Out-Null
$warning++
$range.Interior.ColorIndex = 6
} Else {
$Sheet.Cells.Item($row,8) = "Good"
$good++
}
$row++
}
}
#Add a border for data cells
$row--
$dataRange = $Sheet.Range(("A{0}" -f $initalRow),("H{0}" -f $row))
7..12 | ForEach {
$dataRange.Borders.Item($_).LineStyle = 1
$dataRange.Borders.Item($_).Weight = 2
}
#Auto fit everything so it looks better
$usedRange = $Sheet.UsedRange
$usedRange.EntireColumn.AutoFit() | Out-Null
$critical
$warning
$good
$sheet = $excel.Worksheets.Item(2)
$row++;$row++
$beginChartRow = $Row
$Sheet.Cells.Item($row,$Column) = 'Critical'
$Column++
$Sheet.Cells.Item($row,$Column) = 'Warning'
$Column++
$Sheet.Cells.Item($row,$Column) = 'Good'
$Column = 1
$row++
#Critical formula
$Sheet.Cells.Item($row,$Column)=$critical
$Column++
#Warning formula
$Sheet.Cells.Item($row,$Column)=$warning
$Column++
#Good formula
$Sheet.Cells.Item($row,$Column)= $good
$endChartRow = $row
$chartRange = $Sheet.Range(("A{0}" -f $beginChartRow),("C{0}" -f $endChartRow))
##Add a chart to the workbook
#Open a sheet for charts
$temp = $sheet.Charts.Add()
$temp.Delete()
$chart = $sheet.Shapes.AddChart().Chart
$sheet.Activate()
#Configure the chart
##Use a 3D Pie Chart
$chart.ChartType = 70
$chart.Elevation = 40
#Give it some color
$sheet.Shapes.Item("Chart 1").Fill.ForeColor.TintAndShade = .34
$sheet.Shapes.Item("Chart 1").Fill.ForeColor.ObjectThemeColor = 5
$sheet.Shapes.Item("Chart 1").Fill.BackColor.TintAndShade = .765
$sheet.Shapes.Item("Chart 1").Fill.ForeColor.ObjectThemeColor = 5
$sheet.Shapes.Item("Chart 1").Fill.TwoColorGradient(1,1)
#Set the location of the chart
$sheet.Shapes.Item("Chart 1").Placement = 3
$sheet.Shapes.Item("Chart 1").Top = 30
$sheet.Shapes.Item("Chart 1").Left = 600
$chart.SetSourceData($chartRange)
$chart.HasTitle = $True
$chart.ApplyLayout(6,69)
$chart.ChartTitle.Text = "Disk Space Report"
$chart.ChartStyle = 26
$chart.PlotVisibleOnly = $False
$chart.SeriesCollection(1).DataLabels().ShowValue = $True
$chart.SeriesCollection(1).DataLabels().Separator = ("{0}" -f [char]10)
$chart.SeriesCollection(1).DataLabels().Position = 2
#Critical
$chart.SeriesCollection(1).Points(1).Format.Fill.ForeColor.RGB = 255
#Warning
$chart.SeriesCollection(1).Points(2).Format.Fill.ForeColor.RGB = 65535
#Good
$chart.SeriesCollection(1).Points(3).Format.Fill.ForeColor.RGB = 5287936
#Hide the data
$chartRange.EntireRow.Hidden = $True
$sheet.Name = 'DiskInformation'
$filename = "$DirectoryToSaveTo$filename.xlsx"
if (test-path $filename ) { rm $filename } #delete the file if it already exists
$Sheet.UsedRange.EntireColumn.AutoFit()
$Excel.SaveAs($filename, $xlOpenXMLWorkbook) #save as an XML Workbook (xslx)
$Excel.Saved = $True
$Excel.Close()
$Excel.DisplayAlerts = $False
$Excel.quit()
Function sendEmail([string]$emailFrom, [string]$emailTo, [string]$subject,[string]$body,[string]$smtpServer,[string]$filePath)
{
#initate message
$email = New-Object System.Net.Mail.MailMessage
$email.From = $emailFrom
$email.To.Add($emailTo)
$email.Subject = $subject
$email.Body = $body
# initiate email attachment
$emailAttach = New-Object System.Net.Mail.Attachment $filePath
$email.Attachments.Add($emailAttach)
#initiate sending email
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($email)
}
#Call Function
#sendEmail -emailFrom pjayaram#appvion.com -emailTo 'pjayaram#appvion.com,pthangaraj#appvion.com,rmurugesan#appvion.com' -subject "INVENTORY" -body "Windows Server Inventory - COMPLETE DETAILS" -smtpServer hqmail01.appletonpapers.com -filePath $filename
$message = #"
Hi Team,
The Discovery of Windows Server and Disk Space information for all the listed instances.
Autogenerated Email!!! Please do not reply.
Thank you,
Appvion.com
"#
$date=get-date
sendEmail -emailFrom $fromEmail -emailTo $ToEmail -subject "Windows Server Inventory & Disk Details -$($date)" -body $message -smtpServer $SMTPMail -filePath $filename
Many thanks to you all in advance.
For each computer in an external domain, you will have to get the corresponding credentials at the beginning with, for example :
$storedCredential = Get-Credential
Then, when making WMI calls, you will need to specify these credentials, with for example :
$OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer -Credential $storedCredential
$Bios = Get-WmiObject -Class Win32_BIOS -ComputerName $Computer -Credential $storedCredential
$sheetS = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Computer -Credential $storedCredential

Calculate time differences in log file using Powershell based on linux code

EDITED:
Text1.txt:
123.456.789.189:12345
222.222.222.444:56789
451.200.111.321:55555
333.333.333.111:11223
I want to compare ID with IP that weren't registered.
ERROR:
Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: '123.456.789.189:12345' Key being added: '123.456.789.189:12345'" + $nameHash.Add( $data3[4], $data3[3] )
I think this error is due to the existence of duplicates.
How do I solve an issue with duplicates in Hash Table?
My function to calculate time takes in a startdate and an end date.
Function calTimeDiff( $StartDate, $EndDate )
{
"which is = " + (NEW-TIMESPAN –Start $StartDate –End $EndDate).Hours + " hours, " +
(NEW-TIMESPAN –Start $StartDate –End $EndDate).Minutes + " minutes, " +
(NEW-TIMESPAN –Start $StartDate –End $EndDate).Seconds + " seconds, " +
"diff = " + (NEW-TIMESPAN –Start $StartDate –End $EndDate).TotalSeconds + " sec"
}
$lines1 = Get-Content "C:\Temp\Text1.txt" | Select-Object -Unique
$lines2 = Get-Content "C:\Temp\Text2.txt" | Select-Object -Unique
ForEach( $line2 in $lines2 )
{
$list = ( $date, $time, $client, $clientIP )
$list = $line2.Split( "" )
ForEach( $line1 in $lines1 )
{
$disconnectIP = $line1
If( $disconnectIP -match $list[3] )
{
$date = $list[0]
$time = $list[1]
$client = $list[2]
$clientIP = $list[3]
If( $client -eq "serviceClient" )
{
$start = $date + " " + $time
}
If( $client -eq "Unregistered" )
{
$end = $date + " " + $time
}
calTimeDiff $start $end
}
}
}
How about something along these lines? I think it's basically behaving the way you were asking for (although you might want to tweak the display-span function a bit...)
#requires -Version 3
function parse-log
{
param(
[string]$line
)
$data = $line.split(' ')
$dateString = '{0} {1}' -f $data[0], $data[1]
$timeStamp = Get-Date -Date $dateString
[pscustomobject]#{
TimeStamp = $timeStamp
Client = $data[2]
IPAddress = $data[3]
}
}
function display-span
{
param(
$logSpan
)
'{0} ({1}) ==> {2}' -f $logSpan.IPAddress, $nameHash.Get_Item( $logSpan.IPAddress), $logSpan.Start
'{0} ({1}) ==> {2}' -f $logSpan.IPAddress, $nameHash.Get_Item( $logSpan.IPAddress), $logSpan.End
'Start = {0}, End = {1}, diff = {2}' -f $logSpan.Start, $logSpan.End, $logSpan.TimeSpan
''
}
$ipStateHash = #{}
$nameHash = #{}
$logArray = #()
$lines1 = Get-Content -Path '.\Text1.txt'
$lines2 = Get-Content -Path '.\Text2.txt'
$lines3 = Get-Content -Path '.\Text3.txt'
# Build Name Hash
foreach( $line3 in $lines3 )
{
$data3 = $line3.Split( ' ' )
$nameHash.Add( $data3[4], $data3[3] )
}
foreach( $line2 in $lines2 )
{
$entry = parse-log -line $line2
switch( $entry.Client ) {
'serviceClient'
{
if( $lines1 -contains $entry.IPAddress )
{
if( $ipStateHash.ContainsKey( $entry.IPAddress ) -eq $false )
{
$ipStateHash.Add( $entry.IPAddress, $entry.TimeStamp )
}
}
}
'Unregistered'
{
if( $ipStateHash.ContainsKey( $entry.IPAddress ) -eq $true )
{
$start = $ipStateHash.Get_Item( $entry.IPAddress )
$ipStateHash.Remove( $entry.IPAddress )
$timespan = $entry.TimeStamp - $start
$logArray += [pscustomobject]#{
IPAddress = $entry.IPAddress
Start = $start
End = $entry.TimeStamp
TimeSpan = $timespan
}
}
}
}
}
$logArray | ForEach-Object -Process {
display-span -logSpan $_
}
"IPs that weren't Unregistered:"
$ipStateHash.GetEnumerator() | Sort-Object -Property TimeStamp | ForEach-Object -Process {
'{0} ==> {1}' -f $nameHash.Get_Item( $_.Key ), $_.Value
}
Using your updated data files from above, the script outputs:
123.456.789.189:12345 (BOB) ==> 7/29/2015 6:00:13 AM
123.456.789.189:12345 (BOB) ==> 7/29/2015 6:00:19 AM
Start = 7/29/2015 6:00:13 AM, End = 7/29/2015 6:00:19 AM, diff = 00:00:06
222.222.222.444:56789 (ALICE) ==> 7/29/2015 6:00:18 AM
222.222.222.444:56789 (ALICE) ==> 7/29/2015 6:00:22 AM
Start = 7/29/2015 6:00:18 AM, End = 7/29/2015 6:00:22 AM, diff = 00:00:04
451.200.111.321:55555 (TOM) ==> 7/29/2015 6:20:03 AM
451.200.111.321:55555 (TOM) ==> 7/29/2015 6:21:19 AM
Start = 7/29/2015 6:20:03 AM, End = 7/29/2015 6:21:19 AM, diff = 00:01:16
IPs that weren't Unregistered:
BOB ==> 7/29/2015 6:01:00 AM

Changing Local User password remotely with Powershell

I'm trying to work with this code that I found. It says it is changing the password to the account I specify, but when I try to log into that laptop with that local account password was not changed.
I need to be able to change the password to the local user account remotely to 30 + laptops without logging into each of them to do so.
Any ideas why this is not working?
$erroractionpreference = "SilentlyContinue"
$a = New-Object -comobject Excel.Application
$a.visible = $True
$b = $a.Workbooks.Add()
$c = $b.Worksheets.Item(1)
$c.Cells.Item(1,1) = "Machine Name"
$c.Cells.Item(1,2) = "Password Changed"
$c.Cells.Item(1,3) = "Report Time Stamp"
$d = $c.UsedRange
$d.Interior.ColorIndex = 19
$d.Font.ColorIndex = 11
$d.Font.Bold = $True
$intRow = 2
foreach ($strComputer in get-content C:\MachineList.Txt)
{
$c.Cells.Item($intRow,1) = $strComputer.ToUpper()
# Using .NET method to ping test the servers – This is very cool!
$ping = new-object System.Net.NetworkInformation.Ping
$Reply = $ping.send($strComputer)
if($Reply.status -eq "success")
{
# This is the Key Part
$admin=[adsi]("WinNT://" + $strComputer + "/LocalUser, user")
$admin.psbase.invoke("SetPassword", "Password")
$admin.psbase.CommitChanges()
$pwage = $admin.passwordage
If($pwage.value -ne "0")
{
$c.Cells.Item($intRow,2).Interior.ColorIndex = 4
$c.Cells.Item($intRow,2) = "Yes"
}
Else
{
$c.Cells.Item($intRow,2).Interior.ColorIndex = 3
$c.Cells.Item($intRow,2) = "No"
}
}
Else
{
$c.Cells.Item($intRow,2).Interior.ColorIndex = 3
$c.Cells.Item($intRow,2) = "Not Pingable"
}
$c.Cells.Item($intRow,3) = Get-Date
$Reply = ""
$pwage = ""
$intRow = $intRow + 1
}
$d.EntireColumn.AutoFit()

Download attachments with multiple subjects from Exchange

I am attempting to download attachments from emails with certain subject lines in an inbox, then delete the email.
There are about a dozen different subject lines in total.
I want to schedule this process to run every 10 minutes or so, so I'd like to keep any processing overheads to a minimum..
Current script is in PowerShell (based on this), but I'm unsure how I could make it loop through a bunch of different subjects. I could just repeat the whole script for each subject, but it's quite inefficient this way..
I'm open to non-PowerShell alternatives too..
$MailboxName = "mailbox#address.com"
$Subject = #("Subject1")
$downloadDirectory = "c:\temp"
Function FindTargetFolder($FolderPath){
$tfTargetidRoot = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$tfTargetidRoot)
for ($lint = 1; $lint -lt $pfArray.Length; $lint++) {
$pfArray[$lint]
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+isEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$pfArray[$lint])
$findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -gt 0){
foreach($folder in $findFolderResults.Folders){
$tfTargetFolder = $folder
}
}
else{
"Error Folder Not Found"
$tfTargetFolder = $null
break
}
}
$Global:findFolder = $tfTargetFolder
}
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
$aceuser = [ADSI]$sidbind
$uri=[system.URI] "https://webmail.company.com.au/EWS/Exchange.asmx"
$service.Url = $uri
FindTargetFolder($ProcessedFolderPath)
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$Sfsub = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, $Subject[0])
$Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::HasAttachments, $true)
$sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
$sfCollection.add($Sfsub)
$sfCollection.add($Sfha)
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000)
$frFolderResult = $InboxFolder.FindItems($sfCollection,$view)
foreach ($miMailItems in $frFolderResult.Items){
$miMailItems.Subject
$miMailItems.Load()
foreach($attach in $miMailItems.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()))
}
$miMailItems.isread = $true
$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
$miMailItems.delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::MoveToDeletedItems)
}
Okay, here's what I've got:
$Subjects = #(
'newIM_IPSC',
'newCM_IPSC',
'CNSDI',
'SMEC_Incident_SLM',
'Incident_SLM',
'MEC_Incident_WorkInfo',
'SMEC_Incident_Header',
'SMEC_SR_Header'
)
[regex]$SubjectRegex = ‘^(?i)(‘ + (($Subjects |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’
Then:
foreach($attach in $miMailItems.Attachments){
foreach ($miMailItems in $frFolderResult.Items){
if ($miMailItems.Subject -match $SubjectRegex)
{
$miMailItems.Load()
foreach($attach in $miMailItems.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()))
}
$miMailItems.isread = $true
$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
$miMailItems.delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::MoveToDeletedItems)
}
}
Add or remove subject lines from the $Subjects array as needed.
An explanation of the bits that are building the regex can be found here:
http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/18/speed-up-array-comparisons-in-powershell-with-a-runtime-regex.aspx