VMware Cloud Community
BlueMike
Contributor
Contributor

Script I used for a VMware View rollout of over 1000 users

My company has around 1400 users and we got the mandate to migrate all employee workstations to go to virtual machines.  When we started this migration 2 years ago, we were using vSphere 3.5, but now are running vSphere 4.1 and VMware View 4.6.  Since we implemented VMware View 4.0, we had our View set up with 1:1 pools.  So each user's machine name matches the pool name in View, desktop name in View, and the vSphere virtual center name.   I am fairly sure View 4.5 or 4.6 is necessary to run any of the View commands!

Our template in vSphere runs some PowerShell scripts to add itself to the domain, register it to SCCM and process all installs for the machine, etc, so none of that is addressed with this script.  However, I did simplify our virtual machine builds to this single script just by adding a user name.  I also included a GUI, but it isn't very descriptive at this point, and doesn't take data entry mistakes gracefully.  Either way, this saved hours per build!

In the script sample, I am replacing our server names with <MACHINEROLE> so that it becomes generic.  These would have to be replaced with equivalent servers/machine names should you choose to use this script.  It also requires that the View server have PowerShell 2.0 installed with View PowerCLI and remote pssession turned on.  This frees you from having to run the View PowerCLI commands locally on the View server, but instead can run them implicitly from a client desktop.  I also use Quest's AD PowerShell Plugin.  This just made accessing AD easier on machines that didn't have RSAT installed.  Finally, VMware PowerCLI would need to be installed on the client machine running this script.

Some other things to note.  We name our VM's with V1, V2, V3 followed by the user name.  Some of the logic of this code will show it stripping the first two letters off to get a user name.  Due to the naming convention, this was fairly easy to manage.  V1DoeJ could be tied to user DoeJ by stripping out the first two characters.

Finally, I apologize for some of the sloppy coding.  I am hoping that by releasing this, someone who might have gotten stuck on one of the challenges I addressed might find the key they needed to make things work for them (SUCH AS REMOTE VIEW POWERCLI STRATEGY!) that took me forever to figure out.  Or even better yet that someone might clean this up and make it really pretty and generic for general consumption.  Hey, even in this state, it shaved 3 months off my estimated rollout time!  This was a living script that only looks like this at the end, and will only have limited use going forward.

The GUI is pretty sad, I know.  It uses direct .NET calls from PowerShell, so no additional plugins are required for it so long as .NET is installed.  There is a progress bar that I wanted to use, but just couldn't find a way to reliably capture the clone task for a given build that would allow me to populate that field.  I might fix that later if there is need at my company.

On a side note, I had to write another script that back entitled all VM's that had been created before we implemented View.  I may post that later.

Enjoy and feel free to comment or ask questions.  I can't promise that I will answer frequently, but I may glance in from time to time out of curiousity.

