VMware Cloud Community
vespavbb
Enthusiast
Enthusiast
Jump to solution

GET-WMIObject over Invoke-VMScript

Hi,

Actually I´m looking for a monster script to extend a Windows Drive by passing only the Information " VMname, Driverletter, extendbyGB

The Script should collect all Information like the correct vmdk, check Datastoresfreespace , Extend the vmdk, Extend the correct Drive inside the VM..

this is one part of the script..

Remote WMI is not enalbed and I cant not do a get-wmiObject -servername remotely.

My Idea was to do an Invoke-command to get the wmi information from inside the vm.

Invoke runs, but the output is wrong DeviceID is not recognized, do I need to pass the $Drive to the remotecommand? If yes, how?

$SystemFQFDN = "vmtest01"

$Username = "Administrator"

$Password = "blabla"

$Drive = 'd:'

$VMName = ($SystemFQFDN.Split('.'))[0]

$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force

$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd

Write-Host " invokeWMI $vmname" -ForegroundColor Green

$invokescript = " (((Get-WmiObject -ClassName 'Win32_LogicalDisk') | WHERE {$_.DeviceID -eq $Drive}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') | Select * "

                   

$Windrive = Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $invokescript -GuestUser $UserName -GuestPassword $pw.password

$Windrive

VCP4,VCP5,VCP6,VCP7,VCP8
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The ScriptOutput property of the returned object contains the output from the script that ran inside the guest OS.

The data in there is one string.

One method to interpret the output on the receiving end is to use a well-known format.

In the following, I use the CSV format.

The result will be one or more objects, each with the desired properties.

Write-Host " invokeWMI $vmname" -ForegroundColor Green

$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force

$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd


$MyScript = @"

