I’ve created an awful lot of PowerCLI scripts over the years and even created GUI’s for many of them using PowerShell Studio. It’s incredibly gratifying to be able to craft your own tools to make admin life easier while learning something in the process. It’s not a stretch to say development days are my favorite days at work.
Over the past few weeks I’ve been getting back into Visual Studio to write applications that interface with some Arduino projects I’m working on. Those have been fun winter weekend projects, but during the work week I’m a VMware admin, so how do I keep my C sharp? Surely there must be a way to bring the magic of PowerCLI and .NET together. There is…
In this post I’m going to show you how you can create your own vSphere inventory application. We’ll learn how to make connections to vCenter and poll it for VM, Host, and Cluster objects. We’ll do this by leveraging the VMware.VIM Library used by PowerCLI. The application we create will look something like this.
Creating the form
Create a new C# Windows Forms Application and add three list boxes as shown below.
Add the labels, text boxes, and Connect button.
On to the code!
First, our project needs to reference the VMware.VIM namespace which can be found in the directory where PowerCLI is installed.
(C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\VMware.Vim.dll)
Now we need to hook the VMware.Vim namespace in to our code.
Let’s add the System.Collections.Specialized namespace while we’re here. You’ll see why in a bit.
Next we need to declare some lists to dump the data we receive from the vCenter.
Connecting to vCenter
Now that the framework has been built it’s time to start diving into VMware.VIM.
The connection to vCenter is made by calling the Connect and Login methods of the VIMClient class. To use these methods, we need to create a new object called Client. We’ll use this object to connect to the vCenter’s SDK WebService.
In PowerCLI we simply point the Connect-VIServer cmdlet to the vCenter server, but when accessing it via the VIMclient, we need to include the full SDK URL which is simply https://vcenter-server/sdk.
Because we don’t want to connect before the user has entered their vCenter and credential information, we’ll take these actions on the button (btnConnect) click.
Now that we can connect to vCenter, what’s next? How about we pull some VM names? We can do this by calling our client’s FindEntityViews method.
You’re eager to try this out, I can tell! Go ahead!
That’s great! But what if we just wanted to list Windows VM’s? How do we filter for those? This is pretty easy. We just filter for “Windows” against the Config.GuestFullName property.
To do this we need to create the NameValueCollection called filter (this is why we needed to reference the System.Collections.Specialized name space earlier).
Let’s try it now!
It works! My VCSA named VC1 is no longer displayed! If you want to filter against other VM properties, just add another filter.Add line!
Finally, we need to add the host and cluster views by scoping the view to HostSystem, and ClusterComputerResource.
Success!!
There you have it! You’ve just created your first vSphere tool in C#! If you don’t want to create your own forms and enter the code listed above, feel free to download this solution from GitHub or the new VMware Sample Exchange.
Would it be possible to create / delete a dvPortGroup using the VMware.Vim.dll file?
Hi Kevin,
While I don’t have personal experience with creating or destroying dvPortGroups through this API, I know it can be done. Check out the DistributedVirtualPortgroup class here. You should be able to invoke the AddDVPortgroup_Task method to create the port group (documented here) and can be removed by invoking the DestroyNetwork method (only if it’s not in use). As an alternative you could also use Destroy_Task.
Hope this helps!
Matt
Kevin,
Mathis can be done. Quick and easy.
A good way to get the syntax quickly is to download the VMware fling called ‘Onyx’
It acts as a proxy and generates the C# or powercli code which you can then inject into your app.
If you luck out, let me know.
This is awesome! Now would this concept be useful in creating a webforms page (instead of a win form app)?
I want to create a webpage that displays all entries in multiple data sources (including VMware information) for a single Server Name input. I’m being steered away from the VCDB as an API is more recommended but I’m too much of a novice to understand which API would apply to my project. If you have some time to weigh in I’d appreciate it.
Hi Kyle,
This is an excellent question and I’m happy to tell you that it absolutely can! Here’s a proof of concept ASP.NET application I whipped up in a few minutes…
This is worthy of a post all on its own and I’ll try to get something on this site in a few days.
In short, you would add the reference to the VMware.Vim.dll as we did here, but instead of adding “using VMware.Vim”, we’d just add this as a prefix to all our classes. For example, creating the client object would look like this…
VMware.Vim.VimClient Client = new VMware.Vim.VimClientImpl();
You are absolutely correct to steer away from querying your VCDB directly. Instead of using this API, I’d highly recommend PowerCLI for your application. We’ve developed our own server database at work, as you’ve described, which automatically pulls information from VMware, Hyper-V, and a variety of other sources. The front end is an ASP.NET site that talks to a SQL database. We then use a scheduled PowerCLI script to poll our VMware environment and feed that info to the database using SOAP. The trade off is that we don’t have up to the second information, but we’re not taxing our vCenter with every page refresh, and load times are much faster.
Cheers!
Matt
that’s excellent, I look forward to the future posts.
How are you using SOAP with the external DB? I think this is the way to go and have interacted with SQL via Powershell but copying an entire table of info between databases would be a new experience for me. My main questions would be how are you setting up the “dump table” and how are you making sure old entries (deleted VMs) are removed?
and thanks for your replies, I appreciate your time.
Finally something to get me going.
I’ve had endless pain getting between VIX, the SDK, compiling the dlls and so on.
This has me up and running.
Sadly, it seems that this method of data gathering is still significantly slower than tapping up the DB using EF.
for example:
VimClient client = new VimClientImpl();
client.Connect(sdkpath);
client.Login(_user, _password);
var vmlist = client.FindEntityViews(typeof(VirtualMachine), null, null, null);
takes several seconds, just for the connection – significantly longer than
using (var db = new ….)
{
vmllist = db.VMXV_VMs
}
I’m be inclined for now (although it is poor practice) to still continue using a read only account for DB EF connections in instances where I want to report on data, but attempt to use VIM for commits / edits.
In my case, I have several VCs to interrogate and thread across few a DBs is a quick and painless process.
Irrespective, you have helped me a chunk here.
Thanks
Awesome, will try sometime in coming weekend’s. TFS.
Hi Matt, thanks for your post.
I have some even more basic questions:
1. how can I run an instance of a VM (assuming I have a VMWare.exe file to run)? (then, I will use your code to communicate with this instance).
2. what is vCenter? how to set it up? why isn’t it enough to have few instances of VMs?
3. what are the instances of VMs in vCenter? how are they started?
thanks in advance,
Shai
Hi Matt !
Thanks for this tutorial !
But I have a big question… how to show in our created C# window the VM ? Because I can connect to my server, execute actions on my VMs but I can’t show them… HELP ME PLEASE !
Thanks in advance
Pierre
I have been researching how to make a program to get stats from the vms server.
Example:
Server
Total, free:
-Hard disk, CPU cores, ram
I do not know exactly how to do it
First I’m trying to get the basic data from the vms,
But I have an error with this. (FindEntityViews)
Client.FindEntityViews(typeof(VirtualMachine), null, filter, null);
The type ‘NameValueCollection’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Collections.Specialized, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’.
if someone could help me.
Hi Matt, very very nice tuturial. perfect four beginners. I will try connect to my vsphere esxi 6.5 but i get a certificate error. Can you tell me how to ignore this certificate issue? thanks and regards from germany Alex
Matt
Great video. I am using it as a basis to explore different types of information about my environment. I am having a little issue I was hoping you might be able to comment on. I built a test interface with two list boxes. The hope is to have the first populate with all the host machine names and when you select one it will populate the second with just the VMs on that host. The problem I am running into is that I cannot find the hostname anywhere in the properties. Well, I can find it, it is just NULL. not sure what to do to make this happen. Any thoughts?
thanks
Kyle