I am trying to find the exact moment when my application is locking up (see my previous topic). So I write a string to a log file on several places giving me a clue when the application hangs.
At the moment I use the ASCII driver of Clarion to write to the log file. But a colleague pointed out that if the Clarion runtime hangs it might not be able to write to the log file. So in that case I don’t see the last point the application came.
He also suggested that should use OutputDebugString. Is it possible to redirect OutputDebugString directly to a log file without using the DebugView application?
It is possible at runtime to hook the DLLs that call OutputDebugString by changing the DLL Import Table to point to your own replacement function. I used that method to hook the RTL call to WinHelp and instead call HtmlHelp. I thought I posted the code here or GitHub but cannot find it. This is complicated. It would be much easier to call your own Trace() function that calls OutputDebug plus writes a file.
This is a risk which is why like @CarlBarnes has suggested, use outputdebugstring to get the data to a different program thats not using the clarion runtime.
One suggestion I would make is subclass the procedures and have outputdebugstring in there, that way you can get a copy of all the windows messages before they get processed, and if you already have subclass procedures in use, you can chain them one after the after before they get processed by the clarion runtime.
One other thing that I’ve found which helps with stability, is using the critical sections class.
This can help with race conditions. Have you looked into what cpu’s the problems are appearing on because this has been a factor for me in the past, ie Intel or AMD.
Edit. I dont know if this will help. This might have bugs because I’ll have been updating the templates and I access the last working version at the moment.
If you have your own template file, just add a #Include line to call the TPW. If you dont, insert a #Template line on line 1 and change the file extension from .tpw to .tpl I think this template is the one that subclasses every procedure and then sends the wm messages to debugview.
IS_Subclass.tpw (23.2 KB)
I’ve not tested that template in C11 ie C7+ but it worked on C6.
Will this be needed when using C12 as its reported to support Unicode?
To force OutputDebugStringW to correctly output Unicode strings, debuggers are required to call WaitForDebugEventEx to opt into the new behavior. On calling WaitForDebugEventEx , the operating system will know that the debugger supports Unicode and is specifically opting into receiving Unicode strings.
You do not need in WaitForDebugEvent or WaitForDebugEventEx unless you’re going to write a debugger. If the need is just some kind of logging, either write to a file or use OutputDebugString/OutputDebugStringW and some utility like DebugView.
Thank you for the responses so far. I realize that I didn’t mention that the log file is the only thing I need. Because the error occurs randomly I want to have log files which I can examine from time to time. There will be no real time debug logging with DebugView.
So what I want is replacing my writing to file with the ASCII driver with something else that is able to write to a log file. I am hoping that it is possible to redirect the OutputDebugString to file without DebugView opened.
Do you mean I need to have DebugView running to be able to write to a log file also?
Unfortunate I am not that familiar with subclassing so I might missing things you all are trying to point out to me.
If your program uses OutputDebugString for logging, yes, you must have DebugView (or another such utility) running too.
Subclassing for the logging has sense if you need analyze messages sending/posting to windows or controls. In most cases it’s better to use MS’s Spy++ utility for that instead of subclassing for this purpose.
If you need some logging from the programs, there are 3 major ways:
write information to a file
write information to standard output or standard error console stream (see the STARTUPINFO structure)
If you’re going to call OutputDebugString you need something to capture the output. Either a debugger, or an app like DebugView (there are others). But ultimately you’ll need another app running at the same time as your application. If your users can’t handle that then you’ll have to find something else to do instead.
The template would add a subclass procedure to every procedure which is a window, and then that could be sent off to debugview to ultimately save in a log file. The Template would be a starting point to capture as much or as little of the windows messages that you need to help isolate whats happening.
Debugview++ has a command line version so when your app starts, and both accept command line input so you could call debugview from your app and get the output captured and saved to a log file.
Thats basically it, but its the only way I know to trap these random events, but when they happen, get your users to inform you straight away so you can get the most recent log file and then discard the earlier ones. And once a day or once a week clear remove the old log files so they dont junk up their hard drives too much.
Its tedious work but you should be able to start at the last entry and work backwards to see if anything obvious is happening. You might need 2 or 3 or even more of these logs to establish the pattern. It could be time of day, other apps runming, it could be anything, even anti virus. I’m reminded of a program back in the 90’s or early 00’s which intercepted all the DDE messages for itself, which messed up sending faxes to Winfax as that used DDE to control. So dont rule out your app hanging because of another program.
There is a screen shot at this link of one of my templates which works with debugview, which might give you some ideas, for logging.
The Taskkill /IM is a hack, I need to move some code into it to identify the debugview process and kill it more cleanly when the app closes, which should make it work better with Debugview++ as well then, but sysinternals debugview will only capture on the first instance of debugview, so you can start as many instances of debugview as you like, its only the first instance actually capturing any of the debug output.
Thank you all for your suggestions. I was thinking that using OutputDebugString could do the trick, but apparently I need
so that won’t work easily. Unfortunate I am not that familiar with subclassing etc. and at the moment that will consume too much time to get it working. So OutputDebugString is not the right way at the moment.
Luckily there is also Capesoft StringTheory. I got the confirmation from B. that StringTheory SaveFile is using the windows API, not the Clarion runtime. And that was what I was looking for, hoping that I can find the more accurate point when my application freezes up.
I see thats another clarion app, now I know from past experience, there are times when all clarion apps hang. For example, I’ve posted on the ngs how when debugging an app using the debugger and I’ve breakpointed it to stop on a line, its caused the other app (two apps communicating with each other) to hang as well, noted by the debugview output stopping as well.
I know in windows that ever app should be loaded into its own user space, but my own experience would suggest this is not the case, which is why I’ve stuck with the sysinternal’s debugview.
I know UltimateDebug the class is by Andy @ Noyantis, which outputs to debugview/debugview++.
Like I said above, I’ve had conditions where two clarion apps talking to each other via pipes iirc both froze when one of them had hit the debugger breakpoint. Now I know that each app should have its own separate memory space, and should be independent of each other, but it wasnt the case, thats why I use the independent debugview, I can eliminate the clarion runtime as a factor then.
Obviously there could have been pragma’s affecting the apps or something else, I only have to look at the implicit_local pragma for an example.
By chance there was this same conversation going on over on the newsgroups. Over there, in order to avoid using the ASCII driver I had suggested a simple function using StringTheory along these lines:
Logit procedure(String pMessage, String pFileName, long pAppend=true, long pODS=true)
if pODS then st.trace(). ! outputs to ODS
if not st.EndsWith('<13,10>') then st.append('<13,10>').
if not st.saveFile(pFileName, pAppend)
message('unable to write to file ' & clip(pFileName) & |
'||Error: ' & st.LastError)
I assumed this was something Andy had written because he had responded so I clicked on his web address under his name in the thread and that took me to his site, but looking on his website right now, its different to what I saw the other day. The other day it was his “old” site with a blue theme and jigsaw piece or two, but I can see thats not the same website.
I get this alot, websites showing all sorts, even search engines websites taking control of themselves clicking links I didnt click. I think its designed to provoke me, doing a psychological job on me.
I know about Marks ultimate debug as I have it here. The other class I didnt know about, but its not what I saw the other day.
Thats why I put a post up with a link to the gentlemans guide to forum spooks in this post.
I mean look getting these adverts straight away now within seconds of posting the above. The advertising networks are imbedded everywhere.