Make a DLL in C# for FoxPro

C

CSLCO

Hello,

I'm beginner in C#, and I want to make several function in a C# DLL,
whiches I can call from FoxPro 9.0.

I try something like that :
FOR the DLL in C# :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;

namespace CmFox
{
public class CarteReseau
{
//using System.Net.NetworkInformation;

public CarteReseau()
{
}
public static string MacAdresse()
{
string resultat = "";
IPGlobalProperties computerProperties =
IPGlobalProperties.GetIPGlobalProperties();
NetworkInterface[] nics =
NetworkInterface.GetAllNetworkInterfaces();
if (nics == null || nics.Length < 1)
{
resultat += String.Format(" No network interfaces
found.");
return (resultat);
}
foreach (NetworkInterface adapter in nics)
{
IPInterfaceProperties properties =
adapter.GetIPProperties();
resultat +=
String.Format("{0}",adapter.GetPhysicalAddress().ToString());
}
return (resultat);
}

}
}

-------------------------------------------------------------------------
-------------------------------------------------------------------------
And this code in FoxPro :

declare string CarteReseau.MacAdresse in cmfox.dll as ReadMac ;
Activate Screen
? ReadMac()
-------------------------------------------------------------------------

And Fox Pro returns me a "No entry point for CarteReseau.MacAdresse in
CmFox.dll"


Could you help me

Thanks fo that
 
N

Nicholas Paldino [.NET/C# MVP]

CSLCO,

You will need to expose your class as a COM object (specifically, a
scriptable automation COM object) and then create instances of it in FoxPro
with the CreateObject function.
 
N

Nicholas Paldino [.NET/C# MVP]

Andrus,

VFP can not consume .NET components directly. You have to use a
bridging technology such as COM interop, as both .NET and VFP support the
creation/consumption of COM components (in this case, all that is needed is
for .NET to support the creation of COM components and for VFP to support
the consumption of them).

Your links don't support the idea that VPF can support consuming .NET
components directly. The first is a link to an ASP.NET-like environment
which is implemented on top of FoxPro. The second link shows how to consume
VFP functions in .NET (VB.NET specifically) and it is through COM interop.
 
A

Andrus

VFP can not consume .NET components directly. You have to use a
bridging technology such as COM interop, as both .NET and VFP support the
creation/consumption of COM components (in this case, all that is needed
is for .NET to support the creation of COM components and for VFP to
support the consumption of them).

COM disadventages:

1. Forgot single click installation. Forgot zero footprint. Forgot running
from quest account -
It requires dll registration on every customer computer.

2. .NET is not usable
Most .NET components do not expose COM interface. Almost every .NET
component requires to create wrapper dll.

So COM is dead end.
Your links don't support the idea that VPF can support consuming .NET
components directly. The first is a link to an ASP.NET-like environment
which is implemented on top of FoxPro.

From first link you can reach to the link

http://www.west-wind.com/wconnect/weblog/ShowEntry.blog?id=631

Which offers a way to Host the CLR directly. It shows wrapper dll source
code and allows to download samples.
The second link shows how to consume VFP functions in .NET (VB.NET
specifically) and it is through COM interop.

From second link you can reach to the link

http://blogs.msdn.com/calvin_hsia/archive/2006/08/07/691467.aspx

which contains C++ code to host the CLR as sample.

So both links provide ways to use .NET without dreaded COM interop from VFP.

Andrus.
 
N

Nicholas Paldino [.NET/C# MVP]

Andrus,

See inline:

Andrus said:
COM disadventages:

1. Forgot single click installation. Forgot zero footprint. Forgot running
from quest account -
It requires dll registration on every customer computer.

Wrong on all counts. You can use reg-free COM to use COM components
without registering them. Also, there is nothing that prevents the use of
COM objects from a guest account. Com objects are not limited by user
accounts (unless they are hosted in COM+, which one can specify
authorization to components).

Even still, registering the components is NOT that big of a deal. Also,
going the route in the blog entry that you pointed out ^still^ uses COM
interop, it just gets around the registration aspect of it. To be quite
frank, it's a ton of work for minimal gain.
2. .NET is not usable
Most .NET components do not expose COM interface. Almost every .NET
component requires to create wrapper dll.

Again, not true. Most of the types in the framework have the ComVisible
attribute attached to them. You will have to create your specific types so
that they are visible in COM, but most of the framework types are already
visible.
So COM is dead end.

Not by a longshot. The links you provided here both have workarounds
which eventally drop down to C++ to use it as a shim (and in some cases, COM
interop anyways), which is really MUCH more work than correctly implementing
a .NET component as a COM component.

If ^anyone^ is going to go through that much work just to get around
using COM, then they deserve the headaches that come from such a roundabout
solution.

Also, COM has been around for the past 15 years, it's deeply integrated
into Windows, and isn't going anywhere soon. Yes, it does require one to be
diligent in regards to versioning and registration, but they really aren't
such big issues. If they were, the technology wouldn't have matured to the
point where it has (where many other technologies and applications are built
on top of it).

It just requires a little understanding of it. Not reams of C++ code
and shims which produce minimal gains for maximal effort.

COM is not "dreaded" and it's not hard to understand or use. You just
have to be willing to understand it.
 
A

Andrus

Wrong on all counts. You can use reg-free COM to use COM components
without registering them.

From

http://msdn.microsoft.com//msdnmag/issues/05/04/RegFreeCOM/default.aspx

sidebar
<quote>
Not every component is a suitable candidate for use under Reg-Free COM. A
component is not considered suitable if any of the following are true:

....

The component is a system component or part of the operating system,
such as XML, Data Access, Internet Explorer, or DirectX® components. For
example, you should not attempt to isolate components such as Microsoft XML
(MSXml.dll) or Microsoft Internet Controls (SHDocVw.dll). These components
are either part of the operating system, or can be installed with a separate
redistributable package.
</quote>


..NET assemblies fall into this category.
There is no way to generate Reg-free manifest nor use .NET assembly as
Reg-free COM component.

So the C++ wrapper dll is the only solution to avoid registry write.

Andrus.
 
N

Nicholas Paldino [.NET/C# MVP]

Andrus,

Again, you are wrong. .NET is not a "system" component. While yes, it
does have data access and xml capabilities (Internet Explorer and DirectX
are separate technologies), the author of that article is referring to ADO
(not ADO.NET) and MSXML (not the classes in the System.Xml namespace), not
..NET. If it was a "system" component then you would not be able to remove
..NET from the Add/Remove Programs screen (which you can).

You really haven't given a good reason ^why^ registering a COM component
is such a nightmare. Yes, you brought up ^some^ valid things to take into
consideration (depending on what the requirements are) when using COM
interop, but the horror story that you are trying to portray COM interop as
just isn't holding up. It's ^NOT^ as difficult as you are making it out to
be, and the issues surrounding it are not showstoppers, or major, by any
means.
 
A

Andrus

Again, you are wrong. .NET is not a "system" component.

The issues which I pointed were:

1. It is impossible to create Reg-Free manifest for .NET assemblies deplyied
with application so that they can be used from VFP.
2. It is impossible to create Reg-Free manifest for accessing .NET system
assemblies from VFP.

So Reg-Free technology in not usable to call .NET assemblies.
You really haven't given a good reason ^why^ registering a COM
component is such a nightmare.

Using .NET from VFP requires registry write access in every customer
computer to register COM compoments.

This is stopper issue since prevents creating zero-footprint zero-install
applications.

Andrus.
 
W

Willy Denoyette [MVP]

Andrus said:
The issues which I pointed were:

1. It is impossible to create Reg-Free manifest for .NET assemblies
deplyied with application so that they can be used from VFP.
2. It is impossible to create Reg-Free manifest for accessing .NET system
assemblies from VFP.

But you don't need them, VFP is a COM client and like all COM clients (VB6,
Delphi etc) it can simply load the CLR and call all COM exposed functions
from mscorlib.dll to setup an Application domain and load your assemblies,
exactly like is illustrated here
http://www.west-wind.com/wconnect/weblog/ShowEntry.blog?id=631 , there is no
need to use a C++ thunk to load the CLR for this, the CLR is automatically
loaded once you call into a COM registered .NET assembly from an unmanaged
COM client.

So Reg-Free technology in not usable to call .NET assemblies.

Not needed!
Using .NET from VFP requires registry write access in every customer
computer to register COM compoments.

No need to register the .NET assembles with COM.
This is stopper issue since prevents creating zero-footprint zero-install
applications.

Willy.
 
A

Andrus

Nicholas,
Again, not true. Most of the types in the framework have the
ComVisible attribute attached to them. You will have to create your
specific types so that they are visible in COM, but most of the framework
types are already visible.

from

http://www.west-wind.com:80/wconnect/weblog/ShowEntry.blog?id=631

<quote>
.... .NET internally has rather few components that are exposed as COM
objects and most components and libraries don't expose to COM directly,
if you ever want to interoperate with these types of components you'll
always have to create a wrapper component first in .NET
....
</quote>

So this information from .NET MVP Rick is wrong?

Andrus.
 
A

Andrus

Willy,
http://www.west-wind.com/wconnect/weblog/ShowEntry.blog?id=631 , there is
no need to use a C++ thunk to load the CLR for this, the CLR is
automatically loaded once you call into a COM registered .NET assembly
from an unmanaged COM client.

From the link above

<quote>
To do this requires some low level code and the easiest way to do this is
with a small shim C++ DLL ...
</quote>

So .NET and former FoxPro MVP Rick wrote that low level (I interpret this
as "non-FoxPro" since this is not possible to replace this with FoxPro code)
code is *required* to invoke .NET CLR hosting from FoxPro.

Is this information wrong ?

Andrus.
 
W

Willy Denoyette [MVP]

Andrus said:
Willy,


From the link above

<quote>
To do this requires some low level code and the easiest way to do this is
with a small shim C++ DLL ...
</quote>

So .NET and former FoxPro MVP Rick wrote that low level (I interpret this
as "non-FoxPro" since this is not possible to replace this with FoxPro
code) code is *required* to invoke .NET CLR hosting from FoxPro.

Is this information wrong ?

I don't say he is wrong, but it's not the easiest way to load the CLR into a
native process.
The easiest way is for the client to load the CLR, is by creating a COM
creatable .NET class (that is a class that is registered for COM interop).
This is exactly what happens if you create/call into .NET from VFP, VB6,
Delphi or any other COM client, the CLR is basically an extension of COM,
who said COM was dead?

For VFP (or any other native COM client) you can simply load the CLR by a
simple call like this:

oList = CREATEOBJECT("System.Collections.SortedList")

supposing this is the first instantiation call in the program, executing
above starts following actions:
- CREATEOBJECT calls into the COM library
- COM loads the COM server dll (mscoree.dll), associated with the CLSID of
"System.Collections.SortedList" passed as arg.
- the Mscoree shim loads the CLR (if not already loaded),
- the CLR creates a default AD and,
- loads the mscorlib (associated with the CLSID) assembly into this AD.
- creates an instance of "SortedList", and
- returns a COM Interface pointer to the caller.

All ComVisible classes from the Framework are registered as COM classes at
Framework install time, if you don't believe me, take a look in the registry
or better, use OleView.exe and watch the .NET Category objects.
The only advantage of using a shim like Rick did (it doesn't even have to be
a C++ shim, it could be written in VB6 C++, VFP), is that you have the
opportunity to 'customize' the CLR hosting process (version of the CLR, type
of GC etc.), but all this is not used in Ricks code and in general there is
no need for this.
If you don't register your .NET classes for COM interop, however, you'll
have to implement a bunch of (managed code) wrappers before you are able to
do something sensible, you don't expect VFP programmers to write these
wrappers do you? only because you are unwilling to register a ComVisible
library for COM interop.


Willy.
 
W

Willy Denoyette [MVP]

Andrus said:
Nicholas,


from

http://www.west-wind.com:80/wconnect/weblog/ShowEntry.blog?id=631

<quote>
... .NET internally has rather few components that are exposed as COM
objects and most components and libraries don't expose to COM directly,
if you ever want to interoperate with these types of components you'll
always have to create a wrapper component first in .NET
...
</quote>

So this information from .NET MVP Rick is wrong?

Judge for yourself, take a look at the number of .NET classes that are
registered for COM interop. Use regedit or better Oleview to look at the
number of classes that are exposed to COM. Don't be surprised to find more
than thousand classes registered, especially if you have SQL server
installed.



Willy.
 
A

Andrus

Judge for yourself, take a look at the number of .NET classes that are
registered for COM interop. Use regedit or better Oleview to look at the
number of classes that are exposed to COM. Don't be surprised to find more
than thousand classes registered, especially if you have SQL server
installed.

Willy,

So i'ts exteremely confusing that .NET MVP website contains totally wrong
information.

Can you send a email to Rick and post this message to as Rick article
comment ?

Andrus.
 
N

Nicholas Paldino [.NET/C# MVP]

Andrus,

Just to let you know, MVPs are not always right. While generally, it
can be said that they are knowledgable in their fields, that doesn't mean
they are infallable.

And its a MVP's site, not THE MVPs site. That site is not reflective of
all MVPs, it's one man's site.

There is nothing stopping you from contacting him (through the site, I'm
assuming there is contact information there) and asking him to update this
information.
 
A

Andrus

Willy,
The easiest way is for the client to load the CLR, is by creating a COM
creatable .NET class (that is a class that is registered for COM interop).

I tried to create code in VFP in the easiest way using your sample

LOCAL olist as System.Collections.SortedList
olist.

intellisence did *not* work, member list after pressing dot does *not*
appear.

In contract if I use usual COM object like

LOCAL olist as MSMAPI.MAPIMessages.1

typing olist. shows mapi class members.

So using .NET COM objects is *much more* difficult that using normal COM
objects.

I havent found *any* sample which makes *any* useful calls to .NET
framework classes in the "easiest" way.

I tried to create first useful sample converting Rick sample to the easiest
way. Even first line in sample

loMsg = CREATEOBJECT("System.Net.Mail.MailMessage")

causes error

Class definition SYSTEM.NET.MAIL.MAILMESSAGE is not found.

So I'm forced to think that calling .NET assemblies directly is practically
not possible: critical classes are *not* COM visible like Rick wrote.
The only advantage of using a shim like Rick did (it doesn't even have to
be a C++ shim, it could be written in VB6 C++, VFP), is that you have the
opportunity to 'customize' the CLR hosting process (version of the CLR,
type of GC etc.), but all this is not used in Ricks code and in general
there is no need for this.

Can you show the code how to send mail by calling .NET classes without using
Ricks wrapper ?
This is quite common operation. Unfortunately I havent found any way for
this.
If you don't register your .NET classes for COM interop, however, you'll
have to implement a bunch of (managed code) wrappers before you are able
to do something sensible, you don't expect VFP programmers to write these
wrappers do you? only because you are unwilling to register a ComVisible
library for COM interop.

As shown below, I must create wrapper to send email anyway.

Without wrapper it is not possible to make *any* real use of .NET framework.
Instantiating .NET framework classes directly from COM is joke.

Only very simple code like

oList = CREATEOBJECT("System.Collections.SortedList")
MESSAGEBOX( oList.ToString() )

works.

Andrus.
 
C

CSLCO

Hello Everybody,

I see that my question makes a lot of discuss....


The solution for me,it is very easy :

I write a text file with my C# application, and I read it with Fox Pro.

Something like that in VFP:

RUN /N MyAppliC#.exe
(which create a txt file with the result of my C# function)
ReadResult()

Procedure ReadResult
CsFile="myfilec#.txt"
if exist()
gnFile = FOPEN(CsFile,12)
IF gnFile >= 0
nSize = FSEEK(gnFile, 0, 2) && EOF
FSEEK(gnFile, 0, 0) &&BOF
TxtinFile=FREAD(gnFile,nSize)
&& Analyse the TxtinFile string to read your result !
Return WhatINeed
endif

endif
return Nothing
endproc

No need something else !

Thx for your interest.

Lionel
 
W

Willy Denoyette [MVP]

Andrus said:
Willy,


I tried to create code in VFP in the easiest way using your sample

LOCAL olist as System.Collections.SortedList
olist.

intellisence did *not* work, member list after pressing dot does *not*
appear.

In contract if I use usual COM object like

LOCAL olist as MSMAPI.MAPIMessages.1

typing olist. shows mapi class members.

So using .NET COM objects is *much more* difficult that using normal COM
objects.

I havent found *any* sample which makes *any* useful calls to .NET
framework classes in the "easiest" way.

I tried to create first useful sample converting Rick sample to the
easiest
way. Even first line in sample

loMsg = CREATEOBJECT("System.Net.Mail.MailMessage")

causes error

Class definition SYSTEM.NET.MAIL.MAILMESSAGE is not found.

So I'm forced to think that calling .NET assemblies directly is
practically
not possible: critical classes are *not* COM visible like Rick wrote.


Can you show the code how to send mail by calling .NET classes without
using
Ricks wrapper ?
This is quite common operation. Unfortunately I havent found any way for
this.


As shown below, I must create wrapper to send email anyway.

Without wrapper it is not possible to make *any* real use of .NET
framework.
Instantiating .NET framework classes directly from COM is joke.

Only very simple code like

oList = CREATEOBJECT("System.Collections.SortedList")
MESSAGEBOX( oList.ToString() )

works.

Andrus.



Where did I say that ALL Framework classes where registered for COM
interop?, I said all *ComVisible* classes. "System.Net.Mail.MailMessage" is
NOT such a class, why would you ever use this class from COM is beyond me?
this class is a wrapper around (a COM component) CDO which is directly
usable from native COM.
Also, I did not suggest you to start using the Framework (BCL) classes from
COM, this is very un-common, all I said is that you don't need a "C++ shim"
to load the CLR in a process and that you can call a bunch of .NET classes
because they are registered for COM interop, please re-read my previous
replies.

For a .NET class to be usable from a COM client (that is, a "COM friendly"
class), it has to obey the rules of COM, but first of all .NET types need to
obey the rules imposed by .NET (the CTS), which is not always possible.
Not all .NET classes can follow the COM rules, or the author did not
consider them usefull for COM, or they pass object types that can not be
marshaled to COM, if this is true, the author will mark the class with
ComVisible="false".
Also, all .NET classes *registered* for COM interop are "automation"
compatible, most of them work perfectly well from early bound COM (VB6, C++
etc..), but there is no guarantee that they are perfectly usable from late
bound clients (like VBScript, JScript). There are a lot of details to
consider when talking about COM interop, this is due to COM not .NET.

The easiest to test the exposed classes from a late bound client is by using
VBScript.
For instance you can run the following:

Csript test.vbs

' File: Test.vbs
dim sortedList, inx
set sortedList = WScript.CreateObject("System.Collections.SortedList")
WScript.Echo sortedList.ToString()

for n = 19 to 0 step -1
sortedList.Add n, "Test-" & n
next
WScript.Echo "Elements in list: " & sortedList.Count
WScript.Echo "Capacity: " & sortedList.Capacity
inx = 0
For n = 0 To sortedList.Count
WScript.Echo sortedList.Item(inx)
inx = inx + 1
Next

Anyway, if you need to expose your classes to COM clients (here I mean not a
specific client like a VFP application), you'll have to follow the rules
(COM and obviously .NET), that is you need to author your classes to be *COM
friendly*. How you do this is all explained in MSDN (search for COM
interop), AND you need to register your assembly for COM interop when
deploying.

Willy.
 
W

Willy Denoyette [MVP]

CSLCO said:
Hello Everybody,

I see that my question makes a lot of discuss....


The solution for me,it is very easy :

I write a text file with my C# application, and I read it with Fox Pro.

Something like that in VFP:

RUN /N MyAppliC#.exe
(which create a txt file with the result of my C# function)
ReadResult()

Procedure ReadResult
CsFile="myfilec#.txt"
if exist()
gnFile = FOPEN(CsFile,12)
IF gnFile >= 0
nSize = FSEEK(gnFile, 0, 2) && EOF
FSEEK(gnFile, 0, 0) &&BOF
TxtinFile=FREAD(gnFile,nSize)
&& Analyse the TxtinFile string to read your result !
Return WhatINeed
endif

endif
return Nothing
endproc

No need something else !

Thx for your interest.

Lionel



Well, AFAIKS you start a C# program from VFP, that program creates a text
file, and you are trying to read it from VFP. Sure you will have to wait
until the file is written and closed, but what problem do you have with
this?

Willy.
 

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