how to use if/else statement to replace a value in PowerShell - azure

function Get-vmstatus {
# Sign into Azure Portal
connect-azaccount
# Fetch the Virtual Machines from the subscription
$azureVMDetails = get-azvm
# Fetch the NIC details from the subscription
$azureNICDetails = Get-AzNetworkInterface | ? { $_.VirtualMachine -NE $null }
#Fetching Virtual Machine Details
$virtual_machine_object = $null
$virtual_machine_object = #()
#Iterating over the NIC Interfaces under the subscription
foreach ($azureNICDetail in $azureNICDetails) {
$azureVMDetail = $azureVMDetails | ? -Property Id -eq $azureNICDetail.VirtualMachine.id
$vm_status = get-azvm -ResourceGroupName $azureVMDetail.resourcegroupname -name $azureVMDetail.name -Status
$vm_tags = ($azureVMDetail.Tags.values) -join ';'
$vmsize = Get-AzVMSize -VMName $azureVMDetail.Name -ResourceGroupName $azureVMDetail.ResourceGroupName | ? { $_.Name -eq $azureVMDetail.HardwareProfile.VmSize }
$OsDisksize = $azureVMDetail.StorageProfile.OsDisk.DiskSizeGB
#Fetching the private IP
$private_ip_address = ($azureNICDetail.IpConfigurations | select-object -ExpandProperty PrivateIpAddress) -Join ';'
#VM Details export
$virtual_machine_object_temp = new-object PSObject
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "Name" -Value $azureVMDetail.Name
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "VCPUs" -Value $vmsize.NumberOfCores
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "Status" -Value $vm_status.Statuses[1].DisplayStatus
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "Memory" -Value $vmsize.MemoryInMB
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "Disk" -Value $OsDisksize
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "Comments" -Value $vm_tags
$virtual_machine_object += $virtual_machine_object_temp
}
$virtual_machine_object | Export-Csv "C:\Users\mouj\Desktop\Inventory\Final Scripts\VM_details_$(get-date -f dd.MM.yyyy).csv" -NoTypeInformation -Force
}
After running the script the Status of the Azure VMs are shown as VM running, VM stopped, VM deallocated. Now i want to replace the VM running with "Active" and VM stopped, VM deallocated with "Offline". How can i do with conditional statement or is there any other way to do it ? Thanks in advance

Use Add-Member to add a ScriptProperty - a dynamic property that can reference the value(s) of other properties on the object:
$virtual_machine_object_temp | Add-Member -MemberType ScriptProperty -Name State -Value { if($_.Status -eq 'Running'){ 'Active' }else{ 'Offline' } }
Now, whenever you look at the new State property, it will resolve to Active whenever the Status property is Running, otherwise Offline

Related

How can i pull out all metrics for a resource in Azure using Powershell?

