|
Hi Guys,
just want to ask if events(like ONCHANGE ...) are working within converted dll's as well?
|
|
|
|
|
hey, im trying to implement this in my projects in VB.NET and evey time i try to export my functions i get this
it find all my classes and functions and then it says its compiling them and thn this
test.il(385) : warning -- Reference to undeclared extern assembly 'ExportDllAttribute'. Attempting Autodetect
test.il(385) : warning -- Failed to autodetect assembly 'ExportDllAttribute'
then the command prompt comes back to me and my function isn't exported.
heres the code, this is just a test project though...
Imports System.Runtime
Imports ExportDllAttribute.ExportDllAttribute
Public Class Main
<exportdllattribute.exportdll("box",> _
Public Shared Sub box()
MsgBox("Hello")
End Sub
End Class
i have tried it with and without the 'Imports ExportDllAttribute.ExportDllAttribute' line and it is the same either way
please help!
|
|
|
|
|
This happens if my dll references another dll in the same folder (for interfaces). The happens because the assembly loader can't find the second dll (because it's looking in the folder with the DllExport exe, not the folder with the dll for processing).
Is there a reason you're using Assembly.Load(byte[]) instead of Assembly.LoadFrom(string filepath)?
In my project I'm using CurrentDomain.AssemblyResolve to help the loader find the extra files, eg:
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
return Assembly.LoadFrom(Path.Combine(Path.GetDirectoryName(filepath), args.Name.Split(',')[0] + ".dll"));
}
catch (Exception)
{
return null;
}
}
|
|
|
|
|
Heh, nevermind. LoadFrom and LoadFile load the dll into the process space, so it becomes locked.
Here's the code I ended up using to fix loading of related dll's:
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs resolveArgs)
{
try
{
return Assembly.LoadFrom(Path.Combine(Path.GetDirectoryName(filepath), resolveArgs.Name.Split(',')[0] + ".dll"));
}
catch (Exception)
{
return null;
}
}; (I added it just before int exportscount = 0; )
|
|
|
|
|
If I export the following function - everything is ok :
using System;
namespace cAddieren
{
public class cAddieren
{
[ExportDllAttribute.ExportDll("Summe",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int Summe(int A, int B)
{
return A + B;
}
}
}
If I export the following function - a problem occurs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassZufallszahl
{
public class Zufallszahl
{
[ExportDllAttribute.ExportDll("Summe",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static String Summe(int A, int B)
{
return A.ToString() + B.ToString() + " ok";
}
}
}
I don't know in detail what Selvin is doing while exporting the function. If I check the exported function in Dependency Walker both examples show the exported function "Summe". Could it be that only C-functions can be exported in every case correctly? Could it be that this dosn't work if you use elements which are only availabe in C# (and not in C)? Could it be that the second exported function doesn't work because the type "String" isn't known in C?
I tried to use the second function in VBA (Excel) as followed:
Public Declare Function add1 Lib _
"C:\Dokumente und Einstellungen\Peter\Eigene Dateien\Visual Studio 2008\Projects\classzufallszahl\classzufallszahl\bin\Release\classzufallszahl.dll" _
Alias "Summe" (ByVal A As Integer, ByVal B As Integer) As String
Sub String_Addieren()
Str = add1(20, 30)
MsgBox Str
End Sub
Excel crashes!!!!!!
If I do the same with the first example in VBA (Excel) ->
|
|
|
|
|
hmmm had you ever write in C/C++
what happen if you call function like this
char* fun()
{
char a[8];
a[0] = 'i';
a[1] = ' ';
a[2] = 'c';
a[3] = 'a';
a[4] = 'n';
a[5] = ''';
a[6] = 't';
a[7] = '\0';
return a;
}
to fix your problem you should write smthing like this
C#
[ExportDllAttribute.ExportDll("Summe")]
public static int Summe(int A, int B, [MarshalAs( UnmanagedType.AnsiBStr)] ref string os)
{
os = A.ToString() + B.ToString() + " ok";
return A + B;
}
VBA
Private Declare Function Summe Lib "MyLib.dll" (ByVal A As Long, ByVal B As Long, ByRef S As String) As Long
Sub test()
Dim S As String
i = Summe(10, 10, S)
MsgBox S
End Sub
now it should works
...works fascinates me...i can stare it for hours...
|
|
|
|
|
Thanks a lot - your solution is perfect! I see you are an epxert in c# and (!) VBA. I have two questions.
First:
namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int ZArray(int beginn, int ende, int anzahl, [MarshalAs(UnmanagedType.LPArray,
SizeParamIndex=1)] ref int[] ZZahl)
{
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return 1;
}
}
}
VBA:
Declare Function Zar Lib _
"C:\.........\ZufallArray.dll" _
Alias "ZArray" (ByVal a As Integer, ByVal b As Integer, ByVal c As Integer, ByRef d() As Integer) As Integer
Sub zarray()
Dim a() As Integer
Dim x As Integer
x = Zar(10, 20, 3, a())
For i = 0 to 2
MsgBox a(i)
Next i
End Sub
There ist somthing wrong with "MarshalAs"!?
Second:
Is it possible to code the example like this:
namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static int[] ZArray(int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl.MarshalAs ...... (something):~;
}
}
;
??
Thanks in advance!
|
|
|
|
|
The problems don't want to disappear! I changed my code like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ZufallArray
{
public class ZufallArray
{
[ExportDllAttribute.ExportDll("ZArray",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
[return:MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
public static int[] ZArray(int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j]= randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}
When I start the "ExportDll.exe" on commandline I get the following error:
"Nicht verifizierbarer Code hat die Richtlinienüberprüfung nicht bestanden. (Ausnahme von HRESULT: 0x80131402)"
Dependency Walker don't show any exported function!
P.S.: As nobody can help me I am forced to abandon.
Peter
|
|
|
|
|
|
Thanks a lot, everything ist perfect when using the following code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace classtest
{
public class test
{
[ExportDllAttribute.ExportDll("Stringtest",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string Stringtest()
{
String Meld = "Geht doch!";
return Meld;
}
}
}
But I try to use a C#-DLL which returns an array, like that:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace classtest
{
public class test
{
[ExportDllAttribute.ExportDll("ArrayTest",
System.Runtime.InteropServices.CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
public static int[] ArrayTest(int beginn, int ende, int anzahl)
{
int[] ZZahl = new int[anzahl];
Random randObj = new Random();
for (int j = 0; j < anzahl; j++)
{
ZZahl[j] = randObj.Next(beginn, ende);
}
return ZZahl;
}
}
}
If I use "[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)]" (the code which I think is wrong) the function will be exported but it does'nt work with VBA.
If I use "[return: MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]" (the code which I think is correct) then I get an error while exporting the function ( .... this german message with HRESULT: 0x80131402 at the end).
|
|
|
|
|
System.Runtime.InteropServices.CallingConvention.Cdecl is bad
VBA use StdCall
[ExportDllAttribute.ExportDll("WesolaTablica1")]<br />
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_I4)]<br />
public static int[] WesolaTablica1(int Od, int Do, int Ile)<br />
{<br />
int[] TablicaPowrot = new int[Ile+1];<br />
Random Losowa = new Random();<br />
for (int i = 1; i < TablicaPowrot.Length; i++)<br />
TablicaPowrot[i] = Losowa.Next(Od, Do);<br />
return TablicaPowrot;<br />
}
Private Declare Function WesolaTablica1 Lib _<br />
"MyLib.dll" (ByVal Od_ As Long, ByVal Do_ As Long, ByVal Ile As Long) As Long()<br />
<br />
sub test()<br />
Dim tablica2() As Long<br />
tablica2 = WesolaTablica1(0, 100, 10)<br />
end sub
...works fascinates me...i can stare it for hours...
|
|
|
|
|
I can only say ...... perfect!!!!!!!
|
|
|
|
|
Does ExportDLL also work in .Net 3.5 ? Is this still the simplest way to expose .Net methods to older Win32 clients ?
Any suggestions and good advice is welcome ! Thanks !
btw,
I'm just entering this arena of .Net development. I need to be able to call a .Net based web service client (which i already implemented in a C# testproject) from a Delphi (version 3) application.
|
|
|
|
|
Well, in the meantime I succeeded in implementing DLLExport for use from a Delphi 3 client application.
So thanks for this tool !
Just in case anybody wanted to see the Delphi3 code, here's an example :
On the .Net library side (I called it ALWSLib.DLL) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ALWSLib
{
public class ALWSLibClass
{
[ExportDllAttribute.ExportDll("DLLMsgBox", CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string MsgBox([MarshalAs(UnmanagedType.AnsiBStr)] string message, [MarshalAs(UnmanagedType.AnsiBStr)]string caption, int buttons, int icon)
{
MessageBox.Show(message, caption, (MessageBoxButtons)buttons, (MessageBoxIcon)icon);
return "I am the return message from the managed function!";
}
[ExportDllAttribute.ExportDll("AddAndReturnAsString", CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.AnsiBStr)]
public static string AddAndReturnAsString(int A, int B)
{
MessageBox.Show("In managed function : AddAndReturnAsString(" + A + ", " + B + "). Returning sum ...");
return (A + B).ToString();
}
}
}
On the Delphi-3 side (where I load the DLL dynamically)
unit Main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Edit1: TEdit;
Edit2: TEdit;
CbxLoaded: TCheckBox;
Button4: TButton;
Edit3: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
ALWSLibInitialized: boolean;
implementation
{$R *.DFM}
type TDLLMsgBox = function(
aMsg: PChar;
aTitle: PChar;
aButtons: Integer;
aIcon: Integer): PChar; stdcall;
type TAddAndReturnAsString = function(
A: integer;
B: integer): PChar; cdecl;
var ALWSLibHandle: THandle;
const PAddAndReturnAsString: TAddAndReturnAsString = nil;
const PDLLMsgBox: TDLLMsgBox = nil;
function DoLoadDLL(ADLL: String): THandle;
var
FileOK: Boolean;
begin
FileOK := FileExists(ADLL);
if FileOK then
Result := LoadLibrary(PChar(ADLL));
if Not(FileOK) or (Result < hInstance_Error) then
begin
MessageDlg('DLL ('+ADLL+') not installed.', mtError,[mbOK],0);
ALWSLibInitialized := False;
Abort;
end;
end;
procedure ALWSLibInitialize;
var
ADLL: String;
begin
if not(ALWSLibInitialized) then
begin
ALWSLibInitialized := True;
ADLL := ExtractFileDir(Application.ExeName)+'\..\DLL\ALWSLib.dll';
ALWSLibHandle := DoLoadDLL(ADLL);
if not(ALWSLibHandle < hInstance_Error) then
begin
@PAddAndReturnAsString := GetProcAddress(ALWSLibHandle, 'AddAndReturnAsString');
@PDLLMsgBox := GetProcAddress(ALWSLibHandle, 'DLLMsgBox');
if not(Assigned(@PAddAndReturnAsString)) or
not(Assigned(@PDLLMsgBox)) then
begin
MessageDlg('Incorrect Library module '+ADLL, mtError,[mbOK],0);
Abort;
end;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ALWSLibInitialize;
CbxLoaded.Checked := (ALWSLibInitialized);
end;
procedure TForm1.Button2Click(Sender: TObject);
var
A, B : integer;
Res: PChar;
StrRes: String;
begin
A := 123;
B := 456;
if ALWSLibInitialized then
begin
Res := PAddAndReturnAsString(A, B);
SetString(StrRes, Res, StrLen(Res));
Edit1.Text := StrRes;
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
aMessage, aCaption : String;
A, B : integer;
Res: PChar;
StrRes: String;
begin
aMessage := 'Het is hier goed weer in .Net land...';
aCaption := 'MsgBox in .Net';
A := 0;
B := 32;
if ALWSLibInitialized then
begin
Res := PDLLMsgBox(PChar(aMessage),
PChar(aCaption),
A, B);
SetString(StrRes, Res, StrLen(Res));
Edit2.Text := StrRes;
end;
end;
initialization
ALWSLibInitialized := false;
end.
|
|
|
|
|
C#
[ExportDllAttribute.ExportDll("Test2", CallingConvention.Cdecl)]
public static void Test2([MarshalAs(UnmanagedType.AnsiBStr)] ref string s2)
{
}
VB6
Public Declare Sub Test2 Lib "file.dll" _
(ByRef s1 As String)
This doesn't work for me when calling Test2. I'm getting
Run-time error '49':
Bad DLL calling convention
Any ideas anyone?
Regards,
Mike
modified 7-Feb-13 21:40pm.
|
|
|
|
|
|
Hi
When I run dependency walker over a dll that has been created using ExportDll I get the following dlls that could not be found:
c:\windows\system32\ADVAPI32.DLL
c:\windows\system32\MPR.DLL
c:\windows\system32\SHLWAPI.DLL
c:\windows\system32\USER32.DLL
Do you know how or why this is happening?
|
|
|
|
|
Ugh ?
.NET dlls depends on
a) MSCOREE.DLL only (which depends on "windows core" dlls like those U mentioned) without using PInvoke
b) other native dlls if U're using PInvoke
I dont where is ur problem
...works fascinates me...i can stare it for hours...
|
|
|
|
|
hi I am working with vc6++ only.
how can I use MSTSC.MSRDPClient in c++ vc6++
only? (aspecially I am searching how to
sink the MSRdpClient_OnDisconnect Event
to a c++ win32 static linked lib. )
only simple code
|
|
|
|
|
Hi Selvin,
Could you explain to me step by step how to export a function in a visual basic dll created in Visual Studio 2008?
Thanks a lot
|
|
|
|
|
Hi,
We are having the same issue. Tried the example C# code and everything works fine. When we try it with VB.NET then all we see on the output from ExportDll.exe is "Debug: false" and the command prompt returns.
Is ExportDll.exe only for C# dll assemblies?
Here is the VB code we were trying to test with.
Imports oracle.DataAccess.Client
Imports ExportDLLAttribute
Imports System.Runtime.InteropServices
Public Class CS_dbsvrconn
<ExportDllAttribute.ExportDll("CheckForOracle", CallingConvention.StdCall)> _
Public Function CheckForOracle(ByVal DatabaseServer As String, _
ByVal TNSName As String, _
ByVal OraclePort As String, _
ByVal UserID As String, _
ByVal PassWord As String) As Boolean
Dim con As OracleConnection = New OracleConnection()
con.ConnectionString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)" + _
"(HOST=" + DatabaseServer + ")(PORT=" + OraclePort + "))" + _
"(CONNECT_DATA=(SERVICE_NAME=" + TNSName + ")));" + _
"User Id=" + UserID + ";Password=" + PassWord + ";"
Try
con.Open()
con.Close()
con.Dispose()
Return True
Catch ex As Exception
con.Dispose()
Return False
End Try
End Function
End Class
|
|
|
|
|
Hi all,
I created a dll in Visual Basic using Visual Studio 2008 and I need to export the only function (Ocr) in the dll. I tried what you wrote at "http://www.codeproject.com/KB/dotnet/DllExport.aspx" to export my dll but it doesn't change when I compile it since when I use Dependecy Walker I don't see any exported method in my dll. I summarize what I did following your instructions:
1)I created my dll in Visual Studio 2008 as a project Class Library in Visual Basic.My dll is called Bollettino.dll. It contains only a Sub called Ocr.
2) I downloaded the ExportDll code and I added ExportAttribute.dll as an address in my project .
3) Before the Sub Ocr I added in my code the statement
ExportDllAttribute.ExportDll("Ocr()", System.Runtime.InteropServices.CallingConvention.Cdecl); _
ecause ExportDll.exe needs to know which functions need to be exported.
4) I add in Project property named "Post-build event command" the following statement
C:\Release\ExportDll.exe C:\Projects_VS_2008\Bollettino\Bollettino\bin\Release\Bollettino.dll /$(ConfigurationName)
thata represents the paths of ExportDll and of my dll
5) I compile my dll but it doesn't happen...Because I don't see any exported method in my dll if I use Dependency Walker.
I don't receive any error messages and I don't understand why it doesn't work.
What is wrong in my procedure???
Can you help me??
I hope that this message could be read by Slevin who is the author of the article I refers to.
Thanks in advance.
Bye
P.S Here is the code:
Public Class Class1
'[ExportDll("Ocr",System.Runtime.InteropServices.CallingConvention.Cdecl)]
<ExportDllAttribute.ExportDll("Ocr()", System.Runtime.InteropServices.CallingConvention.Cdecl)> _
Public Sub Ocr()
Dim inputFile As String = "C:\\Boll.tif"
Dim strRecText As String = ""
Dim Doc1 As MODI.Document
Doc1 = New MODI.Document
Doc1.Create(inputFile)
Doc1.OCR() ' this will ocr all pages of a multi-page tiff file
Doc1.Save() ' this will save the deskewed reoriented images, and the OCR text, back to the inputFile
For imageCounter As Integer = 0 To (Doc1.Images.Count - 1) ' work your way through each page of results
strRecText &= Doc1.Images(imageCounter).Layout.Text ' this puts the ocr results into a string
Next
System.IO.File.Delete("C:\\test5.txt")
System.IO.File.AppendAllText("C:\\test5.txt", strRecText) ' write the OCR file out to disk
'System.IO.File.Create("C:\\test2.txt", strRecText)
Doc1.Close() ' clean up
Doc1 = Nothing
End Sub
End Class
|
|
|
|
|
Hello I have a question, this exe can compile a dll for 64 bits operating system or is necesary to change something?
thanks and regards
|
|
|
|
|
i really don't know(coz i didn't test)
but i think - it should work there as well
...works fascinates me...i can stare it for hours...
|
|
|
|
|
...or (if its not working)...
change
wholeilfile.Add(string.Format(".vtfixup [{0}] int32 fromunmanaged at VT_01", exportscount));
wholeilfile.Add(string.Format(".data VT_01 = int32[{0}]", exportscount));
to
wholeilfile.Add(string.Format(".vtfixup [{0}] int64 fromunmanaged at VT_01", exportscount));
wholeilfile.Add(string.Format(".data VT_01 = int64[{0}]", exportscount));
...works fascinates me...i can stare it for hours...
|
|
|
|
|