IVSS State Management Conundrum


I recently received
this C# code snippet from a customer (my question follows):

 
//remove all instances of label “bad label” in the versions collection objVSSVersion
foreach(IVSSVersion
objVssVersion in myVssItem.get_Versions(0))

    
{
         
if (objVssVersion.Label == “Bad Label”)
         
objVssVersion.VSSItem.Label(“”,””);
    
}

Upon running
this code, the customer sees one of two errors:

·  “A
history operation is already in progress”

·  “File
VSSSERVERPATH\data\s\sfvaaaaa is already open”

Conundrum
There
appears to be another VSSVersions object instantiated. At present, you can have
only one at a time. 

To work
around this limitation, we have to figure out how to finalize the existing object,
right?  I have some idea about how to do this but would like to hear your thoughts. 
How does one do this?  Is it even possible in C#?

Have you
run into this problem with an IVSS… object before?  If so, what was your workaround.

Related
Posts and Resources

++++++++++++++++++++++
Microsoft
kann für die Richtigkeit und Vollständigkeit der Inhalte in dieser Newsgroup keine
Haftung übernehmen.
Este mensaje se proporciona “como
está” sin garantías de ninguna clase, y no otorga ningún derecho. Ce message est fourni
en l état, sans garantie d aucune sorte, et ne vous confère aucun droit. Vous assumez
tous les risques liés à son utilisation.

Comments (4)

  1. If it’s in the same process and it’s releasing the COM object you’re after I suggest using System.Runtime.InteropServices.Marshal.ReleaseComObject(objVssVersion) as the last line in the foreach. Ofcourse, I might be off beat on this one.

  2. Don McNamara says:

    I’m not sure about releasing the COM object. I’ll have to try that.

    I know this is a very sad solution, but here is what I found to work… (if there is a bettter way, please let me know.)

    You have to loop through the entire iterator.

    basically something like this:
    IVSSItem badItem;
    foreach(IVSSVersion objVssVersion in myVssItem.get_Versions(0))
    {
    if (objVssVersion.Label == "Bad Label")
    badItem = objVssVersion.VSSItem;
    }
    //Now that the iterator is closed, you can label something.
    badItem.Label("", "");

    Good luck!!!

  3. ReleaseCOMObject() was my initial guess but I haven’t gotten it to work….

    Thanks for the workaround, Don. I’ll go try it now.

    Craig Skibo dives into an explanation of this issue in his blog today (Reference counting, garbage collection, and zombies, oh my! [1]). Thanks Craig! Can we infer that it is possible to work around this IVSS limitation in C++ but not in C#? If so, does it have to be unmanaged C++ to work?

    [1]http://blogs.gotdotnet.com/craigs/PermaLink.aspx/a141255d-2ee6-40fc-b8cd-9cc48743e75f

  4. Kevin Jackson says:

    I’ve run into the same issue and agree with the analysis that a COM reference isn’t being freed unless foreach is allow to iterate through the entire collection. Looks like something undocumented is happening in the final iteration when MoveNext() returns false.

    I couldn’t find a way to avoid iterating through the entire collection, but to reduce the amount of actual being done during iteration, I’ve used the following workaround:

    using System.Collections;



    String findLabel = "find me";

    vssVersion = vssItem.get_Versions(…)

    IEnumerator it = versions.GetEnumerator();

    for (it.Reset(); it.MoveNext(); )

    {

    IVSSVersion version = it.Current as IVSSVersion;

    if (version != null) {

    String label = version.Label;

    if (label == findLabel) {

    while (it.MoveNext()) {};

    }

    }

    }