I am at the moment running the following Powershell scipt pull out metrics from Azure
` #login to azure and set context
$Resource = Get-AzResource -ResourceName <appservicename> -ResourceGroupName <resourcegroup> - ResourceType "Microsoft.Web/sites"
$ResourceID = $Resource.ResourceId
$MetricsDefinition = Get-AzMetricDefinition -ResourceId $ResourceID
$MetricsDefinitionHash = #{}
$MetricsDefinition | % {
$Name = $_.Name
$Unit = $_.Unit
$MetricsDefinitionHash.Add($Name,$Unit)
}
$TotalResult = #()
$Metrics = Get-AzMetric -ResourceId $ResourceID -StartTime (Get-date).AddHours(-24) -TimeGrain 00:01:00
$Metrics | % {
if($_.Data -ne $null)
{
$Calc, $metricName, $Result = $Null
$i=0;
$MetricName = $_.Name
$_.Data | % {
$calc += $_.Average
$i++
}
$Result = $Calc/$i
$MetricUnit = $MetricsDefinitionHash["$MetricName"]
$MetricResult = New-Object PSObject
$MetricResult | add-member Noteproperty MetricName $metricName
$MetricResult | add-member Noteproperty MetricValue $Result
$MetricResult | add-member Noteproperty MetricUnit $MetricUnit
$TotalResult += $MetricResult
}
}
`
I expected a result of
MetricName MetricValue MetricUnit
AverageResponseTime 0.7866443 Seconds
AverageMemoryWorkingSet 80747385.625 Bytes
MemoryWorkingSet
Http5xx
Http4xx
Http406
Http404
Http403
Http401
Http3xx 0
Http2xx 0
BytesSent 4699.123
BytesReceived 7.8
Requests 9.4444
CpuTime 0.1111
I have left some values empty , but you get the idea.
The issue is im only getting CpuTime .
Any ideas on why i would only be getting that ?
I have tried in my environments to get those metrics
$Resource = Get-AzResource -ResourceName “metricdemoapp” -ResourceGroupName “xxx” -ResourceType "Microsoft.Web/sites"
$ResourceID = $Resource.ResourceId
$Metrics = Get-AzMetric -ResourceId $ResourceID -StartTime (Get-date).AddHours(-24) -TimeGrain 00:01:00
The above returns variable $Metrics returns only metrics of CpuTime and its details like Id, name, type ,unit ,Data,timeseries as it is the first metric that appears
With Id : /subscriptions/xxxxxx23f/resourceGroups/xxxxx/providers/Microsoft.Web/sites/metricdemoapp/providers/Microsoft.Insights/metrics/CpuTime
After Checking the supported metrics in portal in my case , web app service
when tried with other metric name, got the units as required.
Where as below command for definition gives details of all metrics along with details one by one.
$MetricsDefinition = Get-AzMetricDefinition -ResourceId $ResourceID
$MetricsDefinition
Powershell :
$Resource = Get-AzResource -ResourceName “metricdemoapp” -ResourceGroupName “xxx” -ResourceType "Microsoft.Web/sites"
$ResourceID = $Resource.ResourceId
$MetricsDefinition = Get-AzMetricDefinition -ResourceId $ResourceID
$MetricsDefinition
$i=0
foreach($metric in $MetricsDefinition)
{
$MetricName=$MetricsDefinition.Name.Value[$i]
$MetricDetails= Get-AzMetric -ResourceId $ResourceID -MetricName $MetricName
$MetricDataValue=$MetricDetails.Data
$Timestamp=$MetricDetails.Data.TimeStamp
$Average=$MetricDetails.Data.Average
$mCount=$MetricName.Value.Count
$count=$mCount-1
$MetricUnit=$metric.Unit
$MetricUnit
$MetricValue=$MetricName.Value
$MetricValue
$MetricResult = New-Object PSObject
$MetricResult | add-member Noteproperty MetricName $MetricName
$MetricResult | add-member Noteproperty MetricUnit $MetricUnit
$MetricResult | add-member Noteproperty MetricDetails $MetricDetails
$MetricResult | add-member Noteproperty MetricDataValue $MetricDataValue
$MetricResult | add-member Noteproperty TimeStamp $Timestamp
$MetricResult | add-member Noteproperty Average $Average
$MetricResult
$i++
}
Output:
Will be something like:
MetricName : CpuTime
MetricUnit : Seconds
MetricDetails : Microsoft.Azure.Commands.Insights.OutputClasses.PSMetricNoDetails
MetricDataValue : {Microsoft.Azure.Commands.Insights.OutputClasses.PSMetricValue, Microsoft.Azure.Commands.Insights.OutputClasses.PSMetricValue, Microsoft.Azure.Commands.Insights.OutputClasses.PSMetricValue,
Microsoft.Azure.Commands.Insights.OutputClasses.PSMetricValue…}
TimeStamp : {11/24/2022 6:23:00 AM, 11/24/2022 6:24:00 AM, 11/24/2022 6:25:00 AM, 11/24/2022 6:26:00 AM…}
Average : {$null, $null, $null, $null…}
And continues for every metric like below
Where AverageResponseTime is one of the metrics you can see
EDIT: 28/11/2022
Try adding aggregation type Average lie $MetricDetails= Get-AzMetric -ResourceId $ResourceID -MetricName $MetricName -AggregationType Average -TimeGrain 06:00:00
$MetricsDefinition = Get-AzMetricDefinition -ResourceId $ResourceID
$i=0
foreach($metric in $MetricsDefinition)
{
$MetricName=$MetricsDefinition.Name.Value[$i]
$MetricDetails= Get-AzMetric -ResourceId $ResourceID -MetricName $MetricName -AggregationType Average -TimeGrain 06:00:00
$MetricDataValue=$MetricDetails.Data
$Timestamp=$MetricDetails.Data.TimeStamp
$Average=$MetricDetails.Data.Average
$mCount=$MetricName.Value.Count
$count=$mCount-1
$MetricUnit=$metric.Unit
$MetricUnit
$MetricValue=$MetricName.Value
$MetricValue
$MetricResult = New-Object PSObject
$MetricResult | add-member Noteproperty MetricName $MetricName
$MetricResult | add-member Noteproperty MetricUnit $MetricUnit
$MetricResult | add-member Noteproperty MetricDetails $MetricDetails
$MetricResult | add-member Noteproperty MetricDataValue $MetricDataValue
$MetricResult | add-member Noteproperty TimeStamp $Timestamp
$MetricResult | add-member Noteproperty Average $Average
$MetricResult
$i++
}

