|
Unbelievably handy little app you have here.
Why the heck MS doesn't make this kind of thing available directly from the VS ide is beyond me.
Works perfectly!
5 stars!
vbfengshui
|
|
|
|
|
Fantastic works great thanks a lot
|
|
|
|
|
This all works but I cannot debug my C# DLL. I think the problem is that since the DLL was modified after it was compiled, the debugger sees it as no longer being in sync, and breakpoints are disabled and doesn't get hit.
Am I doing something wrong or is this a flaw in this concept (as far as debugging goes)?
|
|
|
|
|
Hi. There are some changes maded by me:
* added usage information
* added verbose option (tool is quiet by default now)
* added option to set out file name
* added relative paths support (rough)
* added wow64 path support (if ildasm path contains "program files", this tool looks at "program files (x86)" also). just for convenience
* added custom attributes support (previous version have an incorrect method parser; now tool shows warning in such cases)
* made some mistake corrections (e.g. ".custum" => ".custom")
Modified sources here: exportdll.zip
|
|
|
|
|
Hi,
I'm in test with a two-method library, but my VS09 compiler return this:
error CS0579: Duplicate 'ExportDllAttribute.ExportDll' attribute
How I can solve this error?
|
|
|
|
|
Could you provide a minimal example?
|
|
|
|
|
here my cs code where the second "[ExportDllAttribute.ExportDll..." declaration, report that duplicate error.....
/////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using ExportDllAttribute;
namespace TestSharpLibrary
{
public class Class1
{
[ExportDllAttribute.ExportDll("Function1", System.Runtime.InteropServices.CallingConvention.Cdecl)]
[ExportDllAttribute.ExportDll("Function2", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static void Function1(int num1, int num2,out int retValue)
{
retValue = num1 + num2;
}
public static void Function2(int num1, int num2,out int retValue)
{
retValue = num1 * num2;
}
}
}
|
|
|
|
|
muhahahaha
[ExportDllAttribute.ExportDll("Function1", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static void Function1(int num1, int num2,out int retValue)
.
.
.
[ExportDllAttribute.ExportDll("Function2", System.Runtime.InteropServices.CallingConvention.Cdecl)]
public static void Function2(int num1, int num2,out int retValue)
.
.
.
...works fascinates me...i can stare it for hours...
|
|
|
|
|
|
The modified sources file are no longer available at the given link. Can you post them again, or better yet, update the files on this site?
Thanks
derMeister
|
|
|
|
|
Please upload it again. This tool is so helpfull! In your description you add an output file option ... with this your tool would be perfect for me ![Smile | :)](https://codeproject.global.ssl.fastly.net/script/Forums/Images/smiley_smile.gif)
|
|
|
|
|
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) -> ![Cool | :cool:](https://codeproject.global.ssl.fastly.net/script/Forums/Images/smiley_cool.gif)
|
|
|
|
|
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!!!!!!!![Cool | :cool:](https://codeproject.global.ssl.fastly.net/script/Forums/Images/smiley_cool.gif)
|
|
|
|
|
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.
|
|
|
|
|