Generating VMware Web Service Proxies for .NET

The current VMware 5.1 SDK no longer redistributes pre-built .NET proxies, just the source WSDL. Not a problem you may think (the WSDL tool or Visual Studio “Add Service Reference” is not so hard use). However, according to their documentation, unless you manually edit the WSDL generated files you could suffer long hangs when your application connects to a VMware server! And you should use XML serialization assemblies anyway to ensure maximum performance.

EDIT 2013.04.24 – The easiest way is to extract the official proxy assemblies from a VMware PowerCLI installation. But if you want to generate your own proxies you can still use this method.

Further examination shows that there are 100s of lines to change in order to complete the process properly. So I decided to script this up to avoid human error and save time when new versions are released.

It deals with the following issues:

  • Automation of the tedious post-processing of WSDL generated proxy file according to VMware SDK 5.1 documentation.
  • Strong name signing.
  • Adds missing version and other common assembly information.

You need only the “wsdl” subdirectory from the current 5.1 SDK ZIP then the following three files copied into the parent directory (so “wsdl” is below them):

Build.cmd – runs the build…


[code]@echo off
setlocal
echo *** Adding paths to .NET SDK tools from Visual Studio 2012…
call "%vs110comntools%vsvars32"
if %errorlevel% neq 0 goto Error

echo *** Subtituting drive for path to avoid long name and space issues…
set PathDrive=X:
subst %PathDrive% "%~dp0."
if %errorlevel% neq 0 goto Error

echo *** Checking (or generating) strong name key…
if not exist "%PathDrive%Vmware.snk" sn -k "%PathDrive%Vmware.snk"

echo *** Cleaning-up any old files…
if exist "%TempPath%Vim*.cs" del "%TempPath%Vim*.cs"

echo *** Building old "VimApi" proxy (ESX 3 and vCenter 2)…
wsdl /n:VimApi "%PathDrive%wsdlVimvim.wsdl" "%PathDrive%wsdlVimvimService.wsdl" /out:"%PathDrive%VimService2012.cs"
if %errorlevel% neq 0 goto Error
csc /t:library /out:"%PathDrive%VimService2012.dll" "%PathDrive%VimService2012.cs" "%PathDrive%AssemblyInfo.cs" /keyfile:"%PathDrive%Vmware.snk"
if %errorlevel% neq 0 goto Error
sgen /p "%PathDrive%VimService2012.dll" /force /compiler:"/keyfile:""%PathDrive%VMware.snk""
if %errorlevel% neq 0 goto Error
powershell -File "%PathDrive%FixVmwareWsdlSource.ps1" "%PathDrive%VimService2012.cs" VimService2012.XmlSerializers "%PathDrive%VimService2012WithXmlSerializers.cs"
if %errorlevel% neq 0 goto Error
csc /t:library /out:"%PathDrive%VimService2012.dll" "%PathDrive%VimService2012WithXmlSerializers.cs" "%PathDrive%AssemblyInfo.cs" /keyfile:"%PathDrive%Vmware.snk"
if %errorlevel% neq 0 goto Error

echo *** Building new "Vim25Api" proxy (ESXi 4-5, ESX 3.5 and vCenter 4-5)…
wsdl /n:Vim25Api "%PathDrive%wsdlVim25vim.wsdl" "%PathDrive%wsdlVim25vimService.wsdl" /out:"%PathDrive%Vim25Service2012.cs"
if %errorlevel% neq 0 goto Error
csc /t:library /out:"%PathDrive%Vim25Service2012.dll" "%PathDrive%Vim25Service2012.cs" "%PathDrive%AssemblyInfo.cs" /keyfile:"%PathDrive%Vmware.snk"
if %errorlevel% neq 0 goto Error
sgen /p "%PathDrive%Vim25Service2012.dll" /force /compiler:"/keyfile:""%PathDrive%VMware.snk"""
if %errorlevel% neq 0 goto Error
powershell -File "%PathDrive%FixVmwareWsdlSource.ps1" "%PathDrive%Vim25Service2012.cs" Vim25Service2012.XmlSerializers "%PathDrive%Vim25Service2012WithXmlSerializers.cs"
if %errorlevel% neq 0 goto Error
csc /t:library /out:"%PathDrive%Vim25Service2012.dll" "%PathDrive%Vim25Service2012WithXmlSerializers.cs" "%PathDrive%AssemblyInfo.cs" /keyfile:"%PathDrive%Vmware.snk"
if %errorlevel% neq 0 goto Error

