External exception C0000006 - delphi

I've wrote some program in Delphi and when I am running it from a disk on key. At some point I'm required to unplug the disk on key while the application is running. If I do this on a computer with at least 1gb of ram everything is okay. When I do this on a machine with 512mb I get an external exception C0000006. If I'm not mistaken, this is because the OS is trying to read the next line of code but cannot find the resource for it (meaning, the application wasn't loaded to the ram) which is absurd because it's a 500kb application.
How can I solve this? or at least handle this exception in a more elegant way? (Since I can't catch it since it's an external exception).
Oh, and my Delphi application is a console application under windows xp.

What you need to do is tell windows to load your whole program into memory, rather than allowing it to demand load pages when it needs to. I have done this successfully for applications running off a CD. I don't have the code with me right now, but I recall that I found hints on how to do it in source for the fantastic open source install program Inno Setup.
Edit: Actually, after doing a little research, you can use a Delphi compiler directive to tell windows to load the full executable. This works if you have Delphi > 2006. This will have the effect that you will never get the external exception.
Put this line in your applications project file:
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
This tells windows that the executable is going to be used from removable media, so load the the executable into memory (or the swap file). Then you don't need to worry about things like copying the file to the machine first, etc.
Edit 2: I currently have access to Delphi 7 and I can confirm, as noted by others, that this also works with Delphi 7 (and likely Delphi 6) with the following code:
const
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
For Delphi < 6, you can go down the path of forcing the executable to be paged in. There is an example of how to do it in C++ here (unless you find a way to modify the PE header flags after link time, which looks to be complicated)
N#

That's EXCEPTION_IN_PAGE_ERROR. It means that the OS loader failed to page in some data required for the application to run, probably due to an I/O error or other error. Since you're removing the disk, that would make sense.
Perhaps the working set (the set of often-used memory pages) for the application was allowed to grow large enough on 1GB machines such that recourse to the disk to reload pages wasn't necessary, but that wasn't the case on 512MB machines?
I would suggest trying to copy the executable to a temporary location and starting it from there, possibly with delayed deletion; or use some other mechanism to guarantee on-disk backing for all memory pages touched by the application in normal use, and prevent this error in cases of memory pressure, where the OS will trim the working set of running processes.

Like #Barry, I would recommend checking the drive type of the volume that your executable is running from; if it is a removeable drive (and missing a "already in temp" command line parameter) copy the executable (and any of its dependencies) to the user's %TEMP% folder and then re-launch it from there with an extra command line parameter to indicate "already in temp".
Create each temporary file using File.Create(targetPath, bufferSize, FileOptions.DeleteOnClose) (or one of the FileStream constructors that takes a FileOptions parameter), but make sure to hang onto the returned File instance until after the second copy is launched (e.g. in a List<File>).
Copy the contents of each file.
Launch the executable from the temp folder.
Call Close() on each of the File instances saved above.
Exit the original executable.
This way the files get closed regardless of which process finishes first, and the source volume can be removed earlier.

The solution
uses Windows;
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
is available for Delphi since version 6.

There's a Delphi working version of RunImageLocally from MSJ which forces the executable/dll to be paged in. This can prevent C0000006 errors when running from network or removable media...
Check it out at https://github.com/jrsoftware/issrc/blob/master/Projects/SetupLdr.dpr

This exception C0000006 also often occurs if your software is run from a network drive. To prevent that problem you can combine the flag
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
with the following flag:
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEFlags $0C00}

Related

Random error when loading project into Delphi XE6

