VMware Cloud Community
maikeru1028
Contributor
Contributor

Export the list of virtual machines hosted on an ESXi server

Hi.  I'm completely new the this and don't intend to study it in-depth, I just need to get the job done for a small task at work, and before I go on nuts researching and learning, I'd like to confirm that:

A) a script or guide for what I want to do doesn't already exist

and if not B) I'm on the right track

---

So we have 4 ESXi servers hosting like 8 machines each.  We often have to re-allocate machines to other ESXi servers based on resource requirements for a task, etc.  This makes it hard to keep track of where each virtual machine is, and at present, the only way we have to find a desired machine is to go through vSphere Client for each ESX server until we find what we want.

So what we want is to integrate a C#/ASP.NET page into our internal web service that will display the virtual machine names from each ESXi server.

My thinking is, a Refresh button on the C#/ASP.NET page that will execute four scripts (one for each server).  Each script contacts the respective ESXi server, grabs the list of virtual machines attached to that ESXi server, and outputs a text file or HTML file of just a list of those names.  The C#/ASP.NET page will then pull the names from those four text/HTML files, and format them nicely onto the web page.  So that when we want to find out where a virtual machine is, we just go to this page, hit Refresh, and bam, you get a nicely formatted table saying where what is.

I've taken a look at several sample scripts and whatnot and I have a general idea with what's going on, but my main questions are:

1)  How would you make a Refresh button on a C#/ASP.NET page to execute four PowerCLI scripts?  What kind of code would you need to add to make that happen from C# (using Visual Studio 2010)?

2)  Is it necessary to make four scripts, or can I just have one that you can supply with four different parameters (in this case, the ESXi IP addresses)?

3)  Do the script(s) go on the ESXi server or...how does that work?

That's all for now I guess.

Thanks.

(I realize I'm going to get a reply or two that say RTFM and whatnot, and that's entirely what I intend to do, if there isn't some kind of very simple pre-made implementation that someone can just point me in the direction of first.  I've already been reading guides for hours here and still don't even understand the basics, and don't really care to, I just need this one stupid thing to work.  If that's what it comes to though, I will.  Just checking first!)

0 Kudos
9 Replies
LucD
Leadership
Leadership

A quick shot at your questions

1) Have a look at Using PowerShell 2.0 from ASP.NET Part 1

That could help you in setting up the ASP page and the button.

2) You can use 1 script and use the IP address of the ESXi server as a parameter

param($Name)

Connect-VIServer -Server $Name -User $user -Password $pswd

Get-VM

Note that you will need to have a way to provide the user and password to the Connect-VIServer cmdlet.

3) A PowerCLI script runs on any Windows client that has PowerShell and the PowerCLI snapin installed.

With the Connect-VIServer cmdlet you make the connection to the ESX(i) server or the vCenter


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

maikeru1028
Contributor
Contributor

Thank you for the quick reply, the helpful attitude, and the useful answers.  Amazing how you managed to knock down in a few lines what I've been trying to figure out for over an hour or so Smiley Happy

0 Kudos
maikeru1028
Contributor
Contributor

I've made a lot of progress on this, and in fact I think I'm almost finished.  I got the script together (which works fine when run from PowerShell or PowerCLI), and I made the ASP.NET/C# page with a button that invokes the script and puts the output into a textbox.  Miraculously, the textbox is filling with some data (meaning that I've successfully made some kind of connection between script and C#, the part that I thought was going to be impossible), but what's filling the textbox is not the same result as running the script from PowerShell or PowerCLI.

Here's my script:

-----------------------------------

Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer -Server 1.1.1.1 -User $user -Password $password
$VMs = Get-VM
foreach ($VM in $VMs)
{
Write-Host $VM.Name
}
-----------------------------------

When I run this in PowerShell or PowerCLI, I get the exact result I desire:

Name                   Port  User

----                       ----  ----

1.1.1.1                 111   user

virtualpc1

virtualpc2

virtualpcn

When I attempt to run this via an ASP.NET button into a textbox, the single and only thing I get is the IP address of the server, "1.1.1.1".

