Reference File Attachment problem -- Access violation while calling mdlRefFile_completeAttachment

Hi All,

I'm working on a C++ MDL Application using OpenCities Map CONNECT Edition 10.6.1.2.

(Microstation CONNECT Edition SDK version: 10.14.00.111)

My application is frequently crashing when I call mdlRefFile_completeAttachment.

The error message says it is an Internal error: Access violation.

Could you please help me what am I doing wrong?

Here you can find my Test.cpp code:

#include    <Mstn\MdlApi\MdlApi.h>
#include    <DgnPlatform\DgnPlatformApi.h>

#include    "test.h"
#include	"test_cmd.h"

#define MAP_LENGTH 20

USING_NAMESPACE_BENTLEY_DGNPLATFORM

DgnModelRefP    tMapsRef[MAP_LENGTH];
int             nTerkep = MAP_LENGTH;
MAPS			tMaps[MAP_LENGTH];
bool		    tMapIsSwitchedOn[MAP_LENGTH];
int				IsUpdate = 0, IsCommand = 0, counter = 0;

static void    func_updateRef()
{
	int         i;
	WString     logical, err;
	StatusInt stat;

	//randomize map attach and detach
	//originally this information is stored in a database but now i try to
	//mimic the behaviour that maps are detached and attached as we move the map in the view
	for (i = 0; i < nTerkep; i++)
	{
		tMapIsSwitchedOn[i] = rand() % 2 == 1 ? true : false;
	}

	/* .............................. detach maps ..................................... */
	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_updateRef detach maps.", L"", OutputMessageAlert::None);
	for (i = 0; i < nTerkep; i++)
	{
		if (tMapsRef[i] && !tMapIsSwitchedOn[i])
		{
			err.Sprintf(L"detach map: %s", tMaps[i].full_file_path.GetWCharCP());
			mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
			stat = mdlRefFile_detach(tMapsRef[i]);
			if (stat != SUCCESS)
			{
				err.Sprintf(L"mdlRefFile_detach error. Reference file name: %s -- error code: %d", tMaps[i].full_file_path, stat);
				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
			}
			tMapsRef[i] = NULL;
		}
	}
	/* .............................. level switch .................................... */
	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_updateRef level switch.", L"", OutputMessageAlert::None);
	for (i = 0; i < nTerkep; i++)
	{
		if (tMapsRef[i] && tMapIsSwitchedOn[i])
		{
			err.Sprintf(L"level switch %s", tMaps[i].full_file_path.GetWCharCP());
			mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
			//func_setLevel(i);
			stat = mdlRefFile_updateReference(tMapsRef[i], DgnPlatform::DRAW_MODE_Normal);
			if (stat != SUCCESS)
			{
				err.Sprintf(L"mdlRefFile_completeAttachment error. Reference file name: %s, Error code: %d", tMaps[i].full_file_path.GetWCharCP(), stat);
				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
			}
		}
	}
	/* .............................. attach maps ..................................... */
	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_updateRef attach maps ", L"", OutputMessageAlert::None);
	DgnAttachmentP attachment = 0;
	WString  fileName;
	for (i = 0; i < nTerkep; i++)
	{
		if (!tMapsRef[i] && tMapIsSwitchedOn[i])
		{
			err.Sprintf(L"attaching map: %s", tMaps[i].full_file_path.GetWCharCP());
			mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);

			logical.Sprintf(L"%d", tMaps[i].id);
			DgnAttachmentBuilder builder;
			fileName = tMaps[i].full_file_path;
			fileName.ReplaceAll(L"\\", L"/");
			stat = mdlRefFile_beginAttachmentToModel(builder, fileName.GetWCharCP(), L"Default", logical.GetWCharCP(), L"Default description", MASTERFILE);
			if (stat != SUCCESS)
			{
				err.Sprintf(L"mdlRefFile_completeAttachment error. Reference file name: %s, Error code: %d", fileName, stat);
				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
				return;
			}

			if (builder.GetDgnAttachmentP() == NULL)
				return;
			builder->SetAttachDescription(L"");
			stat = mdlRefFile_completeAttachment(attachment, builder, RefAttachNestMode::None, -1, false);
			if (stat != SUCCESS)
			{
				err.Sprintf(L"mdlRefFile_completeAttachment error. Reference file name: %s, Error code: %d", fileName, stat);
				return;
			}
			tMapsRef[i] = attachment->GetDgnModelP();
			if (tMapsRef[i] == NULL)
				return;
			//func_setLevel(i);

			stat = mdlRefFile_updateReference(tMapsRef[i], DgnPlatform::DRAW_MODE_Normal);
			if (stat != SUCCESS)
			{
				err.Sprintf(L"mdlRefFile_updateReference error. Reference file name: %s, Error code: %d", tMaps[i].full_file_path.GetWCharCP(), stat);
				mdlOutput_messageCenter(OutputMessagePriority::Debug, err.GetWCharCP(), err.GetWCharCP(), OutputMessageAlert::None);
			}
		}
	}
}

