Home > OS >  Powershell ForEach-Object: You cannot call a method on a null-valued expression
Powershell ForEach-Object: You cannot call a method on a null-valued expression

Time:09-20

I am trying to extract the tag values for SystemOwner and TechnicalOwner. However I get the error "ForEach-Object: You cannot call a method on a null-valued expression" I already know that the "$Tags = $RG.Tags" could be the issue because running this variable does not give me any results. Then how do I get the resource group tags?

$RGs = (Get-AzResourceGroup).ResourceGroupName
ForEach-Object $RG in $RGs
{
# Get email address value for each SystemOwner and TechnicalOwner Tag in the RG 
$Tags = $RG.Tags
$TO = ($Tags.GetEnumerator() | Where-Object {$_.Key -eq "Technical*"}).value
If ($TO)
{
    if ($TO.Value -ne $null) {
        Write-Host "Technical Owner Found in the Resource Group, building an Array"
        $contactemailadress  = $TO.Value
     }
}
$SO = $Tags.GetEnumerator() | Where-Object {$_.Key -eq "SystemOwner"} #looking for Resource Group tag Names that have a space in the name
If ($SO)
{
    if ($SO.Value -ne $null) {
        Write-Host "System Owner Found in the Resource Group, building an Array"
        $contactemailadress  = $SO.Value
     }
}
}

CodePudding user response:

I think you could do something like this:

$contactemailadress = @()
$RGs = Get-AzResourceGroup
$RGs | ForEach-Object {
    # Get email address value for each SystemOwner and TechnicalOwner Tag in the RG 
    $Tags = $_.Tags

    If ($Tags -and $Tags['TechnicalOwner'])
    {
            Write-Host "Technical Owner Found in the Resource Group, building an Array"
            $contactemailadress  = $Tags['TechnicalOwner']
    }

    #looking for Resource Group tag Names that have a space in the name
    If ($Tags -and $Tags['SystemOwner'])
    {
            Write-Host "System Owner Found in the Resource Group, building an Array"
            $contactemailadress  = $Tags['SystemOwner']
    }
}

The main issue you have is that (Get-AzResourceGroup).ResourceGroupName returns the Resource Group Name - however, in order for the tags to be returned you would need the full object.

You can prove this by checking for Properties on the Get-AzResourceGroup command you are running:

(Get-AzResourceGroup -Name resource_group_name).ResourceGroupName | Get-Member -Type Property

   TypeName: System.String

Name   MemberType Definition
----   ---------- ----------
Length Property   int Length {get;}

As you can see, this command only has one property - length, which is not useful for your scripts purpose.

If you run this instead, you get the full object with all properties:

Get-AzResourceGroup -Name resource_group_name | Get-Member -Type Property

   TypeName: Microsoft.Azure.Commands.ResourceManager.Cmdlets.SdkModels.PSResourceGroup

Name              MemberType Definition
----              ---------- ----------
Location          Property   string Location {get;set;}
ManagedBy         Property   string ManagedBy {get;set;}
ProvisioningState Property   string ProvisioningState {get;set;}
ResourceGroupName Property   string ResourceGroupName {get;set;}
ResourceId        Property   string ResourceId {get;set;}
Tags              Property   hashtable Tags {get;set;}
TagsTable         Property   string TagsTable {get;}

You can use foreach or ForEach-Object, both should work but when using the latter you can query the variable inside the loop using the $_ notation.

Lastly, in your script there seem to be some variables unnecessarily used (but I don't know if you would need them later on), such as $TO and two if-statements that more or less do the same (i.E. If ($SO) and if ($SO.Value -ne $null)).

  • Related