{"id":182,"date":"2007-08-25T09:15:00","date_gmt":"2007-08-25T09:15:00","guid":{"rendered":"\/lisa\/post\/2007\/08\/25\/Straight-Talk-about-Built-In-Files.aspx"},"modified":"2007-08-25T09:15:00","modified_gmt":"2007-08-25T09:15:00","slug":"straight-talk-about-built-in-files","status":"publish","type":"post","link":"https:\/\/spacefold.com\/lisa\/2007\/08\/25\/straight-talk-about-built-in-files\/","title":{"rendered":"Straight Talk about Built-In Files"},"content":{"rendered":"<p>\nIt&#39;s back-to-basics time, VFP folks.\n<\/p>\n<p>\nAs I <a href=\"\/lisa\/2007\/08\/16\/SP2-Sedna-FFC-ReportListener-Beta-Info\/\" title=\"Sedna Beta Info\">posted in reference to the Sedna Beta files<\/a>, the &quot;swapcopy&quot; code we&#39;ve put into _ReportListener and leveraged in gfxNoRender has to be used very carefully, and we are tightening it up as much as possible so that it serves as a good example of handling a new-in-SP2 product feature. &nbsp;(If you&#39;re not up-to-speed on this already, that new feature is read-write ReportListener.CommandClauses.File value in the LoadReport event.)&nbsp;\n<\/p>\n<p>\nThe thing we&#39;re trying to provide an example of is a very-specific-to-reporting feature.&nbsp; The basic problem-to-solve, however, as described in the &quot;Backstory&quot; section of that post, is not.&nbsp;That basic problem is&nbsp;how to handle files built into APP\/EXEs and&nbsp;how to use them as resources in Xbase code.&nbsp;\n<\/p>\n<p>\nI am constantly amazed by the number of people who find a bug in the way something of this nature is handled and don&#39;t know how to correct it, as a result of which they conclude that the whole thing is impossible to resolve.\n<\/p>\n<h5>Basic principle #1: SYS(2000) and FILE() are different.&nbsp; Use both, and use each&nbsp;appropriately.<\/h5>\n<p>\nUse SYS(2000) when you want to absolutely, positively ensure that you have a copy on disk&nbsp; &#8212; for example, you need to edit the file.&nbsp;\n<\/p>\n<p>\nUse FILE() when your code needs to &quot;see&quot; a file but it may be a readonly resource built into an APP or EXE. If FILE() can &quot;see&quot; it you can work with it, for example to create a copy of it on disk that you can further manipulate.\n<\/p>\n<p>\nEvery time you need to check that a file exists, you should evaluate: <em>which function should&nbsp;I use here<\/em>?\n<\/p>\n<p>\nIn what situation might a file exist&nbsp;and be available to your application but not be available to your Xbase code? In other words, in what situations is FILE() a&nbsp;required check? If you don&#39;t know the answer, see principle #4 below.\n<\/p>\n<p>\nIn FFC reportlistener code, you will see both functions used all over the place. For what it&#39;s worth, I didn&#39;t use the wrong function in the new swapcopy code, I was just so intent on a specialized version check (was SP2 functionality available?) that I forgot to do an additional&nbsp;FILE() check before attempting to USE the FRX in two new places.&nbsp;\n<\/p>\n<p>\nYou often have to use both functions in one operation.&nbsp; For example, use the FILE() check to see if you can make a copy of the file and then, afterwards, use SYS(2000) to make sure that the copy on disk exists before proceeding.\n<\/p>\n<h5>Basic principle #2: Use FULLPATH() and understand the results.<\/h5>\n<p>\nYou won&#39;t see&nbsp;a use of FULLPATH()&nbsp;illustrated in the reporting example under discussion in our swapcopy code, because ReportListener.CommandClauses.File is already fullpath&#39;d.&nbsp; The important thing to realize is that the result of FULLPATH() &#8212; and also the path you see in ReportListener.CommandClauses.File &#8212; may not actually exist if the file is built into the APP\/EXE file. But that is perfectly okay.&nbsp;\n<\/p>\n<p>\nWhat you&#39;re seeing is an indication of how the APP\/EXE &quot;thinks&quot; about that file within the structure of the compiled version, to distinguish between it and other potential files with the same filename that are also built in.&nbsp; It&#39;s more like an file ID or a virtual path than a physically-pathed filename. It doesn&#39;t matter that the path looks like nonsense on the deployment machine; if FILE() sees the file, then your other code working on that file will also see it.\n<\/p>\n<p>\nIn other words, it&#39;s really not a bug, it really <em>is<\/em> a feature. And it&#39;s misunderstanding this feature that causes a lot of people not to be able to use built-in files successfully.\n<\/p>\n<h5>Basic principle #3: Most code will work with files that FILE() can &quot;see&quot; &#8212; but some won&#39;t.<\/h5>\n<p>\nIn scenarios where&nbsp;you&#39;ve chosen to use FILE() rather than SYS(2000) to validate the availability of a file, verify the availability of the syntax with which you manipulate that file.\n<\/p>\n<p>\nWhen you work with a built-in file, it&#39;s read-only.&nbsp; That much is obvious. For example, you can&#39;t USE a built-in lookup DBF and append a record to it.\n<\/p>\n<p>\nBut some things are not quite so obvious, so it&#39;s always a good idea to check <em>any<\/em> operation you think should be usable against a built-in file.&nbsp; For example, you will see this code in the FFC&#39;s <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms995317(VS.80)\/\" title=\"XMLDisplayListener help topic\">XMLDisplayListener<\/a> class, where it is going to publish an image to your stipulated external files location as part of the support files for an XML version of the report output:\n<\/p>\n<p class=\"code\">\nIF EMPTY(SYS(2000,m.lcFile))<font style=\"color: green\"><br \/>\n&nbsp;&nbsp; * used to be:<br \/>\n&nbsp;&nbsp; * COPY FILE (cContentsToBeRendered) TO (lcFile)<br \/>\n&nbsp;&nbsp; * to handle files built into an app<\/font><br \/>\n&nbsp;&nbsp; STRTOFILE(FILETOSTR(m.cContentsToBeRendered),m.lcFile)<br \/>\nENDIF\n<\/p>\n<p>\n.. the nested STRTOFILE(FILETOSTR()) simply worked better than COPY FILE to reproduce the image files faithfully, and I switched.\n<\/p>\n<h5>Basic principle #4: Xbase code using FILE() and other built-in file-access can&#39;t travel up code modules in the calling chain.<\/h5>\n<p>\nOne of the little-known &quot;deep&quot; changes that had to be made for _REPORTOUTPUT and a separate REPORTOUTPUT.APP to work at all was in the base class reportlistener code. If you&#39;re using REPORTOUTPUT.APP to get your reportlistener and you&#39;ve built in your FRXs and\/or images referenced in your FRXs to your APP\/EXE, the base class has to&nbsp;be able to see those images to render the report. Our Xbase code also gets to make an extra &quot;hop&quot; in this unique situation, to a certain extent.&nbsp;\n<\/p>\n<p>\n<em>It&#39;s not infinitely extensible behavior. <\/em>If you modularize your application and (say) have a master EXE that hands listener references to a reporting APP\/EXE, you&#39;re going to run into some limitations, no matter what your design.\n<\/p>\n<p>\nAs I mentioned in&nbsp;that <a href=\"\/lisa\/2007\/08\/16\/SP2-Sedna-FFC-ReportListener-Beta-Info\/\" title=\"Sedna Beta Info\">previous post<\/a>, this is a fact of Xbase life and not specific to reporting at all, but making Xbase code such an integral, seamless&nbsp;part of the base reporting process really pushes this fact into the forefront of our collective Xbase development consciousness.&nbsp;\n<\/p>\n<p>\nYou can bring reporting back into alignment with the rest of your Xbase code, in this area, by simply removing REPORTOUTPUT.APP from the equation. I cannot stress enough the fact that REPORTOUTPUT.APP was just a leg up to bridge the two syntaxes (SET REPORTBEHAVIOR 80 and object-assisted 90).&nbsp; Please do remove the extra hop and bring the coordination of APP\/EXEs under your direct code by eliminating REPORTOUTPUT.APP; you can get the same functionality by simply pointing _REPORTOUTPUT at frxoutput.PRG instead.&nbsp; The FFC _ReportListener.VCX library is identical to the files used in REPORTOUTPUT.APP, by design. The discussion in the docs that introduces this critical point is in the topic <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/x87zy1z1(VS.80)\/\" title=\"Distributing Report Files help topic\">Including Report Files for Distribution<\/a>.&nbsp; The simple method required to build in the necessary components is identical for all three REPORT*.APPs and is covered in the topic <a href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms978865(VS.80)\/\" title=\"Build in reporting system files to your app-exe\">How To: Specify and Distribute ReportBuilder.App<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#39;s back-to-basics time, VFP folks. As I posted in reference to the Sedna Beta files, the &quot;swapcopy&quot; code we&#39;ve put into _ReportListener and leveraged in gfxNoRender has to be used very carefully, and we are tightening it up as much as possible so that it serves as a good example of handling a new-in-SP2 product<a class=\"more-link\" href=\"https:\/\/spacefold.com\/lisa\/2007\/08\/25\/straight-talk-about-built-in-files\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-182","post","type-post","status-publish","format-standard","hentry","category-visual-foxpro"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/182","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/comments?post=182"}],"version-history":[{"count":0,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/182\/revisions"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/media?parent=182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/categories?post=182"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/tags?post=182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}