$FormatEnumerationLimit = -1 within a PowerShell script - powershell

I have created a PowerShell script, but the output gets cut off with ...}
If I type $FormatEnumerationLimit = -1 before I run the script, it works. But the problem is I can't seem to include this command within my script. If I add this command at the top of my script, it doesn't work.
How can I get this included in the script?? Sorry I don't think the script copied over correctly in the window.
$FormatEnumerationLimit = -1
Get-ChildItem hklm:\SOFTWARE\Wow6432Node\software\nameofsoftware | ForEach- Object {
Get-ItemProperty $_.pspath
} | Foreach-Object {
$Properties = #{
Name = $_.Name
Header= $_.Header
True= $_.True
Schedule = $_.Schedule
}
New-Object -TypeName PSObject -Property $Properties
} | FL | Out-File C:\test.txt -Width 10000
Send-MailMessage -from "joe#joe.com" -to "joe#joe.com" -subject "Test"
-smtpserver 192.168.5.2 -port 25 -Attachments C:\test.txt

FL output is meant for the screen, rather than for files. Besides, why package all the information up to an object only to try and take it apart immediately? You could output the information in the format you want, directly:
} | Foreach-Object {
"Name: " + $_.Name
"Header: " + $_.Header
"True: " + $_.True
"Schedule: " + $_.Schedule
} | Set-Content C:\test.txt

Related

How to read input through a csv file and write the output in an output file in power shell script?

[This is the powershell script to get the selected services status of servers,where list of servers are given through input csv file and the status of those server should be stored in an output file.
-----------Below is the script----------
$Servers = Get-Content "C:\temp\input.csv"
$Log = #()
foreach($Server in $Servers)
{
$Services = Get-Service *HRRA*, "SQL Server Reporting Services" -ComputerName $COMPUTERNAME
foreach ($Service in $Services)
{
$properties = #(
#{n='ServiceName';e={$Service.Name}}
#{n='Status';e={$Service.Status}}
#{n='ServerName';e={$Server}}
)
$Log += "" | select $properties
}
}
$Log | Format-Table -AutoSize | Out-File "D:\temp\test.txt" -Force
------------------------------------New Script----------------------------------
$Computers = Import-Csv "C:\Temp\Input.csv"
#$mailboxdata = Get-Service *HRRA*,"SQL Server Reporting Services" -ComputerName $ComputerName| select machinename,name, status | sort machinename |
#format-table -AutoSize |Out-File "D:\Temp\RRR.txt"
#LogWrite "$ComputerName"
foreach($row in $computers)
{
{
Add-Content -Path D:\Temp\SSRS.txt -Value $mailboxdata }
Get-Content -Path D:\Temp\SSRS.txt
$ComputerName= $row.ComputerName;
$mailboxdata = Get-Service *HRRA*,"SQL Server Reporting Services" -ComputerName $ComputerName| select machinename,name, status | sort machinename |
format-table -AutoSize |Out-File "D:\Temp\SSR.txt"
$fromaddress = "Reporting.Services#accenture.com"
$toaddress = "aditi.m.singh#accenture.Com"
#$toaddress1 = "s.ab.balakrishnan#accenture.com"
$Subject = "SSRS Services Status"
$body = "Please find attached - test"
$attachment = "D:\Temp\SSR.txt"
$smtpserver = "AMRINT.SMTP.ACCENTURE.COM"
$message = new-object System.Net.Mail.MailMessage
$message.From = $fromaddress
$message.To.Add($toaddress)
#$message.To.Add($toaddress1)
$message.IsBodyHtml = $True
$message.Subject = $Subject
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$message.body = $body
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)
}
If i am running the script with static value its giving me output for both the servers---Below is the script----
Get-Service *HRRA*,"SQL Server Reporting Services" -ComputerName VW118627, VW118623 | select name, status, machinename | sort machinename | format-table -AutoSize |
Out-File "D:\Temp\Report.txt"
Looking at the screenshot, I can see the input csv is really a Comma Separated Values file. For these, you use the Import-Csv cmdlet to retrieve an array of computer names from the file.
$outputFile = "D:\temp\test.csv"
# make sure the field name matches what is in the CSV header
$Servers = (Import-Csv -Path "C:\temp\input.csv").ComputerName
$Log = foreach($Server in $Servers) {
# add a test to see if we can reach the server
if (Test-Connection -ComputerName $Server -Count 1 -Quiet -ErrorAction SilentlyContinue) {
Get-Service -Name *HRRA*, "SQL Server Reporting Services" -ComputerName $Server |
Select-Object #{Name = 'MachineName'; Expression = {$Server}},
#{Name = 'ServiceName'; Expression = {$_.Name}},
#{Name = 'Status'; Expression = {$_.Status}}
}
else {
Write-Warning "Server '$Server' is unreachable"
}
}
# if you want the log sorted, do
$Log = $Log | Sort-Object MachineName
# output on screen
$Log | Format-Table -AutoSize
# output to CSV file
$Log | Export-Csv -Path $outputFile -Force -NoTypeInformation
# mail the output csv file using Send-MailMessage
# collect the parameters in a hashtable
$mailParams = #{
SmtpServer = "AMRINT.SMTP.ACCENTURE.COM"
From = "Reporting.Services#accenture.com"
To = "aditi.m.singh#accenture.com"
Subject = "SSRS Services Status"
Body = "Please find attached - test"
BodyAsHtml = $true
Attachments = $outputFile
# add other parameters if needed
# see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage
}
# use 'splatting' to send the email
# see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting
Send-MailMessage #mailParams
P.S. The Format-Table cmdlet is for displaying the object(s) on screen only.