How to split different values in powershell by a line

With this script i am able to fetch all the Tags that a VM has but i want that in output the each key and its value should be separated by a line in the way that each key and its value appears on different lines like this
reference image
# Sign into Azure Portal
connect-azaccount
# Fetch the Virtual Machines from the subscription
$azureVMDetails = get-azvm
# Fetch the NIC details from the subscription
$azureNICDetails = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
#Fetching Virtual Machine Details
$virtual_machine_object = $null
$virtual_machine_object = #()
#Iterating over the NIC Interfaces under the subscription
foreach($azureNICDetail in $azureNICDetails){
#Fetching the VM Name
$azureVMDetail = $azureVMDetails | ? -Property Id -eq $azureNICDetail.VirtualMachine.id
#Fetching the VM Tags
foreach($azureDetail in $azureVMDetails) {
$vm_tags = $azureVMDetail| Select-Object -Property (
#{name='Tags'; expression = {($_.tags.GetEnumerator().ForEach({ '{0} : {1}' -f $_.key, $_.value }) -join ';')}}
)
}
#VM Details export
$virtual_machine_object_temp = new-object PSObject
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "name" -Value $azureVMDetail.Name
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "comments" -Value ($vm_tags.Tags -join ';')
$virtual_machine_object += $virtual_machine_object_temp
}
#Report format and path
$virtual_machine_object | Export-Csv "C:\Users\JOHN\Desktop\Inventory\Final Scripts\VM_details_$(get-date -f dd.MM.yyyy).csv" -NoTypeInformation -Force
I tried to reproduce the same in my environment and got the results successfully by using the below PowerShell script:
$vmdeatil = Get-AzVm -Name testvm | Select -ExpandProperty Tags
$value = $vmdeatil
foreach($i in 0..($value.Count -1))
{
$ErrorActionPreference = ‘SilentlyContinue’
[array]$report += [pscustomobject] #{
key = $key[$i]
name = $value[$i]
}
}
$report | Export-Csv -Path "C:\Users\ruk1.csv" -NoTypeInformation
Response:
The output is successfully exported in the csv file like below:

Programatically Get ADF pipeline consumption report

I'm interested in querying the pipeline consumption report that is available from the Data Factory monitor. Is there a table on Log Analytics or PowerShell cmdlet that would return this information? I checked the ADFv2 PowerShell module but couldn't find any. My goal is to aggregate the information available in this report to identify what are the most costly pipelines.
reference: https://techcommunity.microsoft.com/t5/azure-data-factory/new-adf-pipeline-consumption-report/ba-p/1394671
Thank you
Doing more research someone pointed me to a GitHub page where the product team posted a PowerShell script to find part of what I was looking for {1}. So I did some modifications to the script to have the output that I needed. With the output below I can extract the values from the MS calculator to get an estimated cost for each pipeline run. {2}
$startTime = "21/6/2021 7:00:00"
$endTime = "21/6/2021 10:00:00"
$adf = '<data factory name>'
$rg = '<resrouce group name>'
$outputObj = #()
$pipelineRuns = Get-AzDataFactoryV2PipelineRun -ResourceGroupName $rg -DataFactoryName $adf -LastUpdatedAfter $startTime -LastUpdatedBefore $endTime
# loop through all pipelines and child activities to return billable information
foreach ($pipelineRun in $pipelineRuns) {
$activtiyRuns = Get-AzDataFactoryV2ActivityRun -ResourceGroupName $rg -DataFactoryName $adf -pipelineRunId $pipelineRun.RunId -RunStartedAfter $startTime -RunStartedBefore $endTime
foreach ($activtiyRun in $activtiyRuns) {
if ($null -ne $activtiyRun.Output -and $null -ne $activtiyRun.Output.SelectToken("billingReference.billableDuration")) {
$obj = #()
$obj = $activtiyRun.Output.SelectToken("billingReference.billableDuration").ToString() | ConvertFrom-Json
$obj | Add-Member -MemberType NoteProperty -Name activityType -value $activtiyRun.Output.SelectToken("billingReference.activityType").ToString()
$obj | Add-Member -MemberType NoteProperty -Name pipelineName -value $pipelineRun.PipelineName
$obj | Add-Member -MemberType NoteProperty -Name activtiyRuns -value $activtiyRuns.Count
$outputObj += $obj
}
else {}
}
}
# output aggregated result set as table
$groupedObj = $outputObj | Group-Object -Property pipelineName, activityType, meterType
$groupedObj | ForEach-Object {
$value = $_.name -split ', '
New-Object psobject -Property #{
activityType = $value[1];
meterType = $value[2];
pipelineName = $value[0];
executionHours = [math]::Round(($_.Group | Measure-object -Property duration -sum).Sum, 4)
orchestrationActivityRuns = $groupedObj.group.activtiyRuns[0]
}
} | Sort-Object -Property meterType | Format-Table
Output sample:
Consumption report from the Data Factory monitor
reference:
https://github.com/Azure/Azure-DataFactory/tree/main/SamplesV2/PastRunDetails#simple-script-that-prints--activity-level-run-details-in-45-day-range {1}
https://azure.microsoft.com/en-us/pricing/calculator/?service=data-factory%2F {2}