((Get-WmiObject -ClassName 'Win32_LogicalDisk' |

WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') |

Select-Object -Property SCSIBus,SCSITargetId,SerialNumber |

ConvertTo-Csv

"@


Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestCredential $creds |

Select -ExpandProperty ScriptOutput |

ConvertFrom-Csv -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

0 Kudos
7 Replies
LucD
Leadership
Leadership
Jump to solution

I hate to disappoint you but there is no fool-proof method to link a VMDK to a guest OS partition.

On the script, you placed it in double quotes, that means  that all variables will be substituted, including $_.DeviceID and $Drive.
If I understand your intention correctly, that is probably not what you want for $_.DeviceId.

One option is to escape the $-sign with a back-tick.

A short demo snippet

$var1 = 1

$var2 = 2

$t1 = "$var1 and $var2"

$t1

$t2 = "`$var1 and $var2"

$t2


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
vespavbb
Enthusiast
Enthusiast
Jump to solution

Hi Luc,

sorry I dont unterstand for sure.

but in Gerneral, how can i pass some $var´s in a scripttext over Invoke? Sometimes I see scripttext, or scriptblock

I testet someting like this, but its not working.:-(

thanks for your patience

Example

$SystemFQFDN = "vmtest01.test.local"

$UserName = 'administrator' # Subscribe your Variable for User with access to VCenter and VM

$pw = "mypass"

$Drive = 'd:'

$argsArray = @()

$argsArray += $Drive

$VMName = ($SystemFQFDN.Split('.'))[0]

$SecureStringPwd = $Pw | ConvertTo-SecureString -AsPlainText -Force

$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd

$Windrive = Invoke-VMscript -vm $vmname -ScriptType Powershell -GuestUser $UserName -GuestPassword $pw.password  -ScriptText {

Param(

        [string]$Drive

    )

    (((Get-WmiObject -ClassName 'Win32_LogicalDisk') | WHERE {$_.DeviceID -eq $Drive}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') | Select *

$resultArray = @()

return  $resultArray

}

$Windrive

VCP4,VCP5,VCP6,VCP7,VCP8
0 Kudos
LucD
Leadership
Leadership
Jump to solution

I use a code-block with single quotes.
And I escape (backtick) the dollar signs I don't want to have substituted.

Have a look at my Here string and variable substitution dive


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
vespavbb
Enthusiast
Enthusiast
Jump to solution

ok now i found out how to invoke this. The Problem now is, that the output is a text arry and I dont know how to pic a special line like SCSIBUS,SCSITargetID,DiskSNfromWMI

I used the "ScriptOutput funktion, I guess this is the only way to get the output nativ.

Write-Host " invokeWMI $vmname" -ForegroundColor Green

$MyScript = @"

(((Get-WmiObject -ClassName 'Win32_LogicalDisk') | WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') | Select *

"@

                    

$Windrivetemp = Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestUser $UserName -GuestPassword $pw.password

$Windrive = $windrivetemp.ScriptOutput

$Windrive

#$outputarray = ($Windrivetemp -split('\n'))

###this is not working

$SCSIBus = $Windrive.SCSIBus

$SCSITargetId =$Windrive.SCSITargetId

$DiskSNfromWMI = $Windrive.SerialNumber

VCP4,VCP5,VCP6,VCP7,VCP8
0 Kudos
LucD
Leadership
Leadership
Jump to solution

The ScriptOutput property of the returned object contains the output from the script that ran inside the guest OS.

The data in there is one string.

One method to interpret the output on the receiving end is to use a well-known format.

In the following, I use the CSV format.

The result will be one or more objects, each with the desired properties.

Write-Host " invokeWMI $vmname" -ForegroundColor Green

$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force

$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd


$MyScript = @"

((Get-WmiObject -ClassName 'Win32_LogicalDisk' |

WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') |

Select-Object -Property SCSIBus,SCSITargetId,SerialNumber |

ConvertTo-Csv

"@


Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestCredential $creds |

Select -ExpandProperty ScriptOutput |

ConvertFrom-Csv -UseCulture


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos
vespavbb
Enthusiast
Enthusiast
Jump to solution

ok, here is the final script

Extend VMDK and Windows Drive inside the VM with Parameter of VMname and Driveletter

In my case it was working, just the check Datastore Freespace thing is not done yet

what do you think?

Param(

    $DeineVM = (Read-Host "Select VMname"),

    $Drive = (Read-Host "Select Drive Letter")+":"

)

$SystemFQFDN = $DeineVM #Subscribe the Published Data of the affected VM

$UserName = 'administrator' # Subscribe your Variable for User with access to VCenter and VM

#getting the Laps pw

$pw = get-adcomputer $SystemFQFDN -Properties * | select @{Label="Name";Expression={$_.name}}, @{Label="OS";Expression={$_.operatingsystem}}, @{Label="Distinguished name";Expression={$_.'distinguishedname'}}, @{Label="Password";Expression={$_.'ms-Mcs-AdmPwd'}} | select Password

$Password = $pw # Subscribe your encrypted Variable for the Password

#VName equals Netbios name here

$VMName = ($SystemFQFDN.Split('.'))[0]

#Make Credentials

$SecureStringPwd = $Password | ConvertTo-SecureString -AsPlainText -Force

$creds = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecureStringPwd

Write-Host " invokeWMI $vmname" -ForegroundColor Green

#$invokescript = " ipconfig /all"

$MyScript = @"

((Get-WmiObject -ClassName 'Win32_LogicalDisk' |

WHERE {`$_.DeviceID -eq "$Drive"}).GetRelated('Win32_DiskPartition')).GetRelated('Win32_DiskDrive') |

Select-Object -Property SCSIBus,SCSITargetId,SerialNumber |

ConvertTo-Csv

"@

$Windrive = Invoke-VMScript -vm $vmname -ScriptType Powershell -ScriptText $myScript -GuestUser $UserName -GuestPassword $pw.password |

Select -ExpandProperty ScriptOutput |

ConvertFrom-Csv -UseCulture

                    

$Windrive

#$outputarray = ($Windrive -split('\n'))

$SCSIBus = $Windrive.SCSIBus

$SCSITargetId =$Windrive.SCSITargetId

$DiskSNfromWMI = $Windrive.SerialNumber

# Match the VMWare Disk with the windows Disk

$vm = Get-VM -Name $VMName

foreach($ctrl in Get-ScsiController -VM $vm)

{

foreach($disk in (Get-HardDisk -VM $vm | where{$_.ExtensionData.ControllerKey -eq $ctrl.Key}))

{

IF (($disk.ExtensionData.UnitNumber -eq $SCSITargetId )-and (($disk.ExtensionData.Backing.Uuid).Replace('-','') -eq $DiskSNfromWMI) )

{

# The below Variables are for the tab Published Data of "Run .Net Script" Activiy

$VMDiskName = $disk.Name

$VMDiskFilename = $disk.Filename

$DiskUID = $disk.Uid

$DiskCapacityGB = $disk.CapacityGB

$DiskFreeSpaceGB = ((Get-VMGuest -VM $vm).Disks | where {$_.Path -eq "$Drive\"}).FreeSpaceGB

$DiskFreeSpaceGB = "{0:N3}" -f ([math]::Round($DiskFreeSpaceGB,3))

}

}

}

$LUN = Get-HardDisk -vm $vm | Where {$_.Uid -eq $DiskUID} | Get-Datastore

$LUNName = $LUN.Name

$FreespaceGB = "{0:N3}" -f ([math]::Round($LUN.FreeSpaceGB,3))

$CapacityGB = "{0:N3}" -f ([math]::Round($LUN.CapacityGB,3))

##################

#Driveletter will be extended with 10GB

$extend10GB = "10"

$newsize = $DiskCapacityGB + $extend10GB

# Extend VMDK

Get-HardDisk -vm $vm | Where {$_.Name -eq "$VMDiskName"} | Set-HardDisk -CapacityGB $newsize -ResizeGuestPartition -Confirm:$false

#rescan

Invoke-VMScript -vm $VM -ScriptText "echo select vol $drive > c:\diskpart.txt && echo rescan >> c:\diskpart.txt && diskpart.exe /s c:\diskpart.txt" -ScriptType BAT -GuestUser $UserName -GuestPassword $pw.password

#Extend Disc inside

Invoke-VMScript -vm $VM -ScriptText "echo select vol $drive > c:\diskpart.txt && echo extend >> c:\diskpart.txt && diskpart.exe /s c:\diskpart.txt" -ScriptType BAT -GuestUser $UserName -GuestPassword $pw.password

VCP4,VCP5,VCP6,VCP7,VCP8
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Well, if it is working in your environment, so much the better.
Just be aware that the logic how you link the VMDK to the drive/partition might have issues when you start adding/removing harddisks to the VM and also when you start reconfiguring partitions inside the Guest OS.

What is missing with regards to the FreeSpaceGB?


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

0 Kudos