rainereds

C++  ArcMap-Addin: An unhandled win32 exception occurred in ArcMap.exe

Discussion created by rainereds on May 20, 2010
Hi everyone,

I have developed an ArcMap add-in (COM/ATL-Application written in C++). This add-in reads IMG-files (Erdas Imagine format), does some calculations and writes new IMG-files. Optionally the new IMG-files can be visualized in ArcMap.

Sometimes after closing the add-in and closing ArcMap I get the Message "An unhandled win32 exception occurred in ArcMap.exe" from Visual Studio Debugger. I monitored this only when visualizing the map in ArcMap and if the add-in was built in  release mode. No exception occour if the add-in was build in debug mode.

In environments without Visual Studio, I monitor that the ArcMap.exe prozess doesn't disappear after closing ArcMap (instead of the exception message above).

In Method ShowDistibutionMap the variable HRESULT hr is everytime S_OK.

The error is not solid reproducable.

I'm using
- Visual Studio 2005 Professional Edition
- ArcGIS Desktop 9.2.0.1324 with ArcGIS Service Pack: 6 (build 9.2.6.1500)
- C++

What is the cause of the exceptions? How can I avoid it?


Any help would be greatly appreciated.

Thanks,
Rainer

HRESULT CRasterUtil::ShowDistibutionMap( 
 const CString& sRasterFile, 
 const char* pTableFile,
 IRasterLayer* pRasterLayer
 )
{
 if ( !PathFileExists( sRasterFile ) )
  return S_FALSE;

 CSplitPath sp( sRasterFile );
 CString sPath  = sp.GetDrive() + sp.GetDirectory();
 CString sFile    = sp.GetFileName() + sp.GetExtension();
 CString sTmpFile = sPath + sp.GetFileName() + "_at oll" + sp.GetExtension(); 
 
 if ( PathFileExists( sTmpFile ) )
  remove( sTmpFile );
 
 IWorkspaceFactoryPtr ipWkspFac(CLSID_RasterWorkspaceFactory);
 
 //Open Workspace
 IWorkspacePtr ipWksp;
 HRESULT hr = ipWkspFac->OpenFromFile(sPath.AllocSysString(), 0, &ipWksp);

 // Open the Geo file dataset
   IRasterDatasetPtr pGeoDataset;
   hr = ((IRasterWorkspacePtr) ipWksp)->OpenRasterDataset(sFile.AllocSysString(),&pGeoDataset); 
 
 //IRasterLayerPtr pRasterLayer(CLSID_RasterLayer);
 
 hr = pRasterLayer->CreateFromDataset(pGeoDataset);

 IRasterPtr pRaster;
 hr = pRasterLayer->get_Raster( &pRaster );

 IRasterPropsPtr sRasterProp( pRaster );

 double dSizeX;
 double dSizeY;
 getCellSize(sRasterProp, dSizeX, dSizeY);

 double dFactor = 1;
 if( m_normalizeTrafficVolume )
 {
  double cp2 = 2.;
  double dFac = 1000. / dSizeX;
  dFactor = pow(dFac, cp2);
 }

 HISTODATA* pHisto = GetHistogram(pTableFile);
 if ( pHisto == NULL)
  return S_FALSE;

 SAFEARRAYBOUND rgsabound;
        _variant_t  var;
        _variant_t Array;
        rgsabound.lLbound = 1;
        rgsabound.cElements = pHisto->lCount;

 // Equivalent to: Dim aiNew(1 To 8) As Double.
 SAFEARRAY *pDoubleArray = SafeArrayCreate(VT_R8, 1, &rgsabound);
 if( !pDoubleArray )
  return S_FALSE;

 SAFEARRAY *pLongArray = SafeArrayCreate(VT_UI4, 1, &rgsabound);
 if( !pLongArray )
  return S_FALSE;
                
 for (long i=0; i<pHisto->lCount; i++)
  {
  double dVal = pHisto->pValue[i] * dFactor;
  SafeArrayPutElement(pDoubleArray, &i, (void *)&dVal ); //&pHisto->pValue[i]);
  SafeArrayPutElement(pLongArray, &i, (void *)&pHisto->pFrequence[i]);
  }

 //Delete the data struct
 if ( pHisto )
  {
  if ( pHisto->pFrequence )
   delete pHisto->pFrequence;
  if ( pHisto->pValue )
   delete pHisto->pValue;
  delete pHisto;
  }

 VARIANT sValues;
 VariantInit(&sValues);
 sValues.vt = VT_ARRAY|VT_R8;
       sValues.parray = pDoubleArray;

 VARIANT sFrequence;
 VariantInit(&sFrequence);
 sFrequence.vt = VT_ARRAY|VT_UI4;
        sFrequence.parray = pLongArray;
  
 if ( m_StatusBar )
  {
  hr = m_StatusBar->put_Message(0, L"Preparing distribution map for Atoll..."); 
  hr = m_StatusBar->put_Visible(VARIANT_TRUE);
  }

 IRasterBandCollectionPtr pRasterCol(pRaster);

// Create classfy renderer and QI RasterRenderer interface
        IRasterClassifyColorRampRendererPtr pClassRen(CLSID_RasterClassifyColorRampRenderer);
 IRasterRendererPtr pRasRen = pClassRen;
 hr = pRasRen->putref_Raster( pRaster );
 hr = pRasRen->Update();

//  To set classification method, we need to get the histogram of the
//  raster. To simplify the sample, we only consider a raster that has
//  a table.
    
 if ( m_StatusBar )
  {
  hr = m_StatusBar->put_Message(0, L"Prepare distribution map for Atoll..."); 
  hr = m_StatusBar->put_Visible(VARIANT_TRUE);
  }

 IRasterBandCollectionPtr pBandCol( pRaster ); 

 IEnumRasterBandPtr pEnumRasterBand;
 hr = pRasterCol->get_Bands(&pEnumRasterBand);

 IRasterBandPtr pRasBand;
 hr = pEnumRasterBand->Next( &pRasBand );

 BSTR sField = L"Value [Erlang/qkm]";
 double dMax = 0.;

 IClassifyPtr pClassify(CLSID_Quantile); //EqualInterval);

//  Create EqualInterval classification and obtain the UID
 //hr = pClassify->SetHistogramData( vValues, vFrequences); 
 hr = pClassify->SetHistogramData( sValues, sFrequence); 
 
 int NumOfClass = 20; //5;
 hr = pClassify->Classify( &NumOfClass ); 

 VARIANT ClassBreak; 
 hr = pClassify->get_ClassBreaks( &ClassBreak );
 
 double *clsBreaks; // Pointer to double elements
       SafeArrayAccessData(ClassBreak.parray, (void**) &clsBreaks);

 IUIDPtr ipUID;
 hr = pClassify->get_ClassID( &ipUID );
 
// Using IRasterClassifyUIProperties to set classification method to
// the raster classify render. If it is not set, NatrualBreak
//  classification will be used  

 IRasterClassifyUIPropertiesPtr pClassProp (pClassRen);
 hr = pClassProp->putref_ClassificationMethod( ipUID );

// Set raster classify renderer
 hr = pClassRen->put_ClassCount( NumOfClass );
 hr = pClassRen->put_ClassField( sField );
  
 for (int i=0; i<NumOfClass; i++)  
  double dval = clsBreaks[i];

 hr = pClassRen->put_Break(0, 0);
 //for (int i=2; i<NumOfClass; i++)
 for (int i=0; i<NumOfClass; i++)
  hr = pClassRen->put_Break(i+1, clsBreaks[i]); //*dFACTOR);
 

// Create a color ramp to use
        IAlgorithmicColorRampPtr ipRamp(CLSID_AlgorithmicColorRamp);
     
 IRgbColorPtr pStartColor(CLSID_RgbColor);
 hr = pStartColor->put_Red(0);
 hr = pStartColor->put_Blue(255);
 hr = pStartColor->put_Green(0); 

 hr = ipRamp->put_FromColor(pStartColor); 

 IRgbColorPtr pEndColor(CLSID_RgbColor);
 hr = pEndColor->put_Red(0);
 hr = pEndColor->put_Blue(0);
 hr = pEndColor->put_Green(255); 

 hr = ipRamp->put_ToColor( pEndColor );
 
 long lCount = NumOfClass; //256;
 hr = ipRamp->put_Size( lCount );

        VARIANT_BOOL ok;
        hr = ipRamp->CreateRamp(&ok);

// Create symbol for the classes
        IFillSymbolPtr ipFSymbol(CLSID_SimpleFillSymbol);
 ISymbolPtr ipSymbol(ipFSymbol);

 IEnumColorsPtr pEnumColors;
 hr = ipRamp->get_Colors ( &pEnumColors );

 IRgbColorPtr pColorStart(CLSID_RgbColor);
 hr = pColorStart->put_Red(255);
 hr = pColorStart->put_Blue(255);
 hr = pColorStart->put_Green(255); 

 IRgbColorPtr pRedColor(CLSID_RgbColor);
 hr = pRedColor->put_Red(255);
 hr = pRedColor->put_Blue(0);
 hr = pRedColor->put_Green(0); 

 IColorPtr pColor;
 for (int i=0; i<lCount; i++)
  {
  hr = pEnumColors->Next ( &pColor );
  
  if ( i == 0)
   hr = ipFSymbol->put_Color( pColorStart );
  else if ( i == (lCount - 1) )
   hr = ipFSymbol->put_Color( pRedColor );
  else
   hr = ipFSymbol->put_Color( pColor );

                hr = pClassRen->put_Symbol(i, ipSymbol);

  double dIntervalEnd = 0.;
  if ( i )  
   dIntervalEnd = (i == (lCount - 1)) ? dMax : clsBreaks[i + 1]; //*dFACTOR;
  
  _bstr_t bstrClsBreaksBegin(clsBreaks[i]); //*dFACTOR);  // i==1 ? 1 : clsBreaks[i]*dFACTOR);
                _bstr_t bstrClsBreaksEnd(dIntervalEnd);

  if ( i )
   bstrClsBreaksBegin += CComBSTR(L" - ") + bstrClsBreaksEnd;
         
  hr = pClassRen->put_Label(i,  bstrClsBreaksBegin.Detach());
 
  }

// Update the renderer and plug into layer
        hr = pRasRen->Update();
 hr = pRasterLayer->putref_Renderer( pRasRen );

 // Save img as layer
 CString sLayerFile(sRasterFile);
 sLayerFile.Append(".lyr");

 if ( PathFileExists( sLayerFile ) )
  remove( sLayerFile );

 IGxLayerPtr pGxLayer(CLSID_GxLayer);
 IGxFilePtr pFile(pGxLayer);
 
 hr = pFile->put_Path( sLayerFile.AllocSysString() );
 
 hr = pGxLayer->putref_Layer( pRasterLayer );

 return hr;

}

Outcomes