Object within a hashtable

I'm trying to put objects in a hashtable. I'm not getting errors but cannot access the data.
$Level1Hashtable = #{}
$Level2Object = New-Object System.Object
$Level2Object | Add-Member -MemberType NoteProperty -Name Name -Value "abc"
$Level2Object | Add-Member -MemberType NoteProperty -Name IpAddress -Value "192.168.1.1"
$Level1Hashtable.Add("Test1",$Level2Object)
$Level2Object = New-Object System.Object
$Level2Object | Add-Member -MemberType NoteProperty -Name Name -Value "123"
$Level2Object | Add-Member -MemberType NoteProperty -Name IpAddress -Value "192.168.1.1"
$Level1Hashtable.Add("Test2",$Level2Object)
$Level1Hashtable.Test1.IpAddress
This kind of redundant instantiation doesn't really impress me, so I went a slightly different route:
$Servers =
#{
"DC1" = [pscustomobject]#{ FQDN = "dc1.ad.foobar.com"; IpAddress = "192.168.2.1"}
"DC2" = [pscustomobject]#{ FQDN = "dc2.ad.foobar.com"; IpAddress = "192.168.2.2"}
"STS" = [pscustomobject]#{ FQDN = "sts.ad.foobar.com"; IpAddress = "192.168.2.3"}
}
Then you can also access elements very easily:
Servers["DC1"].IpAddress = "192.168.2.4"
Tested on PowerShell Core (aka PowerShell 6), works like a charm. Cheers.
That works for me using V4. Running in V2 it doesn't work, but does if I switch from using System.Object to PSObject for the object type in the New-Object cmdlets.
$Level1Hashtable = #{}
$Level2Object = New-Object PSObject
$Level2Object | Add-Member -MemberType NoteProperty -Name Name -Value "abc"
$Level2Object | Add-Member -MemberType NoteProperty -Name IpAddress -Value "192.168.1.1"
$Level1Hashtable.Add("Test1",$Level2Object)
$Level2Object = New-Object PSObject
$Level2Object | Add-Member -MemberType NoteProperty -Name Name -Value "123"
$Level2Object | Add-Member -MemberType NoteProperty -Name IpAddress -Value "192.168.1.1"
$Level1Hashtable.Add("Test2",$Level2Object)
$Level1Hashtable.Test1.IpAddress
Depending on the version of PowerShell you're using Add-Member had an issue (v1 and maybe v2) where you had to use -PassThru and reassign to the original object e.g.:
$Level2Object = $Level2Object | Add-Member NoteProperty Name abc -PassThru
In V3 you can create this more simply like so:
$Level2Object = [pscustomobject]#{Name='abc';IpAddress='192.168.1.1'}
In V2 you can use the Property parameter on new-object to simplify as well:
$Level2Object = new-object psobject -property #{Name='abc';IpAddress='192.168.1.1'}

Using PowerShell's Add-Member results in an error

