bug or drawback of AcApDocManager::closeDocument()

bug or drawback of AcApDocManager::closeDocument()

Anonymous
Not applicable
1,047 Views
7 Replies
Message 1 of 8

bug or drawback of AcApDocManager::closeDocument()

Anonymous
Not applicable
typedef std::vector<AcApDocument*> vecApDoc;

vecApDoc getAllOpenDoc()
{
	vecApDoc rec;
	AcApDocumentIterator * it = acDocManager->newAcApDocumentIterator();
	for(;!it->done();it->step())
	{
		rec.push_back(it->document());
	}
	delete it; it = NULL;
	return rec;
}
//find no active doc,delete it void close1Doc_and_delete() { vecApDoc docs = getAllOpenDoc(); for (int d = 0; d < docs.size(); d++) { AcApDocument* p = docs[d]; if(p == acDocManager->curDocument()) continue; acDocManager->closeDocument(p); //(1) //delete dwg file int res = remove(p->fileName());// !!!Failed!!! if(res != 0 ){//remove() failed vecApDoc docOpen= getAllOpenDoc(); for (int f = 0; f < docOpen.size(); f++) { //following line assert fail!!! //Prove that (1) closeDocument() code not really work! ASSERT(strcmp(docOpen[f]->fileName(),p->fileName()) != 0); } } break; } } Note: I'm sure all the opened files are not modified.And Now opened with write right.
Located in local disk and normal place.

How can I really closeDocument() immediately or synchronously.
As far as I known,after the acDocManager->closeDocument(p) that file is not write-access.

any hint? any way to accomplish it!

 

0 Likes
Accepted solutions (1)
1,048 Views
7 Replies
Replies (7)
Message 2 of 8

Alexander.Rivilis
Mentor
Mentor

1. What context of executing of close1Doc_and_delete function? Document or Application?

closeDocument have to be called only from Application context.

2. What about to call p->database()->closeInput(); before acDocManager->closeDocument(p); ?

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 3 of 8

Anonymous
Not applicable

I have tried!

 

	JASSERT(acDocManager->isApplicationContext());              //OK!
	Acad::ErrorStatus rec = ap->database()->closeInput(true);   //Acad:eOk!
acDocManager->closeDocument(ap); JASSERT(!_tremove(ap->fileName())); //remove still failed!

 Btw

Acad::ErrorStatus rec = ap->database()->closeInput(true);    //neight true & false parameter works!

So next ?  what I can do?

 

thanks anyway! But I really hope some can help me out.

0 Likes
Message 4 of 8

Alexander.Rivilis
Mentor
Mentor

What about acDocManager->enableDocumentActivation(true); ?

What result (Acad::ErrorStatus) of acDocManager->closeDocument(ap); ?

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 5 of 8

Anonymous
Not applicable
	JASSERT(acDocManager->isApplicationContext());              //OK!
	Acad::ErrorStatus rec = ap->database()->closeInput(true);   //Acad:eOk!

	rec = acDocManager->enableDocumentActivation();	//Acad::eInvalidContext
	rec = acDocManager->closeDocument(ap);		//Acad:eOk!
	JASSERT(!_tremove(ap->fileName()));  

 I have modified the code,you can see the result. the problem is still here,(I have tried comment out ap->database()->closeInput(true),but don't make any difference.)

 

thanks but any one have idea for this?

0 Likes
Message 6 of 8

autodaug
Autodesk
Autodesk

I don't think closeInput() matters. Let's focus on what's going on here:

		acDocManager->closeDocument(p); //(1)
		//delete dwg file
		int res = remove(p->fileName());// !!!Failed!!!

The thing about closeDocument() is that it operates asynchronously. It queues up the closeDoc msg internally and then returns to you immediately. The actual destruction of the Document and the updating of the U/I Windows etc happens shortly after your command returns and the AutoCAD message loop resumes. Btw, it's even okay to close the current document this way.

 

This asynchronous behavior is what allows your p->fileName() call to succeed - the underlying AcApDocument object has not yet been deleted. If it had been deleted, then p would be pointing to random heap memory and p->fileName() might return garbage (or crash). It's also why your remove() call fails, because the Document still exists and so still has the file open.

 

If you want to delete the files in this way, then you'll need to somehow wait until the Documents are actually closed. Maybe do the file deletion during OnIdle or in a documentDestroyed notification.

 

A couple caveats: this assumes you're in MDI mode, not SDI. Also, I'm looking specifically at AutoCAD 2016.

 

Message 7 of 8

Anonymous
Not applicable

hi autodang!

 

I absolutely understand what you're saying. and really give me the reason why the remove() failed .

so thank you very much.

 

you said "Maybe do the file deletion during OnIdle or in a documentDestroyed notification."

 

  • Actually to remove() the dwg file it's not my final target. what  i want is just have the write-access to that file.
  • Because I want to overwrite it ,it will fail as it currently be write-opened. SO I WANT TO CLOSE IT and OVER-WRITE it by generate a new dwg file just after I CLOSE it.Maybe this's similar with remove().

But to achieve it during ONIDLE or In documentDestroyed notification.

I'm really not very familiar with that. any sample? or code snippet? by reactor? ONIDLE involved which class and function? etc.

 

thanks in advance!

0 Likes
Message 8 of 8

autodaug
Autodesk
Autodesk
Accepted solution

There is probably a doc reactor sample in the ARX SDK somewhere. Or maybe you can find one by googling. Or buy a book 🙂 Basically you just derive your reactor class from the AcApDocManagerReactor class, then instantiate your reactor and register it with the AcApDocManager.

 

For OnIdle events, you can use acedRegisterOnIdleWinMsg(). I don't see any sample code for it, but it looks like a simple call to register your callback function. This callback function will be called very frequently.

 

Yet another trick you could use is to call sendStringToExecute() to queue up a command that you have registered. By the time your command is invoked, the documents should have been destroyed. You might want to register this command with the ACRX_CMD_SESSION flag, so it is invoked in session context outside any documents.