From time to time, when I load a project into the XE6 IDE, the following error occurs
This error results in the TZConnection component being removed from the Datamodule for some inexplicable reason. Note that the project has been loading without issue for ages and just out of the blue, this occurs.
Has anyone seen this before and know of a way of stopping it from occuring ?
It also occurs with other components, not always the TZConnection component but mostly ZConnection.
Like I said before, this appears randomly. I could close project A, open project B then close it and return to Project A and bang!, the error occurs.
Any clues ? (note that this also used to occur in Delphi 2007)
The Zeos libraries are themselves causing this problem.
To see why, and to fix it, use Delphi to launch a second instance of Delphi, and debug the issue directly.
I wrote a blog post showing exact steps here.
The key is to set the executable that will be run for your zeos package, be sure to build them in debug configuration, and then click the Run button on the Delphi IDE toolbar. A second delphi instance will start. Open the affected form but be sure to be using the IDE instance that is Being debugged as opposed to the one which is currently doing the debugging, when the exception occurs that is causing your component to delete itself, you will be able to step into the package code and see the problem.
I suspect a DLL-hell path issue. (Multiple copies of Zeos or other core BPL/DLLs in your path.)
Actually, it doesn't sound that inexplicable - it's probably caused by an exception occurring as the DataModule (or some form with db-aware components connected to it via properties) is being loaded into the IDE (see below). Have you tried checking that wherever your ZEOS .BPL files are located is on your system Path? Likewise any .BPLs they depend upon - see the "requires" clause in the .DPK file(s) for Zeos.
This sort of problem arises fairly frequently with flaky DB components, maybe more so than other types of component because db components more frequently involve linkages between datamodules and forms, e.g. when db-aware components on the forms are connected to others on the datamodule.
So, sometimes, whether this sort of problem shows up or not depends on the order in which the IDE will re-open them - try closing the project with only the dm open and then re-opening it. A bit of experimenting with which datamodules and forms are open in the IDE and in which order may help you pin down the problem. If/when you have a reproducible sequence of steps to provoke the problem, report it to the authors.
A fairly reliable way to determine whether the problem is being caused by an exception as a project loads is to run one instance of the IDE inside another. As long as the first ("outer") instance of the IDE has the debugger set to "Break on Language exceptions" it should be able to take you straight to the source of the exception (assuming it occurs, of course) when the project is loaded by the second instance. It may take a few goes to "catch it in the act" of course, but it is hugely satisfying when you manage to. Good luck!
Unlike MartynA I doubt this would be caused by an exception.
I would more likely expect such issues to be caused by windows path environment variable being too long.
Unfortunately still many component vendors and even some programs modify "windows path environment variable` to make their own files accessible by other programs.
And when windows path environment variable fails to provide sufficient information windows will try to find the files in default system directory which is C:\Windows\System32
So I would strongly advise checking the windows path environment variable to check its length.
The easiest way to do this is by simply starting the command prompt and typing in path directive or perhaps path >> D:\path.log to export the path environment variable information into a file for easier reading in case if it is long.
EDIT: BTW I just checked my path environment variable and I see that I will have to do some cleaning because it contains entries for both Delphi XE8 and Delphi XE 10 Seattle file locations even thou I have removed Delphi XE8 from my computer. Not to mention some entries from some programs that I have removed quite some time ago.

Application version updated but older version executed due to offline files

When i install a new version of my Delphi 7.0 application on the network and i restart the application on the client desktop it sometimes executes the previous version, but the modified date is the new one...
After some googleing i found out that Windows Offline Files sometimes causes this, and therefore i added the folowing PE Flags to my .dpr
const
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = $8000;
// Following are already defined in D7's Windows.pas
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
or IMAGE_FILE_NET_RUN_FROM_SWAP}
Even though i added these flags i (sometimes - it is not really reproducable) still have the same issues.
Can someone explain what these PE flags do and how to prevent windows to "cache" my exefile when running from a network path.
The PE Flags
When a process is created, the executable files are mapped into memory. These executable files are held in virtual memory pages like other virtual memory such as stack or heap memory.
The virtual memory manager may decide to unload pages from physical memory if the memory is needed elsewhere. And that could happen to your executable's pages.
Another scenario is that the executable file was never in physical memory at all. The process starts and mapped pages are loaded on demand. If some parts of the executable file are not touched then they will not get fetched from disk.
If the file resides on removable media, or on network volumes this can cause problems. Running process may be unable to access their own executable's memory. This results in runtime failure.
These PE flags force the executable to be copied to the swap file and mapped from there. The copy happens during the process creation and is potentially expensive.
These PE flags won't help you at all. If you start the process and the network is not available, all you have to work with is the offline copy. Include these PE flags and you'll just get the loader to copy the offline copy to the swap file. With the same end result.
Preventing the executable file from being cached
Before you can get an answer to that you would need to get a clean diagnosis of what causes the behaviour you observe. As it stands you suspect offline files, but I see no evidence for that being the cause. Perhaps something else is behind this. Perhaps your file server is mis-configured. Really, there could be all sorts of explanations for this.
Instead of adding PE flags to your executable, you really need to step back and accurately diagnose the problem. Once you know what the problem is then you will be in a position to attempt to solve it.

