Debugging Templates with Debugview

This works in C11, havent tried in any other earlier versions of the C7+ 32bit ide, but adding this to template code makes it possible to send messages to debugview without much effort so its another way to debug templates instead of using the built in template debug facility .txt file.

Do not use Win32

#Group(%SendDebugViewMessage,%Localdbgvwmsg)
#RunDll(‘Kernel32.dll’,‘OutputDebugStringA’,%Localdbgvwmsg),Release,Win32

It sends this output.

[4488] m\<[À[l[ [xm\h [H
[4488] [Pm\Lm\Dm\<m\,m\ä [P [t©b

Do use Pascal

#Group(%SendDebugViewMessage,%Localdbgvwmsg)
#RunDll(‘Kernel32.dll’,‘OutputDebugStringA’,%Localdbgvwmsg),Release,Pascal

which sends

[4488] Test Message for Debugview
[4488] Test Message for Debugview

So you can add a button or other template code to call debugview.

#Button(‘Test Debugview’),WhenAccepted(%SendDebugViewMessage(‘Test Message for Debugview’))
#EndButton

#Call(%SendDebugViewMessage(‘Test Message for Debugview’) )

I dont think an example for debugging templates specifically exists, but it just got a bit easier, and I dont think Brahns addon does Template debugging
How to have DebugView++ Embedded in the IDE - marketplace - ClarionHub
A quick and dirty way to attach “DebugView++.exe” to a window handle - code / Interop - ClarionHub

Now to save on typing, you could shrink the group name & parameter down to something like

#Group(%D,%M)

and use

#Call(%D(‘Some message’))

#Call(%D(%Control))

#Call(%D(%Procedure))
etc etc

FWIW.

That’s interesting.
Years ago I wrote a small DLL for Russ Eggen,
So he could call OutputDebugString from templates
I’m not sure, he might’ve even written a clarionMag article on the subject

I think you have tried this in earlier versions as it comes directly from your question on comp.lang.clarion of 5th July 2019
Subject: Template Debugger

The other day I was going over some old clarion websites and I thought I saw something either code or something else that could produce template output abit like debugview type of output.

to which I responded…

You can use DebugView, declare a #GROUP and use #RUNDLL to call OutputDebugStringA with a single string parameter…

#GROUP(%ODS,%inputString)
#RUNDLL(‘Kernel32.dll’,‘outputdebugstringA’,%inputString),pascal

Usage…

#CALL(%ODS,'End of #PREPARE - Value of %MNField1 ’ & %MNField1)

There’s also comments within that thread on why it’s not advisable to use Clarion to create DLLs for RUNDLL usage.

You see thats interesting because I cant even get OutputDebugStringA to working using Rundll32 here on my XP vm with C6.

Using #Run in a C6 template this works

rundll32 user32.dll,MessageBeep

but this does not work.

rundll32 kernel32.dll,OutputDebugStringA “Some message can go here”
The above doesnt even work from a dos command line!

DebugView just refuses to work on this C6 XP virtual machine, there is something weird going on with it.

Info taken from here
Passing arguments via rundll32.exe to function exported by DLL (stmxcsr.com)

There is so much stuff that just does not work on even my Win10 machine, its like its hacked but even Windows Defender doesnt find anything wrong with it!!!

I get something working then it stops working.

I’ve stopped using the newsgroups because they are unencrypted so anyone can do a MITM and I noticed that some of the posts I’ve downloaded from the newsgroup server had been changed when I downloaded them again years later.

Mike Hanson did a post on using 64bit variables, cant remember it off the top of my head but I used it in an app, but when I happened to have downloaded the msgs from the ngs again some years later on a new machine, I noticed the post was different to the code and notes I had in an app here where I was using it, so someone had edited it.

I found the ClarionMag article
A Template Debugger” by Russell Eggen Published 2006-Sept-06
ClarionMag monthly PDFs and source ZIPs (2006) - ClarionMag Archive - Confluence (jira.com)

My code is almost identical but I’m missing the maincode pragam when its compiled as a DLL, as an EXE works when I use a command line parameter for the message.

#pragma define(maincode=>off)

So I’ll try it with that.

I’ve actually written a template which does a single procedure app which writes out code like this but there are embeds in there and I have the option to use the window and report designer with an accept loop if I want something that fair.

Program

Map
    Module('WinAPI')
        OutputDebugStringA(*cstring),Raw,Pascal,Name('OutputDebugStringA')
    End
    SendDbgView (*cstring dbgvwmsg)
End
Glo:CommandString       CSTRING(2048) !Embed code to test

  Code
    Glo:CommandString = Command('')
    Glo:CommandString = 'Test Message'
    !SendDbgView(Glo:CommandString)
    Omit('***')
    ***

SendDbgView      Procedure (*cstring dbgvwmsg)
  !SENDDBGVIEW@FRsc @F
  Code
    OutputDebugStringA(dbgvwmsg)
    !OutputDebugStringA(*cstring),Raw,Pascal,Name('OutputDebugStringA')
    !dbgvwmsg

This was my PRJ file

    -- SimpleApp
    #noedit
    #system win32
    #model clarion dll
    #pragma debug(vid=>full)
    #pragma debug(line_num=>on)
    #pragma optimize(cpu=>386)
    #compile "SimpleApp.clw"
    #link "SimpleApp.exe"

I was hoping the Rundll32 would recognise when stuff needs to be sent in a cstring and convert the string into a cstring, but it doesnt.

The #Model Clarion DLL seems to be case sensitive.
If I just use %ProgramExtension which is upper case, I cant load the .PRJ file, it has to be lower case.

The number of #Pragma’s can also be reduced.

This currently works for a template generated .PRJ file and compiles, yet to test using #RunDll in a template though.

-- Filename
#noedit
#system win32
#model clarion dll
#pragma define(maincode=>off)
#pragma debug(vid=>full)
#compile "Filename.clw"
#link "Filename.DLL"

I created am ODS.dll following the ClarionMag instructions.

I want to share it here for anyone interested.

Note: The Clarion project to build the DLL is in the ZIP. Also included the EXP file.

TemplateDebug.zip (4.4 KB)

1 Like

Build Don’s project and place the ODS.DLL in your Clarion BIN folder. Because it links to the CLARUN.DLL you will need to build it for each version.

Adding a few details quoted from the article Mark posted in #5 above on how to use the DLL Don posted.

Next, you need to add a small #GROUP to your templates. I called mine ODS as well.
Here’s the source:

#GROUP(%ODS,%Debug)
#RUNDLL('ODS.DLL','ODS','DonTpl: ' & %Debug),WIN32

#GROUP statements are like template procedures, and the first line of the #GROUP is like a procedure
prototype. The first parameter is the name of the #GROUP i.e. %ODS. The second parameter is a string value, passed by value i.e. %Debug. This lets me pass expressions as well as variables.

#RUNDLL calls my ODS.DLL, which is listed in the first parameter. The second parameter ‘ODS’ is the public procedure name in my DLL, and the third is the parameter passed to my procedure.


Examples of usage:

#PROMPT('Activate Debuger class ?',CHECK),%DebugTrue,DEFAULT(%True),
 WHENACCEPTED(%ODS('DebugTrue set to ' & %DebugTrue)

#INSERT(%ODS,'Symbol value is ' & MySymbol)
#CALL(%ODS,'My debug message here')

This is the ODS DLL source that was in Don’s Zip file that shows its a simple wrapper for the API:

  PROGRAM
  MAP
    ODS(*CSTRING),Name('ODS')
    MODULE('Winapi')
        OutputDebugString(*CSTRING),PASCAL,RAW,NAME('OutputDebugStringA'),DLL(1)
    END
  END
  CODE

ODS PROCEDURE(*CSTRING argMsg)
    CODE
    OutputDebugString(argMsg)

To build it you will need this EXP file. Note above that the MAP Procedure specifies NAME('ODA') which makes that the external name and not the mangled name: ODS@FRsc @?.

NAME 'ODS' GUI
EXPORTS
ODS @?
;    ODS@FRsc @?   FYI <--- Mangled name