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.
Related
With our 80MB Delphi app on a network share we are finding that a right mouse click Properties in explorer is very slow (around 30 seconds) Similar sized programs on the same drive don't have the problem.
I'm wondering if the Delphi linker organizes the exe in a way that means explorer needs to read the whole file to find the properties information and if there is a way to change this? I can't see anything obvious in the project settings.
EDIT
We have these options in the project file:
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP}
but I think these will only affect the program when it is executed.
The delay was caused by the PW option flags I mentioned in the question. Taking them out and all is well.
Now I need to find out why they were put there.
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.
I'm building an application using delphi 7 with ms access 2007 as the database for a client. it runs normally on my laptop (asus) but after I copy the whole project folder and run the Project.exe, it gives me an error "Disk write error".
I've tried googling about "disk write error delphi application" but only found about I/O errors. my application only opens a file after a button click in a form that is called when I click on a submenu, so I'm guessing it's not about I/O..
what is the solution?
thanks in advance
P.S.:
in the project options, the checkbox for building application using runtime packages is already unchecked.
my PC and my client's PC are both using windows 7 32bit (I haven't actually confirmed this with him but I'm guessing he's also using 32bit version because he's not a techy guy)
his PC doesn't have delphi installed
UPDATE :
I forgot that the exact error message was "Disk or network error" instead of "Disk write error".
after googling for the correct error message, I've found out that the problem is that I use a full path for the DataSource in the ADOs' connection string. after I change connection string into "DataSource=.\db\my_db.mdb", the application works perfectly.
even though this question has a negative mark, I'll just leave this solution here in case someone needs it in the future...
Here are some different questions.
The "Disk write error" probably is that you need permissions to write in the folder. A simple test is that you execute your application with "admin permissions" to test this.
Different question is the "using runtime packages" check in project options.
If you compile your application with this check, you need to copy the BPL's needed for your application with the executable.
If you compile with this option unchecked, your exe file include all the libraries for execute (not included DLL's or external dependencies).
This is occurring on 2 machines that are both running Windows XP Pro SP3, yet it runs OK on my development machine within in or outside the Delphi IDE.
Running Windows XP Pro. Exe compiled under Delphi 2010.
When I run the exe I get the Windows Reporting error "Neopos.exe has encountered a problem and needs to close. We are sorry for the inconvenience"
I know it is happening somewhere in the form create of the main form.
Application.Initialize; //Runs this
Application.CreateForm(TfmMain, fmMain); //FAILS HERE
It does not get to: procedure TfmMain.FormCreate(Sender: TObject); in the Main Form and I don't know how to track down this error and debug it.
What happens between: Application.CreateForm(TfmUDF, fmUDF); AND procedure TfmMain.FormCreate(Sender: TObject) in my main form.
How can I trace this to find out what the hell is causing the Windows Error.
Of course the Windows Error report contains a long listing of information. Where can I look in that to find the cause or at least a clue on the cause of the error.
This error has now stopped all development work (and ruined my weekend) so I urgently need to fix this.
The most straightforward route to take would be to include a product like MadExcept or JCL Debugger into your application, to get a full call stack (including line number) of the point of failure. We've rolled our own years ago, and it has been a tremendous help in situations like this.
One alternative, but lots more cumbersome, would be to generate a MAP file from your project, use MAP2DBG to generate a .MAP file, and use the Windows Debbuging Tools to get about the same information. This approach is a lot more hardcore, and only advisable if you really want to learn a lot about the internals of windows debugging (and enjoy working with arcane tools).
Another alternative would be to attach to the failing application from your development environment using Remote Debugging. Only applicable if you have a fair amount of control over the failing machines.
#user576639, here are some debugging ideas:
Look into the System's Event Viewer
If you got the exe has encountered a problem and needs to close chances are you'll find something about it in the System's Event Viewer. That should be your first step.
Any special DLL's required?
Do you need MIDAS.DLL?
Are you using an database engine? Does it require some sort of client library?
I'm talking from experience here: My development machine obviously has all the libraries I might need. Most of my clients also have most of those libraries because they have my software installed. At times I put out small helping applications that don't go throw extensive testing and they fail to work on SOME machines but work fine on other machines. Why? I used TClientDataset and forgot to include MIDAS.DLL with the application; Or the application is trying to access a Firebird SQL server but the user doesn't have Firebird client library installed.
Printer driver issues
Boy I hate Delphi's printer handling. Also hate buggy printer drivers, haven't made up my mind about what's worst. If you have something on your main form that might be requesting information about the default Windows printer (example: an REPORT) give this a try: Install an sane/simple printer and set it as the default printer. If the user has Office 2007+ installed, set the "Microsoft XPS Document Writer" the default printer.
I have seen bad printer driver + delphi issues manifest themselves with the "exe needs to close" symptom.
Prepare an special build of your application
If you got this far without fixing your issue it's time to create an special build of your application that's capable of providing more information. First of all I'd try adding this to your DPR file; Don't know if this is still useful for Delphi 2010 but it did help me see some early exceptions with a Delphi 7 application:
function HandleUnhandledException:integer;stdcall;
begin
Result := 1; // 1 = EXCEPTION_EXECUTE_HANDLER
end;
// and then immediately after "begin" in your DPR file:
begin
SetUnhandledExceptionFilter(#HandleUnhandledException);
// ... the usual stuff goes here
end;
Add some ShowMessage-s to your Main Form's code, in your OnCreate handler (if you have one), in your Create constructor (again, if you have one). If you're adding an ShowMessage to your Create destructor, make sure it's after the "inherited" call. This will help pin-point how far the loading of the form goes before it fails.
If all else fails...
Create a new, blank form; Make it the new Main Form (so it's initialized before your former Main Form). Test it on the client's machine - does it show up? It most likely will, if it doesn't you've got some serious problems.
Start copying the components from the former main form to the new main form; Only the components need to be copied, not the code: Your error is probably caused by some component failing to initialize properly. Make sure no component has "Active=True"! Copy the components in small batches, test often. If you spot the component that causes your form not to load on the client's computer, tell us about it and we'll try to help.
If you manage to get all your components on the new form, write an OnCreate handler that sets Active := True for all the components that need that. Did that fix the issue?
If you got this far then all the components you used on your main form can load properly. The problem's related to YOUR CODE. Start copying all the code from your old main form to your new main form, in small bits, and test. You're bound to find the peace of code that causes your application to stop loading.
Use dependency walker to see if you're missing a required DLL.
You can use information from system reporting (your error and suggestion to send it ) with Error Report Grabber ( http://www.maxerist.net/main/soft-for-win/err-rep-grabber ). I developed this tool when I desperately needed to track a error that appeared very rarely so almost non-reproducible. It helped me to track the information from stack to find actual place in the code.
The tool works only on XP (MS removed this dialog in Win7 and probably Vista), but I see that your cases are XP so this can help.
UPDATE: if you're not familiar with assembler and everything, this can work like this.
You should compile you program and don't change anything. Save the report on a bad machine, copy the file to your developer machine and open to view the contents. Look at the stack of your main thread in the report and find numbers more than $00400000, they're usually the addresses inside the procedures that called some other procedure and wait for return. In your developer machine, start the program and stop at any line, open CPU Window and on the main list with assembler instruction right-click and choose go to address, enter this address. You will see other assembler lines, but wrapped with pascal constructions you can probably recognize as yours
Thanks a lot for the help.
In the end I reverted to a recent backup and traced it down to a particular form.
I did not actually find the error, which is a bit worrying, but in any case I am back up and running (phew!!)
I made the error to occur on my development machine also, when, and only when, I use my install program (Inno Setup) to compile a setup.exe and which installs the exe as well as installing postgreSQL. Seems really strange, as though there is a problem with the setup compiler. In any case I have not seen the error again. I guess it will remains a mystery, like women.
In Delphi withing debugging options select debug dcu's, this will allow you to debug into the Delphi source code for TForm and its descendants and you may be able to track down a more likely culprit.
Set a breakpoint on
Application.CreateForm(TfmMain, fmMain); //FAILS HERE
and then step into the code to see where the issue is.
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}