Format the results of a PowerShell script - powershell

I'm trying to retrieve Azure service bus queues who has exceeded a specific message count, and the script is working well so far, but when it retrieves the values, it just does it in the following format:
The limit has been exceeded for the following queues:q1-monitoring-endpoint q1-monitoring-endpoint q2-monitoring-endpoint q3-monitoring-endpoint
I need to retrieve them in a better format.
Here is the script, I'm using:
$NS = Get-AzureRmServiceBusNamespace
foreach ($NS in $NS)
{
$Queue = Get-AzureRmServiceBusQueue -ResourceGroupName $NS.ResourceGroup -Namespace $NS.Name
if ($Queue.MessageCount -eq 0 )
{
"The limit has been exceeded for the following queues:" + $Queue.Name
}
}

I don't have access to an Azure subscription at the moment to test this, but consider doing something along these lines:
Get-AzureRmServiceBusNamespace |
ForEach-Object {
Get-AzureRmServiceBusQueue -ResourceGroupName $_.ResourceGroup -Namespace $_.Name |
ForEach-Object {
[PsCustomObject]#{
Queue = $_.Name
LimitExceeded = ($_.MessageCount -eq 0)
}
}
}
This will (hopefully) produce output similar to the following:
Queue LimitExceeded
------ -------------
Queue1 False
Queue2 True
Queue3 False
Not only is this a neater format than the original string output, it means you get some objects as output, which can be further manipulated.

You should explain "in a better format". However, your main issue is within your foreach loop where you try to iterate over $NS but assign the current object to $NS. You need to choose a different variable:
$NS = Get-AzureRmServiceBusNamespace
foreach ($N in $NS)
{
$Queue = Get-AzureRmServiceBusQueue -ResourceGroupName $N.ResourceGroup -Namespace $N.Name
if ($Queue.MessageCount -eq 0 )
{
"The limit has been exceeded for the following queues:" + $Queue.Name
}
}
Note: I would recommend to retrieve all empty queues and save it in a variable (which enables you to use it later):
$emptyQueue = Get-AzureRmServiceBusNamespace |
ForEach-Object {
Get-AzureRmServiceBusQueue -ResourceGroupName $_.ResourceGroup -Namespace $_.Name
} |
Where-Object MessageCount -eq 0
Finally, output it in your desired format:
Write-Host "The limit has been exceeded for the following queues: $($Queue.Name -join ',')"

You can try the Format commands available in powershell to get the output in a better format.
You can define your custom format as well with Format-Custom command.
Reference for Format commands in Powershell : https://learn.microsoft.com/en-us/powershell/scripting/getting-started/cookbooks/using-format-commands-to-change-output-view?view=powershell-6

Related

Using Get-Job to test-connection, but quite different [duplicate]

This question already has answers here:
If using Test-Connection on multiple computers with -Quiet how do I know which result is for which computer?
(2 answers)
Closed 2 years ago.
It's my first post here, I'm tring to write scripts on PS on my own, now my target is to write script that checks if computer is online at network, for example: test-Connection 192.168.0.1, 2, 3 etc. Doing this one by one on loop for takes some time if some computers are offline, I've found some tutorials on this site to use -AsJob param, but I'm not really Sure how could it work. I mean I'd like to output every checked PC to excel, so i need if operator. eg:
if (Job1 completed successfull (computer pings)){
do smth}...
I need to get output from Job boolean (true/false), but one by one. I'm taking my first steps in PS, I've made program that checks it one by one in for loop, but as i said it take some time till my excel file fill...
I can see, that AsJob makes working more effective and I think it's important to understand it
Thanks and sorry for bad text formatting, by the time I'll go on with this!
In your example, in the Start-Job scriptblock you are trying to access $_ which is not available in the codeblock scope. If you replace $_ with $args[0] it should work since you are passing in the $ip value as an argument
Your Example
$ipki = Get-Content 'C:\Users\pchor\Desktop\ipki.txt'
foreach ($ip in $ipki) {
Start-Job -Name "$ip" -ScriptBlock {
Test-Connection $_ -Count 1 # <---- replace $_ with $args[0]
} -ArgumentList $_ # <----- change $_ to $ip
}
You'll probably also want to wait for all the jobs to finish. I recommend something like this
$computers = #(
'www.google.com'
'www.yahoo.com'
)
$jobs = $computers |
ForEach-Object {
Start-Job -ScriptBlock {
[pscustomobject]#{
Computer = $using:_
Alive = Test-Connection $using:_ -Count 1 -Quiet
}
}
}
# Loop until all jobs have stopped running
While ($jobs |
Where-Object { $_.state -eq 'Running' }) {
"# of jobs still running $( ($jobs | Where-Object {$_.state -eq 'Running'}).Count )";
Start-Sleep -Seconds 2
}
$results = $jobs | Receive-Job | Select-Object Computer, Alive
$results | Format-Table
Output
Computer Alive
-------- -----
www.google.com True
www.yahoo.com True
To modify the properties to what you want there are different ways of doing this. Easiest in this case is probably to use a calculated property
$newResults = $results |
Select-Object Computer,
#{Label = 'State'; Expression = { if ($_.Alive) { 'Online' } else { 'Offline' } } }
Objects will now look like this (I added another fake address to illustrate offline state)
Computer State
-------- -----
www.google.com Online
www.yahoo.com Online
xxx.NotAValidAddress.xxx Offline
You can then export the objects to csv using Export-csv
$newResults | Export-Csv -Path c:\temp\output.csv

