c++ Excel COM automation: querying server status - c++

I have a problem and I have done several day's worth of research but found no answer.
I have a c++ application that controls Excel programmatically. Specifically I use VS2017 and MS Office 2019.
To cut a long story short, I don't seem to have away to get feedback from Excel on its status and its readiness to receive a command from my application. As a result if Excel is busy and my application sends a command, there is a memory leak in the application leading it to crash.
In particular I am using Microsoft's Autowrap function to send commands to the com interface.
The relevant block of code is this:
{
VARIANT hresult;
VariantInit(&hresult);
try{
AutoWrap(DISPATCH_PROPERTYGET, &hresult, xlApp, L"ActiveCell", 0);
}
catch (...)
{
std::wcout << "crashed!" << '\n';
}
xlActiveCell[book - 1] = hresult.pdispVal;
}
There is actually nothing wrong with that code. It works fine in 99% of the cases. The problem is that if I click repeatedly on an excel cell with high frequency (double click for example), Excel is busy processing the first click when my App sends the next query 500ms later to get the active cell, and at that point Autowrap throws a message window saying:
IDispatch GetIDsOfNames("ActiveCell") failed w/err 0x80010001
I researched into this and this error means RPC_E_CALL_REJECTED.
it seems obvious that if the above condition occurs, it should be handled and the method calling Autowrap should return empty handed but not crash the application.
Somehow I cannot find a way to do this. try/catch block doesn't seem to do anything, and I cannot modify Autowrap to not open a message window but instead just return with an error to be handled later. It seems that Autowrap is made to stop execution of everything if it hits this error.
Why? Is there no way around this? Am I missing something?

Related

Where do I look to trace application exit call?

I have a VB.NET WinForms application which calls a video display subsystem written in Native C++. (DirectShow)
After a number of sessions rendering several video files, the application simply exits, without any indicators as to why.
There is no exception, unhandled or otherwise.
As best I can determine from log file records, the application exits when it should be at an idle state, waiting for the next window action (button click) on the form.
There is a Forms_Closing event handler, but it never seems to be called.
The problem is intermittent, and rare. I suspect some kind of memory corruption in the C++ Native code might be the cause.
How can I hook the method which is calling the "Application.Exit" processing?
Is there some other way to determine where the call originates which shuts down the application?

How to detect if computer is shutting down to save session

I am making an RPG game with C++/x86 asm. My question is related to the C++ component. In C++/win32 how would I detect if the computer is shutting down or turning off, or whatever else - so that I can save the game session. My game has a 'save' option, but if the user or another program decides to shut off the computer how can I detect this with some kind of API hook so that I can instantly save the game session to the text file.
Now please don't suggest an option by creating a thread to run passively as I want to keep the file size to a minimum, so if you can suggest some sort of WM_ hook that would be great. I'd refer to MSDN but I don't want to be searching for hours through their WM directory.
You can handle session saving in response to the WM_ENDSESSION message. Note that after your message handler returns from handling this, your process may be terminated at any time, so you need to save it directly during the message handler, and not just set a flag to let some later code handle the saving, because that later code might not get to execute.
A comment suggests the WM_QUERYENDSESSION message. This has a slightly different meaning: it gives applications the chance to complain about the session ending, and gives the user a chance to not log off / shut down the system. Based on your question, you have no intention of preventing any such thing, so WM_ENDSESSION seems like a better match to me.

C++ Program freezing and UI turn all white

I'm working in a software built in C++ using C++ Builder which is freezing once a month.
I'm looking in the code but it is too big to find it.
The freezes make the UI gets all white. I tried to simulate this error with some proposital bad codes (null pointers, while(1) and this kind of stuff) but never got the same blank UI.
I ran a What's Hang when it's stopped but I got nothing with it.
Someone knows what can I do in the next time to get more informations which could help me find the reason of the freezing?
A blank (white) UI generally occurs when a UI paint message is queued but not processed. Simply blocking the message queue from processing new messages is not enough if you don't do something within the UI to trigger a repaint in the first place.
As for troubleshooting the original problem - you should be looking for any code in the main thread that runs longs loop without processing new messages, or long waits on waitable objects using WaitForSingleObject() or WaitForMultipleOBjects() instead of MsgWaitForMultipleObjects(), calls to TThread::WaitFor() for threads that do not terminate in a timely manner, etc.
It is hard to troubleshoot this kind of problem without knowing what steps the user performs to lead up to the frozen UI so you know what code to start looking at.

Qt Program Hangs (Not Responding) Until Function ends then starts working again