echo *** Completed successfully
subst %PathDrive% /d
endlocal
exit /b 0

:Error
set result=%errorlevel%
echo *** Error %result%!
subst %PathDrive% /d
endlocal
exit /b %result%[/code]


FixVmwareWsdlSource.ps1 – automatically applies corrections to the WSDL output…


[code language=”PowerShell”]# Check syntax
If ($args.Count -lt 3)
{
Write-Host "Syntax: FixVmwareWdslSource <Input WSDL CS File> <SGEN File Name> <Output WSDL CS File>"
Exit 1
}

# Parse arguments
$filePath = $args[0]
$serializerFileName = $args[1]
$outputFilePath = $args[2]
Write-Host "Processing $filePath with $serializerFileName into $outputFilePath…"

# Delete output file if already exists
If (Test-Path $outputFilePath) { del $outputFilePath }

# Process file
Get-Content $filePath |
ForEach-Object {
$line = $_
If ($line -match "[System.Xml.Serialization.XmlIncludeAttribute")
{
# Comment XmlInclude attributes which cause hang
Write-Output "//$_"
}
Else
{
If ($_ -match "public partial class VimService")
{
# Add reference to previously generated XML serialization assembly
Write-Output "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""$serializerFileName"")]"
Write-Output $line
}
Else
{
# Copy other lines without change
Write-Output $line
}
}
} |
Out-File $outputFilePath -Append[/code]


AssemblyInfo.cs – gives us sensible assembly level attributes, at least required to avoid having version “0.0.0.0” built…


[code language=”CSharp”]using System;
using System.Reflection;
using System.Runtime.InteropServices;

