VMWare对象上的ConvertTo-Json不起作用

时间:2016-06-24 12:04:33

标签: json powershell type-conversion vmware powercli

在将VM对象转换为json时的powershell中, ($ json = ConvertTo-Json $ vm -Compress)

我收到“已经添加了具有相同密钥的项目”例外。

PS SQLSERVER:\> C:\Users\admin\Desktop\inventory.ps1
ConvertTo-Json : An item with the same key has already been added.
At C:\Users\huradmin\Desktop\inventory.ps1:68 char:31
+     if($vm -ne $null){$json = ConvertTo-Json $vm -Compress;      insertToElasticSearc ...
+                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [ConvertTo-Json], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertToJsonCommand

insertToElasticSearch : Cannot bind argument to parameter 'json' because it is null.
At C:\Users\admin\Desktop\inventory.ps1:68 char:89
+ ... icSearch -json $json -info:$true -Verbose:$true}
+                    ~~~~~
+ CategoryInfo          : InvalidData: (:) [insertToElasticSearch], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,insertToElasticSearch

getVMHosts函数返回VM guest虚拟机列表。请在下面找到我的代码。

function getVMHosts{
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$vcenter,
[Parameter(Mandatory=$False)]
[switch]$info=$false
)
try
{
    Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Importing VMWare modules" -verbose:$info
    Get-Module -ListAvailable -Name "VMware.*" | Import-Module
    Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Connecting to Vcenter:$vcenter" -verbose:$info
    [void]::$(Connect-VIServer -Server $vcenter -ErrorAction SilentlyContinue)
    Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Getting Data center servers" -verbose:$info
    $DCs = Get-Datacenter
    $VMs = $null
    foreach($dc in $DCs)
    {
        Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Getting VM servers for Data Center:$dc" -verbose:$info
        $VMs=$VMs+ $(Get-Datacenter -Name $dc.Name | Get-VM -Verbose:$info| Select PowerState,Name, NumCpu,MemoryMB,GuestId,VMHost, @{N="IP Address";E={@($_.guest.IPAddress[0])}})
    }
    Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Disconnecting from VCenter:$vcenter" -verbose:$info
    Disconnect-VIServer -Server $vcenter -ErrorAction SilentlyContinue -Confirm:$false
    Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Returning VM Lists" -verbose:$info
    return $VMs
}
catch
{
    $errorMessage = "$($_.Exception.Message)`n$(($_|select -ExpandProperty invocationinfo).PositionMessage)"
    Write-Warning -Message "Catched an exception in Function:$($MyInvocation.MyCommand)`n$errorMessage" -Verbose:$true
}
}
$vmHosts = getVMHosts -vcenter "vcenter"
$counter = 0
foreach($vm in $vmHosts)
{    
if($vm -ne $null){$json = ConvertTo-Json $vm -Compress;insertToElasticSearch json $json -info:$true -Verbose:$true}   
}

4 个答案:

答案 0 :(得分:0)

试试ConvertTo-JSON -Depth 1Sounds like对象中的属性具有相同的名称。

答案 1 :(得分:0)

我没有VCenter来验证脚本,但我重构了你的脚本以使它更具有强大的功能。

注意:

CmdletBinding为您提供-Verbose和其他功能
默认情况下,任何未设置为变量的对象都将输出到管道 Return没有达到大多数开发人员所期望的那样

function getVMHosts{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$True,Position=1)]
        [string]$vcenter,
    )
    try
    {
        Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Importing VMWare modules"
        Get-Module -ListAvailable -Name "VMware.*" | Import-Module
        Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Connecting to Vcenter:$vcenter"
        [void]$(Connect-VIServer -Server $vcenter -ErrorAction SilentlyContinue)
        Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Getting Data center servers"
        Get-Datacenter |
            ForEach-Object {
                Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Getting VM servers for Data Center:$_"
                Get-Datacenter -Name $_.Name |
                    Get-VM -Verbose:$Verbose|
                    Select PowerState, Name, NumCpu, MemoryMB, GuestId, VMHost, @{N="IP Address";E={@($_.guest.IPAddress[0])}}
        }

        Write-Verbose "$(get-date -Format "dd/MM/yyyy HH:mm") - Function:$($MyInvocation.MyCommand) - Disconnecting from VCenter:$vcenter"
        [void]Disconnect-VIServer -Server $vcenter -ErrorAction SilentlyContinue -Confirm:$false
    }
    catch
    {
        $errorMessage = "$($_.Exception.Message)`n$(($_|select -ExpandProperty invocationinfo).PositionMessage)"
        Write-Warning -Message "Exception caught in Function:$($MyInvocation.MyCommand)`n$errorMessage"
    }
}

getVMHosts -vcenter "vcenter" |
    ForEach-Object {
        $json = ConvertTo-Json $_ -Compress;
        insertToElasticSearch json $json -info:$true -Verbose:$true
    }
}

答案 2 :(得分:0)

答案已删除,因为可能没有帮助

答案 3 :(得分:0)

正如 noam 所说,那里有物体导致了这种情况。提取基础案例作为例子

get-vm <insertexamplevmname> | Select PowerState, Name, NumCpu, MemoryMB, GuestId, VMHost, @{N="IP Address";E={@($_.guest.IPAddress[0])}} | convertto-json -Depth 1

您将看到 VMHost 不仅仅是运行它的主机的名称,而是实际的主机对象,它也具有 Name 属性,就像 VM 具有 Name 一样。

所以您可能想要的是像从来宾对象中提取 IP 地址一样提取 VMHost 名称。

get-vm <insertexamplevmname> | Select PowerState, Name, NumCpu, MemoryMB, GuestId, @{N="Hostname";E={@($_.VMhost.Name)}}, @{N="IP Address";E={@($_.guest.IPAddress[0])}} | convertto-json