Sending foreach output via email

I have a script that is checking mirror status of databases. Output in Powershell is fine, but when I try to send it via mail, I'm getting "Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData" instead of data itself. I've tried to change it to Out-String but then I'm getting all results in one line. How this could be done to have formated output the same way as it is formated directly in PowerShell?
# rozszerzenie do obslugi
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null;
$mail_from = "xxx";
$mail_to = "xxx";
$mail_subject = "Status mirrorowanych baz";
$mail_encoding = "UTF8";
$mail_smtp = "xxx";
# lista serwerow
$list = #("SERVER01V",
"SERVER02V"
);
$output = foreach($server in $list)
{
$srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" $server;
# pokaz tylko mirrorowane
$databases = $srv.Databases | Where-Object {$_.IsMirroringEnabled -eq $true};
Write-Output "<br>==================================<br>";
Write-Output $server;
Write-Output "<br>==================================<br>";
$databases | Select-Object -Property Name, MirroringStatus | Format-Table -AutoSize | Out-String;
Write-Output "<br>";
}
$mail_body = $output;
Send-MailMessage -To $mail_to -From $mail_from -Subject $mail_subject -SmtpServer $mail_smtp -Encoding $mail_encoding -Body $mail_body -BodyAsHtml
You're currently sending a HTML mail. As such line breaks won't matter. If you want line breaks in your mail you either need to use text format or replace line breaks with a <br /> or something similar. It's probably going to be wise to have manually add <br /> in your look to have a consistent pattern and replace.
Try gather all data into an array, then use ConvertTo-HTML cmdlet, and the 'BodyAsHTML' switch in Send-MailMessage
$DatabaseArray=#()
ForEach ($server in $list) {
$srv = New-Object "Microsoft.SqlServer.Management.Smo.Server" $server
$DatabaseArray += $srv.Databases | Where-Object {$_.IsMirroringEnabled -eq $true} | Select-Object Name,MirroringStatus
}
$HTMLBody = $DatabaseArray | ConvertTo-HTML
Send-MailMessage -subject x -body $HTMLBody -BodyAsHTML

Unable to generate HTML table from Powershell function

