I am attempting to use Compare-Object to find elements that are in one array ($fileArray) but not in another ($dictionaryArray). For some reason, Compare-Object is only comparing the last two elements in fileArray. Here is the code I am trying to run.
$dictionary = Get-Content "C:\Users\Joe\Documents\PowerShell Scripts\Work\PCI Numbers\dictionary.txt"
$file = Get-Content "C:\Users\Joe\Documents\PowerShell Scripts\Work\PCI Numbers\file.txt"
$dictionaryArray = #()
$fileArray = #()
$dictionaryLength = $dictionary | Measure-Object -Line
$fileLength = $file | Measure-Object -Line
$i = 0
while($i -lt $dictionaryLength.Lines){
$name = $dictionary | Select -Index $i
$i++
while($dictionary[$i] -ne " " -and $i -lt $dictionaryLength.Lines){
$dictionaryObject = New-Object -TypeName PSObject
$dictionaryObject | Add-Member -Name 'PC' -MemberType Noteproperty -Value $name
$dictionaryObject | Add-Member -Name 'File' -MemberType Noteproperty -Value $dictionary[$i]
$dictionaryArray += $dictionaryObject
$i++
}
$i++
}
$i = 0
while($i -lt $fileLength.Lines){
$name = $file | Select -Index $i
$i++
while($file[$i] -ne " " -and $i -lt $fileLength.Lines){
$fileObject = New-Object -TypeName PSObject
$fileObject | Add-Member -Name 'PC' -MemberType Noteproperty -Value $name
$fileObject | Add-Member -Name 'File' -MemberType Noteproperty -Value $file[$i]
$fileArray += $fileObject
$i++
}
$i++
}
$i = 0
Compare-Object -ReferenceObject $fileArray -DifferenceObject $dictionaryArray |
Where-Object {$_.SideIndicator -eq '<='} |
ForEach-Object {Write-Output $_.InputObject}
When I simply run Compare-Object -ReferenceObject $fileArray
-DifferenceObject $dictionaryArray, I get the output
InputObject SideIndicator
#{PC=Joe; File=nopethere} <=
#{PC=Joe; File=hi!!!#} <=
There are more items than this in the fileArray. When I run $fileArray, I get
PC File
Eric I like to
Eric there
Joe code because
Joe hello
Joe but why?
Joe *no\thank/ you :c
Joe nopethere
Joe hi!!!#
Why is my code not comparing each one of these objects?
EDIT
Here is dictionary.txt
Eric
because
hello there
Joe
but why?
*no\thank/ you :c
nope
Here is file.txt
Eric
I like to
there
Joe
code because
hello
but why?
*no\thank/ you :c
nopethere
hi!!!#
I use my loop to create objects. The first line of each paragraph is the "PC" for each subsequent object. Then, each line is the "File" of each object. I want to check which objects are in fileArray and not in dictionaryArray. I would expect the output to be
PC File
Eric I like to
Joe code because
Joe hello
Joe nopethere
Joe hi!!!#
Any help would be appreciated!
Word Doc content: [(7)]/[(8)] [ Security Agent 1] as security trustee for the Secured Parties (the "Security Agent") ; and
Value to extract is "Security Agent 1"
It extracts 7 as thats the first within bracket.
Below code works fine, but will give only first occurence/value within brackets. Need to loop it through multiple values within bracket and give me the 3rd value in bracket
$FinalTable = Get-Content $SourceFile|
select-string -pattern $SearchKeyword |
Select -Property #{Name = 'Name'; Expression = {$_.Line}}, #{Name = 'LineNo'; Expression = {$_.LineNumber}}, #{Name='Criteria';Expression = {$_.Category}} |
ForEach-Object {
$str = $_.Name
$LineNumber = $_.LineNo
$Criteria = $_.Criteria
$start = $str.indexOf("[") + 1
$end = $str.indexOf("]", $start)
$length = $end - $start
$result = ($str.substring($start, $length)).trim()
#Creating a custom object to display in table format
$Obj = New-Object -TypeName PSCustomObject
Add-Member -InputObject $Obj -MemberType NoteProperty -Name Category -Value $Category
Add-Member -InputObject $Obj -MemberType NoteProperty -Name Description -Value $result
$obj
}
$FinalTable | Export-Csv -Path $DestinationFile -NoTypeInformation -Encoding ASCII
Trying this as theo suggested but didn't worked
$FinalTable = Get-Content $SourceFile|
select-string -pattern $SearchKeyword |
Select -Property #{Name = 'Name'; Expression = {$_.Line}}, #{Name = 'LineNo'; Expression = {$_.LineNumber}}, #{Name='Criteria';Expression = {$_.Category}} |
ForEach-Object {
$str = $_.Name
$LineNumber = $_.LineNo
$Criteria = $_.Criteria
#$start = $str.indexOf("[") + 1
#$end = $str.indexOf("]", $start)
#$length = $end - $start
#$result = ($str.substring($start, $length)).trim()
#Write-host $str
if ($str -match '(\[[^\]]+])\/(\[[^\]]+])\s*\[\s*([^\]]+)]') {
# $matches[1] --> "(7)"
# $matches[2] --> "(8)"
$result = $matches[3] # --> "Security Agent 1"
}
Write-Host $result
#Creating a custom object to display in table format
$Obj = New-Object -TypeName PSCustomObject
Add-Member -InputObject $Obj -MemberType NoteProperty -Name Category -Value $Category
Add-Member -InputObject $Obj -MemberType NoteProperty -Name Description -Value $result
$obj
}
$FinalTable | Export-Csv -Path $DestinationFile -NoTypeInformation -Encoding ASCII
You could use Regular Expression to get the parts between the brackets in a string like [(7)]/[(8)] [ Security Agent 1] as security trustee for the Secured Parties (the "Security Agent").
Instead of
$start = $str.indexOf("[") + 1
$end = $str.indexOf("]", $start)
$length = $end - $start
$result = ($str.substring($start, $length)).trim()
do
if ($str -match '\[([^\]]+)\]\/\[([^\]]+)\]\s*\[\s*([^\]]+)]') {
# $matches[1] --> "(7)"
# $matches[2] --> "(8)"
$result = $matches[3] # --> "Security Agent 1"
}
else {
$result = '' # should not happen..
}
I have a script which finds snapshots that are older than 3 days and below are my code and output. However I want to add a new column for each VM displaying the actual age of that snapshots, say for example 5 days or 4 days. I have tried getting age by subtracting created date from today's date. But I am not sure how to add it as a column to my output.
I used this to calculate age:
$StartDate = Get-Date
$created = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object Created
$age = New-Timespan -Start $StartDate -End $created
Full code:
Add-PSSnapin VMware.VimAutomation.Core
# HTML formatting
$a = "<style>"
$a = $a + "BODY{background-color:white;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: LightBlue}"
$a = $a + "TD{border-width: 1px;padding: 5px;border-style: solid;border-color: black;foreground-color: black;background-color: white}"
$a = $a + "</style>"
Connect-VIServer -Server ***** -User ****** -Password ******
# Main section of check
Write-Host "Checking VMs for for snapshots"
$date = Get-Date
$datefile = Get-Date -UFormat '%m-%d-%Y-%H%M%S'
$filename = "C:\Temp\snaps_older_than_3\" + $datefile + ".htm"
$created = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object Created
$age = New-Timespan -Start $StartDate -End $created
$ss = Get-VM |
Get-Snapshot |
Where {$_.Created -lt (Get-Date).AddDays(-1)} |
Select-Object vm, name, SizeGB, SizeMB, Created, powerstate + $age |
ConvertTo-HTML -Head $a -Body "<H2>VM Snapshot Report </H2>"|
Out-File $filename
Write-Host " Complete " -ForegroundColor Green
Write-Host "Your snapshot report has been saved to:" $filename
$SMTPServer = "*******"
$SMTPPort = 25
$username = "vcenter#mmmm.com"
#Define the receiver of the report
$to = "mmmmm#hcl.com"
$subject = "VM Snapshot Report"
$body = "VM Snapshot Report"
$attachment = New-Object Net.Mail.Attachment($filename)
$message = New-Object System.Net.Mail.MailMessage
$message.Subject = $subject
$message.Body = $body
$message.To.Add($to)
$message.From = $username
$message.Attachments.Add($attachment)
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $false
$smtp.Send($message)
Write-Host "Mail Sent"
Output:
I want to add a new column named "age".
Use a calculated property:
Get-VM |Select-Object VM,Name,SizeGB,SizeMB,Created,PowerState,#{Name='Age';Expression={New-TimeSpan -Start $StartDate -End $_.Created}}
From the help text for Select-Object:
-Property
Specifies the properties to select. Wildcards are permitted.
The value of the Property parameter can be a new calculated property.
To create a calculated property, use a hash table. Valid keys are:
Name (or Label) <string>
Expression <string> or <script block>
I have written the following PowerShell script for getting disk space information for servers in our environment.
$servers = Get-Content E:\POC.txt
$array = #()
foreach($server in $servers){
$sysinfo = Get-WmiObject Win32_Volume -ComputerName $server
for($i = 0;$i -lt $sysinfo.Count; $i++){
$sname = $sysinfo[$i].SystemName
$servername = $server
$label = $sysinfo[$i].Label
if(($label) -and (!($label.Contains("FILLER")))){
write-host "Processing $label from $server"
$name = $sysinfo[$i].Name
$capacity = [math]::round(($sysinfo[$i].Capacity/1GB),2)
$fspace = [math]::round(($sysinfo[$i].FreeSpace/1GB),2)
$sused = [math]::round((($sysinfo[$i].Capacity - $sysinfo[$i].FreeSpace)/1GB),2)
$fspacepercent = [math]::Round((($sysinfo[$i].FreeSpace*100)/$sysinfo[$i].Capacity),2)
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name "SystemName" -Value $sname
$obj | Add-Member -MemberType NoteProperty -Name "ServerName" -Value $server
$obj | Add-Member -MemberType NoteProperty -Name "Label" -Value $label
$obj | Add-Member -MemberType NoteProperty -Name "Name" -Value $name
$obj | Add-Member -MemberType NoteProperty -Name "Capacity(GB)" -Value $capacity
$obj | Add-Member -MemberType NoteProperty -Name "FreeSpace(GB)" -Value $fspace
$obj | Add-Member -MemberType NoteProperty -Name "Used(GB)" -Value $sused
$obj | Add-Member -MemberType NoteProperty -Name "FreeSpace%" -Value $fspacepercent
$array += $obj
}
}
$array += write-output " "
$totalSize = ($array | Measure-Object 'Capacity(GB)' -Sum).Sum
$array += $totalsize
$array += write-output " "
}
$filename = "E:\VolumeReport.csv"
$array | Export-CSV $filename -NoTypeInformation
One additional requirement here is to get the sum of the columns for Capacity, Size and Freespace for each server. I tried using Measure-Object but no success.
No values are getting outputted here. Just blank. Please look into this and kindly assist.
Let try this on for size shall we.
$servers = Get-Content E:\POC.txt
$propertyOrdered = "SystemName","ServerName","Label","Name","Capacity(GB)","FreeSpace(GB)","Used(GB)","FreeSpace%"
$filename = "C:\temp\VolumeReport.csv"
('"{0}"' -f ($propertyOrdered -join '","')) | Set-Content $filename
foreach($server in $servers){
$sysinfo = Get-WmiObject Win32_Volume -ComputerName $server
$serverDetails = #()
for($i = 0;$i -lt $sysinfo.Count; $i++){
$sname = $sysinfo[$i].SystemName
$servername = $server
$label = $sysinfo[$i].Label
if(($label) -and (!($label.Contains("FILLER")))){
write-host "Processing $label from $server"
$name = $sysinfo[$i].Name
$capacity = [math]::round(($sysinfo[$i].Capacity/1GB),2)
$fspace = [math]::round(($sysinfo[$i].FreeSpace/1GB),2)
$sused = [math]::round((($sysinfo[$i].Capacity - $sysinfo[$i].FreeSpace)/1GB),2)
$fspacepercent = [math]::Round((($sysinfo[$i].FreeSpace*100)/$sysinfo[$i].Capacity),2)
$props = #{
"SystemName" = $sname
"ServerName" = $server
"Label" = $label
"Name" = $name
"Capacity(GB)" = $capacity
"FreeSpace(GB)" = $fspace
"Used(GB)" = $sused
"FreeSpace%" = $fspacepercent
}
# Build this server object.
$serverDetails += New-Object PSObject -Property $props
}
}
# Output current details to file.
$serverDetails | Select $propertyOrdered | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Add-Content $filename
#Calculate Totals and append to file.
$totals = '"","","","Totals",{0},{1},{2},""' -f ($serverDetails | Measure-Object -Property "Capacity(GB)" -Sum).Sum,
($serverDetails | Measure-Object -Property "FreeSpace(GB)" -Sum).Sum,
($serverDetails | Measure-Object -Property "Used(GB)" -Sum).Sum
$totals | Add-Content $filename
}
Part of the issue here is that you were mixing object output and static string output which most likely would have been holding you back. I tidied up the object generation in a way that should be 2.0 compliant. Not that what you were going was wrong in anyway but this is a little more pleasing to the eye then all the Add-Members
I removed $array since it did not have a place anymore since the logic here is constantly output data to the output file as supposed to storing it temporarily.
For every $server we build an array of disk information in the variable $serverDetails. Once all the disks have been calculated (using your formulas still) we then create a totals line. You were not really clear on how you wanted your output so I guessed. The above code should net output like the following. (It looks a lot nicer in Excel or in a csv aware reader. )
"SystemName","ServerName","Label","Name","Capacity(GB)","FreeSpace(GB)","Used(GB)","FreeSpace%"
"server01","server01","System Reserved","\\?\Volume{24dbe945-3ea6-11e0-afbd-806e6f6e6963}\","0.1","0.07","0.03","71.85"
"","","","Totals",0.1,0.07,0.03,""
"server02","server02","System Reserved","\\?\Volume{24dbe945-3ea6-11e0-afbd-806e6f6e6963}\","0.1","0.07","0.03","69.27"
"server02","server02","images","I:\","1953.12","152.1","1801.02","7.79"
"server02","server02","Data","E:\","79.76","34.59","45.18","43.36"
"","","","Totals",2032.98,186.76,1846.23,""
Using the following and would like to know how to output the results to HTML file
$Start = (Get-Date).AddMinutes(-5)
$Computername = gc C:\Temp\List.txt
$Events = gc C:\Temp\ErrorCodes.txt
Get-EventLog -AsString -ComputerName $Computername |
ForEach-Object {
# write status info
Write-Progress -Activity "Checking Eventlogs on \\$ComputerName" -Status $_
# get event entries and add the name of the log this came from
Get-EventLog -LogName $_ -EntryType Error, Warning -After $Start -ComputerName $ComputerName -ErrorAction SilentlyContinue |
Add-Member NoteProperty EventLog $_ -PassThru | Where-Object {$Events -contains $_.eventid}
} |
# select the properties for the report
Select-Object EventLog, EventID, TimeGenerated, EntryType, Source, Message
This will get it to print with pretty colors. You can tinker around with it and change whatever you want.
$a = "<style>"
$a = $a + "BODY{background-color:peachpuff;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color:black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"
$a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:palegoldenrod}"
$a = $a + "</style>"
$Variable = get-what_I_want
$Variable2 = get-what_I_want
$VariableHTML = $Variable | ConvertTo-HTML -head $a -body "<H2>Title I want</H2>"
$Variable2HTML = $Variable2 | ConvertTo-HTML -head $a -body "<H1>Header One</H1> <H2>Header Two</H2> <H3>Header Three</H3> <p>Paragraph<p/>"
$VariableHTML > C:\PoSH\My_Exported_HTML.html
I added a second variable. As you can see, you can add different levels of headers and a Paragraph. I found this helpful for single line items or if you want a better description.
If I would say: ConvertTo-Html is what you need, than probably that would be enough to add a comment.
Instead I will say: before asking questions outside PowerShell, ask them inside PowerShell first.
Get-Help *html*