[GIS] Custom Application throws HRESULT if MXD/MXT has layers with data source missing

arcobjects

This is in continuation to Getting ArcMap reference without launching application?.

The idea of the application is to map layers (pointing currently to an unreachable server; server may be down, non-operational or behind a firewall) of a MXD/MXT of a document to another data source.

While I was able to achieve it, I faced a different issue as I move forward.
These are the steps I followed:

  • Checkout ArcEditor license
  • If checkout successful above, try connecting to SDE.DEFAULT
  • If connection to ArcSDE successful, parse map layers
  • For every layer parsed, change its source
  • Finally, save map and close

The issue is, as soon as I try to get the map count (data frames) in the document, the application throws a HRESULT error (see below), and I am unable to proceed.

could not be found. (Exception from HRESULT: 0x80030002 (STG_E_FILENOTFOUND))

I searched the internet for this error and at some places they have talked about ArcGIS not being able to "access" a file. In this case I doubt if thats an issue…

I am attaching relevant portions of the code, showing the location of the error.

I am not sure where I am going wrong.

public static bool LicenseCheckout()
    {
        try
        {
            int ESRILicenseCheckoutReturnCode;
            bool ReturnResult;

            //checkout ESRI license: ArcEditor
            pESRILicense = new AoInitializeClass();
            ESRILicenseCheckoutReturnCode = (int)pESRILicense.Initialize(esriLicenseProductCode.esriLicenseProductCodeArcEditor);

            ReturnResult = false;

            switch (ESRILicenseCheckoutReturnCode)
            {
                case 10:
                    //esriLicenseAvailable
                    ReturnResult = true;
                    break;

                case 20:
                    //esriLicenseNotLicensed
                    MessageBox.Show("You are not licensed to use the product!", "License Checkout Failure");
                    ReturnResult = false;
                    break;

                case 30:
                    //esriLicenseUnavailable
                    MessageBox.Show("You are not licensed to use the product!", "License Checkout Failure");
                    ReturnResult = false;
                    break;

                case 40:
                    //esriLicenseFailure
                    MessageBox.Show("There has been a licensing Failure!", "License Checkout Failure");
                    ReturnResult = false;
                    break;

                case 50:
                    //esriLicenseAlreadyInitialized
                    MessageBox.Show("The Product license has already been initialized." +
                    "Initialization can only be performed once!", "License Checkout Failure");
                    ReturnResult = true;
                    break;

                case 60:
                    //esriLicenseNotInitialized
                    MessageBox.Show("License not Initialized!");
                    ReturnResult = false;
                    break;

                case 70:
                    //esriLicenseCheckedOut
                    ReturnResult = true;
                    break;

                case 80:
                    //esriLicenseCheckedIn
                    MessageBox.Show("License ChekedIn successfully!");
                    ReturnResult = true;
                    break;
            }

            return ReturnResult;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return false;
        }
    }  

public static bool ConnectToSDE(string User, string Password, string Server, string Instance)
    {
        try
        {
            if (SDEConnectionSuccessful(User, Password, Server, Instance))
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception)
        {
            throw;
        }
    }  

 private static bool SDEConnectionSuccessful(string User, string Password, string Server, string Instance)
    {
        try
        {
            pConnectionProperties = new PropertySetClass();

            pConnectionProperties.SetProperty(Constants.ARCSDE_PROPERTY_SERVER, Server);
            pConnectionProperties.SetProperty(Constants.ARCSDE_PROPERTY_INSTANCE, Instance);
            pConnectionProperties.SetProperty(Constants.ARCSDE_PROPERTY_USER, User);
            pConnectionProperties.SetProperty(Constants.ARCSDE_PROPERTY_PASSWORD, Password);
            pConnectionProperties.SetProperty(Constants.ARCSDE_PROPERTY_DATABASE, ""); //not required for Oracle connections
            pConnectionProperties.SetProperty(Constants.ARCSDE_PROPERTY_VERSION, Constants.ARCSDE_VERSION);

            pWSF = new SdeWorkspaceFactoryClass();
            pWS = pWSF.Open(pConnectionProperties, 0);

            if (pWS != null)
            {
                //connection successful
                return true;
            }
            else
            {
                return false;
            }
        }
        catch (Exception ex)
        {
            //cleanup
            pConnectionProperties = null;
            pWS = null;
            pWSF = null;

            ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(pConnectionProperties);
            ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(pWS);
            ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(pWSF);

            MessageBox.Show(ex.Message, "Exception");
            throw;
        }
        finally
        {
            //nothing to release as objects will be needed later
        }
    }

    public static void ParseMapLayers()
    {
        try
        {
            //get a reference to ArcMap
            pMapDoc.Open(MXDFilePath, null); 
            pMap = pMapDoc.get_Map(0); // <<<<<<---- error at this line <<

            //iterate through all the layers            
            pLayers = pMap.get_Layers(null, true);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    public static void ChangeSource()
    {
        pLayers.Reset();

        pLayer = pLayers.Next();
        while (pLayer != null)
        {
            if (pLayer is IFeatureLayer)
            {
                ChangeLayerDataSource((IFeatureLayer)pLayer);
            }

            pLayer = pLayers.Next();

        }
    }

Best Answer

Usually when you have a resource in a SDE instance the layer will reference a SDE file followed by the resource (e.g. C:\ArcGIS\Catalog\connection_file.sde\sde_server_name.sde_account.my_mosaic_dataset). You might be able to get around all this if you place a .sde file in the location those layers are looking, and setting them up in Catalog to point to your development SDE instance.