Windows API calls from managed code

I followed the instructions from this link:

I tried setting a procedure-pointer to the Windows libraries in order to load them but I get error 173 when executing the set procedure pointer statements.

For example:  set pp to entry "kernel32.dll".

I had to set up project references to the libraries in my SysWOW64 folder.  Does anyone know why setting a procedure-pointer isn't working?

This happens even if I include SywWOW64 in the path.

  • Hi Phil,

    You shouldn't get a 173 error on the set statement but you might get a 173 on the call of the WinAPI function if the .dll wasn't loaded correctly.

    I just tested this here and although the set proc-pointer method used to work it no longer appears to in 2.3.2.

    The recommended way to get these loaded now is actually to use the compiler directive ilpinvoke which is the same thing as adding a project reference but you only require the base name of the .dll and then the correct bitism will be loaded at run-time:

    $set ilpinvoke"kernel32"

  • The set proc-pointer approach should work but you should add the $set noilnative directive to your program. When I add this to my example it will load kernel32 ok.

    Please note that when you load a non-COBOL .dll such as kernel32.dll in this manner using managed code, the pointer variable might still be set to null even when it is successful. This is because it is looking for a main entry point with the same name as the .dll and if it doesn't exist it will be set to null. Therefore it is difficult to check if the load was successful prior to calling the actual function.

  • After coding the following, the WinAPI call works although I get the exception below in my event log when I execute "SET MYPOINTER":

         $set noilnative

         $set ilpinvoke"kernel32"

         $set ilpinvoke"gdi32"

          01 MYPOINTER                            PROCEDURE-POINTER.

           SET MYPOINTER TO ENTRY "kernel32.dll"

    "Could not load file or assembly 'file:///C:\windows\system32\kernel32.dll' or one of its dependencies. The module was expected to contain an assembly manifest."

  • Verified Answer

    Your first suggestion produced no errors.  I really don't need to set a procedure pointer.  I only needed to add these lines to the top of the program:

         $set ilpinvoke"kernel32"

         $set ilpinvoke"gdi32"

  • You should do either the $set ilpinvoke"kernel32" or the set proc-pointer statement but not both.

  • "set ilpinvoke" was working for VC 2.3.1 but we just installed 2.3.2 and I now get this compile error:

    "ILPINVOKE invalid or not allowed here".

    So I removed the ilpinvoke set statements and added "set noilnative" and tried using a procedure pointer

    to load kernel32.dll.  I also added a project reference to it in SysWOW64.  I'm now getting this exception when setting the procedure pointer:


    Could not load file or assembly 'file:///S:\V63\AWCBL\DEBUG\kernel32.dll' or one of its dependencies. The module was expected to contain an assembly manifest.

    Even though I get an exception, the WINAPI calls work but I get a run time error when exiting our application:

    "MgLoad has stopped working".  MgLoad is the managed driver for our application and is the first program called.

    I would like to get the "set ilpinvoke" statement working again, like it did for VC 2.3.1.

  • Hi Phil,

    Please open up a support incident for this as ilpinvoke works fine for me here in 2.3 U2. It sounds as if your path has been corrupted or perhaps you inadvertently changed your project type from x86 to x64 or anyCPU?