I have got a powershell function that gets all errors and warnings from the event logs, counts the occurance of each Event ID and returns a Powershell table. THe code that does this is as follows -
function Get-EventLogs {
[System.Collections.ArrayList]$results = #()
#Do you want to enable transcript for logging all output to file?
$enableLogging = $FALSE
$ExportEnabled = $FALSE
# logging
# if you need detailed logging for troubleshooting this script, you can enable the transcript
# get the script location path and use it as default location for storing logs and results
$log = $MyInvocation.MyCommand.Definition -replace 'ps1','log'
$resultPath = $PSScriptRoot + '\'
Push-Location $resultPath
if ($enableLogging)
{
Start-Transcript -Path $log -ErrorAction SilentlyContinue
Write-Host "Logging enabled..."
Write-Host
Write-Host "Powershell version"
$PSVersionTable.PSVersion
$Host.Version
(Get-Host).Version
Write-host
}
$currentCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture
# Configuration
# selected Event log sources
# limit the feedback only to the following logs
$EventLogList = 'System','Application'
#for FIM Health Check the Security log has less signification value and is skipped
#add it to the eventlog list when you need it
#,'Security'
# if the event logs are containing too much data,
#collect x years of logs
$startdate = ((Get-Date).AddDays(-7))
$Count = 0
$Activity = "Checking log properties"
$allEvents = New-Object System.Collections.Hashtable
$Count = 0
$Activity = "Checking log detaills"
foreach ($eventlog in $EventLogList)
{
#$Count += 1
$pct = ($Count / $EventLogList.Count * 100)
$status = $EventLog + " (" + $Count + "/" + $EventLogList.Count +")"
Write-Progress -Activity $Activity -Status $status -PercentComplete $pct
write-host $count"." $eventlog
[System.Threading.Thread]::CurrentThread.CurrentCulture = New-Object "System.Globalization.CultureInfo" "en-US"
# query the event log
# store the data in a hashtable, to avoid new queries
$allEvents = $Null
$allEvents = Get-WinEvent -FilterHashtable #{logname=$eventlog;StartTime=$startdate;level=0,1,2,3,4,5} -ErrorAction SilentlyContinue
#DEBUG if ($eventlog -eq "Application") { $allevents}
if ($allEvents.count -eq 0)
{
$message = "No events for " + $eventlog + "log since "+ $startdate + "."
Write-Host $message
Write-Host
# no data to process, skip processing for current loop
Continue
}
#For events detailed reporting we're only interested in error events
#not interested in informational events (level 0 and 4)
$evtStats = $allEvents | where -Property level -Notin -Value 0,4 | Group-Object id | Sort-Object Count -Descending
$allevents = $Null
#prep export
$exportfile = $resultPath + "_EventIDStats"+ $eventlog + ".csv.txt"
if ($exportEnabled) {$export | Export-Csv $exportfile -NoTypeInformation}
# evtStats has number and ID attribute
# other attributes must be added:
# - errortype name
# - Source
# - errortype name
# for each event id in the event statistics
# display the most recent event
$Activity = "Looking up last event occurrence..."
$i= 0
foreach ($item in $evtStats)
{
$i += 1
$pct = ($i / $evtStats.Count * 100)
$eventID = $item.Name
$status = "EventID: "+ $item.Name
Write-Progress -Activity $Activity -Status $status -PercentComplete $pct
$customobj = "" | select Count,ErrorID,ErrorType,Message
$customobj.Count = $item.Count
$customobj.ErrorID = $item.Name
#get most recent event from the eventID
$id = $item.Name.ToInt32($Null)
[System.Threading.Thread]::CurrentThread.CurrentCulture = New-Object "System.Globalization.CultureInfo" "en-US"
$lastevent = get-winevent -FilterHashtable #{LogName=$eventlog;Id=$id} -MaxEvents 1 -ErrorAction SilentlyContinue
#depending on local settings, query might fail, if it fails reset to local culture
if ($lastevent.LevelDisplayName.Length -eq 0)
{
[System.Threading.Thread]::CurrentThread.CurrentCulture = $currentCulture
$lastevent = get-winevent -FilterHashtable #{LogName=$eventlog;Id=$id} -MaxEvents 1
}
$customobj.ErrorType = $lastevent.LevelDisplayName
$customobj.Message = $lastevent.Message
#prep EventID export
$exportfile = $resultPath + $eventlog +'_EventID_' + $customobj.ErrorID + ".csv.txt"
if ($exportEnabled)
{
$customobj | Export-Csv $exportfile -NoTypeInformation
}
$results += $customobj
}
#display with format
$results | Format-Table -AutoSize
return ,$results
if ($exportEnabled)
{
$exportfile = $resultPath + "_lastEvents_short_" + $eventlog + ".txt"
$results| Format-Table -AutoSize | out-file $exportfile
$exportfile = $resultPath + "_lastEvents_detail_" + $eventlog + ".txt"
$results | out-file $exportfile
}
}
#Write-Output $results | Format-Table -AutoSize
}
I then need to format the output of this function as a HTML table, so I can show it in my report.
$elogs = (Get-EventLogs) | Out-String
The code above outputs it as a long string (to be expected). But I cannot figure out how to format it as a HTML table. THe code that finally generates the report is as follows -
$Report = ConvertTo-Html -Title "$Computername" `
-Head "<center><h1>Server Report for <br><br>$Computername</h1></center><br /><br />" `
-Body "$Heading $Hardware $elogs $PercentFree $Output $Restarted $Services $Stopped $Css" }
Is there a way to output this as a table?
ConvertTo-Html is able to take an object and render that object as a HTML table. For simplicity's sake, I'll include the -Fragment switch that will ONLY return a HTML table (not all the HTML header, etc.).
Take a simple object, such as some basic process data, and you can create a HTML table:
[PS] $p = Get-Process | Select -First 3 -Property Name,ID
[PS] $p | ConvertTo-Html -Fragment
<table>
<colgroup><col/><col/></colgroup>
<tr><th>Name</th><th>Id</th></tr>
<tr><td>Process1</td><td>1888</td></tr>
<tr><td>Process2</td><td>1536</td></tr>
<tr><td>Process3</td><td>13920</td></tr>
</table>
Note that we don't need to specify a -Body with all the variables; we just need to make sure that we have all the data collected in an object (with the appropriate property names) and the cmdlet does the rest.
Going back to your script, there are a few things to look at:
Don't use Write-Host. If you want debug messages, consider using Write-verbose and Write-Debug. You'll need to set the $VerbosePreference and $DebugPreference variables to "Continue" to make this output visible.
Similarly, avoid using Format-Table
Your script returns an object ,$results. You should be able to pipe this into ConvertTo-Html with additional header and body content.
Note finally that the -Body switch doesn't format your object; it just includes extra HTML in front of the HTML table.

