I have a DLL it crated with Delphi xe10.2 and it contain a function
function calc(b : integer;a:integer) : Integer;
begin
Result := a+b;
end;
and i will call it on other program like this
function calc(b : integer;a:integer): Integer; stdcall; external 'my.dll';
i copied the DLL in System32 folder and application .exe folder
procedure TForm1.Button1Click(Sender: TObject);
begin
showmessage(inttostr(calc(2,3)));
end;
but when i run from delphi IDE nothing happened.it dont show any error and also dont show application main form...
how can i fix this ?!
System32 is the 64-bit system folder. Your application is a 32-bit application, and hence does not search for DLLs in System32. It will search in SysWOW64 instead, which is the 32-bit system folder. If you ran the program without debugging, you would see an error message telling you that the DLL could not be located.
Now, you should never modify the contents of system folders. Remove the DLL from System32 and instead place it in the same directory as your executable file.
The other problem, given the code shown, is that the exported DLL function uses the register calling convention, but you import it using the stdcall calling convention. You must ensure that the calling conventions used by DLL and EXE match each other.
Related
When I start a program in the IDE, I use the following code to generate a log file. All of the paths are correct, checked with F8, but the log file is not output.
When I run the executable outside of the IDE, the log file is output properly.
Is there a setting somewhere in XE7 that prohibits this?
procedure LogProgram(const aEvent: String);
var
TheLogFileName, TheLogLine: String;
TheLogFile: TextFile;
TheDay, TheMonth, TheYear, TheHour, TheMinute, TheSecond,
TheMilliSecond: Word;
begin
TheLogFileName := Format('%s%d.log', [usPATH_LOGS, Trunc(Now)]);
AssignFile(TheLogFile, TheLogFileName);
if not FileExists(TheLogFileName) then
Rewrite(TheLogFile);
Append(TheLogFile);
DecodeDateTime(Now, TheYear, TheMonth, TheDay, TheHour, TheMinute, TheSecond,
TheMilliSecond);
TheLogLine := Format('%d-%d-%d: %d:%d:%d:%d%s%s', [TheYear, TheMonth, TheDay,
TheHour, TheMinute, TheSecond, TheMilliSecond, #9, aEvent]);
Writeln(TheLogFile, TheLogLine);
CloseFile(TheLogFile);
end;
I tried to output a file, using the above code, while a program was running in the Delphi XE7 IDE, expected a log (text) file and got no output. Running the same program outside of the IDE generates the log (text) file properly.
#fpiette I checked Windows Security and folder protection is not active.
#Andreas-Rejbrand I'm using relative paths. Paths are being calculated relative to the path of the executable
#SilverWarior I did not change anything in Delphi through menu Run->Parameters. There are no paths listed there.
I did a global search (on my computer) for the name of the file, I was trying to create and discovered it in a containment folder (c:\VTRoot) managed by Comodo antivirus.
It turned out that if Comodo thought the file being created was a security risk, it moved it to the containment area on C:\
I went to the Comodo dashboard and disabled Auto-Containment and now Delphi XE7 works as it should.
I have a dll that can be called from different exe applications (dll and exe's are written in Delphi 5).
Is it possible to know inside the dll which exe application it was called from?
In other words let's say I have App1.exe, App2.exe and MyDll.dll. App1.exe called the MyDll.exe. I want to know inside the dll that it was called from App1 but not from App2.
If you call the Windows API function GetModuleFileName() passing NULL (0) as the module handle (first parameter) then this will return the filename of the process, i.e. the executable:
function GetProcessFileName: String;
var
buf: array[0..MAX_PATH-1] of Char;
begin
GetModuleFileName(0, #buf, Length(buf));
result := buf;
end;
NOTE: As Raymond Chen always says, sample programs do little or no error checking! :)
For further information on the use of this API consult the documentation and use accordingly.
I have two applications in Delphi for which I don't have any code source:
I use an interface from application A to call an DLL file from application B. Example, I usually pass a service number, 200011, from interface A to call DLL file B for a value return. But, recently the application A have changed the variable. I have to add P00200011 to call DLL file B.
I have tried to create an DLL C#, but the DLL in B is created with the fastcall convention and I cannot change this DLL file.
What are others ways I can do it? I'm out of ideas.
You need to write a wrapper DLL. You build your DLL with the functions you want to intercept, and in your code you simply load and call the original DLL. Then you place your wrapper in the same directory of your application. All calls from the application will go to your wrapper DLL and from there to the original DLL.
Here is a simple example
supose you have this library (B.DLL)
library B;
function B_FUNCTION(value:integer): integer; export;
begin
result:=value+1;
end;
exports B_FUNCTION;
end.
And this program that uses it
program A;
{$apptype console}
function B_FUNCTION(value:integer): integer; external 'b.dll';
var i:integer;
begin
i:=B_FUNCTION(2010);
writeln(i);
end.
Compile both programs and run them. The result printed is 2011.
Now, code your wrapper DLL
library w;
uses windows;
function B_FUNCTION(value:integer): integer; export;
var
adll: Thandle;
afunc: function(v:integer):integer;
begin
adll:=LoadLibrary('TRUE_B.DLL');
afunc:= GetProcAddress(adll,'B_FUNCTION');
result:=afunc(value+1);
FreeLibrary(adll);
end;
exports B_FUNCTION;
end.
Build it, you'll have A.EXE, B.DLL and W.DLL. Replace them
REN B.DLL TRUE_B.DLL
REN W.DLL B.DLL
Execute A, now it will spit 2012.
It's not entirely obvious to me which parts are yours and what calls what, but you should be able to create your own intermediate DLL in Delphi with an interface that uses fastcall and which forwards the call to the real DLL using another calling convention.
Need some help in creating function which can create folders recursively with giving path:
C:\TestFolder\Another\AndAnother
Delphi function MkDir returning IOerror = 3.
MkDir('C:\TestFolder\Another\AndAnother');
Use
ForceDirectories('C:\TestFolder\Another\AndAnother');
(This is a standard RTL function, found in SysUtils.pas. Hence you do not need to create your own function, even though that wouldn't have been difficult.)
SysUtils is obsolete now and ForceDirectories is not UNC aware!
There is a new library in since Delphi XE7 (or even earlyer?) called IOUtils.
IOUtils is cross-platform compatible and UNC aware.
function ForceDirectories(FullPath: string): Boolean; // Works with UNC paths
begin
TDirectory.CreateDirectory(FullPath);
Result:= DirectoryExists(FullPath);
end;
Note: The function is from Delphi LightSaber library. There are several other similar I/O functions there (like ListFilesOf(Folder)).
I have an application which Should be converted to a library. I' ve only copied the project dpr and changed the source file:
library aLibrary;
uses
FastMM4,
Forms,
SysUtils,
Windows,
Mainfrm in 'Mainfrm.pas' {Mainform};
{$R *.res}
Procedure DllMain(Reason: Integer);
Begin
If Reason = DLL_PROCESS_ATTACH Then
Begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
ExitCode := 0;
End;
If Reason = DLL_PROCESS_DETACH Then
Begin
Application.Terminate;
MainForm.Free;
End;
End;
Begin
DllProc := #DllMain;
DllProc(DLL_PROCESS_ATTACH);
End.
As you can see, I've simply removed the usually auto-generated code lines related to the app initialization and put them in the DllMain procedure, changed the 'program' keyword to 'library'.
The dll loads well, the embedded program runs well too, but I can't manage to free it (FreeLibrary) in the host process. The dll freezes, whatever the DLL_PROCESS_DETACH code is (even when nothing is put for this case).
What would be the proper way to free all the application stuffs ?
You're doing way too much in your DLL procedure.
While loading a DLL, the OS acquires the loader lock. That prevents any other libraries from being loaded at the same time. If you call a function that's in a library that hasn't already been loaded, then that will trigger an attempt to load that library. Since you're still inside the loader lock, that other library blocks while attempting to acquire the lock itself, and you get deadlock. Similar rules apply for unloading.
You should do the absolute minimum in the DllMain function to get your library loaded or unloaded. Leave everything else to a separate function that the DLL host can call after loading is complete or just before unloading begins. In your case, the minimum is probably nothing at all.
Ok, I've well understood your summary about dll locks and I've put the embedded application constructor/destructor in some standard exported dll routines, so there 's no more DllMain. However calling freelibrary still reveals a deadlock. My dll is instantiated by another dll, which is itself instantiated in an executable. Maybe the lock is introduced at a lower level in the processes hierarchy.