How To fix "add-member : Cannot add a member with the name "" because a member with that name already exists" - azure

I need to list multiple FTP connexion on LogicApp service and export this list on csv file. This export is use for see if the SSL protocol connexion is activate or not. My script generate this error.
add-member : Cannot add a member with the name "FTP" because a member with that name already exists. To overwrite the member anyway, add the Force parameter to your command.
LogicApp FTP connexion :
https://learn.microsoft.com/en-us/azure/connectors/connectors-create-api-ftp
I need to add these FTP connections in this format on excel :
format need
$LogicApp_temp = $null
$LogicApp_obj = #()
$LogicApp_temp = new-object PSObject
$FTPAll = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections
foreach ( $FTPAlls in $FTPAll ) {
$FTPName = $FTPAlls.name
$FTPName1 = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections -Name $FTPName
foreach ($FTPName2 in $FTPName1) {
$FTPcheckType = $FTPName2.Properties.api.name
if ( $FTPcheckType -eq "ftp") {
$FTPSSL1 = $FTPName1.Properties.parameterValues.isSSL
}
else {
}
$LogicApp_temp | add-member -MemberType NoteProperty -Name "FTP" -Value "$FTPName2.Properties.displayName $FTPSSL1"
}
}
$LogicApp_obj += $LogicApp_temp
Write-Output "LogicApp Name : $Name Ressource Group : $RG OK"
# CSV Exports :
$LogicApp_obj | Export-Csv $csvPath -Append -NoTypeInformation
thank you in advance for your help

Because the PSObject property just could be set one value at one time, if you use the -Force, it will overwrite the value before.
If you want to get the .csv file like the format you provided, we could just append every string like joyftp True first.
My working sample:
$RG = "<resource group name>"
$LogicApp_obj = #()
$value = ""
$FTPAll = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections
foreach ( $FTPAlls in $FTPAll ) {
$FTPName = $FTPAlls.name
$FTPName1 = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections -Name $FTPName
foreach ($FTPName2 in $FTPName1) {
$FTPcheckType = $FTPName2.Properties.api.name
$displayname = $FTPName2.Properties.displayName
$LogicApp_temp = New-Object -TypeName PSObject
if ( $FTPcheckType -eq "ftp") {
$FTPSSL1 = $FTPName1.Properties.parameterValues.isSSL
$value += "$displayname $FTPSSL1 | "
$LogicApp_temp | add-member -MemberType NoteProperty -Name "FTP" -Value "$value" -Force
}
}
}
Write-Output "LogicApp Name : $Name Ressource Group : $RG OK"
# CSV Exports :
$LogicApp_temp | Export-Csv -Path "C:\Users\joyw\Desktop\ftp.csv" -NoTypeInformation
The .csv file:

Related

Powershell does not create CSV if there is no data to export in Azure

