I'm using the Vestris.VMWareLib API to remotely control my VMs on an ESX 5.0 server. I use the VMWareVirtualMachine.Open method to power on my virtual images. My code is written in C#. The problem is that you need to know the path to the datastore before you can power on the image - I'd like to be able to power it on knowing the VM name only. Is there a way to do this? I've included my current code below.
Thanks, John
using Vestris.VMWareLib;
//Works if VM name is in the path but what if it isn't?
List<VMWareVirtualMachine> vitualMachines = esxServer.RegisteredVirtualMachines.ToList();
VMWareVirtualMachine virtualMachine = vitualMachines.Where(vm => vm.PathName.Contains(vmName)).First();
VMWareVirtualMachine virtualMachine = esxServer.Open(vmName);
There's a method called VMWareVirtualMachine.GetProperty() which can be used to obtain the VM name but I don't know how to use it. Any suggestions or ideas how I can do this?
Thanks,
John
There's been a commit to VMWareTasks that adds the property "Name" to the VMWareVirtualMachine class, it is taken from the "displayName" property in the vmx file. The property is not in VMWareTasks 1.7 so as of right now, you will need to pull the source and build it yourself.
Use it to iterate the registered guests, checking this variable and then power on the appropriate one.
using Vestris.VMWareLib;
private void powerOnVm(string vmName)
{
using (VMWareVirtualHost esxServer = new VMWareVirtualHost())
{
esxServer.ConnectToVMWareVIServer("yourHost", "yourUser", "yourPassword");
using (VMWareVirtualMachine virtualMachine = esxServer.RegisteredVirtualMachines.FirstOrDefault(vm => vm.Name == vmName))
{
if (virtualMachine != null && !virtualMachine.IsRunning)
virtualMachine.PowerOn();
}
}
}
I just tested the above and it worked fine.
Related
I need to get the Application Title from an access database via C#. I have seen some samples using Office VBA: I.E: https://learn.microsoft.com/en-us/office/vba/api/access.application.apptitle
The issue is that I don't have a reference to a class library to be able to access the Application.AppTitle property. I have tried a few references, most notably:
using Microsoft.Office.Interop.Access.Dao
But I can't access the Application.AppTitle via any of the properties. For example:
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
var db = dbe.OpenDatabase(#"c:\\Sample.mdb");
// Show database properties
// db.Properties. "When I expand this there is no AppTitle"
Does anyone have any other approach that has worked for them to access the MS Access AppTitle via C#?
Thanks in advance!
Ian
The AppTitle property doesn't show up until you set it in Access or via code (and with RefreshTitleBar
Your code works because you're looping to check for the name. You won't find the property if it's empty.
You can use the loop method like you do above or check for it directly using database.properties("AppTitle") - just make sure you trap for an error in case it's empty
Update: I figured it out. This was different than I expected, but the solution was:
var dbEngine = new DBEngine();
var database = dbEngine.OpenDatabase(#"c:\\Sample.mdb");
Microsoft.Office.Interop.Access.Dao.Property allowBypassKeyProperty = null;
foreach (Microsoft.Office.Interop.Access.Dao.Property property in database.Properties)
{
if (property != null)
{
if (property.Name == "AppTitle")
{
MessageBox.Show(property.Name.ToString());
MessageBox.Show(property.Value.ToString());
}
}
}
I was wondering if there is a way to get all the computer names that show up in my network places using C#.
You will want to use the NetServerEnum() API. I dont believe there is a managed wrapper for this in the base .NET libraries but I was able to find this with a quick google search: http://www.codeproject.com/Articles/16113/Retreiving-a-list-of-network-computer-names-using
NOTE: I haven't tested or thoroughly reviewed the codeproject code but it should be enough of a starting point for what you need if there are any issues.
EDIT: Do not use DirectoryServices unless your sure of a domain environment. The System.DirectoryServices class is an ADSI wrapper that dosent work without an Active Directory to query against. NetServerEnum() works on workgroups and domains but dosen't guarantee the most reliable data (not all machines may show up). It relies on the Computer Browser service.
The best solution would probably be a class that wraps both possibilities and merges the results :/
This works, but it takes a while. :/
public List<String> ListNetworkComputers()
{
List<String> _ComputerNames = new List<String>();
String _ComputerSchema = "Computer";
System.DirectoryServices.DirectoryEntry _WinNTDirectoryEntries = new System.DirectoryServices.DirectoryEntry("WinNT:");
foreach (System.DirectoryServices.DirectoryEntry _AvailDomains in _WinNTDirectoryEntries.Children) {
foreach (System.DirectoryServices.DirectoryEntry _PCNameEntry in _AvailDomains.Children) {
if (_PCNameEntry.SchemaClassName.ToLower().Contains(_ComputerSchema.ToLower())) {
_ComputerNames.Add(_PCNameEntry.Name);
}
}
}
return _ComputerNames;
}
Depends on the user's permission, the application may or may not get those information.
Try using ActiveDirectory. This should get you precise information about the local network.
Use System.DirectoryServices.
I got the following snippet (SomeName/SomeDomain contains real values in my code)
var entry = new DirectoryEntry("LDAP://CN=SomeName,OU=All Groups,dc=SomeDomain,dc=com");
foreach (object property in entry.Properties)
{
Console.WriteLine(property);
}
It prints OK for the first 21 properties, but then fail with:
COMException {"Unknown error (0x8000500c)"}
at System.DirectoryServices.PropertyValueCollection.PopulateList()
at System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry, String propertyName)
at System.DirectoryServices.PropertyCollection.PropertyEnumerator.get_Entry()
at System.DirectoryServices.PropertyCollection.PropertyEnumerator.get_Current()
at ActiveDirectory.Tests.IntegrationTests.ObjectFactoryTests.TestMethod1() in MyTests.cs:line 22
Why? How can I prevent it?
Update
It's a custom attribute that fails.
I've tried to use entry.RefreshCache() and entry.RefreshCache(new[]{"theAttributeName"}) before enumerating the properties (which didn't help).
Update2
entry.InvokeGet("theAttributeName") works (and without RefreshCache).
Can someone explain why?
Update3
It works if I supply the FQDN to the item: LDAP://srv00014.ssab.com/CN=SomeName,xxxx
Bounty
I'm looking for an answer which addresses the following:
Why entry.Properties["customAttributeName"] fails with the mentioned exception
Why entry.InvokeGet("customAttributeName") works
The cause of the exception
How to get both working
If one wants to access a custom attribute from a machine that is not
part of the domain where the custom attribute resides (the credentials
of the logged in user don't matter) one needs to pass the fully
qualified name of the object is trying to access otherwise the schema
cache on the client machine is not properly refreshed, nevermind all
the schema.refresh() calls you make
Found here. This sounds like your problem, given the updates made to the question.
Using the Err.exe tool here
http://www.microsoft.com/download/en/details.aspx?id=985
It spits out:
for hex 0x8000500c / decimal -2147463156 :
E_ADS_CANT_CONVERT_DATATYPE adserr.h
The directory datatype cannot be converted to/from a native
DS datatype
1 matches found for "0x8000500c"
Googled "The directory datatype cannot be converted to/from a native" and found this KB:
http://support.microsoft.com/kb/907462
I have the same failure. I´m read and saw a lot of questions about the error 0x8000500c by listing attribute from a DirectoryEntry.
I could see, with the Process Monitor (Sysinternals), that my process has read a schema file. This schema file is saved under
C:\Users\xxxx\AppData\Local\Microsoft\Windows\SchCache\xyz.sch.
Remove this file and the program works fine :)
I just encountered the issue and mine was with a web application.
I had this bit of code which pulls the user out of windows authentication in IIS and pulls their info from AD.
using (var context = new PrincipalContext(ContextType.Domain))
{
var name = UserPrincipal.Current.DisplayName;
var principal = UserPrincipal.FindByIdentity(context, this.user.Identity.Name);
if (principal != null)
{
this.fullName = principal.GivenName + " " + principal.Surname;
}
else
{
this.fullName = string.Empty;
}
}
This worked fine in my tests, but when I published the website it would come up with this error on FindByIdentity call.
I fixed the issue by using correct user for the app-pool of the website. As soon as I fixed that, this started working.
I had the same problem with a custom attribute of a weird data type. I had a utility program that would extract the value, but some more structured code in a service that would not.
The utility was working directly with a SearchResult object, while the service was using a DirectoryEntry.
It distilled out to this.
SearchResult result;
result.Properties[customProp]; // might work for you
result.Properties[customProp][0]; // works for me. see below
using (DirectoryEntry entry = result.GetDirectoryEntry())
{
entry.Properties[customProp]; // fails
entry.InvokeGet(customProp); // fails as well for the weird data
}
My gut feel is that the SearchResult is a little less of an enforcer and returns back whatever it has.
When this is converted to a DirectoryEntry, this code munges the weird data type so that even InvokeGet fails.
My actual extraction code with the extra [0] looks like:
byte[] bytes = (byte[])((result.Properties[customProp][0]));
String customValue = System.Text.Encoding.UTF8.GetString(bytes);
I picked up the second line from another posting on the site.
Vmware's .net api reference is somewhat confusing and hard to follow. I have been able to connect to my vcenter host then get a list of esxi hosts. Then I have been able get all the running modules on the host using HostKernelModuleSystem, and probe the properties on the variable "mod"... but I am not able to figure out how to get license info, I tried creating an object lic below, trying all different kinds of "types" from vmware with the word license in the type. but, it never works it has a problem converting the line with LicenseManagerLicenseInfo lic = .... I always get the following:
"Cannot convert type 'Vmware.Vim.Viewbase' to
'Vmware.Vim.LicenseManagerLicenseInfo'"
but the declaration above it for "mod" works fine.
I have also tried:
HostLicenseConnectInfo
LicenseAssignmentManagerLicenseAssignment
LicenseManager
I am hoping someone who has worked with vmware .net api can shed some light on what i am doing wrong? I am new to C# about 1 year :) but these VMware APIs are somewhat confusing to me.
esxList = client.FindEntityViews(typeof(HostSystem), null, null, null);
foreach (HostSystem host in esxList)
{
HostKernelModuleSystem mod = (HostKernelModuleSystem)client.GetView(host.ConfigManager.KernelModuleSystem, null);
LicenseManagerLicenseInfo lic = (LicenseManagerLicenseInfo)client.GetView(host.ConfigManager.LicenseManager, null);
string name = lic.Name;
}
I'll have to go to work tomorrow to look at this ( don't have ESX and VMWare SDK for .NET at home ) but I've done a bit of this work.
I wrote a generics method that wraps FindEntityViews and takes a filter as an argument. That makes it easy to search for anything. Also I've noticed that searches come back as ManagedObjectReferences and can't be cast to the subclasses. You have to construct them passing the ManagedObjectReference as an argument.
Also I find searching for PowerCLI examples and watching the classes in the immeadiate window very help in navigating this API. It's a fairly decent SDK but they put all of the classes in a single namespace and there's lots of little style inconsistencies ( Device instead of Devices and properties that take strings instead of enums when an enum exists ).
i figured out how to do it :) , by using http://vcenter_hostname/mob I was able to walk through api better. here is what I did, plus instead of of using "host" which was type HostSystem I jused my instance of my vCenter host "client"
VMware.Vim.LicenseManager lic_manager = (VMware.Vim.LicenseManager)client.GetView(client.ServiceContent.LicenseManager, null);
LicenseManagerLicenseInfo[] lic_found = lic_manager.Licenses;
foreach (LicenseManagerLicenseInfo lic in lic_found)
{
string test = lic.Name.ToString();
string test2 = lic.LicenseKey.ToString();
}
After creating a web site, i notice that it sets the asp.net version to 1.1. I would like to in code change this to version 2.0.50727. I found that in the ScriptMaps property there are string list of all the file extensions and code mapping. But I have not figured out how to change all of the values that are connected to .net? Or is there a way to tell it to use an other verison with .invoke?
DirectoryEntry sited = new DirectoryEntry(string.Format("IIS://localhost/w3svc/{0}/Root", websiteID.ToString()));
sited.Properties["AccessRead"].Add(true);
PropertyValueCollection testScriptMap = sited.Properties["ScriptMaps"];
object[] allValues = (object[])testScriptMap.Value;
object[] newValues = new object[allValues.Length];
string oldVersion = "v1.1.4322";
string newVersion = "v2.0.50727";
for (int i = 0; i < allValues.Length; i++)
{
if (allValues[i] is string)
{
string temp = allValues[i] as string;
if (temp.Contains(oldVersion))
{
newValues[i] = temp.Replace(oldVersion, newVersion);
}
else
{
newValues[i] = allValues[i];
}
}
else
{
newValues[i] = allValues[i];
}
}
testScriptMap.Value = newValues;
sited.CommitChanges();
After little trial and error I found a solution. I took all the objects in the created site and made a copy where i changed the version part of the path string. Then I set the value property of the scriptMaps object to point to the new updated object array.
One easy way is to execute "aspnet_regiis -i". The aspnet_regiis.exe file will be located at - C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe.
Alternately, you can take the hard way, and take a look at an article on modification of IIS Metabase.
Taking the harder way, to me, is much cooler than the easy one!
The following command installs the ASP.NET version associated with the tool and updates the script maps of all existing ASP.NET applications. Note that only applications that are currently mapped to an earlier version of ASP.NET are affected.
Aspnet_regiis -i
the Aspnet_regiis.exe is under the following path:
C:\WINDOWS\Microsoft.NET\Framework\"dot net version you want to change to"
in your case will be under v2.0.50727:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
source: ASP.NET IIS Registration Tool