And now the code (I hope that line breaks don't ruin it...  I will attach a copy as well I suppose):

#This normalizes the manager name from the DN
function Strip-ManagerName {
Param ($Full)
$Segments=$Full.split(",")
$FirstSegment=$Segments[0]
$SplitSegment=$FirstSegment.split("=")
$NormalGroupName=$SplitSegment[1]
return ($NormalGroupName)
}
function Pick-User
{
param($VMUserName)
Set-Variable -Name UserOutput.Text -Value "Processing User information.  Please wait!" -Scope 1
$User = Get-QADUser -SearchAttributes @{SamAccountName=$VMUserName} -IncludeAllProperties
$vSphereData = @(get-vm -name *$VMUserName)
$ADData = Get-QADComputer -Name *$VMUserName
# ==============================================
# =        -= Output User Information =-      =
# ==============================================
$global:UserInformationArray = @()
$global:UserInformationArray += "User: " + $User.DisplayName + "`r"
$global:UserInformationArray += "Username: " + $User.SamAccountName + "`r"
$global:UserInformationArray += "Title: " + $User.Title + "`r"
$global:UserInformationArray += "Location: " + $User.Office + "`r"
$global:UserInformationArray += "Manager: " + (Strip-ManagerName $User.Manager) + "`r"
$global:UserInformationArray += "" + "`r"
$global:UserInformationArray += "Here are the VM's currently ending with '" + $User.SamAccountName + "' (Test VC's Included):" + "`r" + "`r"
$global:UserInformationArray += $vSphereData + "`r"
$global:UserInformationArray +=  "" + "`r"
$global:UserInformationArray += "Here are the Computers currently ending with " + $User.SamAccountName + " in Active Directory:" + "`r" + "`r"
$ADData | sort-object -property Name | ForEach-Object `
{
$global:UserInformationArray += $_.Name  + "`r"
$global:UserInformationArray += "  OS: " + $_.OSName + "`r"
$global:UserInformationArray += "  OU: " + $_.ParentContainer + "`r"
$global:UserInformationArray += "  Created: " + $_.CreationDate + "`r"
$global:UserInformationArray += "`r"
}
return ($User)
}
#Generated Form Function
function GenerateForm {
########################################################################
# Code Generated By: SAPIEN Technologies PrimalForms (Community Edition) v1.0.9.0
# Generated On: 5/31/2011 1:48 PM
# Generated By: BlueMike
########################################################################
#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
#endregion
#region Generated Form Objects
$VDIBuildForm = New-Object System.Windows.Forms.Form
$ClusterLabel = New-Object System.Windows.Forms.Label
$ClusterSelect = New-Object System.Windows.Forms.ComboBox
$BuildProgressBar = New-Object System.Windows.Forms.ProgressBar
$ProcessMachineButton = New-Object System.Windows.Forms.Button
$button1 = New-Object System.Windows.Forms.Button
$VDIBuildData = New-Object System.Windows.Forms.DataGridView
$UserInformationLabel = New-Object System.Windows.Forms.Label
$UserOutput = New-Object System.Windows.Forms.RichTextBox
$UserNameInput = New-Object System.Windows.Forms.TextBox
$OtherButton = New-Object System.Windows.Forms.RadioButton
$UserButton = New-Object System.Windows.Forms.RadioButton
$ProcessStatusLabel = New-Object System.Windows.Forms.Label
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects
$ClusterSelect.DataSource = $ClusterList
#----------------------------------------------
#Generated Event Script Blocks
#----------------------------------------------
#Provide Custom Code for events specified in PrimalForms.
$button1_OnClick=
{
#TODO: Place custom script here for the BUILD button.
##Code to make the progress bar work##
##There is no graceful way to determine which task is the one you started, so I need to find the latest build going on after starting the build.
$TaskList = @()
$NewVMTasks = 0
#Are any builds currently
$TaskList = @(Get-Task | Where-Object {$_.Name -like "CloneVM_Task"}) ; $NewVMTasks = $TaskList.Count
$CloneVMTask = New-VM -Name $VMName -Template $template -OSCustomizationSpec $CustSpec -VMHost $vmhost -Datastore $VMDatastoreName -Location $buildfolder #-RunAsync
$ProcessStatusLabel.text = "VDI Build Started.  This can take up to 20 minutes."
Start-Sleep 10
$TaskList = @()
$NewVMTasks = 0
$TaskList = @(Get-Task | Where-Object {$_.Name -like "CloneVM_Task"} | Sort-Object -Property StartTime)
$NewVMTasks = $TaskList.Count
$ProcessStatusLabel.text = "Clone complete. Entitling the Virtual Machine now.  VDI build scripts starting shortly."
Remove-Pool -pool_id $VMName -EA "SilentlyContinue" -WA "SilentlyContinue"
Get-DesktopVM -Name $VMName | Add-ManualPool -pool_id $VMName -isUserResetAllowed $true
Add-PoolEntitlement -pool_id $VMName -sid ((Get-QADUser $User).sid)
#Start-VM -VM $VMName
$ProcessStatusLabel.text = "Clone complete."
}
#####################################PROCESS MACHINE BUTTON CODE##########################################
$ProcessMachineButton_OnClick=
{
#TODO: Place custom script here
If ($UserButton.checked) {
$ADData = Pick-User $UserNameInput.text
$User = $ADData.SamAccountName
#=====================================================================================
#=Take the username and determine the name of the next virtual machine for that user.=
#=====================================================================================
$VMName = ""
$VMList = get-vm -name *$User
foreach ($Number in $VDIRange)
{
$VDITestName = ("V" + $Number + $User)
$VMList = get-vm -name $VDITestName -EA "SilentlyContinue"
if ($VMList -notlike "")
{}
else
{
$VMName = $VDITestName
break
}
}
$UserOutput.Text = $UserInformationArray
}
Else {
$VMName = $UserNameInput.text
$UserOutput.Text = ("VDI named " + $VMName + " will be built.")
}
######################################
$VMDatastoreFreespace = 0
Switch ($ClusterSelect.Text)
{
"Cluster 9 - Windows XP" {$vmhost = $Cluster9Host; $template = $Cluster9Template; $buildfolder = $Cluster9BuildFolder; $CustSpec = $Cluster9CustSpec}
"Cluster 10 - Windows 7" {$vmhost = $Cluster10Host; $template = $Cluster10Template; $buildfolder = $Cluster10BuildFolder; $CustSpec = $Cluster10CustSpec}
"Cluster 8 - Windows XP" {$vmhost = $Cluster8Host; $template = $Cluster8Template; $buildfolder = $Cluster8BuildFolder; $CustSpec = $Cluster8CustSpec}
"Cluster 7 - Windows XP" {$vmhost = $Cluster7Host; $template = $Cluster7Template; $buildfolder = $Cluster7BuildFolder; $CustSpec = $Cluster7CustSpec}
"Cluster 6 - Windows XP" {$vmhost = $Cluster6Host; $template = $Cluster6Template; $buildfolder = $Cluster6BuildFolder; $CustSpec = $Cluster6CustSpec}
}
$CurrentBuildHost = $vmhost
#We use some naming filters here that help us identify the appropriate datastore to use for a given cluster.
$CurrentBuildDatastores = Get-Datastore -VMHost $CurrentBuildHost | Where-Object {($_.'Name' -like 'VMSAN*') -or ($_.'Name' -like 'Netapp??VDI??')}
$Datastores = Get-Datastore $CurrentBuildDatastores | Where-Object {$_.'FreeSpaceMB' -ge 130000} | Sort-Object -property 'FreeSpaceMB' -descending
$VMDatastoreName = $Datastores[0].name
Switch ((Get-Task | Where-Object {$_.name -like "CloneVM_Task"}).length)
{
$null {$VMDatastoreFreespace = $Datastores[0].FreeSpaceMB}
1 {$VMDatastoreFreespace = $Datastores[1].FreeSpaceMB}
2 {$VMDatastoreFreespace = $Datastores[2].FreeSpaceMB}
3 {$VMDatastoreFreespace = $Datastores[3].FreeSpaceMB}
}
########################
# Present Information
$VDIBuildData.RowCount = 1
$VDIBuildData.ColumnCount = 2
$VDIBuildData.Rows.Add("VDI Name",$VMName)
$VDIBuildData.Rows.Add("Host Server",$vmhost)
$VDIBuildData.Rows.Add("Template",$template)
$VDIBuildData.Rows.Add("Datastore",$VMDatastoreName)
             $VDIBuildData.Rows.Add("Freespace",$VMDatastoreFreespace)
$VDIBuildData.Rows.Add("Build folder",$buildfolder)
$VDIBuildData.Rows.Add("Customization Specification",$CustSpec)
$column1 = $VDIBuildData.Columns[0]
$column2 = $VDIBuildData.Columns[1]
$column1.Width = 410
$column2.Width = 200
        If ($VMDatastoreName -lt 1) {
            Write-Host ""
            Write-Host "An appropriate datastore could not be found"
            Write-Host "that can store the VDI.  Please contact System"
            Write-Host "Administration.  Aborting build."
            Start-Sleep 10
            Exit
            }
#$VDIBuildData.ColumnCount = 2
#$row = @(
}
$handler_UserNameInput_TextChanged=
{
#TODO: Place custom script here
}
$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
$VDIBuildForm.WindowState = $InitialFormWindowState
}
#----------------------------------------------
#region Generated Form Code
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 895
$System_Drawing_Size.Width = 844
$VDIBuildForm.ClientSize = $System_Drawing_Size
$VDIBuildForm.DataBindings.DefaultDataSourceUpdateMode = 0
$VDIBuildForm.Name = "VDIBuildForm"
$VDIBuildForm.Text = "VDI GUI Build Beta"
$ClusterLabel.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 353
$System_Drawing_Point.Y = 64
$ClusterLabel.Location = $System_Drawing_Point
$ClusterLabel.Name = "ClusterLabel"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 18
$System_Drawing_Size.Width = 231
$ClusterLabel.Size = $System_Drawing_Size
$ClusterLabel.TabIndex = 12
$ClusterLabel.Text = "Select a cluster below"
$VDIBuildForm.Controls.Add($ClusterLabel)
$ClusterSelect.DataBindings.DefaultDataSourceUpdateMode = 0
$ClusterSelect.FormattingEnabled = $True
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 353
$System_Drawing_Point.Y = 90
$ClusterSelect.Location = $System_Drawing_Point
$ClusterSelect.Name = "ClusterSelect"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 21
$System_Drawing_Size.Width = 232
$ClusterSelect.Size = $System_Drawing_Size
$ClusterSelect.TabIndex = 11
$VDIBuildForm.Controls.Add($ClusterSelect)
$BuildProgressBar.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 111
$System_Drawing_Point.Y = 820
$BuildProgressBar.Location = $System_Drawing_Point
$BuildProgressBar.Name = "BuildProgressBar"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 25
$System_Drawing_Size.Width = 721
$BuildProgressBar.Size = $System_Drawing_Size
$BuildProgressBar.TabIndex = 10
$VDIBuildForm.Controls.Add($BuildProgressBar)
$ProcessMachineButton.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 725
$System_Drawing_Point.Y = 64
$ProcessMachineButton.Location = $System_Drawing_Point
$ProcessMachineButton.Name = "ProcessMachineButton"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 47
$System_Drawing_Size.Width = 107
$ProcessMachineButton.Size = $System_Drawing_Size
$ProcessMachineButton.TabIndex = 9
$ProcessMachineButton.Text = "PROCESS MACHINE"
$ProcessMachineButton.UseVisualStyleBackColor = $True
$ProcessMachineButton.add_Click($ProcessMachineButton_OnClick)
$VDIBuildForm.Controls.Add($ProcessMachineButton)
$button1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 818
$button1.Location = $System_Drawing_Point
$button1.Name = "button1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 27
$System_Drawing_Size.Width = 79
$button1.Size = $System_Drawing_Size
$button1.TabIndex = 8
$button1.Text = "BUILD"
$button1.UseVisualStyleBackColor = $True
$button1.add_Click($button1_OnClick)
$VDIBuildForm.Controls.Add($button1)
$VDIBuildData.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 553
$VDIBuildData.Location = $System_Drawing_Point
$VDIBuildData.Name = "VDIBuildData"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 240
$System_Drawing_Size.Width = 820
$VDIBuildData.Size = $System_Drawing_Size
$VDIBuildData.TabIndex = 7
$VDIBuildForm.Controls.Add($VDIBuildData)
$UserInformationLabel.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 353
$System_Drawing_Point.Y = 493
$UserInformationLabel.Location = $System_Drawing_Point
$UserInformationLabel.Name = "UserInformationLabel"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 114
$UserInformationLabel.Size = $System_Drawing_Size
$UserInformationLabel.TabIndex = 6
$UserInformationLabel.Text = "User Information"
$UserInformationLabel.TextAlign = 32
$VDIBuildForm.Controls.Add($UserInformationLabel)
$UserOutput.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 145
$UserOutput.Location = $System_Drawing_Point
$UserOutput.Name = "UserOutput"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 345
$System_Drawing_Size.Width = 820
$UserOutput.Size = $System_Drawing_Size
$UserOutput.TabIndex = 5
$UserOutput.Text = ""
$VDIBuildForm.Controls.Add($UserOutput)
$UserNameInput.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 91
$UserNameInput.Location = $System_Drawing_Point
$UserNameInput.Name = "UserNameInput"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 198
$UserNameInput.Size = $System_Drawing_Size
$UserNameInput.TabIndex = 3
$UserNameInput.add_TextChanged($handler_UserNameInput_TextChanged)
$VDIBuildForm.Controls.Add($UserNameInput)
$OtherButton.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 64
$OtherButton.Location = $System_Drawing_Point
$OtherButton.Name = "OtherButton"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 272
$OtherButton.Size = $System_Drawing_Size
$OtherButton.TabIndex = 2
$OtherButton.Text = "Other Purpose - Enter Machine Name"
$OtherButton.UseVisualStyleBackColor = $True
$VDIBuildForm.Controls.Add($OtherButton)
$UserButton.Checked = $True
$UserButton.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 38
$UserButton.Location = $System_Drawing_Point
$UserButton.Name = "UserButton"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 20
$System_Drawing_Size.Width = 272
$UserButton.Size = $System_Drawing_Size
$UserButton.TabIndex = 1
$UserButton.TabStop = $True
$UserButton.Text = "Standard User - Enter Username"
$UserButton.UseVisualStyleBackColor = $True
$VDIBuildForm.Controls.Add($UserButton)
$ProcessStatusLabel.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 128
$System_Drawing_Point.Y = 862
$ProcessStatusLabel.Location = $System_Drawing_Point
$ProcessStatusLabel.Name = "ProcessStatusLabel"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 24
$System_Drawing_Size.Width = 583
$ProcessStatusLabel.Size = $System_Drawing_Size
$ProcessStatusLabel.TabIndex = 0
$ProcessStatusLabel.Text = "VDI GUI Build 1.0"
$ProcessStatusLabel.TextAlign = 32
$VDIBuildForm.Controls.Add($ProcessStatusLabel)
#endregion Generated Form Code
#Save the initial state of the form
$InitialFormWindowState = $VDIBuildForm.WindowState
#Init the OnLoad event to correct the initial state of the form
$VDIBuildForm.add_Load($OnLoadForm_StateCorrection)
#Show the Form
$VDIBuildForm.ShowDialog()| Out-Null
} #End Function
#CONSTANTS
#VDIRange lists valid V#'s to use.
$VDIRange=(1..9)
$VMUserName = ""
$vSphereData = @()
$ClusterList = @("Cluster 9 - Windows XP","Cluster 10 - Windows 7","Cluster 8 - Windows XP","Cluster 7 - Windows XP","Cluster 6 - Windows XP")
###Cluster 6 Constants###
$Cluster6Host = "<CLUSTER6HOST>"
$Cluster6Template = "Windows XP SP3 2011"
$Cluster6BuildFolder = "Cluster 6 Scriptbuilt"
$Cluster6CustSpec = "Windows XP SP3 2011"
###Cluster 7 Constants###
$Cluster7Host = "<CLUSTER7HOST>"
$Cluster7Template = "Windows XP SP3 2011"
$Cluster7BuildFolder = "Cluster 7 Scriptbuilt"
$Cluster7CustSpec = "Windows XP SP3 2011"
###Cluster 8 Constants###
$Cluster8Host = "<CLUSTER8HOST>"
$Cluster8Template = "Windows XP SP3 2011"
$Cluster8BuildFolder = "Cluster 8 Scriptbuilt"
$Cluster8CustSpec = "Windows XP SP3 2011"
###Cluster 9 Constants###
$Cluster9Host = "<CLUSTER9HOST>"
$Cluster9Template = "Windows XP SP3 2011"
$Cluster9BuildFolder = "Cluster 9 Scriptbuilt"
$Cluster9CustSpec = "Windows XP SP3 2011"
###Cluster 10 Constants###
$Cluster10Host = "<CLUSTER10HOST>"
$Cluster10Template = "Win7 sp1 Gold"
$Cluster10BuildFolder = "Cluster 10 Scriptbuilt"
$Cluster10CustSpec = "Win 7 sp1 Gold"
Write-Host "Creating initial connections to vSphere..."
Add-PSSnapin "Vmware.VimAutomation.Core" -EA "SilentlyContinue" | Out-Null
#VClist determines what virtualcenters to use.  Removing test VC's may
#     cause duplicate VM names being created for some users.
$VClist = ("<Production VirtualCenter>","<Test VirtualCenter>")
foreach ($VCNAME in $VCList)
{
Connect-VIServer -Server $VCNAME -EA "SilentlyContinue" -WA "SilentlyContinue" | Out-Null
}
Write-Host "Creating initial connection to Active Directory..."
Add-PSSnapin Quest.ActiveRoles.ADManagement -EA "SilentlyContinue" | Out-Null
Connect-QADService -service '<DOMAINCONTROLLERFULLYQUALIFIED>' | Out-Null
#This Block of code establishes connectivity to the View server and imports the commands.
Write-Host "View Plugin"
Remove-PSSession * -EA "SilentlyContinue"
$ViewSession = New-PSSession <VIEWSERVER>
Invoke-Command -Session $ViewSession {Add-PSSnapin VMware.View.Broker}
$null = Import-PSSession -Session $ViewSession -EA "SilentlyContinue" -WA "SilentlyContinue"
#Call the Function
GenerateForm

Reply
0 Kudos
2 Replies
BlueMike
Contributor
Contributor

It looks like copy and paste from the quoted area does maintain the appropriate line breaks.  Just keep in mind that it just doesn't look like it when reading from the text above.  If in doubt, copy and paste it into Notepad or your PowerShell editor of choice.

Reply
0 Kudos
LucD
Leadership
Leadership

Wow, impressive script. This will come in handy for many.

Thanks for sharing.


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

Reply
0 Kudos