I am trying to export VM data from Azure and below script is working perfect if subscription has VMs however it does create a .csv if there is no data (VMs) and I need that even if there is no data powershell should create a blank csv. Below is my script which is working fine if subscription has VMs created in it.
function create($path) {
$exists = Test-Path -path $path
Write-Host "tried the following path: $path, it" $(If ($exists) {"Exists"} Else {"Does not Exist!"})
if (!($exists)) { New-Item $path -itemType Directory }
}
# reading file contents
$subs_file = "C:\Scrpting\Subscriptions\Subscriptions.xlsx"
$azSubs = Import-Excel $subs_file
$azSubs
$output_folder = "C:\audit-automation"
# creating folder for outputing data
create("$output_folder")
# New-Item $output_folder -itemType Directory
# iterating over subscriptions
ForEach ( $sub in $azSubs ) {
# sub
$azsub = $sub.Subscription
# app
$app = $sub.Application
$azsub
$app
# creating folder to save data for apps
# New-Item $output_folder\$app -itemType Directory
# setting config for azure
Set-AzContext -SubscriptionName $azsub
# GET VM INFO
$vms = Get-AzVM
$vmrg = Get-AzVM | Select-Object "ResourceGroupName"
$nics = get-AzNetworkInterface | Where-Object { $_.VirtualMachine -NE $null }
# creating folder to save
# New-Item $output_folder\$app\vm_info -itemType Directory
create("$output_folder\$app")
ForEach ($nic in $nics) {
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.NICName = $nic.Name
$info.VMName = $vm.Name
$info.SubscriptionID = $azsub
$info.ResourceGroupName = $vm.ResourceGroupName
$info.PrivateIPAddress = $nic.IpConfigurations.PrivateIpAddress
$PublicIPAddress =
(Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName | ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
$info.PublicIPAddress = if ($null -eq $PublicIPAddress ) { "Not Assigned" } else { $PublicIPAddress }
$info.OS = $vm.StorageProfile.osDisk.osType
$info.Status = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
$info | Export-Csv -Path $output_folder\$app\$app-vm_data$((Get-Date).ToString("yyyy-MM-dd")).csv -Append
}}
You can remove the function create and replace that with just the one line $null = New-Item $output_folder -ItemType Directory -Force.
On file system, the -Force makes the cmdlet return either the DirectoryInfo object of an existing folder or create a new folder and return that.
(don't use this on registry keys!)
Next, if you capture the output you want in the CSV file first, it is easy enough to check if there is output or not and if not, write an empty csv file (only the headers will be in there)
Something like this:
# reading file contents
$subs_file = "C:\Scrpting\Subscriptions\Subscriptions.xlsx"
$azSubs = Import-Excel $subs_file
#$azSubs
$output_folder = "C:\audit-automation"
# creating folder for outputing data
$null = New-Item $output_folder -ItemType Directory -Force
# iterating over subscriptions
foreach($sub in $azSubs) {
# sub
$azsub = $sub.Subscription
# app
$app = $sub.Application
$azsub
$app
# setting config for azure
Set-AzContext -SubscriptionName $azsub
# GET VM INFO
$vms = Get-AzVM
$vmrg = Get-AzVM | Select-Object "ResourceGroupName"
$nics = Get-AzNetworkInterface | Where-Object { $null -ne $_.VirtualMachine }
# creating folder to save
$null = New-Item (Join-Path -Path $output_folder -ChildPath $app) -ItemType Directory -Force
# capture the output of the foreach loop
$result = foreach ($nic in $nics) {
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.NICName = $nic.Name
$info.VMName = $vm.Name
$info.SubscriptionID = $azsub
$info.ResourceGroupName = $vm.ResourceGroupName
$info.PrivateIPAddress = $nic.IpConfigurations.PrivateIpAddress
$PublicIPAddress = (Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName |
ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
$info.PublicIPAddress = if ($null -eq $PublicIPAddress ) { "Not Assigned" } else { $PublicIPAddress }
$info.OS = $vm.StorageProfile.osDisk.osType
$info.Status = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
# output the object to be collected in variable $result
$info
}
# test if you actually have data now in the $result variable
if (!#($result.Count)) {
# no data; create an empty csv with just the headers
$result = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
}
$outFile = Join-Path -Path $output_folder -ChildPath ('{0}\{0}-vm_data{1:yyyy-MM-dd}.csv' -f $app, (Get-Date))
$result | Export-Csv -Path $outFile -NoTypeInformation
}
add outside the loop, since $vms may be empty
if (!($vms)){
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$info | Export-Csv -Path $output_folder\$app\$app-vm_data$((Get-Date).ToString("yyyy-MM-dd")).csv -Append
}

Export Multiple Azure AD group members

I am using below code snippet, Instead of -ALL I am trying to pass specific ObjectId or filter group name but getting below error. pls help to fix this.
$groups=Get-AzureADGroup -ObjectId "Group1" - Works fine with one but not with multiple ObjectId
$groups=Get-AzureADGroup -filter{Name -like "ABC*"} - Get-AzureADGroup : Cannot evaluate parameter 'Filter'
Connect-AzureAD
$groups=Get-AzureADGroup -All $true
$resultsarray =#()
ForEach ($group in $groups){
$members = Get-AzureADGroupMember -ObjectId $group.ObjectId -All $true
ForEach ($member in $members){
$UserObject = new-object PSObject
$UserObject | add-member -membertype NoteProperty -name "Group Name" -Value $group.DisplayName
$UserObject | add-member -membertype NoteProperty -name "Member Name" -Value $member.DisplayName
$UserObject | add-member -membertype NoteProperty -name "ObjType" -Value $member.ObjectType
$UserObject | add-member -membertype NoteProperty -name "UserType" -Value $member.UserType
$UserObject | add-member -membertype NoteProperty -name "UserPrinicpalName" -Value $member.UserPrincipalName
$resultsarray += $UserObject
}
}
$resultsarray | Export-Csv -Encoding UTF8 -Delimiter ";" -Path "C:\scripts\output.csv" -NoTypeInformation
$groups=Get-AzureADGroup -All
$result=new-object system.colletions.arraylist
foreach($group in $groups)
{
$members=$group.members
foreach($member in $members)
{
$result.add(
[PSCustomObject]#{
"Group Name"=$group.DisplayName
"Member Name"=$member.DisplayName
"ObjType"=$member.ObjectType
"UserType"=$member.UserType
"UserPrinicpalName"=$member.UserPrincipalName
}) > $null
}
}
If you wanna search for a specific group you can use -SearchString 'groupName' or a list of groups:
$groups='group1,group2,group3'.split(',')|%{
Get-AzureADGroup -SearchString $_
}

Retrieve azure blob metadata with Powershell

How do I retrieve the metadata of a blob folder's contents (such as name, size etc) with powershell and export it as CSV?
Assume you have azure powershell az module installed(also you can change the code accordingly if you are using AzureRm module).
There are 2 methods:
Method 1: Use PSCustomObject. Sample code as below:
$accountname="xxx"
$accountkey="xxx"
$ctx = New-AzStorageContext -StorageAccountName $accountname -StorageAccountKey $accountkey
$myblobs = Get-AzStorageBlob -Container "aa1" -Context $ctx
$Output = $myblobs | ForEach-Object {
[PSCustomObject]#{
"Name" = $_.Name
"Length" =$_.Length
}
}
$Output | Export-Csv "d:\temp\test2.csv" -NoTypeInformation
Method 2: Use psobject. Sample code as below, save the generated file to location "d:\temp\test2.csv":
$accountname="xxx"
$accountkey="xxx"
$ctx = New-AzStorageContext -StorageAccountName $accountname -StorageAccountKey $accountkey
$myblobs = Get-AzStorageBlob -Container "aa1" -Context $ctx
$i=0
foreach($b in $myblobs)
{
$i++
if($i -eq 1)
{
$obj = New-Object psobject
$obj | add-member -membertype NoteProperty -name "Name" -value $b.name
#the length unit is byte
$obj | add-member -membertype NoteProperty -name "Length" -value $b.length
$obj | Export-Csv "d:\temp\test2.csv" -NoTypeInformation
}
else
{
$obj = New-Object psobject
$obj | add-member -membertype NoteProperty -name "Name" -value $b.name
$obj | add-member -membertype NoteProperty -name "Length" -value $b.length
$obj | Export-Csv "d:\temp\test2.csv" -NoTypeInformation -Append
}
}
Test result as below:

Problem with PSCustomObject data collection

I'm preparing a table with information about VM name and provision date of OS disk. I can easily retrieve that information from $VM.disks.statuses.time[0] command, if individual VM is assigned to $VM, but I when i try to collect data into table, I got an error:
Cannot index into a null array.
At line:4 char:1
+ [PSCustomObject]#{
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
This is my code:
$VMs = Get-AzVM -status
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"VM Name" = $_.Name
"Provision Date" = $_.disks.statuses.time[0].ToString()
}
}
I can reproduce your issue, the issue was caused by the outputs of Get-AzVM -status and Get-AzVM -ResourceGroupName <ResourceGroupName> -Name <Name> -Status are different.
The output of Get-AzVM -status will not has the disks property, but when you get individual VM status via Get-AzVM -ResourceGroupName <ResourceGroupName> -Name <Name> -Status, it will have the property, so you got the error.
Get-AzVM -status:
Get-AzVM -ResourceGroupName <ResourceGroupName> -Name <Name> -Status:
Solution:
To fix the issue, just to use Get-AzVM -ResourceGroupName <ResourceGroupName> -Name <Name> -Status in your script.
$VMs = Get-AzVM -status
$vmOutput = $VMs | ForEach-Object {
$VMstatus = Get-AzVM -ResourceGroupName $_.ResourceGroupName -Name $_.Name -Status
[PSCustomObject]#{
"VM Name" = $VMstatus.Name
"Provision Date" = $VMstatus.disks.statuses.time[0].ToString()
}
}
You can use the Get-AzDisk command to retrieve disk creation information.
$disks = Get-AzDisk | Where-Object { $_.Managedby }
$vmOutput = foreach ($disk in $disks) {
[pscustomobject]#{"VM Name" = ($disk.ManagedBy -split "/")[-1]
"Provisioned Date" = $disk.TimeCreated
}
}
The error says:
Cannot index into a null array.
So my guess is that something here $_.disks.statuses.time[0].ToString() is $null. Therefore you should add some $nullchecks:
$VMs = Get-AzVM -status
$vmOutput = $VMs | ForEach-Object {
if ($_.disks -and $_.disks.statuses -and $_.disks.statuses.time -and ($_.disks.statuses.time.Count -gt 0)){
[PSCustomObject]#{
"VM Name" = $_.Name
"Provision Date" = $_.disks.statuses.time[0].ToString()
}
}
}
Hope that helps.

