Can't reference dll

P

Parrot

I get an error when trying to add a reference to a DLL program from a Realia
COBOL program that is 32 bit. The error message says "Please make sure the
file is accessible and that it is a valid assembly or COM component. I can
access this file using C++ but not C#. My COBOL DLL program passes data by
reference. My coding is shown below:

[DllImport("progcmp1.dll", CharSet=CharSet.Auto, EntryPoint="TRANPROG",
CallingConvention=CallingConvention.StdCall)]
public static extern void TRANPROG(string parms);

private void OnSubmit(object sender, EventArgs e)
{
StringBuilder parms = new StringBuilder("00000000", 87);
TRANPROG(parms.ToString());
}
 
J

jp2msft

Just a thought:

You might want to try sending your info as a reference also.

[DllImport("progcmp1.dll", CharSet=CharSet.Auto, EntryPoint="TRANPROG",
CallingConvention=CallingConvention.StdCall)]
public static extern void TRANPROG(ref string parms);

private void OnSubmit(object sender, EventArgs e)
{
StringBuilder parms = new StringBuilder("00000000", 87);
string strParams = params.ToString();
TRANPROG(ref strParms);
}
 
J

Jeroen Mostert

Parrot said:
I get an error when trying to add a reference to a DLL program from a Realia
COBOL program that is 32 bit. The error message says "Please make sure the
file is accessible and that it is a valid assembly or COM component.

You can't add a reference to a DLL to your project unless it's an assembly
or a COM library. If you want to access a DLL that's neither, simply copy it
to an accessible place (the \bin directory of your application, for
example). Do not add it as a reference.
 
J

jp2msft

Mr. Mostert:

I'm curious: If you don't add a DLL to your project and include it in the
\bin folder instead... how do you call it?

I have no experience in this, but someone at work recently came asking me
how to do something very similar.
 
B

Ben Voigt [C++ MVP]

jp2msft said:
Mr. Mostert:

I'm curious: If you don't add a DLL to your project and include it in
the \bin folder instead... how do you call it?

The name of the DLL is the first argument to the DllImport attribute, you
can also specify the exported name using the EntryPoint property of
DllImport.

This along with the function signature enables .NET to call the function
through p/invoke.
 
P

Parrot

Thanks for you replies. I added the reference parameter suggested by Jp2msft
and moved my progcmp1.ddl and progcmp1.lib files into my bin directory and I
still get the error message saying 'Unable to load DLL 'progcmp1.dll': The
specified module could not be found. I really want this to work as I want to
call an older COBOL program from C# rather than having to rewrite everything.
What bothers me is that I can call this program ok from a C++ program but
not from C# program. Something got lost in the upgrade to C#. Surely there
are other COBOL programmers who want to do what I want to do. Any other
suggestions?

Dave
 
J

jp2msft

Did you try Mr. Voigt's suggestion of dropping your DLL into the \bin folder?

I'm guessing if placed "progcmp1.dll" in the bin folder, your P/Invoke call
below might work.

[DllImport("progcmp1.dll", CharSet=CharSet.Auto, EntryPoint="TRANPROG",
CallingConvention=CallingConvention.StdCall)]
public static extern void TRANPROG(string parms);
 
P

Parrot

Yes,
I did put my program in the bin folder and I still get an error saying it
can't find the program.
Dave

jp2msft said:
Did you try Mr. Voigt's suggestion of dropping your DLL into the \bin folder?

I'm guessing if placed "progcmp1.dll" in the bin folder, your P/Invoke call
below might work.

[DllImport("progcmp1.dll", CharSet=CharSet.Auto, EntryPoint="TRANPROG",
CallingConvention=CallingConvention.StdCall)]
public static extern void TRANPROG(string parms);

Parrot said:
Thanks for you replies. I added the reference parameter suggested by Jp2msft
and moved my progcmp1.ddl and progcmp1.lib files into my bin directory and I
still get the error message saying 'Unable to load DLL 'progcmp1.dll': The
specified module could not be found. I really want this to work as I want to
call an older COBOL program from C# rather than having to rewrite everything.
What bothers me is that I can call this program ok from a C++ program but
not from C# program. Something got lost in the upgrade to C#. Surely there
are other COBOL programmers who want to do what I want to do. Any other
suggestions?

Dave
 
B

Ben Voigt [C++ MVP]

jp2msft said:
Did you try Mr. Voigt's suggestion of dropping your DLL into the \bin
folder?

That wasn't actually my suggestion.

My recommended next steps in troubleshooting would be to run Process Monitor
from the sysInternals division of Microsoft and find out where .NET is
looking for the DLL.

IIRC you have an ASP.NET project? If so, I think that code-behind files are
compiled to a different location than precompiled assemblies. If the
DllImport is in a codebehind file try moving it into a class library
project.

If you have a client-side project (not ASP.NET) then the dll needs to go
into the directory containing the executable, either $ProjectDir\bin\Release
or $ProjectDir\bin\Debug, not just bin.

Of course you could also add the directory containing the DLL to your path
(system path for ASP.NET, user path for client-side) or move the DLL into a
directory already listed in the path.
I'm guessing if placed "progcmp1.dll" in the bin folder, your
P/Invoke call below might work.

[DllImport("progcmp1.dll", CharSet=CharSet.Auto,
EntryPoint="TRANPROG", CallingConvention=CallingConvention.StdCall)]
public static extern void TRANPROG(string parms);