Here is my C# code:

    protected void RunScriptButton_Click(object sender, EventArgs e)

    {

        TextBox155.Text = string.Empty;

        string scripttext = System.IO.File.ReadAllText(@"C:\users\mward\desktop\getvmscript155.ps1");

        var shell155 = PowerShell.Create();

        shell155.Commands.AddScript(scripttext);

        var results155 = shell155.Invoke();

        var builder155 = new System.Text.StringBuilder();

        foreach (var psObject in results155)

        {

            builder155.Append(psObject.BaseObject.ToString() + Environment.NewLine);

        }

        TextBox155.Text = Server.HtmlEncode(builder155.ToString());

    }

Help! Smiley Happy

0 Kudos
bulletprooffool
Champion
Champion

You're shelling out, then capturing a response and it appears only getting the first line as a response.

try :

http://www.codeproject.com/KB/cs/HowToRunPowerShell.aspx for running Powershell code directly in c#.

Otherwise, get your PS script to return am object that is a plain string.

One day I will virtualise myself . . .
0 Kudos
maikeru1028
Contributor
Contributor

You're shelling out, then capturing a response and it appears only getting the first line as a response.

I thought this might be the case, but if so, why am I only getting the IP address, and not also the port and user (which are also on the same line)?

And that site was one that I was reading throughout the day and couldn't quite get to work --- particularly pipeline.Invoke() would cause a runtime error that caused the program to crash, saying that there is no Invoke method.  Several other sites go into pipelines and runspaces and all of that, but I'm fairly certain after all I read that that is overkill for this small tiny task.

Otherwise, get your PS script to return am object that is a plain string.

Would love to, but don't know how.  Would that be some kind flag on Get-VM, like "Get-VM -plainoutput" or something?    

0 Kudos
RvdNieuwendijk
Leadership
Leadership

You can get the output of your script as one string with the Out-String cmdlet. Also you probably only want the virtual machine names and don't want the output of the Connect-VIserver cmdlet to appear in your program. You can remove the Connect-VIserver output by piping it to the Out-Null cmdlet. Like this:

Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer -Server 1.1.1.1 -User $user -Password $password | Out-Null
$VMs = Get-VM
foreach ($VM in $VMs)
{
Write-Host $VM.Name
} | Out-String

Regards, Robert

Blog: https://rvdnieuwendijk.com/ | Twitter: @rvdnieuwendijk | Author of: https://www.packtpub.com/virtualization-and-cloud/learning-powercli-second-edition
0 Kudos
maikeru1028
Contributor
Contributor

Thank you for your time.  The "Out-Null" was helpful because it reduces my results down to exactly what I want (just the VM names).  However, "| Out-String" gives me an error from both C# and PowerCLI, "Empty Pipe Element not Permitted" and I have no idea why.

I tried using some alerts in my code to figure out what is going on, particularly like this:

        foreach (var psObject in results177)
        {
            Response.Write("alert('" + psObject + "')");
            builder177.Append(psObject.BaseObject.ToString() + Environment.NewLine);
        }

and unfortunately this is yielding nothing, it's as if there is nothing in the results177 variable, therefore nothing is getting output.

EDIT: I was able to solve the "Empty Pipe Element not Permitted" by putting the | Out-String directly after $VM.Name, like...

foreach ($VM in $VMs)

{

Write-Host $VM.Name | Out-String

}

Although this works from PowerCLI, there is still no result from C#.

0 Kudos
maikeru1028
Contributor
Contributor

This has fallen to page 2 but I could really use some help; I'm still screwing with this like a week later, when I feel like the solution has got to be something really simple...

0 Kudos
maikeru1028
Contributor
Contributor

Well, a week later again, I've figured out the answer to my problem, and I'll just post it here for completions sake and for other people who may run into the issue in the future.

I had to change the AddCommand calls to AddScript, and that fixed it!

So in other words,

shell155.Commands.AddScript("PSSnapin......."); and so on!

0 Kudos