What are the non-obvious reasons a 32-bit app would fail on a 64-bit machine?
We have a 32-bit library written and compiled in Borland Delph开发者_StackOverflow中文版i. This library is referenced by various other projects including a WCF Web Service hosted in IIS. The web service is compiled using the x86 option and everything works fine on a 32-bit machine. However, on our 64-bit server the service fails when calling into the 32-bit Delphi library. Some of our clients are even having problem with 32-bit .NET Forms calling into the library on a 64-bit machine; though we have not been able to duplicate that particular problem.
So, does anyone know why .NET code compiled with 32-bit option would still fail while calling a non-.NET 32-bit library on a 64-bit machine?
Well, just a wild guess :)
Do you have more than one process interacting?. Does these processes try to write/read to protected folders (for instance %PROGRAMFILES%, %WINDIR%)? (i.e, does these processes use files in such folders as a IPC ?)
Since 64 bits Windows will redirect writes to such folders for 32 bit apps (on a per user base) if the processes run under different user credentials these processes may be just failing to find a file created by the other process.
I'm guessing you're defining the entry point of the method on the .NET side something like this?
internal static class Delphi
{
[DllImport("delphi32bitlibrary.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool Encrypt(
IntPtr parameter1,
string parameter2,
out string parameter3);
}
and then you call it somewhere in a similar fashion?
string encryptedString;
Delphi.Encrypt(IntPtr.Zero, "test", out encryptedString);
If that is the case (your mileage may vary in the actual implementation), can you rewrite it as such:
string encryptedString;
try
{
Delphi.Encrypt(IntPtr.Zero, "test", out encryptedString);
}
catch (Exception ex)
{
EventLog log = new EventLog();
log.WriteEntry(ex.Message + "\n" + ex.StackTrace, EventLogEntryType.Error);
}
This should put in the computer's event log a detailed explanation of what happened when the 32-bit piece was called. From there, you (and possibly us) can get some good evidence as to what may be failing.
Heap corruption! Apparently there is a flag called HeapEnableTerminationOnCorruption that was not previously enabled by default. As a new feature in Windows Vista, the IIS worker process terminates when the heap corruption is detected. So, it only APPEARED to be working in our stand-alone apps and on our 32-bit Windows XP machines, when in actuality it was simply ignoring the error.
To fix the problem we changed our code for calling into the Delphi libraries to use IntPtrs and pass data back using out parameters. For example:
public string CallDLL(string sTest)
{
string s = "";
IntPtr p1 = Marshal.StringToHGlobalAnsi(sTest);
s = Marshal.PtrToStringAnsi(p1);
if (p1 != IntPtr.Zero)
{
Class1.TestDLL(out p1);
s = Marshal.PtrToStringAnsi(p1);
}
Marshal.FreeCoTaskMem(p1);
return s;
}
Hope this helps anyone with the same issue.
精彩评论