通过PowerCLI调用PowerShell获取VM网卡信息时出现异常
批量更换虚拟机网卡类型时PowerCLI调用脚本的问题
问题场景
我正在批量将虚拟机网卡从e1000类型更换为vmxnet3类型,尝试用以下PowerShell命令筛选vmxnet网卡:
get-wmiobject win32_networkadapter | Where-Object {$_.ServiceName -match "Vmxnet"}
该命令在虚拟机内部直接执行可正常返回结果:
PS C:\Users-adm-mxj45375> get-wmiobject win32_networkadapter | Where-Object {$_.ServiceName -match "Vmxnet*"}
ServiceName : vmxnet3ndis6 MACAddress : 00:50:56:88:7E:07 AdapterType
: Ethernet 802.3 DeviceID : 1 Name : vmxnet3 Ethernet Adapter
NetworkAddresses : Speed : 10000000000
但通过PowerCLI的Invoke-VMScript调用该命令时:
$Network = Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText "(get-wmiobject win32_networkadapter | Where-Object {$_.ServiceName -match 'Vmxnet'})"
出现错误:
.ServiceName : The term '.ServiceName' is not recognized as the name
of a cmdlet, function, script file, or operable
我预期能将结果存入$Network变量,以下是完整的批量配置脚本:
Import-Module NetAdapter Connect-VIServer in1graapp022 $vms = Import-CSV "C:\Scripts\servers.csv" $GC = $Host.UI.PromptForCredential("Please enter credentials", "Enter Guest credentials for VM", "", "") foreach ($vm in $vms){ $VMName = $vm.Name $IP = $vm.IP $SNM = $vm.SubnetMask $GW = $vm.Gateway $DNS1 = $vm.DNS1 $DNS2 = $vm.DNS2 $Network = Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText "(get-wmiobject win32_networkadapter | Where-Object {$_.ServiceName -match 'Vmxnet*'}).netconnectionid" $NetworkName = get-networkadapter $VMName | Where-Object {$_.type -eq "vmxnet3"} | Select-Object MacAddress #Write-Host "Setting IP address for $VMname..." -ForegroundColor Yellow #Sleep -Seconds 60 $netadapter = Get-NetAdapter | where MacAddress -ne "$NetworkName"} $netadapter1 | New-NetIPAddress -AddressFamily IPv4 -IPAddress $IP -PrefixLength 24 -Type Unicast -DefaultGateway $GW $netadapter2 | Set-DnsClientServerAddress -ServerAddresses $DNS1 #$netsh = "c:\windows\system32\netsh.exe interface ip set address ""$NetworkName"" static $IP $SNM $GW" #$netsh2 = "c:\windows\system32\netsh.exe interface ip set dnsservers ""$NetworkName"" static $DNS1" #$netsh3 = "c:\windows\system32\netsh.exe interface ip add dnsservers ""$NetworkName"" $DNS2" Invoke-VMScript -VM $VMname -GuestCredential $GC -ScriptType bat -ScriptText $netadapter1 Invoke-VMScript -VM $VMname -GuestCredential $GC -ScriptType bat -ScriptText $netadapter2 #Invoke-VMScript -VM $VMname -GuestCredential $GC -ScriptType bat -ScriptText $netsh3 Write-Host "Setting IP address completed." -ForegroundColor Green Sleep -Seconds 20 ([WMIClass]"\\$vmname\ROOT\CImv2:Win32_Process").Create("cmd.exe /c ipconfig /registerdns") }
错误原因及解决方法
核心错误原因
脚本字符串中的变量解析冲突:本地PowerShell会优先解析Invoke-VMScript传递的脚本字符串里的$_.ServiceName,把$_当成当前本地管道对象,而非虚拟机内脚本的管道对象,导致语法错误。
两种解决方式
- 转义美元符号
将脚本字符串中的$转义为$$,让虚拟机内的PowerShell正确解析变量:
$Network = Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText "(get-wmiobject win32_networkadapter | Where-Object {$$_.ServiceName -match 'Vmxnet'}).netconnectionid" -GuestCredential $GC
- 使用Here-String
用PowerShell的Here-String格式定义脚本内容,避免本地变量解析(注意用反引号转义$`):
$scriptText = @" (get-wmiobject win32_networkadapter | Where-Object `$_.ServiceName -match 'Vmxnet').netconnectionid "@ $Network = Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText $scriptText -GuestCredential $GC
脚本其他问题修正
除了核心错误,原脚本还有几处逻辑问题:
$netadapter = Get-NetAdapter | where MacAddress -ne "$NetworkName"}多了一个闭合大括号},需删除;$netadapter1和$netadapter2未定义,应直接使用$netadapter;- 用
Invoke-VMScript传递PowerShell对象(如$netadapter1)无效,因为该命令需要脚本文本字符串,需将IP/DNS配置逻辑整合到虚拟机内执行的脚本中。
修正后的关键部分示例:
# 获取虚拟机内vmxnet网卡的NetConnectionID $getAdapterScript = @" (get-wmiobject win32_networkadapter | Where-Object `$_.ServiceName -match 'Vmxnet').netconnectionid "@ $Network = Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText $getAdapterScript -GuestCredential $GC # 构造IP与DNS配置脚本 $configScript = @" `$adapter = Get-NetAdapter -Name '$Network' `$adapter | New-NetIPAddress -AddressFamily IPv4 -IPAddress '$IP' -PrefixLength 24 -DefaultGateway '$GW' `$adapter | Set-DnsClientServerAddress -ServerAddresses '$DNS1', '$DNS2' ipconfig /registerdns "@ # 在虚拟机内执行配置 Invoke-VMScript -VM $VMName -ScriptType Powershell -ScriptText $configScript -GuestCredential $GC
内容的提问来源于stack exchange,提问作者Martyn Jeffrey
相关产品推荐
相关产品推荐