User input VM name should start via powerhsell

Purpose - I am trying to start vm if it is in stop state
Note - user will input Vm name , if its stop then it will start otherwise it will pop up that server already in started state.
$user = 'tooltest' #Vmname
$rg = Get-AzureRmResourceGroup
$data= $rg.ResourceGroupName
foreach ( $d in $data){
$res = Get-AzureRmResource | Where-Object {$_.ResourceGroupName -eq $d}
if ( $res.Name -eq $user){
Write-Output $res.Name
Write-Output $res.ResourceGroupName
$gg = Get-AzureRmVM -ResourceGroupName [string]$res.ResourceGroupName -Name $user -Status
If i m trying to print $res.ResourceGroupName - i am getting output of resourcegroup name 26 times (26 resources i have in That RG)
I wanted to print RG only one time , can anybody help me on that
One way to filter your output is just to select how many objects do you want with the Select-Object cmdlet.
Write-Output $res.ResourceGroupName | Select -First 1

SSRS Cache Schedule Re

I have about ~50 reports that are scheduled to be "cached" on a recurring schedule (image below).
Is this information only available in Report Server Database or can the schedule information be retrieved using Powershell? All of the "obvious" methods I've run thus far (with powershell ise) either return no information or boolean values (all 'false')
You can use GetItemHistoryOptions to get the schedule for the report item.
Then based on the type of Item property of the ScheduleDefinitionOrReference [ref] parameter of the method, you can decide how to show the information.
Type of the Item, can be one of MinuteRecurrence, DailyRecurrence, WeeklyRecurrence, MonthlyRecurrence or MonthlyDOWRecurrence.
Example
For example to format MonthlyRecurrence you can use such code:
$svcUrl = 'http://the-host-name/ReportServer/reportservice2010.asmx'
$svc = New-WebServiceProxy -Class 'RS' -Namespace 'RS' -Uri $svcUrl -UseDefaultCredential
$reports = $svc.ListChildren("/", $true) | Where-Object { $_.TypeName -eq "Report" }
$KeepExecutionSnapshots = $false
$ScheduleDefinitionOrReference = New-Object RS.ScheduleDefinitionOrReference
foreach ($report in $reports) {
$result = $svc.GetItemHistoryOptions($report.Path,
[ref]$KeepExecutionSnapshots,
[ref]$ScheduleDefinitionOrReference)
if($ScheduleDefinitionOrReference.Item -is [RS.MonthlyRecurrence])
{
"'$($report.Name)' Schedule Information:"
"StartDateTime: $($ScheduleDefinitionOrReference.StartDateTime)"
"StartDateTime: $($ScheduleDefinitionOrReference.EndDate)"
"EndDateSpecified: $($ScheduleDefinitionOrReference.EndDateSpecified)"
"Days: $($ScheduleDefinitionOrReference.Item.Days)"
$months = Get-Member `
-InputObject $($ScheduleDefinitionOrReference.Item.MonthsOfYear) `
-MemberType Property | Where-Object {
$ScheduleDefinitionOrReference.Item.MonthsOfYear.$($_.Name) -eq $true
}
"Months:$($months.Name -join ",")"
}
}
And the result will be something like this:
'MyReport' Schedule Information:
StartDateTime: 12/19/2017 18:00:00
StartDateTime: 01/01/0001 00:00:00
EndDateSpecified: False
Days: 1,3-5
Months:August,December,July,November,October,September

Parsing multiple valus in multiple variables

I am trying to find a way to execute a command in powershell and put each line of the result in a different variable to use them later in my script. For example if i execute the below command:
C:\> Get-VMHost -Name hq-esxi-prod-01a.nsx.gss | Get-VM | select Name
I will get the below:
Name
----
HQ-LinServ-01a
HQ-Win2012-01a
HQ-Web-02a
I want to have a script that will add each line in a different variable in a script (excluding the first which is name).
how can i do that.
Thank you for your help.
You can use Set-Variable in a loop to put each value in a separate variable:
$i = 0
... | Get-Vm | Select-Objet -Expand Name | ForEach-Object {
Set-Variable -Name "vm$i" -Value $_
$i++
}
However, that usually isn't good advice. It's more common to put all names in one (array) variable:
$vmList = ...| Get-Vm | Select-Object -Expand Name
so you can access individual names via $vmList[<index>], or (if you need access by some kind of name) in a hashtable:
$i = 0
$vmList = #{}
... | Get-Vm | Select-Objet -Expand Name | ForEach-Object {
$vmList["vm$i"] = $_
$i++
}
Best practice would depend on the particular scenario you need this for, though.
Thank you for your reply,
I have tried you answer but it seems that i am using PowerCLI for VMware it does not include Select-Object -Expand (not sure i had an exception), However your answer have mad me reach to a suitable answer for this.
I have used the below and it worked fine using foreach and adding the values in an array and then reading them as below:
$p1vmname = Get-VMHost -Name hq-esxi-prod-01a.nsx.gss | Get-VM | select Name
$p1vmlist = #()
foreach ($p1line in $p1vmname)
{
$p1vmlist += $p1line
}
$p1 = 0
do {
$x = $p1+1
Write-Host -BackgroundColor:Black -ForegroundColor:Yellow "vm number $x is "$p1vmlist[$p1]"."
$p1++
}
until ($p1 -eq $p1vmc)
}
However when using this the names was not totally correct as they had some additional characters as below:
vm number 1 is #{Name=HQ-Web-01a}
vm number 2 is #{Name=HQ-LinServ-01a}
vm number 3 is #{Name=HQ-Win2012-01a}
so i used split and trim to get rid of these as below and worked fine.
$p1vmname = Get-VMHost -Name hq-esxi-prod-01a.nsx.gss | Get-VM | select Name
$p1vmlist = #()
foreach ($p1line in $p1vmname)
{
$p1vmlist += $p1line
}
$p1 = 0
do {
$x = $p1+1
$p1vmlist[$p1] = ($p1vmlist[$p1]) -split("=") | Select-Object -Last 1
$p1vmlist[$p1] = $p1vmlist[$p1].trimend("}")
Write-Host -BackgroundColor:Black -ForegroundColor:Yellow "vm number $x is "$p1vmlist[$p1]"."
$p1++
}
until ($p1 -eq $p1vmc)
}
Output:
vm number 1 is HQ-Web-01a .
vm number 2 is HQ-LinServ-01a .
vm number 3 is HQ-Win2012-01a .
Thank you so much for your answer that helped me a lot.
I am really enjoying scripting now.

