External DLL 32bit vs 64bit

JeFernando

New Member
Hello Guys,

I am having a weird problem with installing external DLL. My Process architecture is 64 bit with Progress version 12. As my ABL application uses crystal reporting tool which only support 32bit, it is set to use prowin32.exe instead of prowin.exe and I am assuming progress doesn't have issue with that, running different prowin version on different OS architecture.

Now the problem from here gets complicated. My 32bit DLL is not working as appbuilder is rejecting it because of different architecture. Now when I build 64bit DLL, appbuilder accepts that DLL but my ABL application rejects it in runtime because its running 32bit and gives the System.BadImageFormatException error.

Even using 'ANY CPU' doesn't helps, because when using Assemblies Reference tool, 64 bit code is loaded into 64 bit process and 32 bit code is loaded into a 32 bit process. So technically any cpu is of no use here.

I could though use Assemblies Reference tool and add 64bit DLL and then replaced the actual DLL file without touching assemblies to 32bit. This works and my application runs the code, but problem comes when I start to compile the code as again app builder will search for right DLL.

Theoretically I should be able to do this programmatically using a simple validation of PROCESS-ARCHITECTURE and PROVERSION keywords to which DLL to be used, but how to do this using these limitation and the way progress handles external DLL.

Sorry for long post, any direction will be highly appreciable.
 

TomBascom

Curmudgeon
In ProTop I take your last approach. lib/windows.p decides, at runtime, which libraries to use:
Code:
/* lib/windows.p
 *
 * select the correct PP to support windows kernel calls
 *
 */

if opsys begins "win" then
  do:

  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    run lib/windows32.p persistent.
  &ELSE
    if process-architecture = 64 then
      run lib/windows64.p persistent.
     else
      run lib/windows32.p persistent.
  &ENDIF

  end.

return.

Code:
/* lib/windows32.p
 *
 * windows kernel calls
 *
 * use this when _progres is a 32 bit executable
 *
 */

session:add-super-procedure( this-procedure ).
  
return.
  
  
PROCEDURE CreateProcessA EXTERNAL "kernel32.dll":
  DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
  DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
  DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
  DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
  DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
  DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
  DEFINE INPUT  PARAMETER lpEnvironment        AS LONG.
  DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.
  DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG.
  DEFINE INPUT  PARAMETER lpProcessInformation AS LONG.
  DEFINE RETURN PARAMETER bResult              AS LONG.
end procedure.
    
procedure OpenProcess external "kernel32.dll" :
  define input  parameter desiredAccess as long.
  define input  parameter inheritFlag   as long.
  define input  parameter pid           as long.
  define return parameter procHdl       as long.
end procedure.
 
/* etc... download protop from https://wss.com/protop if you want to see all of the gory details */


Code:
/* lib/windows64.p
 *
 * windows kernel calls
 *
 * use this when _progres is a 64 bit executable or when running source
 *
 */

&IF "{&PROCESS-ARCHITECTURE}" = "64" &THEN
  &global-define XINT           int64
  &global-define LONGINT        int64
  &global-define PUTLONGINT     PUT-INT64
  &global-define GETLONGINT     GET-INT64
 &ELSE
  &global-define XINT           integer
  &global-define LONGINT        long
  &global-define PUTLONGINT     PUT-LONG
  &global-define GETLONGINT     GET-LONG
&ENDIF
  
session:add-super-procedure( this-procedure ).
  
return.
  
  
procedure CreateProcessA external "kernel32.dll":
    define input  parameter lpApplicationName    as {&LONGINT}.
    define input  parameter lpCommandline        as character.
    define input  parameter lpProcessAttributes  as {&LONGINT}.
    define input  parameter lpThreadAttributes   as {&LONGINT}.
    define input  parameter bInheritHandles      as {&LONGINT}.
    define input  parameter dCreationFlags       as {&LONGINT}.
    define input  parameter lpEnvironment        as {&LONGINT}.
    define input  parameter lpCurrentDirectory   as {&LONGINT}.
    define input  parameter lpStartupInfo        as {&LONGINT}.
    define input  parameter lpProcessInformation as {&LONGINT}.
    define return parameter bResult              as {&LONGINT}.
end procedure.


procedure OpenProcess external "kernel32.dll" :
    define input  parameter desiredAccess as {&LONGINT}.
    define input  parameter inheritFlag   as {&LONGINT}.
    define input  parameter pid           as {&LONGINT}.
    define return parameter procHdl       as {&LONGINT}.
end procedure.

/* etc... download protop from https://wss.com/protop if you want to see all of the gory details */
 

JeFernando

New Member
Thanks Tom, this is great. Only thing is I believe the external keywords post v10.2 won't work on the .NET (forgot to mention that before) libraries code as it will give that entry point error. I can use .tlb files but then the issue remains the same.
I want to code just like lib/windows.p and decide at runtime which libraries to use, but I am afraid there is no way to load .NET DLL libraries programmatically as assemblies.xml are loaded at startup.

Thanks Again
 

TomBascom

Curmudgeon
ProTop also has some DotNet specific code in lib/setpt3dir.p that was provided by Mike Fechner at Consultingwerk.

It works a bit differently though - it uses pre-processor stuff, loads classes ad is xcoded rather than compiled.
 

Cringer

ProgressTalk.com Moderator
Staff member
Which OE12 version specifically? OE12.2.5 has, I believe, had the 32bit AppBuilder re-inserted. All other OE12 versions only have 64 bit AppBuilder.
 

JeFernando

New Member
Which OE12 version specifically? OE12.2.5 has, I believe, had the 32bit AppBuilder re-inserted. All other OE12 versions only have 64 bit AppBuilder.
That is right, its OE 12.0 and has 64bit AppBuilder.
I did a workaround by making my AppBuilder to use prowin32 and hence when adding DLLs the 32 bit architecture is created in assemblies and as my ABL application is already in 32bit, I am not getting any error or issue and DLLs are working as expected.
Only thing is I am not sure is whether its a good idea to convert 32bit Appbuilder instead of original 64bit. Hoping it won't cause any other issues in the system.
 

JeFernando

New Member
Which OE12 version specifically? OE12.2.5 has, I believe, had the 32bit AppBuilder re-inserted. All other OE12 versions only have 64 bit AppBuilder.
Hello, Do you know any specific reason for that change to 32bit in OE12.2.5 or any changelog link I can refer to? Can't find it on the OE website.
 
Top