I have a UI application in Qt, i have a couple of functions that run large scale SQL queries that returns thousands of results.
when the button that runs this query is clicked the UI windows just instantly goes to 'not responding' however i can see from console outputs that everything is still actually running in the background. As soon as the function ends the data is presented as expected and the UI is responding again and fully functional.
i know this is due to the fact that the function is looping thousands of times due to the large number of results, but i was hoping that i could have just put in a loading bar that progresses as the search does instead of just locking up the window making it look like the program has crashed. AFAIK i dont have memory leaks so does anyone have any suggestions?
oh also im thinking its not memory leaks because when i click that button task manager shows only a couple of MB of memory being used for this process and processor is by no means maxing out either
In an application, there's one thread that's responsible for handling UI events, messages, whatever you want to call them. Suppose that you have a button click event. As long as you don't return from the callback function, no other UI event can be triggered (repainting, updating, etc) and UI becomes unresponsive.
To mitigate this, you should considering performing time consuming tasks in a separate thread and once they're complete, update UI accordingly. If you need to block UI while the task is processed, you can disable your controls, display a pop up progress bar, whatever, but keep the UI thread relatively unoccupied to avoid "not responding" problem.
A simpler solution than to use threads is to use QCoreApplication::processEvents(). If your code is something like this:
void slowFunction()
{
lostOfResults = makeSqlQuery(...); // quite fast
for (r in lostOfResults)
doSomethingWithResult(r); // one call is quite fast
}
If one SQL query or one doSomethingWithResult() doesn't take too much time, you can process pending events using QCoreApplication::processEvents() like this:
void slowFunction()
{
lostOfResults = makeSqlQuery(...);
for (r in lostOfResults)
{
doSomethingWithResult(r);
QCoreApplication::processEvents();
}
}
Now the GUI events are processed and the program doesn't freeze. But if the SQL query alone takes a lot of time (several seconds) this doesn't help. Then you should consider separate thread.

moving multiple files under while loop using wxwidget

I have been writing a c++ code for myself,which iterates in a directory and will move files in to a directory of the same name as the file
\\\\
void foldersFrame::OnButton2Click(wxCommandEvent& event)
{
wxFileName mkr;
StaticText1->SetLabel(_("0"));
wxString fn;
wxString newf;
wxDir *dir=new wxDir(TextCtrl1->GetLabel());
bool cont = dir->GetFirst(&fn);
while (cont)
{
int mm=fn.Find('.',true);
newf=fn.Mid(0,mm);
if(! mkr.DirExists(dir->GetName()+_("\\")+fn)){
StaticText2->SetLabel(_("copying ")+fn);
if (! mkr.DirExists(dir->GetName()+_("\\")+newf)){
mkr.Mkdir(dir->GetName()+_("\\")+newf);
if (wxCopyFile(dir->GetName()+_("\\")+fn,dir->GetName()+_("\\")+newf+_("\\")+fn)){
wxRemoveFile(dir->GetName()+_("\\")+fn);
}
newf=StaticText1->GetLabel();
long d1;
if(!newf.ToLong(&d1));
d1+=1;
StaticText1->SetLabel(wxString::Format(wxT("%i"),d1));
}
}
cont = dir->GetNext(&fn);
}
wxSafeShowMessage(_("Message"),_("Finished"));
}
But the code i have written seem to be very inefficient.It takes a lot of time to move files,and the window doesn't respond while copying.Someone please help me rewrite it..!!!!
To keep the application window responsive, but without going to the extra trouble of doing the file copy in a separate thread, try using Yield. Needs care!
wxApp::Yield
bool Yield(bool onlyIfNeeded = false)
Yields control to pending messages in the windowing system. This can be useful, for example, when a time-consuming process writes to a text window. Without an occasional yield, the text window will not be updated properly, and on systems with cooperative multitasking, such as Windows 3.1 other processes will not respond.
Caution should be exercised, however, since yielding may allow the user to perform actions which are not compatible with the current task. Disabling menu items or whole menus during processing can avoid unwanted reentrance of code: see ::wxSafeYield for a better function.
Note that Yield() will not flush the message logs. This is intentional as calling Yield() is usually done to quickly update the screen and popping up a message box dialog may be undesirable. If you do wish to flush the log messages immediately (otherwise it will be done during the next idle loop iteration), call wxLog::FlushActive.
Calling Yield() recursively is normally an error and an assert failure is raised in debug build if such situation is detected. However if the onlyIfNeeded parameter is true, the method will just silently return false instead.
You have two standard ways to implement a long running task.
First one, and by far the best, is to perform this task in a separate background thread. You can update the state of the GUI controls in the main thread by posting wxThreadEvent containing the progress data to the main window easily. The only complication -- but a pretty important one -- in this case is to handle closing the window/application termination/thread exit correctly.
Second one, which could do in a pinch, is to do the task in wxEVT_IDLE handler piece by piece and call wxIdleEvent::RequestMore() after each step. This is not as responsive as using a separate thread because you still block the event handling during the handler execution and the code needs to be rewritten in a different way to be able to resume from where it left off.
Using wxYield() is a pretty bad idea and should be avoided unless no other solution can be implemented.