How to get server information from VMware

I have access to the VMWare GUI and I can easily export all the columns such as UPtime, IPAddress, Notes, DNS, GuestOs, State, Name and so on.
I want to right a script that can automatically get this information daily. So gar I was only able to get the server name, power state and VMhost. for some reason VMware is making it so hard to extract that information. I used the script below and I thought by adding the columns I mentioned above to this script, I should be able to retireve the data I need. But it doesn't work that way. Can someone please tell me how I can get this information?
Thanks,
Add-PSSnapin vmware.vimautomation.core
Connect-VIServer SERVERNAME
Get-VM|Select Name, VMHost, Id, PowerState
Exit 0
After digging into the system and many hours of research I found the solution. I just wish VMWare would make it easier to retrieve data or at least improve the manual.
The following code creates two files; one with the server information and another one with Uptime information.
Get-VM | select name,VMHost, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }}, #{ Name = "PowerState"; Expression = { $_.Guest.State }} , #{ Name = "GuestOS"; Expression = { $_.Guest }}, Notes | Export-Csv -Path "HQstat.csv"
Get-Stat -Entity * -Stat sys.uptime.latest -Realtime -MaxSamples 1| Export-Csv -Path "HQtime.csv"
Why not use the views? They have all the information that you need. Code below assumes you are connected to the vCenter.
$vmView = Get-View -ViewType VirtualMachine -Property Name,Config,Guest,Runtime
$hostView = Get-View -ViewType HostSystem -Property Name
$date = Get-Date
Foreach ($vm in $vmView)
{
If ($vm.Runtime.BootTime -ne $null)
{
$dateDiff = $date.Subtract($vmView.Runtime.BootTime)
}
Else
{
$dateDiff = $null
}
foreach ($h in $hostView)
{
If ($vm.Runtime.Host -eq $h.MoRef)
{
$tempHost = $($h.Name)
Break
}
}
$global:Export += #([PSCustomObject]#{
VMName = $($vm.Name)
ID = $($vm.Config.Uuid) #or use $($vm.MoRef)
Host = $tempHost
PowerState = $($vm.Guest.GuestState)
IPAddress = $($vm.Guest.IPAddress)
Notes = $($vm.Config.Annotations)
UptimeMinutes = $($dateDiff.TotalMinutes)
})
$dateDiff = $null
$tempHost = $null
}
$exportFileName = "C:\temp\VMInformation.csv"
$Export | Export-Csv $exportFileName -Force -NoTypeInformation