It is running now! No more TypeInitializationException when running as a Web Site Web service DLL from a remote host IIS 7.5 w3wp.exe. For that I went back to simple Pascal DLL.
namespace ToolboxPAS;
interface
uses
System;
VAR
Stop_Time: String := "1949.Mar.19";
implementation
end.
because I found out, that what ever I have coded, the effect is always the same; TypeInitializationException when run from a Web Server but not in Unit Test Environments from VS 2012 Ultimate. Or when used local being called by an EXE or any other DLL.
The code builds; then you take ILSpy and look at the emitted C# code.
It looks like that for ToolboxPAS.pas when looking at the __Global class
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ToolboxPAS
{
[CompilerGenerated]
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
public static class __Global
{
public static string Stop_Time = "1949.Mar.19";
}
}
and when looking at the variable emitted it looks as
// ToolboxPAS.__Global
public static string Stop_Time = "1949.Mar.19";
So I am creating a ToolboxCS.cs project, coming as close as possible to the code emitted by ILSpy as C#
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ToolboxCS
{
[CompilerGenerated]
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Auto)]
public static class __Global
{
public static string Stop_Time = "1949.Mar.19";
}
}
I tested both, doing local VS Unit Test, they behave the same. I build my large Web Site Web Service Project and deployed it to IIS 7.5 SpezplaWebService. Under .\bin I watched the two new small DLL’s ToolboxPAS.DLL and ToolboxCS.DLL. Then I started the code and it succeeds in the try catch block for the first line of code but fails with the known exception for the second line of code.
try
{
payout.wscol.get_Item("wsout").Add("stCS",ToolboxCS.__Global.Stop_Time);
payout.wscol.get_Item("wsout").Add("stPAS", ToolboxPAS.__Global.Stop_Time);
} catch (Exception ex)
{
payout.wscol.get_Item("wsout").Add("Exception", ex.Message);
payout.wscol.get_Item("wsout").Add("InnerExce", ex.InnerException.Message);
return false;
}
The InnerException.Message was a
Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
which was wrapped into a TypeInitializationException and sent back to the client.
So what is the difference in code ? NONE
I went for the assembly files in ILSpy and compared the two AssemblyInfos files emitted and found differences.
I made the content of the ToolboxPAS AssemblyInfos the same as the one for ToolboxCS.
I generated a new GUID because there was none, but that had no effect.
Now:
the AssemblyInfos for ToolboxPAS looks
namespace ToolboxPAS;
interface
uses
System,
System.Diagnostics,
System.Reflection,
System.Runtime.CompilerServices,
System.Runtime.InteropServices,
System.Runtime.Versioning,
System.Resources;
[assembly: AssemblyTitle("ToolboxPAS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("AXA Technology Services GmbH")]
[assembly: AssemblyProduct("ToolboxPAS")]
[assembly: AssemblyCopyright("Copyright © AXA Technology Services GmbH 2015")]
[assembly: AssemblyTrademark("")]
//[assembly: AssemblyCulture("")]
[assembly: CompilationRelaxations(8)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default or
DebuggableAttribute.DebuggingModes.DisableOptimizations or
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints or
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("D290EB86-1975-48F3-A3A5-DD2A96ECB700")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory, which in Oxygene by default is the
// same as the project directory. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile('mykey.snk')]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile('')]
//[assembly: AssemblyKeyName('')]
implementation
end.
In short;
I commented out all line not also emitted by the CS compiler, and added all the ones missing !
And since I made all that changes it runs perfect !
I still need to track down, which of this assembly statements needs to be emitted mandatory or dropped mandatory to make a DLL run under an IIS 75 without raising an TypeInitializationException. I have to do this because my other DLL’s written in Oxygene show the same TypeInitializationException when called the first time for what ever reason.
your feedback is very welcome.
Josef