// Information
[assembly: AssemblyDescription("VMware managenent web service proxy.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("VMware")]
[assembly: AssemblyProduct("Management SDK")]
[assembly: AssemblyCopyright("Copyright © VMware")]
[assembly: AssemblyTrademark("All Rights Reserved")]
[assembly: AssemblyCulture("")]

// COM Interop
[assembly: ComVisible(false)]

// Version
[assembly: AssemblyVersion("5.1.0.0")]

// Language compliance
// Not complaint due to use of underscores in parameter and member names, e.g. "_this".
[assembly: CLSCompliant(false)][/code]


Run Build.cmd and wait about 5 minutes.

Following this you only need the Vim25Service.dll and Vim25Service.XmlSerializers.dll for new projects. The VimService.dll and VimService.XmlSerializers.dll are only required if you still have to support very old ESX or vCenter servers. You might want to keep the generated Vmware.snk or adjust the scripts to use your own so you have a persistent strong name key in the future.

11 thoughts on “Generating VMware Web Service Proxies for .NET

  1. Thanks a million for this work! I’m sure it will save me alot of headaches. I do have a question or two… after the build.cmd file was finished a file named VimService2012.cs and one named AssemblyInfo.cs was created in the same folder as the build.cmd. What do I do with these files? I assumed I needed to make a project called “Vim25Service” in the “.dotnetcssamples” folder. Which I did. I created a Class Library and added the vimservice2010.cd file to it. and built it. So, now I’m figuring I have to replace the bad references in all projects? for example, the AppUtil, VimService2010 and VimService2010.XmlSerializers references in all sample projects are broken. So obviously I have to replace tehm in the AppUtil first, then build it.? But the VimService2010.XmlSerializers file is missing… maybe I need to make the VimService Project a WebService ? I’m just not sure… and what do I do with the newly created AssemblyInfo.cs file? do I have to copy it to all Projects? Or only to the 6 Project folders whre there is already a file with that name? thanks for your help

    1. Glad it helped. In answer to your questions…

      The build command uses the WSDL tool to generate those files. The AssemblyInfo.cs and .snk key is just generated so we can add some missing assembly-wide attributes. This is all compiled together into the output DLLs by the build.cmd’s call to the standard CSC .NET C# compiler tool.

      So you could just delete them, but I would keep at least the SNK key because it can be a hassle to update that in Visual Studio or any configuration files which specify it.

      Personally I prefer to check everything into source control in a “Dependencies” solution folder so they are there for future reference.

      The VimService2010 DLL is for accessing older ESX v3.x or vCenter v2.0. The Vim25Service2010 DLL is for accessing current vSphere 4 or vCenter 2.5 and later.

      The *.XmlSerializers DLLs are a pre-compiled .NET serialization assemblies which go together the other DLLs matching their name, e.g. Vim25Service2010.XmlSerializers.dll with Vim25Service2010.dll. They will greatly speed-up access to the VMware services.

      In fact specifically here, one main reason you need this build command, is VMware state there is a real issue whereby your code will just HANG for many minutes if you do not use XML Serialization assemblies! Sounds like a bug to me but nevertheless using XML Serialization assemblies is a good step anyway.

      If we assume most people have vCenter 2.5 or vSphere 4 or later, then most people will just add a reference to Vim25Service.dll and Vim25Service.XmlSerializers.dll.

      One thing which is missing from my post is a replacement compact authentication helper method. VMware have totally changed the way that you authenticate with the service compare to the older VIM SDK I used a while ago.

      Now they use an STS (web service standard Security Token Service) instead of the older SSPI or plain text logon. I wrote a blog entry on the VMware developer site about how to do that in a compact way a long time ago.

      I want to wrap all this up into a nice compact “service agent” (fancy name for some code which makes it easier to access a web service / “proxy helper” in simple terms). But that won’t be done for a month or two so you’ll have to include the AppUtil and several other files from the different VMware samples.

      The problem appears to be that they don’t copy or compile the dependent code into shared assemblies, so the only way you’ll get the VMware samples running is if you keep their directory structure with all projects copied and run their build command to compile everything in the right order. Hard-coded paths to projects outside the solution root folder has always been taboo bad practice, but there you go.

      I must say that generally I get the feeling the new SDK seems to lean more towards Java programmers. I’ll post my complete sample here and maybe Stack Exchange and the VMware developer forum when it’s complete.

      Good luck!
      Tony

  2. you saved my team a lot of time. i don’t understand why vmware makes this process so complicated and also hard to figure out what to do.

  3. thanks!

    I had problem a problem by executing the ps script!

    The command “Set-ExecutionPolicy unrestricted” executed in the ps solved it 😉

  4. Hey CodeChef.

    Whenever i try to run the build.cmd script, i get the following error:

    *** Adding paths to .NET SDK tools from Visual Studio 2012…
    ‘”vsvars32″‘ is not recognized as an internal or external command,
    operable program or batch file.
    *** Error 1!
    Invalid parameter – /D

    What am I doing wrong?

    1. There are two possibilities. First is I just updated my post to ensure all code is enclosed in WordPress code tags. Second, if you were able to copy the code fully, then the %vs110comntools% and %vsvars32% environment variables must exist, which are there by default when you have Visual Studio 2012 installed. If you have an older version of Visual Studio then you need to change the %vs110comntools%, for example to %vs100comntools% for Visual Studio 2010.

      1. Thanks a lot! I was using 2010. Works now. 🙂

        Got my script down from 19 secounds to 5 secounds. !

  5. Hey Code Chief,

    thank you very much for writing this down and getting the scripts VMware was not able to build right!

    Best regards,
    @Kjellski

Leave a Reply

Your email address will not be published. Required fields are marked *