static void func_getRefInfo()
{
	DgnModelRefP        pRef;
	ModelRefIteratorP   iter;
	WChar               str[250];
	int                 i;

	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"func_getRefInfo -- Delete tMapsRef array and load references from MASTERFILE.", L"", OutputMessageAlert::None);

	for (i = 0; i < nTerkep; i++)
	{
		tMapsRef[i] = NULL;
	}

	mdlModelRefIterator_create(&iter, MASTERFILE, MRITERATE_PrimaryChildRefs, 0);
	while (NULL != (pRef = mdlModelRefIterator_getNext(iter)))
	{
		str[0] = 0;
		mdlRefFile_getStringParameters(str, sizeof(str) - 1, REFERENCE_FILENAME, pRef);
		for (i = 0; i < nTerkep; i++)
		{
			if (tMaps[i].full_file_path.CompareToI(str) == 0)
			{
				tMapsRef[i] = pRef;
				break;
			}
		}
	}
	mdlModelRefIterator_free(&iter);
}

static void func_autoUpdateRef()
{
	func_getRefInfo();
	func_updateRef();
}

void viewUpdate(WCharCP)
{
	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"----------View Update Start-----------", L"", OutputMessageAlert::None);

	/* turn off undo in the views */
	for (int vn = 0; vn < DgnPlatform::MAX_VIEWS; vn++)
		mdlUndo_setViewUndoActive(vn, FALSE);

	IsUpdate = 1;

	func_autoUpdateRef();

	/* turn on undo in the views  */
	for (int vn = 0; vn < DgnPlatform::MAX_VIEWS; vn++)
		mdlUndo_setViewUndoActive(vn, TRUE);

	IsUpdate = 0;
	IsCommand = 0;

	mdlOutput_messageCenter(OutputMessagePriority::Debug, L"-----------View Update End------------", L"", OutputMessageAlert::None);
}

static int func_viewUpdate(bool                      preUpdate,          /* => TRUE if called before update */
	DgnPlatform::DgnDrawMode  eraseMode,          /* => display mode */
	DgnModelRefListP          modelRefList,       /* => files involved in update */
	int                       numberRegions,      /* => number of regions */
	Asynch_update_view        regions[],          /* => region descriptions */
	ViewContextP              context,            /* => view context */
	int                       numCovers[],        /* => cover list sizes */
	MSDisplayDescr            *displayDescr[]     /* => display descriptors */)
{
	if (preUpdate)                                                      return SUCCESS;
	if (IsUpdate)                                                       return SUCCESS;
	if (IsCommand)                                                      return SUCCESS;
	IsCommand = 1;
	mdlInput_sendSynchronizedKeyin(L"mdl keyin test eegis test viewupdate", TRUE, INPUTQ_EOQ, NULL);
	return SUCCESS;
}

void init_map_arrays()
{
	WString filename;
	for (int i = 0; i < nTerkep; i++)
	{
		tMaps[i].id = i;
		filename.Sprintf(L"C:\\temp\\%d.dgn", i);
		tMaps[i].full_file_path = filename;
		tMapIsSwitchedOn[i] = true;
	}
}

extern "C" DLLEXPORT  void MdlMain(int argc, WCharCP argv[])
{
	RscFileHandle   rF;

	if (mdlParse_loadCommandTable(NULL) == NULL)
	{
		exit(1);
		return;
	}
	mdlResource_openFile(&rF, NULL, FALSE);

	MdlCommandNumber  commandNumbers[] =
	{
		{ viewUpdate                  ,	CMD_EEGIS_TEST_VIEWUPDATE  },
		0
	};
	mdlSystem_registerCommandNumbers(commandNumbers);

	init_map_arrays();

	ViewCallback::SetUpdatePostFunction(func_viewUpdate);
}

And the included header Test.h:

#pragma once

typedef struct  MAPS
{
	int         id;
	WString     full_file_path;
}MAPS;

My resource file is Test_cmd.r:

#include <Mstn\MdlApi\rscdefs.r.h>
#include <Mstn\MdlApi\cmdclass.r.h>

/*----------------------------------------------------------------------+
|                                                                       |
|  Local Defines                                                        |
|                                                                       |
+----------------------------------------------------------------------*/
#define DLLAPP_TEST  1
#define CT_NONE         0
#define CT_MAIN         1
#define CT_EEGIS        2
#define CT_TEST      	3


/*----------------------------------------------------------------------+
|
|  Register Application and DLL
|
+----------------------------------------------------------------------*/

DllMdlApp DLLAPP_TEST =
    {
    L"TEST", L"test"          // taskid, dllName
    }


/*----------------------------------------------------------------------+
|                                                                       |
|   Main Align Commands                                                 |
|                                                                       |
+----------------------------------------------------------------------*/
CommandTable   CT_MAIN =
{   
    {  1, CT_EEGIS,         INPUT, NONE,        "EEGIS"             },
};

CommandTable CT_EEGIS =
{   
    {  1, CT_TEST ,      INPUT, NONE,        "TEST"           },
};

CommandTable CT_TEST =
{   
    {  1, CT_NONE,     INPUT, NONE,        "VIEWUPDATE"         }
};


I've also attached the project in a zip file. I'm compiling it with VS2017.

Test.zip

Br,

Miklos

  • One more addition:

    The Test application is registering a view event handler by calling ViewCallback::SetUpdatePostFunction(func_viewUpdate);

    Each time the view is updated the application is randomly attaching and detaching some reference files. The reference files are stored in C:\temp directory and named like 0.dgn, 1.dgn, 2.dgn, 3.dgn, ... etc. up to 20.dgn.

    Miklos