How can I call a long-running external program from Excel / VBA? - windows

What is the best way to run an external program from excel. It might run for several minutes. What's the best-practice about how to to this. Ideally,
A model dialog box that let's the user know that the process is executing.
If the executable fails, the user should receive a notification.
A timeout should be enforced.
A cancel button should be on the dialog box.
But any best-practices are welcome. I'm interested in solutions with calling either a .dll or an .exe. Preferably something that works with Excel '03 or earlier, but I'd love to hear a reason to move to a later version as well.

You should check out these two Microsoft KB articles
How to launch a Win32 Application from Visual Basic
and
How To Use a 32-Bit Application to Determine When a Shelled Process Ends
They both quickly give you the framework to launch a process and then check on its completion. Each of the KB articles have some additional references that may be relevant.
The latter knowledgebase article assumes that you want to wait for an infinite amount of time for your shell process to end.
You can modify the ret& = WaitForSingleObject(proc.hProcess, INFINITE) function call to return after some finite amount of time in milliseconds--replace INFINITE with a positive value representing milliseconds and wrap the whole thing in a Do While loop. The return value tells you if the process completed or the timer ran out. The return value will be zero if the process ended.
If the return value is non-zero then the process is still running, but control is given back to your application. During this time while you have positive control of your application, you can determine whether to update some sort of UI status, check on cancellation, etc. Or you can loop around again and wait some more.
There are even additional options if the program you are shelling to is something that you wrote. You could hook into one of its windows and have the program post messages that you can attach to and use as status feedback. This is probably best left for a separate item if you need to consider it.
You can use the process structure to get a return value from the called process. Your process does need to return a value for this to be useful.
My general approach to this kind of need is to:
give the user a non-modal status dialog at the start of the process with a cancel button, which when clicked will set a flag to be checked later. Providing the user with any status is most likely impossible, so giving them an elapsed time or one of those animated GIFs might be helpful in managing expectations.
Start the process
Wait for the process to complete, allowing cancellation check every 500ms
If the process is complete close the dialog and continue along.
If the process is not complete, see if the user hit cancel and if so send a close message to the process' window. This may not work and terminating the process might be required--careful if you do this. Your best bet may be to abandon the process if it won't close properly. You can also check for a timeout at this point and try to take the same path as if the user hit cancel.
Hope this helps,
Bill.

Related

How to send "Is Typing" notifications until response task completed?

How to send Is Typing notification from bot application until bot process another response. I can see currently it is limited to 3 seconds, but I want to extend it until the next response come back from Bot.
Can anyone help me with this? I have seen a couple of approaches where they recommend showing recursively until your task finish its execution but not sure how to Implement this.
Currently, this is not a feature of bot framework. You cannot control the length of time of which the typing indicator is displayed for. Your best bet is to try to resend the typing indicator as many times as needed until you long-running task is completed. This will be a custom solution that there may already be examples of out there.
You can send the typing activity every couple seconds while your processing runs asynchronously. This uses a bit of extra bandwidth, so your call. e.g.
var search = searchclient.Documents.SearchAsync(query);
var typing = turnContext.Activity.CreateReply();
typing.Type = ActivityTypes.Typing;
do {
turnContext.SendActivityAsync(typing);
} while (!search.Wait(2000));
var results = search.Result.Results;
Or set the wait to 4 seconds, or a random number between 2 and 5 seconds, so it looks like the bot is typing a little, thinking, then typing more...
Virtually all chats employ forms of faking the "real time" presence of the typing indicator. You are best to not even try, instead letting it vary randomly at the client side, and heuristically altering to your own logic, and have any end event cancel it. Especially if your API footprint is part of your operating cost.

How to test two interacting browsers (e.g. chat app)

