• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Resolved System.dll Notfoundexception: Unable To Load Dll

Cecil

17+ years progress programming and still learning.
#1
OS: Windows 10 64bit
OE: 11.7.1

I'm calling .NET object but I believe the .NET object is then calling another .dll file (MMMReaderHighLevelAPI.dll). I have the offending .dll but where should it go?

Screen Shot 11-21-17 at 02.18 PM.PNG

So far I have put the offending .ddl in the working directory and C:\windows\system32

What is the order in which it tries to find .dll files?

Here is my code.

Code:
USING MMM.Readers.QA.*                  FROM ASSEMBLY.
USING MMM.Readers.QA.FullPage.*         FROM ASSEMBLY.
USING MMM.Readers.QA.Interop.*          FROM ASSEMBLY.

DEFINE VARIABLE i AS INTEGER     NO-UNDO.

DO ON ERROR UNDO, THROW: 

    MMM.Readers.FullPage.Reader:EnableLogging(true, 1, -1, "HLBlockingExample.Net.log"). /** <--- fails here!! **/
    
    
    

    CATCH e AS Progress.Lang.Error :
    
              DO i = 1 TO e:NumMessages:
            
            MESSAGE e:GetMessage(i)
                VIEW-AS ALERT-BOX ERROR TITLE "SCANNER Error".     
        
        END.
    
    END CATCH.       
END.
 

RealHeavyDude

Well-Known Member
#2
As far as I know, all assemblies you want to use in a .NET or ABL for .NET project must be installed in the Windows assembly cache. The assembly cache is usually located C:\Windows\assembly. From what I know the installation of the 3rd part product should install it there.

Plus, you need to add the assembly to your ALB project - must be registered in the asemblies.xml file whose location you specify with the -assemblies startup parameter.

So far I my only need to dig into this was for a project where we used the CrystalReports .NET objects for reporting based on ProDataSets.


Hope that helps, RealHeavyDue
 

Cringer

ProgressTalk.com Moderator
Staff member
#3
What RHD says sounds logical, but in terms of DLLs, it depends if this is 32bit or 64bit. If it's 32 bit then it (confusingly) needs to go in c:\windows\syswow64
 

Cecil

17+ years progress programming and still learning.
#6
What RHD says sounds logical, but in terms of DLLs, it depends if this is 32bit or 64bit. If it's 32 bit then it (confusingly) needs to go in c:\windows\syswow64
The whole SDK is 64bit, as is the OS and OE.
 

Cecil

17+ years progress programming and still learning.
#7
As far as I know, all assemblies you want to use in a .NET or ABL for .NET project must be installed in the Windows assembly cache. The assembly cache is usually located C:\Windows\assembly. From what I know the installation of the 3rd part product should install it there.

Plus, you need to add the assembly to your ALB project - must be registered in the asemblies.xml file whose location you specify with the -assemblies startup parameter.

So far I my only need to dig into this was for a project where we used the CrystalReports .NET objects for reporting based on ProDataSets.


Hope that helps, RealHeavyDue
I was using the proasmref utility (Assembly Reference) and using the -assemblies client parameter. But the ABL session was still unable to instantiate the .NET objects.
My solution was to use the
gacutil.exe command line tool from .NET to place the .NET objects into the 'Global Assemblies' list, the ABL session was then able it access the .NET objects. I think that's where is copies the .NET .dll files to C:\Windows\assembly.

Here is a code I used to test whether the ABL is able to load/instantiate the .NET objects in the current session. I think this code could be useful for others applications which use .NET objects to test the current application's status before it could crash due other dependent objects not being available at runtime.

(I found the intial code on KBase)

Code:
/** gacutil.exe -i MMMReaderDotNet40.dll **/
/** gacutil.exe -i MMMReaderDotNet40QA.dll **/
/** gacutil.exe -i MMMReaderDotNet20.dll **/
/** gacutil.exe -i MMMReaderDotNet20QA.dll **/

USING System.*.
USING System.Reflection.*.
 
DEFINE VARIABLE checkAssembly AS Assembly.

DEFINE VARIABLE i AS INTEGER     NO-UNDO.

DO ON ERROR UNDO, THROW:
    checkAssembly = Assembly:ReflectionOnlyLoad("MMMReaderDotNet40, Version=4.3.3.0, Culture=neutral, PublicKeyToken=628dd6318974115c").
    CATCH e AS Progress.Lang.Error :
    /* handle exceptions if needed. For this example, it's enough to check if the
       reference returned is valid - if it is the assembly can be loaded. */
     
        DO i = 1 TO e:NumMessages:
           
            MESSAGE e:GetMessage(i)
                VIEW-AS ALERT-BOX ERROR TITLE "Error".    
       
        END.
     
    END CATCH.
END.

IF VALID-OBJECT(checkAssembly) THEN
DO:
    /* insert appropriate code here. For example, set application-wide flags to check
       in order to enable/disable specific features. */
    MESSAGE "assembly can be loaded" VIEW-AS ALERT-BOX.
END.
 

Cecil

17+ years progress programming and still learning.
#8
MY SOLUTION was to put the applications SDK folder location into Windows' PATH environment parameter. To me, this seems to be a bit of a hack and here is why?

According to MSDN about the order of process in finding a DLL is a follows:

  1. .DLL located in the same directory as the executable.
  2. .DLL located in the working directory of the application .i.e. WRK
  3. .DLL located in the WINDOWS SYSTEM FOLDER i.e. C:\Windows\System32 (let's not get hung up about 32/64bit )
  4. .DLL located in the WINDOWS root directory C:\Windows
  5. .DLL found in the PATH environmental variable.
The MMMReaderHighLevelAPI.dll was copied to the %DLC%\bin folder and the WRK folder, C:\WINDOWS\SYSTEM32 and none of these worked until I made changes to the PATH environmental variable.

So now as part of the deployment, I have to make sure the PATH environmental variable is updated to include the folder location od the SDK. It seems like I should not have to do this.
 

RealHeavyDude

Well-Known Member
#9
That's a behavior on Windows which I don't like: Everybody's need to put everything into the Windows PATH. If you display the PATH variable on a typical Windows system you will find all kinds of crap on it. This is, where I think, Progress is superior with the PROPATH ...