GinShell.Azure/Public/Get-GsAzureVmFullInfo.ps1

function Get-GsAzureVmFullInfo {
    <#
    .SYNOPSIS
        Returns detailed VM information including disks, NICs, IPs, and NSGs.
    .PARAMETER VmName
        One or more VM names to query. If omitted, returns all VMs.
    .PARAMETER ResourceGroupName
        Optionally scope the query to a single resource group.
    .EXAMPLE
        Get-GsAzureVmFullInfo -VmName 'WebServer01' -ResourceGroupName 'Production'
    #>

    [CmdletBinding()]
    param (
        [string[]]$VmName,
        [string]$ResourceGroupName
    )

    try {
        Write-GsLog -Message "Fetching Azure VM details..." -Type Info

        $allVms = if ($ResourceGroupName) {
            Get-AzVM -ResourceGroupName $ResourceGroupName -ErrorAction Stop
        }
        else {
            Get-AzVM -ErrorAction Stop
        }

        $filteredVms = if ($VmName) {
            $allVms | Where-Object { $_.Name -in $VmName }
        }
        else {
            $allVms
        }

        if (-not $filteredVms) {
            Write-GsLog -Message "No matching VMs found." -Type Warning
            return
        }

        $vmDetailsList = foreach ($vm in $filteredVms) {
            $vmStatus = Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status -ErrorAction Stop

            # Disk info
            $osDiskName   = $vm.StorageProfile.OSDisk.Name
            $dataDiskNames = $vm.StorageProfile.DataDisks.Name
            $allDiskNames  = @($osDiskName) + $dataDiskNames
            $disks = $allDiskNames | ForEach-Object {
                Get-AzDisk -ResourceGroupName $vm.ResourceGroupName -DiskName $_ -ErrorAction SilentlyContinue
            }

            # NIC info
            $nics = $vm.NetworkProfile.NetworkInterfaces.Id | ForEach-Object {
                Get-AzNetworkInterface -ResourceId $_ -ErrorAction SilentlyContinue
            }

            $nicDetails = foreach ($nic in $nics) {
                $ipConfigs = $nic.IpConfigurations | ForEach-Object {
                    [PSCustomObject]@{
                        PrivateIpAddress = $_.PrivateIpAddress
                        PublicIpAddress  = if ($_.PublicIpAddress) {
                            (Get-AzPublicIpAddress -ResourceGroupName $vm.ResourceGroupName -Name ($_.PublicIpAddress.Id.Split('/')[-1])).IpAddress
                        } else { $null }
                        Subnet = $_.Subnet.Id.Split('/')[-1]
                        Vnet   = $_.Subnet.Id.Split('/')[-3]
                    }
                }

                [PSCustomObject]@{
                    NicName   = $nic.Name
                    IpConfigs = $ipConfigs
                    Nsg       = if ($nic.NetworkSecurityGroup) {
                        ($nic.NetworkSecurityGroup.Id.Split('/')[-1])
                    } else { $null }
                }
            }

            [PSCustomObject]@{
                Name           = $vm.Name
                ResourceGroup  = $vm.ResourceGroupName
                Location       = $vm.Location
                VmSize         = $vm.HardwareProfile.VmSize
                OSType         = $vm.StorageProfile.OSDisk.OsType
                ComputerName   = $vm.OsProfile.ComputerName
                ProvisionState = $vmStatus.ProvisioningState
                PowerState     = ($vmStatus.Statuses | Where-Object { $_.Code -like 'PowerState/*' }).DisplayStatus
                Disks          = $disks
                Nics           = $nicDetails
            }
        }

        return $vmDetailsList
    }
    catch {
        Write-GsLog -Message "Failed to retrieve VM details: $($_.Exception.Message)" -Type Error
        throw
    }
}