CPU & Memory Usage Script

Hi I am running this script again multiple servers (initially posted here) & I would like to get each specific servers names to be appeared in the result. But right now, I am able to get with the heading CPU & Memory Usage & then the usage for each server one after the other. Pls let me know how to get each server name & the result.
$Output = 'C:\temp\Result.txt'
$ServerList = Get-Content 'C:\temp\ServerNames.txt'
$ScriptBLock = {
$CPUPercent = #{
Label = 'CPUUsed'
Expression = {
$SecsUsed = (New-Timespan -Start $_.StartTime).TotalSeconds
[Math]::Round($_.CPU * 10 / $SecsUsed)
}
}
$MemUsage = #{
Label ='RAM(MB)'
Expression = {
[Math]::Round(($_.WS / 1MB),2)
}
}
Get-Process | Select-Object -Property Name, CPU, $CPUPercent, $MemUsage,
Description |
Sort-Object -Property CPUUsed -Descending |
Select-Object -First 15 | Format-Table -AutoSize
}
foreach ($ServerNames in $ServerList) {
Invoke-Command -ComputerName $ServerNames {Write-Output "CPU & Memory Usage"}
| Out-File $Output -Append
Invoke-Command -ScriptBlock $ScriptBLock -ComputerName $ServerNames |
Out-File $Output -Append
I see you're running with a loop on the servers names ($ServerNames is each server for each iteration), so why don't you use:
"Working on $ServerNames.." | Out-File $Output -Append
on the first line after the "foreach" statement?
Anyway, I think you can change your script like this:
On the script block add:
Write-Output "CPU & Memory Usage"
hostname | out-file $output -Append # this will throw the server name
Once you have this on the Scriptblock, you can run it like this:
Invoke-Command -ScriptBlock $ScriptBLock -ComputerName $ServerList
($ServerList is the original servers' array, which "Invoke-Command" knows how to handle).

Adding a config file to loop through for a PS script

My powershell script is setup as follows:
$body = Get-ChildItem E:\log -File -Recurse | Where Name -Match '(\d{8})\.' |
Foreach {Add-Member -Inp $_ NoteProperty ReturnDate ($matches[1]) -PassThru} |
Group DirectoryName |
Foreach {$_.Group | Sort ReturnDate -Desc | Select -First 1 | Out-String }
$emailSmtpServer = "server"
$emailFrom = "email"
$emailTo = "email"
$emailSubject = "Testing e-mail"
$emailBody = $body
Send-MailMessage -To $emailTo -From $emailFrom -Subject $emailSubject -Body ($body|Out-String) -SmtpServer $emailSmtpServer
In the log folder I have a bunch of subfolders, e.g. folder1, folder2, folder3. These are likely to change so I'd like to setup a config file to be able to maintain them instead of going through the entire E:\log folder each time I run the script.
I want to add something such as
$configfile = Get-Content -path E:\config.txt
This outputs Process1, Process2, Process3, etc and I'm uncertain how to put that data into my script the way it's currently structured. Any advice would be appreciated. I was trying to add
$body = Get-Childitem E:\log\$_
to my initial line, but that was not working
Try this:
get-childitem ( get-content e:/config.txt )