For vSphere tagging, most PowerCLI users go for the “Get-Tag”,”Get-TagCategory”, or “Get-TagAssignment” methods.
Depending on the size of your vCenter, inventory count, but more importantly, Tag count, the CisService methods may provide better performance for vSphere Tagging.

To access these APIs, you will need to log in to vcenter with the following string.  (Adjust vcenter/user/pass as needed)
connect-cisserver “” -username “administrator@vsphere.local” -pass “mypassword”

To start, each method has documentation.  I will say, it’s not extremely easy to read, but its better than leaving us stranded.
I will show you how to pull the command documentation for Tag Categories and you should be able to translate this for other methods.
Pasting the following two lines will show you the “Operations” you can complete within the “tagging.category.”
$allCateMethod = Get-CisService com.vmware.cis.tagging.category

From here, you can expand the help.  Lets say you want to create a new Tag Category.  You add on “create” to the help command and it will show you what you need to complete the command.

Below, I will post the most common methods I use.

# Create a new Tagging Category: (I included all possible options for the specs after the comment hash)
$allCateMethod = Get-CisService com.vmware.cis.tagging.category
$spec = $allCateMethod.Help.create.create_spec
$ = “myFirstCategory”
$spec.description = “”
$spec.cardinality = “MULTIPLE” # “SINGLE” # yes it needs to be all caps….
$spec.associable_types = “virtualmachine”,”vmhost” # Cluster, Datacenter, Datastore, DatastoreCluster, DistributedPortGroup, DistributedSwitch, Folder, ResourcePool, VApp, VirtualPortGroup

# Get all Tag Categories:
$allCateMethod = Get-CisService com.vmware.cis.tagging.category
$allcate = $allcateMethod.list()
$cates = @()
foreach ($cate in $allcate) {
$cates += $allCateMethod.Get($cate)

# Create a new Tag:  (a Tag needs a category so be sure to create one first)
$alltagMethod = Get-CisService com.vmware.cis.tagging.tag
$spec = $alltagMethod.Help.create.create_spec
$ = “myFirstTag”
$spec.description = “”
$spec.category_id = $cates | where {$ -eq “myFirstCategory”} | %{$}

# Get all Tags:
$alltagMethod = Get-CisService com.vmware.cis.tagging.tag
$alltag = $alltagMethod.list()
$tags = @()
foreach ($tag in $alltag) {
$tags += $alltagMethod.Get($tag)

# From here, you can now Attach, Detach, or Query tags to objects.   To access those objects (like a Virtual Machine) you will need to connect to vcenter with our VIServer connection.
connect-viserver “” -username “administrator@vsphere.local” -pass “mypassword”

Now we can pull in object IDs and match them with Tag IDs.
# Attach a Tag to a VirtualMachine:
$mytag = $tags | where {$ -eq “myFirstTag”}
$vm = Get-VM -Name “myFirstVM”
$tagAssign = Get-CisService -Name com.vmware.cis.tagging.tag_association
$spec = $tagAssign.Help.attach.object_id.Create()
$spec.type = $vm.ExtensionData.MoRef.Type
$ = $vm.ExtensionData.MoRef.Value
$tagAssign.attach($, $spec)

# Then to check the Association:
$tagAsso = Get-CisService -Name com.vmware.cis.tagging.tag_association

If you dig deep into the documentation of these methods, you will find ways to Add, Delete, Create, and even Batch assign tags.  I gave you the starting point here.

One extra for the road:
# Quick method to delete a Tag Category:   (Quick note…. Deleting a category WILL delete all of the tags under it and the API call will not prompt you about it.)
$mycateID = $cates |where {$ -eq “myFirstCategory”} |%{$}
$allCateMethod = Get-CisService com.vmware.cis.tagging.category

Let me know if you have any questions @vmnick0 on twitter.

Run this to reduce the load time of your Powershell windows when using the Powershell add-ons.
You will need to run this for both 32 and 64bit powershell environments.
You will also need to run this each time you install a new version of PowerCLI.
The window may take a few minutes to complete.

Launch a 64 and 32bit powershell window and runAS an Administrator.
Paste this into each window. 

Set-Alias ngen (Join-Path ([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()) ngen.exe)

Get-ChildItem -Path $env:SystemRoot\assembly\GAC_MSIL\VimService*.XmlSerializers |
ForEach-Object {
if ($_) {
$Name = $_.Name
Get-ChildItem -Path $_
} |
Select-Object -Property @{N=”Name”;E={$Name}},@{N=”Version”;E={$_.Name.Split(“_”)[0]}},@{N=”PublicKeyToken”;E={$_.Name.Split(“_”)[-1]}} |
ForEach-Object {
if ($_) {
ngen install “$($_.Name), Version=$($_.Version), Culture=neutral, PublicKeyToken=$($_.PublicKeyToken)”

I’ve found that the Powershell Window performace is limited unless you make some changes.
Below are some quick things you can do to increase the performance and hopefully reduce the time of your script execution.

–  This command will check and set the Max Memory that each Powershell session can use.
Default is 150MB:
Get-item WSMan:\localhost\Shell\MaxMemoryPerShellMB
Set-item WSMan:\localhost\Shell\MaxMemoryPerShellMB 1024 -Force

–  This command, added to your script, will run garbage colection and free up some RAM.

– It was found that Windows Tasks will launch your Powershell scripts at “Below Normal” CPU priority.
This is how you can fix that issue.  Its a pain but VERY worth it if you use Windows Tasks to launch your scripts.
Step1 – Export your Task to an XML file.
–   schtasks /query /tn “\MyTask” /xml > “c:\temp\MyTask.xml”
Step2 – Edit the XML file (Notepad works) and change this part “<Priority>4</Priority>”
–  You should see that the orginal is set to a value of 7.  Setting it to 4 makes a world of difference.
Step3 – Import the XML back into the Tasks window.
– Within Task Scheduler, right click the folder you want the task to live and select “Import Task.”
– Browse to your file, Click Open, edit your task as needed and save  it