Delphi - invalid stream format errors on run

Delphi 6 Prof.
We have many applications. The programs have 8-12 MB size.
In this period we many times got reports about "Invalid stream format" errors.
We use shared Windows (or Linux) folders to store the applications, and users running them from these directories with links.
This meaning that OS is paging the files, and loading the needed parts only.
Formerly we got C000006 exceptions.
As I know this meaning that the file paging (loading) failed on any network problem (timeout, etc).
Now we face with "Invalid stream format" errors, and "invalid property xxxx" errors.
If I know well, both error caused by "paging problem", but C06 happens in code, and stream error in the data area of the Exe.
But maybe I know wrong...
Anyway the problem is strange. Sometimes we got it, sometimes we not.
How to avoid it? These errors prevents the users to create new dialogs, to use the programs...
(In other place the user used wifi - then we got same side effects.)
Maybe you have any idea how to prevent, avoid this problem.
UPX (vs. Antiviruses)?
Copy the exe-s to local place?
The system administrators of this customer are "our enemies", because they said: "everything is ok". The source of the problem isn't identifiable...
Thanks for every idea: dd
Assuming your analysis is correct, and the problem is that the executable is located on a network drive with a flaky connection, then there is a solution. You need to add PE flags to your executable that forces Windows to copy the file from the network to the local machine before running it.
Make sure that your .dpr file's uses clause includes the Windows unit. And then add this line:
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
just before the begin in your .dpr file. We added the Windows unit so that the two constants would be recognised.
Another possibility could be to pack the exe with upx tool for instance.
http://upx.sourceforge.net/
It will expand the whole file in memory before run.
And it will save bandwidth.

Getting External Exception C0000006 in D2006 app - how can I force delphi to load the whole executable?

I get this occasionally when exiting my app - my app is running the EXE over a network. I understand it's a page fault when part of the EXE is loaded on demand.
I have also observed it in the OnDrawCell method of a TDrawGrid, so I'm mystified how that might have caused a page load. Also, the exception kept happening.
So my questions:
Can Error C0000006 result from other causes? I have made fairly major changes to the way the app manages memory, though nothing out of the ordinary, and I'm confident the code is behaving.
How can you make the app load all of itself into memory on startup (in Delphi 2006 - I understand there are directives for later versions of Delphi).
TIA
The directive $SetPEFlags seems to be part of Delphi 2006, at least Hallvard talks about it in this article in the context of D2006. Have a look here on how to use it.
We experience this too. The system puts some of the executable pages out to swap and then fails to page it back some time later. It appears to be related to network connections being restored after sleep.
The only viable solution that we have found is to locate executables on the local machine.
This exception C0000006 also often occurs if your software is run from a network drive. To prevent that problem you can combine the flag
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP}
with the following flag:
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEFlags $0C00}

How do I embed a binary within a Delphi executable and extract at runtime?

I'd like to embed an executable inside of my Delphi binary and extract it at runtime. The purpose of this is to ensure that a helper utility is always available on the system, without having to distribute multiple files.
With Delphi 2007 I have used JvDataEmbedded, but I am building a console application and I want to know if anyone knows of another way to do it without having to add a hidden form for JvDataEmbedded.
I am using Delphi 2010.
Build a RC file that embeds this program as a resource, and then at runtime you can extract it with a TResourceStream. (See the accepted answer to this question of mine for the general principle.) You can chain the TResourceStream to a TFileStream to write it out to a temp file, then run it.
Cool Trick, Mason!
To add... It occurred to me that this could run into trouble with UAC/permissions if the "mothership" dumps teh "scout ship" diretly into the same directory as it's running from. If you're on Vista/Windows7, regular programs are prevented from writing to the "\program files" directory, when run without elevated permissions. So in that case, the file will likely be placed into a shadow directory. It gets better: you may have different results if you launch the "mothership" program from an installer, as setup programs have special access, and they may temporarily give that access to programs that they launch (which makes it somewhat hazardous to always say YES to "do you want to run the program now?" at the end of installation).
Use a TDataModule to hold the TJvDataEmbedded instead of a TForm.

Resources