Why does the script below come up with the following error?
"Add-Member : Cannot process command because of one or more missing
mandatory parameters: InputObject.
+ $obj = Add-Member <<<< -MemberType NoteProperty -Name ComputerName -Value $ComputerName
+ CategoryInfo : InvalidArgument: (:) [Add-Member], ParameterBindingException
+ FullyQualifiedErrorId : MissingMandatoryParameter,Microsoft.PowerShell.Commands.AddMemberCommand"
Script
# Receives the computer name and stores the required results in $obj.
Function WorkerNetworkAdaptMacAddress {
Param($ComputerName)
$colItems = GWMI -cl "Win32_NetworkAdapterConfiguration" -name "root\CimV2" -comp $ComputerName -filter "IpEnabled = TRUE"
$obj = New-Object -TypeName PSobject
ForEach ($objItem in $colItems)
{
$obj = Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName
$obj = Add-Member -MemberType NoteProperty -Name MacAddress -Value $objItem.MacAddress
$obj = Add-Member -MemberType NoteProperty -Name IPAdress -Value $objitem.IpAddress
}
Write-Output $obj
}
# Receives the computer name and passes it to WorkerNetworkAdaptMacAddress.
Function Get-NetworkAdaptMacAddress {
begin {}
process{
WorkerNetworkAdaptMacAddress -computername $_
}
end {}
}
# Passes a computer name to get-networkAdaptMacAddress
'tbh00363' | Get-NetworkAdaptMacAddress
You need to move the PSObject creation into the loop. Otherwise, you'll get errors that the properties already exist on the object.
Secondly, you need to tell Add-Member on which object to operate. You do it either by piping the object to the cmdlet or by specifying it on the InputObject parameter. Finally, return the object back to the pipeline by specifying the PassThru switch on the last Add-Member call:
ForEach ($objItem in $colItems)
{
$obj = New-Object -TypeName PSobject
Add-Member -InputObject $obj -MemberType NoteProperty -Name ComputerName -Value $ComputerName
Add-Member -InputObject $obj -MemberType NoteProperty -Name MacAddress -Value $objItem.MacAddress
Add-Member -InputObject $obj -MemberType NoteProperty -Name IPAddress -Value $objitem.IpAddress -PassThru
}
Alternatively, you could simplify the process with New-Object's -Property parameter:
Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $ComputerName -Filter "IpEnabled=TRUE" | Foreach-Object {
New-Object -TypeName PSobject -Property #{
ComputerName=$ComputerName
MacAddress=$_.MacAddress
IPAddress=$_.IpAddress
}
}
Or by using Select-Object:
Get-WmiObject ... | Select-Object #{n='ComputerName';e={$_.__SERVER}},MacAddress,IpAddress
First you need to specify the input object to which the property should be added by piping it to the Add-Member cmdlet.
Then, if you want the cmdlet to return the modified object, you should invoke it with the -PassThru argument:
When you use the PassThru parameter, Add-Member returns the
newly-extended object. Otherwise, this cmdlet does not generate any
output.
Here's a slightly modified version of your script:
$obj = $objItem | Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName -PassThru
However, since in your case you don't really need to save the output object in a new variable, you could also simply say:
$obj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName
Try like this:
$objcol = #()
ForEach ($objItem in $colItems)
{
$obj = New-Object System.Object
$obj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName
$obj | Add-Member -MemberType NoteProperty -Name MacAddress -Value $objItem.MacAddress
$obj | Add-Member -MemberType NoteProperty -Name IPAdress -Value $objitem.IpAddress
$objcol += $obj
}
Write-Output $objcol
As indicated by Enrico, Shay and Christian, you should specify the object on which Add-Member operates, either by piping the object to Add-Member or by explicitly specifying the object on the InputObject parameter. When adding multiple members using Add-Member I usually add the PassThru switch to avoid repeating the InputObject and to provide a visual cue.
ForEach ($objItem in $colItems) {
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName -PassThru `
| Add-Member -MemberType NoteProperty -Name MacAddress -Value $objItem.MacAddress -PassThru `
| Add-Member -MemberType NoteProperty -Name IPAdress -Value $objitem.IpAddress -PassThru
}
You're assigning the result of Add-Member to a variable, not adding it to a property collection within $obj.
Instead of
$obj = Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName
Try this:
Add-Member -MemberType NoteProperty -Name ComputerName -Value $ComputerName -inputObject $obj

Resources