Olaf Doschke
Programmer
It is a well known fact an EXE you compile from VFP source code will look for files in it's own body with highest priority, then in current directory, SET PATH paths and further. There is a nice article from Andy Kramek on this at and Tamar Granor also had this covered in the Hackers Guide, I think. But this "strange" effect showing when you don't address files with a full qualified path also has it's pros, you can use embedded files, as if they existed on hdd, even dbfs.
The gotcha with files included in the EXE is, they are readonly, of course, how should vfp update the data of a dbf in an exe? EXE modification is impossible, as it runs. To prevent that problem the project manager quite intelligently puts files in Excluded/Included mode depending on their type. For example code is of course included by default and data is kept excluded.
It also is well known, you can copy files out of your exe to hdd, by using [tt]STRTOFILE()[/tt] of [tt]FILETOSTR()[/tt] and one of the gotchas here is without naming the external file differently than the internal, you'll never be able to address the external file. There is no such easy fix for a DBC and its DBFs, as both of them contain their file names, eg the DBF header of a database table points back to the DBC file it belongs to and also the DBC references the DBF file in a record holding the long table name (which by the way may differ from the DBF file name).
One solution would be to nevertheless rename the files in the project manager to later rename them when flushing them out of the EXE. That way you would restore them back to their original names and make them work as external data. Yes, this can work, but then you have wrongly named files during development in your source project and can't use, extend and debug with that database tables, that's quite useless. That might be solved with a copy of the data elsewhere, with correct file names, but that has the gotcha of changes you make not reflecting directly in your project files.
One simple way out is to zip all database related files (DBC/DCX/DCT/DBF/CDX/FPT/...etc...) and add it to the other files section, which also means you can export this one included ZIP file with a single STRTOFILE(FILETOSTR()) call. That still has the gotcha you need to remember to do this just before each build to have all files in their current state included in the EXE, but here the project hook class comes to the rescue.
For now just a hint for advanced developers here: It works nicely, if you use the BeforeBuild event to zip some predefined files (eg a certain subfolder of the pjx), add this zip to your project, then exit from Beforebuild and in the following AfterBuild remove the file again, deleting the zip at that post build moment and finally cleanup the project. That way the project seemingly hasn't changed at all and yet you still have a zip embodied in the belly of the fox EXE. Just one more pitfall to prevent is, after any operation writing or changing files, eg creating the zip and also adding it to the pjx, let a [tt]DOEVENTS FORCE[/tt] finalize that change to let it reflect in the file system, Windows tends to delay writing and the build process needs to see this and also get exclusive access during compilation.
To zip a dbc you have in our project (set excluded just like normal), the best bet is to temporarily remove the DBC from the project, as the project manager tends to keep it open during development and that also still is in your way in the BeforeBuild event to zip it. You also want to ensure the zip really is closed and added to the pjx, set to [tt]Exclude=.F.[/tt], before you end the BeforeBuild event, again [tt]DOEVENTS FORCE[/tt] will do the trick to wait for Windows file handling to close files and flush caches as far as necessary for the build to see the files in their current state.
I think now you want to see the project hook code. Well, I may add that a few days later, but most probably rather as a download than a post or FAQ.
A specific use case for the embedding of a zipped DBC is to have a template database in your EXE, which can't get lost and enables you to restore a database structure. A setup can also simply be fed with all the files making up your database and where to install the files at the destination computer, the setup also can do lots of things you can't do at runtime, setting file permissions etc, because it has elevated permissions during the installation, but it can only do things once at setup time. Repair installation? Despair installation. Well, that also only works for the admin of a company.
You can also generate an empty database by using gendbc to generate a script for you, but, well, that does not include any data, I recommend it sometimes and it has it's pros of having no binary overhead. But in the end, with a zip of the concrete files, you get 1:1 what you had and that can be accompanied not only by data in the dbfs, but by any additional external files. As zipping and unzipping is quite easy to do, it's a nice added feature. Uses of such an embedded zip are manyfold for anything you might need to restore in its original state even years after a setup. You also will upgrade to the latest state of those files with any normal EXE update.
Well, and as you might initially thought from the subject line, you might do a self extracting zip tool this way, with UI and workflow as you like.
Bye, Olaf.
The gotcha with files included in the EXE is, they are readonly, of course, how should vfp update the data of a dbf in an exe? EXE modification is impossible, as it runs. To prevent that problem the project manager quite intelligently puts files in Excluded/Included mode depending on their type. For example code is of course included by default and data is kept excluded.
It also is well known, you can copy files out of your exe to hdd, by using [tt]STRTOFILE()[/tt] of [tt]FILETOSTR()[/tt] and one of the gotchas here is without naming the external file differently than the internal, you'll never be able to address the external file. There is no such easy fix for a DBC and its DBFs, as both of them contain their file names, eg the DBF header of a database table points back to the DBC file it belongs to and also the DBC references the DBF file in a record holding the long table name (which by the way may differ from the DBF file name).
One solution would be to nevertheless rename the files in the project manager to later rename them when flushing them out of the EXE. That way you would restore them back to their original names and make them work as external data. Yes, this can work, but then you have wrongly named files during development in your source project and can't use, extend and debug with that database tables, that's quite useless. That might be solved with a copy of the data elsewhere, with correct file names, but that has the gotcha of changes you make not reflecting directly in your project files.
One simple way out is to zip all database related files (DBC/DCX/DCT/DBF/CDX/FPT/...etc...) and add it to the other files section, which also means you can export this one included ZIP file with a single STRTOFILE(FILETOSTR()) call. That still has the gotcha you need to remember to do this just before each build to have all files in their current state included in the EXE, but here the project hook class comes to the rescue.
For now just a hint for advanced developers here: It works nicely, if you use the BeforeBuild event to zip some predefined files (eg a certain subfolder of the pjx), add this zip to your project, then exit from Beforebuild and in the following AfterBuild remove the file again, deleting the zip at that post build moment and finally cleanup the project. That way the project seemingly hasn't changed at all and yet you still have a zip embodied in the belly of the fox EXE. Just one more pitfall to prevent is, after any operation writing or changing files, eg creating the zip and also adding it to the pjx, let a [tt]DOEVENTS FORCE[/tt] finalize that change to let it reflect in the file system, Windows tends to delay writing and the build process needs to see this and also get exclusive access during compilation.
To zip a dbc you have in our project (set excluded just like normal), the best bet is to temporarily remove the DBC from the project, as the project manager tends to keep it open during development and that also still is in your way in the BeforeBuild event to zip it. You also want to ensure the zip really is closed and added to the pjx, set to [tt]Exclude=.F.[/tt], before you end the BeforeBuild event, again [tt]DOEVENTS FORCE[/tt] will do the trick to wait for Windows file handling to close files and flush caches as far as necessary for the build to see the files in their current state.
I think now you want to see the project hook code. Well, I may add that a few days later, but most probably rather as a download than a post or FAQ.
A specific use case for the embedding of a zipped DBC is to have a template database in your EXE, which can't get lost and enables you to restore a database structure. A setup can also simply be fed with all the files making up your database and where to install the files at the destination computer, the setup also can do lots of things you can't do at runtime, setting file permissions etc, because it has elevated permissions during the installation, but it can only do things once at setup time. Repair installation? Despair installation. Well, that also only works for the admin of a company.
You can also generate an empty database by using gendbc to generate a script for you, but, well, that does not include any data, I recommend it sometimes and it has it's pros of having no binary overhead. But in the end, with a zip of the concrete files, you get 1:1 what you had and that can be accompanied not only by data in the dbfs, but by any additional external files. As zipping and unzipping is quite easy to do, it's a nice added feature. Uses of such an embedded zip are manyfold for anything you might need to restore in its original state even years after a setup. You also will upgrade to the latest state of those files with any normal EXE update.
Well, and as you might initially thought from the subject line, you might do a self extracting zip tool this way, with UI and workflow as you like.
Bye, Olaf.