I want to test the interaction between two users, communicating through a remote server, using CasperJS. My app is not a chat app, but that is an easy way to illustrate what I want to do.
So I'll login browser window A, then login to browser window B, then back in browser window A I'd input the chat message, call click() on the send button, and then back in browser B I'd wait for the message to appear. Then write a message, and go back to browser A to make sure it arrives.
I found this discussion on parallel browsing, which turns out to be serial. Serial is fine for me, but it appears doing more than one action in each browser is going to get very messy. It'd be something like this:
A.start(...);
A.then(...);
A.then(...);
B.start(...);
B.when(...);
A.run(function(){
B.run(function(){
A.start(...);
A.then(...);
A.run(function(){
B.start(...);
B.run(function(){
//and so on
});
});
});
});
(I've not actually tested that will work; I started writing it that way and thought there must be a better way?!)
and let each of them run asynchronously from the commandline
+1
I would do it that way :
Two scripts :
script A with A login
script B with B login
Then script A first step (after login) : writing in the chat.
Script B first step : waiting for A text then sending its answer.
Script A second step : waiting for B answer etc...
You launch these two scripts in parallel using node (child process) and they will interact with the wait() statements.
There is just one delicate point : wait for the two pages to be rendered -or to login- at the same time (approximatively), because if one of them freeze a little, you could get the timeouterror... So maybe increase the waitTimeout; to be safer. (though for me the 5sec default timeout should be sufficient).
You could also use an external file to 'synchronize' it, but I don't see how it could be helpful, because you would have to wait for the data to be updated in this file anyway.
So this solution it's asynchronous, but it works.
This will not work because of the step/scheduling nature of casperjs. See also Running multiple instances of casperjs.
In your code example the B instance is only started when A is finished, because the execution begins with the call to run.
The easiest would be to write two separate casperjs scripts (or one script, but invoked with different data for the two sides) and let each of them run asynchronously from the commandline. On linux I would use nohup ... & for this.
As for the specific test steps. I think it is easier to let your application handle the events that are needed for the synchronization of the two casperjs clients. If it is a chat app and you want to let the two caspers chat, you would write a dialog beforehand, which includes at what step a client says what.
You can then synchronize the clients using waitForText:
A sends some fixed/known text while B waits for this fixed text to appear
B receives this fixed text while A is in the next step and waits for B's response (also known text)
B sends the next fixed text and A is still waiting
Of course you would need to play around with wait timeouts.

How long does KEY_DOWN event last in windows?

I was always wondering, when I press a key on my keyboard, windows sees it as KEY_DOWN event, and then my program can ask windows if there is such an event, and the windows will answer.
But then, exactly, how long does this event last? I mean, in real world we wouldn't worry about that, because our processors can process many operations per second, much faster than we can click, but what if I could click with a speed of light?
So, how exactly does KEY_DOWN is being timed?
Input events, like key-down, are buffered. When Windows receives the notification from the keyboard driver, it stores the event in the message queue. Which is owned by the thread that owns the foreground window. It will sit there however long it takes to be retrieved by your program. It needs to call GetMessage() or PeekMessage().
How long that takes is entirely unpredictable, it depends on how responsive the UI thread of the program is. Or in other words, how quickly it dispatches messages that it receives and calls GetMessage() again to retrieve the next messsage. A UI thread going comatose for a while is not unusual. Even on fast processors, a poorly written program that executes a dbase query that returns thousands of rows and waits for its result is common enough.
The buffering ensures that this doesn't cause a problem. No matter how fast the user types, his keystrokes cannot get lost.

MFC - Add function call to mainloop?

I am fixing a MFC applivation written in C++. It is a GUI and it communicates with an external module connected to the PC via USB.
I want to avoid using a separate thread. Is there a way I can add things to the mainloop so that it runs continously rather than being event based?
I want the mainloop to make a call to a function runCommStack() in every loop.
Some possible approaches:
You can use CWnd::SetTimer to set a timer.
You can override CWinApp::OnIdle (called by CWinApp::Run).
You can override CWinApp:Run, copying and modifying the original MFC's CWinApp:Run. This definitely is not the easiest solution.
You can create a background thread.
It depends on the requirements of runCommStack(). Is this function running long times? Then you probably won't want to run it in the GUI thread. Does runCommStack need to get called every n milliseconds? Then it might also be better to run it in it's own thread. In other cases you can just use the timer or OnIdle approach.
Regarding solution 1: as Tim pointed out WM_TIMER messages are low priority messages and will not be passed to the application while other higher-priority messages are in the message queue. See also Determine priority of a window message.
With solution 2 you should remind that OnIdle will only be called if no window message is available. So this is quite the same as solution 1 (in fact a little worse).
Also keep in mind that solutions 2 and 3 might result in your runCommStack not getting called if a dialog's DoModal() is called or if a message box is displayed. This is because during MessageBox() the control is not returned to CWinApp::Run().
I'ld implement solution 1 or 4.
When there are no messages (like keys, mouse, repaint) arriving the main loop suspends the program, waiting for the next message. So the idea of adding a call to the main loop will give you very erratic operation. For example, minimizing your window will stop all the USB communication.
Using SetTimer and calling your runCommStack function in a WM_TIMER handler will probably be much more satisfactory.
You can use idle processing with CWinApp::OnIdle; this will work if reading your USB device takes only a short amount of time, otherwise the user interface will be blocked during long reads.
But using a separate thread is definitely a better method.

Windows: Child Process with Redirected Input and Output

I'm trying to create a Child Process with Redirected Input and Output (as described here - http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx).
For the people that don't want to bother reading the source code on that page, the author is using anonymous pipes to redirect the child's input and output. The parent process writes to the child process's input and reads from the child process's output.
In that code however, the program is closing the pipes after reading and writing (in WriteToPipe and ReadFromPipe), so actually the program just reads a file, dumps it on the child process input stream and then reads the child process response.
Now, what I'm looking for is a code where we will not close the pipes, but we will continuously post requests and read the child process response (in contrast to making just 1 request).
I've tried several modifications to the source code given on the link posted above, but no matter what I try, the program always hangs when calling ReadFile() in the ReadFromPipe() function (it probably waits for the child to quit - but as I said I like to get the child response, and then send other requests to it).
Any ideas on how I can get over this?
Update:
Can anyone at least tell me whether using the .NET Process class with RedirectStandardInput and RedirectStandardOutput is a good option?
Had exactly the same problem, and solved it by using PeekNamedPipe (which according to MSDN is also fine for anonymous read pipes) to check for available data before each call to ReadFile. That removed the blocking issues I was getting, and allowed my GetExitCodeProcess() to see that the process had exited and cleanup the pipes.
Yes - the .Net Process class redirects the standard input / output of the child process with anonymous pipes in a very similar way to the linked sample if you use RedirectStandardInput and RedirectStandardOutput, so this is probably a fairly good option.
As for why ReadFile is hanging - it sounds like this function is waiting for the child process to either send some data back, or to close the pipe. If you want to continuously post requests to the child process then you need to either:
Know exactly when it is appropriate to read so that you are not left waiting / blocked for the child process (so for example you only read immediately after a request has been sent). This strategy is very risky as there is always a chance that the child process doesn't behave as expected and you are left waiting on the child process indefinitely.
Have a dedicated thread for reading - if you have a dedicated thread for reading then it doesn't matter that the thread may wait indefinitely for the child process as your other threads are still able to send requests and operate as normal. This method is more complex than the first option, however when done properly is far more robust. The only other drawback to this approach is that it requires you have an additional read thread for each child process, meaning that it doesn't scale very well if you need to communicate with a large number of child processes.
Use asynchronous IO - It is possible to call the ReadFile function in a way such that it always immediately returns, however notifies you when a read has completed (I'm a little fuzzy on the exact details on how this works as I'm more used to C#). This is know as Asynchronous IO and is the most versatile of these 3 methods as it allows you to communicate with many child processes without needing a dedicated thread for each one. The tradeoff however is that it is also the most complex to do correctly (at least in my opinion).

Resources