Debug AVFP ver.6.03 with WS 2012

Topics: Developer Forum
Developer
Oct 31, 2013 at 3:08 AM
I don't think we got the debugger working in Ver 6.03(?).

If not, then this may be of interest.

I am was able to hook into VFP application object, when running AVFP under Visual Studio 2012. This gives 'set step' ability of VFP, from anywhere in the AVFP Project and also from any avfp pages.

But it is rudimentary and needs more development time. i.e.
1) fixing permission settings for VFP.. for doing ajax 'POST' ( I think..??),
2) has FoxPro environment settings ( I.e. set('xx')) of locally installed VFP IDE and not that to IIS server OLE session ( I think ..??),
3) gives VFP warnings on oResponse.Redirects() (...about current thread aborting.. WTF??),
4) etc etc...& etc.

Thing is, I already have developed a debugger more suitable for my customized version of AVFP and I do not want to spend any time on this new debugger (which is more suitable in CodePlex AVFP version).

If anyone wants to get my notes and work on it, I'll be happy to assist.
Coordinator
Oct 31, 2013 at 3:37 PM
It's listed in the items to fix but only has gotten 2 votes:

http://activevfp.codeplex.com/workitem/34439

The first page works in 6.03 just like 5.53 debugging. It's all the subsequent pages that aren't being debugged properly. There's probably a decent workaround that's not too difficult to implement.
Developer
Oct 31, 2013 at 6:02 PM
Edited Nov 9, 2013 at 2:14 PM
Yep, I cannot understand the reason for low votes. I would think, the ability to debug can make or break project timelines. The procedure to start debugging is the same as listed in documentation for 5.53. And I seem to I have reached much further then the first page. However, I am unable to make ajax POST calls (i.e. error 405 - method not allowed) using VFP proxy server and unless that works, it not something I can offer in codeplex. Other then this, I know the reasons that are creating the problems, so they should be easier to solve. I'll dump my notes here, so that it can be use as a reference for anyone attempting it in future. 1) AVFPHandler should tie down the least number of web resources. Ignoring security issues for the moment, we first need to remove all web.config files from subfolders ( css, image, etc). Change the root web config file as follows: ( note the change for REST handler for extension less calls) ``` <?xml version="1.0" encoding="UTF-8"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <httpModules> <clear /> <add name="HttpModule_ProcessManifest" type="MazeComputer.AspManifestHelpers.HttpModule_ProcessManifest, AspManifestHelpers" /> <add name="Session" type="System.Web.SessionState.SessionStateModule" /> </httpModules> <compilation debug="true" /> <httpHandlers> <add verb="*" path="*.avfp" type="AVFPHandler" /> <add verb="*" path="*.css" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*.bmp" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*.gif" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*.png" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*.ico" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*.js" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*.pdf" type="System.Web.StaticFileHandler" validate="false" /> <add verb="*" path="*" type="AVFPHandler" /> </httpHandlers> </system.web> <system.webServer> <modules> <add name="HttpModule_ProcessManifest" type="MazeComputer.AspManifestHelpers.HttpModule_ProcessManifest, AspManifestHelpers" preCondition="managedHandler" /> </modules> <validation validateIntegratedModeConfiguration="false" /> <defaultDocument> <files> <clear/> <add value="default.avfp"/> </files> </defaultDocument> <handlers> <add verb="*" path="*.avfp" name="AVFPHandler" type="AVFPHandler" /> <add verb="*" path="*." name="AVFPRESTHandler" type="AVFPHandler" /> </handlers> </system.webServer> </configuration> ``` 2) Changes in Proxystub.prg ``` FUNCTION Debugger() LOCAL loFox, lcReturn lcReturn = "" loFox = GETOBJECT(,"visualfoxpro.application.9") loFox.SetVar("oRequest",THIS.oRequest) loFox.SetVar("oSession",THIS.oSession) loFox.SetVar("oResponse",THIS.oResponse) loFox.SetVar("oServer",THIS.oServer) loFox.SetVar("oApplication",THIS.oApplication) loFox.DoCmd("SET RESOURCE OFF") loFox.DoCmd("SET EXCLUSIVE OFF") loFox.DoCmd("SET CPDIALOG OFF") loFox.DoCmd("SET DELETED ON") loFox.DoCmd("SET EXACT OFF") loFox.DoCmd("SET SAFETY OFF") loFox.DoCmd("SET REPROCESS TO 2 SECONDS") lcReturn = loFox.eval("proxystub()") RELEASE loFox RETURN lcReturn ENDFUNC ``` 3) Change in Proxstub ( replace all the code between the beginning of the file ...and.... 'DEFINE CLASS server AS ActiveVFP OLEPUBLIC' as follows.. ``` #DEFINE crlf CHR(13)+CHR(10) SET STEP ON oProp=NEWOBJECT('AVFPproperties','activevfp.prg') && create properties shared among classes oHTML=NEWOBJECT('AVFPhtml','activevfp.prg') oCookie=NEWOBJECT('AVFPcookie','activevfp.prg') oProp.ScriptPath=oRequest.servervariables("SCRIPT_NAME") oProp.SessID=NVL(oRequest.querystring("sid"),"") oProp.AppStartPath=JUSTPATH(oRequest.ServerVariables("PATH_TRANSLATED"))+[\] &&JUSTPATH(APPLICATION.SERVERNAME)+"\" oProp.AppName=STREXTRACT(oRequest.ServerVariables("PATH_INFO"),[/],[/]) &&blank if installed to root &&JUSTSTEM(APPLICATION.SERVERNAME) oProp.RunningPrg=[main.prg] ************************************************************** * REST-like APIs implementation * * Author: Victor Espina * Date: April 2012 * ************************************************************** * Create an instancia of RESTHelper class LOCAL oRESTHelper, cRootPath cRootPath = oRequest.serverVariables("APPL_PHYSICAL_PATH") oRESTHelper = NEWOBJECT("restHelper","PRG\RESTHelper.PRG") oRESTHelper.setFolder("ROOT", cRootPath) oRESTHelper.setFolder("CONTROLLERS", ADDBS(cRootPath) + "prg/rest/controllers") oRESTHelper.loadControllers() * Use RESTHelper object to check if the request conforms a REST-like API call. If so, pass * the request object to RESTHelper in order to let the right resource controller handle it. IF oRESTHelper.isREST(oRequest) oProp.appStartPath = oRequest.serverVariables("APPL_PHYSICAL_PATH") RETURN oRESTHelper.handleRequest(oRequest, oProp) ENDIF * If the request was not a REST-like API call, check if MAIN.PRG exists in * oProp.appStartPath. If it doesn't, we change oProp.appStartPath to point * to app's root folder. This will avoid an innecessary "file not found" * error. IF NOT FILE(oProp.appStartPath + "\PRG\MAIN.PRG") oProp.appStartPath = oRequest.serverVariables("APPL_PHYSICAL_PATH") ENDIF * If for some reason we can't find a valid processor, return * an error message IF NOT FILE(oProp.AppStartPath+'\prg\main.prg') RETURN "oRESTHelper: cannot find " + oProp.appStartPath+"\prg\main.prg" ENDIF ************************************************************** lcScript=FILETOSTR(oProp.AppStartPath+'\prg\main.prg') lcHTMLout= EXECSCRIPT(lcScript) &&main() && run the application RETURN lcHTMLout ``` 4) Add the following just below the line 'FUNCTION Process' in the proxystub.prg. Note that this is __only for debugging__. you must comment out the entire portion in production. Also this may be the cause of thread aborting message. Better manner may be to make change in the dll itself (and I don't know how to do that). In __fact if you start avfp, and if the following code has 'not' been commented out, then you will always get Run time__ error. To __avoid this error, open VFP (as administrator) before running AVFP__ in the manner documented for debugging V5.x In fact I have this portion running based on an <appSettings> value in Web.Config. ``` *-------+IMP:: Delete this in Production... Local loFox loFox = GETOBJECT(,"visualfoxpro.application.9") If VARTYPE(loFox) = "O" loFox = null Release loFox oProp=NEWOBJECT('AVFPproperties') Return this.Debugger() Endif Release loFox *-------+ Imp:: Delete this in Production... ``` 5) Change the main.prg. Replace the 'otherwise' portion of the Case .. endcase as follows. ``` OTHERWISE && get .avfp script *------+ Activate the debug thru VS 2012 Do Case case LOWER(oProp.Action) == "default" and LOWER(oProp.Ext) == ".aspx" oProp.Action = "default" oProp.Ext = ".avfp" lcHTMLout= FILETOSTR(oProp.HtmlPath+oProp.Action+oProp.Ext) oProp.RunningPrg=oProp.Action+oProp.Ext lcHTMLout= oHTML.mergescript(lcHTMLout) case !ISNULL(oProp.Action) .AND. FILE(oProp.HtmlPath+oProp.Action+oProp.Ext) * This section must stay here for pure scripting mode lcHTMLout= FILETOSTR(oProp.HtmlPath+oProp.Action+oProp.Ext) oProp.RunningPrg=oProp.Action+oProp.Ext lcHTMLout= oHTML.mergescript(lcHTMLout) Otherwise && goto default page * USE mydbf && test error CookieLogin() && checks for cookie to authenticate lcHTMLfile = 'default'+oProp.Ext If !FILE(oProp.HtmlPath+lcHTMLfile) *----+ Oct 2013.. default document is not being served by IIS.. force it. Local lcPath lcPath = ALLTRIM(oRequest.ServerVariables("SCRIPT_NAME")) lcPath = lcPath + IIF(RIGHT(lcPath,1) != '/','/','') oResponse.Redirect(lcPath+'default.avfp') endif lcHTMLout= FILETOSTR(oProp.HtmlPath+lcHTMLfile) oProp.RunningPrg=[default]+oProp.Ext lcHTMLout= oHTML.mergescript(lcHTMLout) Endcase ENDCASE ``` 6) To debug.. Follow the normal manner to open VS & VFP. However, you will need to use Default.aspx to start debugging. Debug properties for VS Start Options -> Start action -> Use current page Start Options -> server -> Use default web server Start Options -> debugger -> asp.net. Build -> start action -> benefire running startup page: -> Nobuild Build-> target framework 4.5 -> .net framework 4.5 Is IIS manager, Application pool -> <select the application pool used by your application> ->Basic Settings-> set .net framework to 4.0 and pipeline to integrated. 7) I hope I have included all the changes.. If you get it working for Ajax, please share. Good luck.
Coordinator
Oct 31, 2013 at 8:40 PM
Thanks. I'll try it. If we can SET STEP ON in the VFP debugger and step thru the VFP code on pages other than the first one with your techniques, that in itself would be a huge improvement for 6.03.
Developer
Nov 4, 2013 at 5:00 AM
Edited Nov 9, 2013 at 2:06 PM
Final update.... hopefully, we should now be able to have full 'set step' ability in V 6.03 also.

I've made debugging work when the web site's 'application pool' is on .net ver 2, in integrated mode. I think, this would be least disruptive to existing installs.
Update: .net ver 2 causes htmlencoding holes. I have application pool back on .net ver 4 in integrated mode.


I've already updated the changes required in the web.config file (in my previous comments). Note that we are now calling the images as static files in httpHandlers. If I missed any static file extension, then, it will need to be added in this section.

Also note that I have used both httphandlers ( which are related to .Net ver 2) and also handlers ( which are related to .net ver 3 or 4). This is done to handle Ajax calls.

Note that we have noticeable differences in IIS and .net development server. I did not try IIS Express.

Apart from deleting all web.config files ( except the web.config file in the application root), you can ( if you want to ), now revert these sub-directories to their 'non-application' states in IIS. To do this, go to the virtual 'sub' directory in IIS manager window, and do a right click, then click 'remove' in the context menu that comes up.
Developer
Nov 6, 2013 at 12:20 PM
Hi claudefox,

what does the following, in web.config, do?
    <add name="HttpModule_ProcessManifest" type="MazeComputer.AspManifestHelpers.HttpModule_ProcessManifest, AspManifestHelpers" />
It seems that I was unable to use Application pool using .net framework 4 (i.e. ajax was not working in debug mode). Suddenly, now it all seems to work. The only thing that I changed was to remove these MazeCoputer lines from web.config. Interestingly, it works now even after I restore these lines back into web.config. It could be, but I doubt it's to do with anything else... hence this question.

BTW, I did not delete the assembly from bin, just changed web.config.
Coordinator
Nov 6, 2013 at 2:12 PM
Edited Nov 6, 2013 at 2:17 PM
That's the side by side COM registration stuff. If you take that out you have to register the VFP server manually. And if you register the VFP server manually, you are basically limited to one ActiveVFP backend server per machine. IOW, all copies of your web apps in different folders will be using the one registered ActiveVFP instead of their own copy. Not good in my opinion.

If you register manually and have more than one folder/web application, it may work but you probably will start running into "file not found" errors and just general confusion since you may delete one folder with the registered ActiveVFP and then nothing will work. Again not good.

The best course is just to use the built-in side by side COM registration. It should always work automagically, but, if it doesn't, you should try to find out why it doesn't work and make it work instead of manually registering activevfp.dll, imo.
Developer
Nov 7, 2013 at 2:06 PM
Thanks. It'll make sense to keep it.

What I've not been able to figure out is even when I have application pool in IIS set to using .net framework 4.0 in integrated mode, AVFP seems to be behaving like it is set to using .net framework 4.0 in classic mode ( i.e. see the Web.config above).

Could it be because these dlls in bin folder are created in .net ver 2.0? If you can give me pointers on how to recreate these dlls in VS 2012 I'll be able to test them out.
Developer
Nov 9, 2013 at 2:38 PM
Waaaa...

I updated my comments dated Oct 31 above and now those comments lost all it's formatting. If anyone has an email of the original code, could they fix it from that email?

The change I was making to those comments, related to, 1) using the application pool set to .net framework 4.0 in integrated mode and 2) running the VS in no-build mode using .net framework 4.X

Also ensure that you have loaded the symbols. If S does not start debugger, then you can force VS to reload by flipping the .net framework ( point 2 above) to something else and putting it back to original value after re-opening VS.

Thanks
Coordinator
Feb 8 at 2:30 PM
This is very important. Can you detail the steps for debugging avfp603 exactly as you have done them?

And what do you mean by "hook into VFP application object, when running AVFP under Visual Studio 2012" ?? Do you mean attach process??

thanks!!