1

I'm working with ArcObjects to set up a batch import from xls and csv files into a geodatabase. That part works fine, but after the import, I want to delete the file. This, however, doesn't work, because the file is still open. None of the interfaces being used descend from IDisposable or expose a Close method. I've also tried using a ComReleaser to force close all of the COM objects that I open, but that doesn't work either. The only things I've seen pertaining to closing a connection say that I need to remove all references to these types and force garbage collection, which is against standards (for good reason).

Here's the method I'm using for the excel import:

private ServiceResult<IEnumerable<int>> InsertControlsFromXls(FileInfo xlsFile) {
  ServiceResult<IEnumerable<int>> result = new ServiceResult<IEnumerable<int>>();


  using(ComReleaser comReleaser = new ComReleaser()) {

    //read in the spreadsheet as a workspace
    Type factoryType = Type.GetTypeFromProgID("esriDataSourcesOleDB.ExcelWorkspaceFactory");
    IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);

    IWorkspace workspace = workspaceFactory.OpenFromFile(xlsFile.FullName, 0);
    IFeatureWorkspace remoteWorkspace = (IFeatureWorkspace)OpenWorkspace();
    IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
    IWorkspaceEdit2 session = (IWorkspaceEdit2)remoteWorkspace;
    IMultiuserWorkspaceEdit multiuserWorkspace = (IMultiuserWorkspaceEdit)remoteWorkspace;

    comReleaser.ManageLifetime(workspaceFactory);
    comReleaser.ManageLifetime(workspace);
    comReleaser.ManageLifetime(remoteWorkspace);
    comReleaser.ManageLifetime(featureWorkspace);
    comReleaser.ManageLifetime(session);
    comReleaser.ManageLifetime(multiuserWorkspace);

    try {
      //session.StartEditing(false);
      multiuserWorkspace.StartMultiuserEditing(esriMultiuserEditSessionMode.esriMESMVersioned);
      session.StartEditOperation();

      Match tableMatch = _tableRecReg.Match(xlsFile.Name);
      string tableName = tableMatch.Success ? tableMatch.Groups[1].Value + "$" : "Sheet1$";

      ITable table = featureWorkspace.OpenTable(tableName);

      result.Value = CopyAllFeatures(table, remoteWorkspace.OpenFeatureClass(AppSettings.DefaultSchema + "." + ControlMap.TableName));

      session.StopEditOperation();
      session.StopEditing(true);

    } catch {
      session.AbortEditOperation();
      session.StopEditing(false);
      throw;
    }
  }

  return result;
}

I asked this question on Stack Exchange too, but no responses so far: https://stackoverflow.com/questions/30783703/arcobjects-excelworkspacefactory-wont-release-excel-file

Edit: To clarify, this is using ArcObjects 10.3, for which the API is slightly different from 9.3.

  • I've always used ReleaseComObject when I'm done... msdn.microsoft.com/en-us/library/…, I would release any rows, cursors, table/featureclass and workspace that you've opened using this method. – Michael Stimson Jun 15 '15 at 2:54
  • 1
    @MichaelMiles-Stimson I tried that too after reading the link Brad listed, but that didn't work either. I guess I may have missed something, but I'm pretty sure I called it on everything. That being said, though, the ComReleaser class is supposed to be using ReleaseComObject under the hood. I'm not sure what the implementation is like, though, so who knows if it's recursive or what not. – Ixonal Jun 15 '15 at 13:22
1

Ok, I got it to work by going hog-wild with ComReleaser objects. Basically, I scanned through my code, and anytime I found anything that was at all from ArcObjects, I attached a ComReleaser to manage it. Basically, I'm just doing manual memory management. At any rate, it does seem to release the file, so long as EVERYTHING is released (even if it doesn't seem relevant). As stated in comments above, the ComReleaser class should use ReleaseComObject under the hood, so that path should work as well.

  • It's much better to manually call ReleaseComObject when the object needs to be released, than to attach the ComReleaser to each object. ComReleaser greatly increases your chance of releasing a RCW needed elsewhere in your app. – Rich Wawrzonek Jun 15 '15 at 19:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.