Azure VM OS Build - Powershell

I am trying to create a powershell command to loop through all my Azure subscriptions and get the OS build number of the VMs
param(
# Specify the location of the audit file
$csvFilePath = "C:\agentAudit.csv"
)
cls
$ErrorActionPreference = 'Stop'
Write-Host "Validating Azure Accounts..."
try{
$subscriptionList = Get-AzureRmSubscription | Sort SubscriptionName
}
catch {
Write-Host "Reauthenticating..."
Login-AzureRmAccount | Out-Null
$subscriptionList = Get-AzureRmSubscription | Sort SubscriptionName
}
if (Test-Path $csvFilePath) {
Remove-Item -Path $csvFilePath
}
foreach($subscription in $subscriptionList) {
Select-AzureRmSubscription -SubscriptionId $subscription.SubscriptionId | Out-Null
Write-Output "`n Working on subscription: $($subscription.SubscriptionName) `n"
$vms = Get-AzureRmVM -WarningAction Ignore
foreach ($vm in $vms) {
$VMs = Get-AzureRmVM
$vmlist = #()
$VMs | ForEach-Object {
$VMObj = New-Object -TypeName PSObject
$VMObj | Add-Member -MemberType Noteproperty -Name "VM Name" -Value $_.Name
$VMObj | Add-Member -MemberType Noteproperty -Name "OS type" -Value $_.StorageProfile.ImageReference.Sku
$VMObj | Add-Member -MemberType Noteproperty -Name "OS Offer" -Value $_.StorageProfile.ImageReference.Offer
$VMObj | Add-Member -MemberType Noteproperty -Name "OS Publisher" -Value $_.StorageProfile.ImageReference.Publisher
$VMObj | Add-Member -MemberType Noteproperty -Name "OS Version" -Value $_.StorageProfile.ImageReference.Version
$vmlist += $VMObj
}
$vmlist
}
}
I am pretty new to to Powershell and still learning to understand and write PS
Long time back i created a script for generating the Azure inventory. May be this can help you. You just need to tweak it a bit
Add-AzureRmAccount
$SubscriptionNames = "Prototypes","Development"
foreach($SubscriptionName in $SubscriptionNames)
{
try
{
Select-AzureRmSubscription -SubscriptionName $SubscriptionName
$VMinventory = Get-AzurermVM -ErrorAction Stop
$OutputPath = "C:\VMInventoryRM-" + $SubscriptionName + ".csv"
$report=#()
foreach ($vm in $VMinventory)
{
$VMinfo = " " | select Powerstate, Location, VMSize
# Display
write-host($vm.Name)
$vmStatus = $null
$Location = $null
$VMSize = $null
$vmStatus = (get-azurermvm -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status).Statuses[1].Code
$Location = $vm.Location
$VMSize = $vm.HardwareProfile.VmSize
$VMinfo.Powerstate = $vmStatus
$VMinfo.Location = $Location
$VMinfo.VMSize = $VMSize
$Report += $VMinfo
$i++
}
$Report | export-csv $OutputPath -NoTypeInformation
}
catch
{}
}
I found the answer in the below technet article
function Get-WindowsVersion {
<#
.SYNOPSIS
List Windows Version from computer. Compatible with PSVersion 3 or higher.
.DESCRIPTION
List Windows Version from computer. Compatible with PSVersion 3 or higher.
.PARAMETER ComputerName
Name of server to list Windows Version from remote computer.
.PARAMETER SearchBase
AD-SearchBase of server to list Windows Version from remote computer.
.PARAMETER History
List History Windows Version from computer.
.PARAMETER Force
Disable the built-in Format-Table and Sort-Object.
.NOTES
Name: Get-WindowsVersion.psm1
Author: Johannes Sebald
Version: 1.2.5
DateCreated: 2016-09-13
DateEdit: 2018-07-11
.LINK
https://www.dertechblog.de
.EXAMPLE
Get-WindowsVersion
List Windows Version on local computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1
List Windows Version on remote computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2
List Windows Version on multiple remote computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -SearchBase "OU=Computers,DC=comodo,DC=com" with built-in Format-Table and Sort-Object.
List Windows Version on Active Directory SearchBase computer.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2 -Force
List Windows Version on multiple remote computer and disable the built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -History with built-in Format-Table and Sort-Object.
List History Windows Version on local computer.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2 -History
List History Windows Version on multiple remote computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2 -History -Force
List History Windows Version on multiple remote computer and disable built-in Format-Table and Sort-Object.
#>
[cmdletbinding()]
param (
[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string[]]$ComputerName = "localhost",
[string]$SearchBase,
[switch]$History,
[switch]$Force
)
if ($($PsVersionTable.PSVersion.Major) -gt "2") {
# SearchBase
if ($SearchBase) {
if (Get-Command Get-AD* -ErrorAction SilentlyContinue) {
if (Get-ADOrganizationalUnit -Filter "distinguishedName -eq '$SearchBase'" -ErrorAction SilentlyContinue) {
$Table = Get-ADComputer -SearchBase $SearchBase -Filter *
$ComputerName = $Table.Name
}
else {Write-Warning "No SearchBase found"}
}
else {Write-Warning "No AD Cmdlet found"}
}
# Loop 1
$Tmp = New-TemporaryFile
foreach ($Computer in $ComputerName) {
if (Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue) {
try {
$WmiObj = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer
}
catch {
Write-Warning "$Computer no wmi access"
}
if ($WmiObj) {
# Variables
$WmiClass = [WmiClass]"\\$Computer\root\default:stdRegProv"
$HKLM = 2147483650
$Reg1 = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
$Reg2 = "SYSTEM\Setup"
if ($History) {$KeyArr = ($WmiClass.EnumKey($HKLM, $Reg2)).snames -like "Source*"} else {$KeyArr = $Reg1}
# Loop 2
foreach ($Key in $KeyArr) {
if ($History) {$Reg = "$Reg2\$Key"} else {$Reg = $Key}
$Major = $WmiClass.GetDWordValue($HKLM, $Reg, "CurrentMajorVersionNumber").UValue
$Minor = $WmiClass.GetDWordValue($HKLM, $Reg, "CurrentMinorVersionNumber").UValue
$Build = $WmiClass.GetStringValue($HKLM, $Reg, "CurrentBuildNumber").sValue
$UBR = $WmiClass.GetDWordValue($HKLM, $Reg, "UBR").UValue
$ReleaseId = $WmiClass.GetStringValue($HKLM, $Reg, "ReleaseId").sValue
$ProductName = $WmiClass.GetStringValue($HKLM, $Reg, "ProductName").sValue
$ProductId = $WmiClass.GetStringValue($HKLM, $Reg, "ProductId").sValue
$InstallTime1 = $WmiClass.GetQWordValue($HKLM, $Reg, "InstallTime").UValue
$InstallTime2 = ([datetime]::FromFileTime($InstallTime1))
# Variables Windows 6.x
if ($Major.Length -le 0) {$Major = $WmiClass.GetStringValue($HKLM, $Reg, "CurrentVersion").sValue}
if ($ReleaseId.Length -le 0) {$ReleaseId = $WmiClass.GetStringValue($HKLM, $Reg, "CSDVersion").sValue}
if ($InstallTime1.Length -le 0) {$InstallTime2 = ([WMI]"").ConvertToDateTime($WmiObj.InstallDate)}
# Add Points
if (-not($Major.Length -le 0)) {$Major = "$Major."}
if (-not($Minor.Length -le 0)) {$Minor = "$Minor."}
if (-not($UBR.Length -le 0)) {$UBR = ".$UBR"}
# Output
$Output = New-Object -TypeName PSobject
$Output | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.toUpper()
$Output | Add-Member -MemberType NoteProperty -Name ProductName -Value $ProductName
$Output | Add-Member -MemberType NoteProperty -Name WindowsVersion -Value $ReleaseId
$Output | Add-Member -MemberType NoteProperty -Name WindowsBuild -Value "$Major$Minor$Build$UBR"
$Output | Add-Member -MemberType NoteProperty -Name ProductId -Value $ProductId
$Output | Add-Member -MemberType NoteProperty -Name InstallTime -Value $InstallTime2
$Output | Export-Csv -Path $Tmp -Append
}
}
}
else {Write-Warning "$Computer not reachable"}
}
# Output
if ($Force) {Import-Csv -Path $Tmp} else {Import-Csv -Path $Tmp | Sort-Object -Property ComputerName, WindowsVersion | Format-Table -AutoSize}
}
else {Write-Warning "PSVersion to low"}
}
https://gallery.technet.microsoft.com/scriptcenter/Get-WindowsVersion-can-0726c5d4#
Thank You Johannes Sebald

Resources