Parrot said:
Thanks for you replies. I added the reference parameter suggested
by Jp2msft and moved my progcmp1.ddl and progcmp1.lib files into my
bin directory and I still get the error message saying 'Unable to
load DLL 'progcmp1.dll': The specified module could not be found.
I really want this to work as I want to call an older COBOL program
from C# rather than having to rewrite everything. What bothers me
is that I can call this program ok from a C++ program but not from
C# program. Something got lost in the upgrade to C#. Surely there
are other COBOL programmers who want to do what I want to do. Any
other suggestions?

Dave
 
P

Parrot

I change my approach to trying to call a C++ program with no arguments to
pass. I compiled the C++ DLL program and it created a
mydll.intermediate.manifest file whatever the heck that is. I copied the dll
file to my bin directory and in my calling program I inserted the following
code:

[DllImport("c:\\apps\\callprog\\callprog\\bin\\mydll.dll.intermediate.manifest", EntryPoint = "TRANS", SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern void TRANS();

With this code I get the following error: An unhandled exception of type
'System.BadImageFormatException' occurred in callprog.exe

Additional information: An attempt was made to load a program with an
incorrect format. (Exception from HRESULT: 0x8007000B)

So now I can't even call a C++ program with no arguments. What are you
supposed to be able to call from a C# program. I am ready to give up on this
as I can't believe it should be so hard to call one program from another. In
COBOL and C++ its a snap, in C# it seems impossible. Is that progress?
Dave

Ben Voigt said:
jp2msft said:
Did you try Mr. Voigt's suggestion of dropping your DLL into the \bin
folder?

That wasn't actually my suggestion.

My recommended next steps in troubleshooting would be to run Process Monitor
from the sysInternals division of Microsoft and find out where .NET is
looking for the DLL.

IIRC you have an ASP.NET project? If so, I think that code-behind files are
compiled to a different location than precompiled assemblies. If the
DllImport is in a codebehind file try moving it into a class library
project.

If you have a client-side project (not ASP.NET) then the dll needs to go
into the directory containing the executable, either $ProjectDir\bin\Release
or $ProjectDir\bin\Debug, not just bin.

Of course you could also add the directory containing the DLL to your path
(system path for ASP.NET, user path for client-side) or move the DLL into a
directory already listed in the path.
I'm guessing if placed "progcmp1.dll" in the bin folder, your
P/Invoke call below might work.

[DllImport("progcmp1.dll", CharSet=CharSet.Auto,
EntryPoint="TRANPROG", CallingConvention=CallingConvention.StdCall)]
public static extern void TRANPROG(string parms);

Parrot said:
Thanks for you replies. I added the reference parameter suggested
by Jp2msft and moved my progcmp1.ddl and progcmp1.lib files into my
bin directory and I still get the error message saying 'Unable to
load DLL 'progcmp1.dll': The specified module could not be found.
I really want this to work as I want to call an older COBOL program
from C# rather than having to rewrite everything. What bothers me
is that I can call this program ok from a C++ program but not from
C# program. Something got lost in the upgrade to C#. Surely there
are other COBOL programmers who want to do what I want to do. Any
other suggestions?

Dave

:

Parrot wrote:
I get an error when trying to add a reference to a DLL program
from a Realia COBOL program that is 32 bit. The error message
says "Please make sure the file is accessible and that it is a
valid assembly or COM component.

You can't add a reference to a DLL to your project unless it's an
assembly or a COM library. If you want to access a DLL that's
neither, simply copy it to an accessible place (the \bin directory
of your application, for example). Do not add it as a reference.
 
J

Jeroen Mostert

Parrot said:
I change my approach to trying to call a C++ program with no arguments to
pass. I compiled the C++ DLL program and it created a
mydll.intermediate.manifest file whatever the heck that is.

It's just the manifest file (doesn't matter unless you're on Vista). If you
don't have a DLL file, your build either didn't succeed or the file's in
another directory. Check bin\debug and bin\release.
I copied the dll file to my bin directory and in my calling program I
inserted the following code:

[DllImport("c:\\apps\\callprog\\callprog\\bin\\mydll.dll.intermediate.manifest",

Well, "mydll.dll.intermediate.manifest" is not a DLL. Reference "mydll.dll"
instead.
So now I can't even call a C++ program with no arguments. What are you
supposed to be able to call from a C# program. I am ready to give up on this
as I can't believe it should be so hard to call one program from another. In
COBOL and C++ its a snap, in C# it seems impossible. Is that progress?

If at first you don't succeed, get a better understanding of what you're
doing and try again.

The DLL you reference in the DllImport attribute:

- Must be a valid Win32 DLL file. It must be 32-bit if your executable is
32-bit and 64-bit if your executable is 64-bit.

- Must be reachable when the executable runs. That means it must be in the
executable's search path. See http://msdn.microsoft.com/library/7d83bc18.
Basically, copying the file to the same directory where your executable
resides should do the trick.

- Should not use an absolute path but rely on the search path instead.
Otherwise you tie your application to one particular path.

These rules are not specific to C#. You may have found it easier in C++ and
COBOL because these environments take care of putting the right file in the
right place for you.
 
C

Chris Dunaway

Thanks for you replies. I added the reference parameter suggested by Jp2msft
and moved my progcmp1.ddl and progcmp1.lib files into my bin directory and I

This says you have a .ddl and .lib file in your bin directory. Do you
have a ".dll" file? As far as I'm aware, .Net cannot p/invoke a .ddl
or .lib file.

If you have the .dll in the correct location and the p/invoke
signature in your C# code correct, then it should just work.

Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top