I am developing a plug-in using C#/ASPX (.Net 4.0) and vSphere 5.0. I want to allow the user to search for files in a known location on the datastore.
I have been looking in the forums for others using SearchDatastore_Task, but I don't see anyone running into this issue.
Using the Managed Object Browser, I can get all of the files every time. If I use the C# AppUtil class and set up my objects with the same data that I use in the Managed Object Browser, the page hangs until I see the following text within the vSphere Client: "This program cannot display the webpage"
If I use the Visual Studio debugger, the code enters the "WaitForTask()" method and then hits a Stack Overflow Exception in the ServiceUtil.cs file ("An unhandled exception of type 'System.StackOverflowException' occurred in Vim25Service2010.XmlSerializers.dll"). Specifically in the ServiceUtil.cs file, the error occurs at the following line:
updateset =
_connection.Service.WaitForUpdates(
_connection.PropCol, version
);
Below, I have the code that I am using for the Managed Object Browser, followed by the code that I am using for C#. Has anyone else run into this before and/or is anyone able to see what I may have done wrong?
Note: In both examples below, the HostDatastoreBrowser is type:HostDatastoreBrowser Value:datastoreBrowser-datastore-63
For the MOB, I use the following and get all 3 ZIP files that are in the folder:
datastorePath (required)
[vzipesxi2-local] c
searchSpec (optional)
<!-- optional -->
<searchSpec>
<!-- optional -->
<!-- array start -->
<!-- optional -->
<query>
</query>
<!-- array end -->
<!-- optional -->
<details>
<fileType>false</fileType>
<fileSize>true</fileSize>
<modification>true</modification>
<fileOwner>false</fileOwner>
</details>
<!-- optional -->
<searchCaseInsensitive>true</searchCaseInsensitive>
<!-- optional -->
<!-- array start -->
<!-- optional -->
<matchPattern>*.zip</matchPattern>
<!-- array end -->
<!-- optional -->
<sortFoldersFirst>false</sortFoldersFirst>
</searchSpec>
For C#, I use the following, and the last line (WaitForTask) is where the code hangs:
FileQueryFlags fqf = new FileQueryFlags();
fqf.fileOwner = false;
fqf.fileOwnerSpecified = true;
fqf.fileSize = true;
fqf.fileType = false;
fqf.modification = true;
HostDatastoreBrowserSearchSpec hdbss = new HostDatastoreBrowserSearchSpec();
hdbss.query = new FileQuery[] {new FolderFileQuery()};
hdbss.details = fqf;
hdbss.matchPattern = new string[] { "*.zip" };
hdbss.searchCaseInsensitive = true;
hdbss.searchCaseInsensitiveSpecified = true;
hdbss.sortFoldersFirst = false;
hdbss.sortFoldersFirstSpecified = true;
ServiceUtil svcUtil = vsAppUtil.getServiceUtil();
ManagedObjectReference hostDSBrowser = (ManagedObjectReference)svcUtil.GetDynamicProperty(searchDatastoreMor, "browser");
searchDatastorePath = "[vzipesxi2-local] c";
apiTaskMor = vsAppUtil._connection._service.SearchDatastore_Task(hostDSBrowser, searchDatastorePath, hdbss);
apiTaskResult = svcUtil.WaitForTask(apiTaskMor);
NOTE: In reviewing other forum posts, I saw where users where setting the hdbss.query to a new FolderFileQuery() object. I didn't think that I needed that, but I have added it. Since then, I get the same results. I have left the line in here for now, but I am not sure that I need it. Note that my Managed Object Browser does not have that value set, and it is working.
Can I answer my own question? I am going to put what I have learned here from today... maybe it helps someone else.
I am not 100% positive, but I think there is some type of bug in the ServiceUtility.WaitForTask() for C#. As I mentioned I was getting a stack overflow exception earlier. As I continued to investigate, I used the property collector to get the "info" object from the task. Then I could look at the state property of the info-object. The state property is a TaskInfoState type, which can only be one of the following {error, success, running, queued}. With this information, I created my own "Wait For Task" method which will analyze that TaskInfoState property. In my case, I set up a sleep duration and a retry amount... the two of those will give me a "timeout" duration. If the TaskInfoState doesn't come to an "end state" {error, success} after the sleep duration and retry amounts have been exceeded, then I can declare a timeout.
After implementing this, I am getting the proper results from the SearchDatastore_Task() call, and I am no longer getting any stack overflow (as I am no longer using the standard WaitForTask() method).
While I'm sure this isn't perfect, this code works for me. I have pasted the code below:
----------------------------------------------
Calling code looks like this
----------------------------------------------
// Set up your HostDatastoreBrowserSearchSpec as you like... mine is hdbss
----------------------------------------------
----------------------------------------------