i have given a chance to my software user to select dll from openfile dialog.(so my user can download dlls form my website and use it with the main project ). everything is working fine and it can even find that dlls is provided by me or selected an invalid dll.but the problem raises if the user selects a renamed file(eg : apple.txt file renamed to apple.dll ). i typed the code like this
try
dllHandle := LoadLibrary( pwidechar(openfiledialog1.filename)) ;
catch
{ showmessage if it is not a dll (but it can be any dll, it checks this is my dll or 3rd party later )}
end;
error message shown by delphi is 'bad library image selected'
but try catch is not working if the user selects invalid dll it is showing its own error message and struck up.
can anyone help me,i am using delphi 2009
There's no exception to catch because an exception is not raised when LoadLibrary fails; it just returns '0'.
You should check if 'dllHandle' is 0 or not, if it is, show the error information to the user by using GetLastError as documented. Alternatively you can use the Win32Check function in the RTL which will raise an exception with the appropriate error message:
(edit: Documentation of 'LoadLibrary' states that: To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function. So if you don't want the OS to show an additional dialog you'd set the error mode before calling LoadLibrary.)
var
dllHandle: HMODULE;
ErrorMode: UINT;
begin
if OpenDialog1.Execute then begin
ErrorMode := SetErrorMode(SEM_FAILCRITICALERRORS); // disable OS error messages
try
dllHandle := LoadLibrary(PChar(OpenDialog1.FileName));
finally
SetErrorMode(ErrorMode);
end;
if Win32Check(Bool(dllHandle)) then begin // exception raised if false
// use the libary
end;
end;
end;
Related
Experts, take the following code snippet below:
var
aAllTasks : Array [0..1] of ITask //global private var
Procedure SetImage();
begin
//..
//.. Get a URL of an image stored on a server
//..
aAllTasks[0] := TTask.Run(
Procedure
begin
// Download the Image and display the image
end);
aAllTasks[1] := TTask.Run(
Procedure
begin
// Get the rating of the image from a REST server
end);
end;
when the debugger hits
aAllTasks[1] := TTask.Run(...);
I get
First chance exception at $001A30B5. Exception class EThreadNameException with message ''. Process APPNAME (126391)
It throws the exception but it does not seem to crash the App
This only happens when debugging/running iOS apps
iOS 9.2
RS 10 Seattle (with Update 1)
PA server 17.0 (with hotfix.. V 8.0.1.52)
Xcode version 7.2 (7C68)
What would cause this and how would I fix it?
Your code calls, TThread.NameThreadForDebugging. That looks like this:
class procedure TThread.NameThreadForDebugging(AThreadName: string; AThreadID: TThreadID);
{$IF Defined(MSWINDOWS)}
.... // windows specific code removed
{$ELSE MSWINDOWS}
const
cExceptionMessage = 'Type=$1000,Name=%s,ThreadID=%d,Flags=0';
EMBDBKPRESENTNAME = 'EMB_DBK_PRESENT';
{$IF Defined(MACOS)}
OLDEMBDBKPRESENTNAME = 'EMB_MACOSX_DBK_PRESENT';
{$ENDIF}
begin
{$IF Defined(MACOS)}
if (getenv(EMBDBKPRESENTNAME) <> nil) or (getenv(OLDEMBDBKPRESENTNAME) <> nil) then
{$ELSEIF Defined(ANDROID)}
if (System.DebugHook <> 0) or (getenv(EMBDBKPRESENTNAME) <> nil) then
{$ELSE}
if (getenv(EMBDBKPRESENTNAME) <> nil) then
{$ENDIF}
begin
try
raise EThreadNameException.Create(
Format(cExceptionMessage, [AThreadName, AThreadID]));
except
end;
end;
end;
{$ENDIF !MSWINDOWS}
This function is called when you wish to give your thread a name. Now, thread objects do not have names. So when you give your thread a name, it is for debugging purposes only. The debugger keeps track of the names you provide, and associates them with thread IDs. Then when the debugger presents information about threads, it can look up the name from the ID and present that to you. But this is purely a debugger mechanism because the operating system does not support thread names.
So, how do you signal to the debugger that you wish to give a thread a name. Well, you throw a specific exception. The debugger is aware of the exception and gets the first chance to handle the exception. The debugger receives the name and the thread ID in the exception text and makes a note of that information.
Notice that the exception is swallowed immediately and so this does not interrupt the flow of the program.
So, it is normal for this exception to be raised, to be handled by the debugger, and not to impact on the behaviour of the program. What is odd is that the debugger is breaking on that exception. I would have expected that exception to be ignored by the debugger, by default.
An old QC report (QC#105310) for OSX describes exactly the behaviour that you are observing. That issue was closed and marked as fixed in XE7. Perhaps this issue has re-surfaced, or perhaps it was never fixed for the mobile platforms. I suggest that you submit a bug report to Quality Portal.
I have a procedure to call a function named [main()] from a DLL , this is the Caller procedure :
procedure call_dll(path:string);
var
lib: HMODULE;
mainfn: procedure(); stdcall;
begin
if FileExists(path) then
begin
try
lib := LoadLibrary(PAnsiChar(path));
Win32Check(lib <> 0);
try
#mainfn := GetProcAddress(lib, 'main');
Win32Check(Assigned(mainfn));
mainfn();
finally
FreeLibrary(lib);
end;
except
end;
end;
end;
Until yet every thing is working fine , I mean after writing the correct path of the DLL everything work without a problem but if I write a wrong path (other file path) in the path parameter it show me a popup error that this is is not a Win32 DLL but I don't want to bother the user with this type of errors , so I need a function to check the DLL and if it's not then it will automatically ask for another file again without showing the popup error ?
It is your code that is raising the exception. Your code makes an explicit choice to handle errors by raising exceptions. The exception is raised by your code here:
Win32Check(lib <> 0);
If you don't want to raise an exception, don't use Win32Check. Instead check the value of lib and handle any errors by whatever means you see fit.
The same issue is present for your other use of Win32Check.
Of course you are swallowing all exceptions with your catch all exception handler. A catch all exception handler is usually a bad idea. I don't understand why you have included that. I think you should remove it.
So if you are seeing dialogs when running outside the debugger it follows that the system is producing the dialogs. You should be disabling the system's error message dialogs by calling SetErrorMode on startup passing SEM_FAILCRITICALERRORS.
var
Mode: DWORD;
....
Mode := SetErrorMode(SEM_FAILCRITICALERRORS);
SetErrorMode(Mode or SEM_FAILCRITICALERRORS);
The somewhat clunky double call is explained here: http://blogs.msdn.com/b/oldnewthing/archive/2004/07/27/198410.aspx
Prompted by a q here yesterday, I'm trying to re-familiarise myself with TGeckoBrowser
from here: http://sourceforge.net/p/d-gecko/wiki/Home.
(Nb: requires the Mozilla XulRunner package to be installed)
Things seem to have moved backwards a bit since I last tried in the WinXP era, in that
with a minimal D7 project to navigate to a URL, I'm getting errors that I don't recall
seeing before. I've included my code below. These are the errors which I've run into
navigating to sites like www.google.com, news.bbc.co.uk, and here, of course.
The first exception - "Exception in Safecall method" - occurs as my form first displays, before naviagting anywhere at all. I have a work-around in the form of a TApplication.OnException handler.
My q is: a) Does anyone know how to avoid it in the first place or b) is there a tidier way of catching it than setting up a TApplication.Exception handler, which always feels to me like a bit of
an admission of defeat (I mean having one to avoid the user seeing an exception, not having an application-wide handler at all).
This exception occurs in this code:
procedure TCustomGeckoBrowser.Paint;
var
rc: TRect;
baseWin: nsIBaseWindow;
begin
if csDesigning in ComponentState then
begin
rc := ClientRect;
Canvas.FillRect(rc);
end else
begin
baseWin := FWebBrowser as nsIBaseWindow;
baseWin.Repaint(True);
end;
inherited;
end;
in the call to baseWin.Repaint, so presumably it's
presumably coming from the other side of the interface. I only get it the first
time .Paint is called. I noticed that at that point, the baseWin returns False for GetVisibility,
hence the experimental code in my TForm1.Loaded, to see if that would avoid it.
It does not.
2.a After calling GeckoBrowser1.LoadURI, I get "Invalid floating point operation"
once or more depending on the URL being loaded.
2.b Again, depending on the URL, I get: "Access violation at address 556318B3 in module js3250.dll. Read of address 00000008." or similar. On some pages it occurs every few seconds (thanks I imagine to some JS timer code in the page).
2a & 2b are avoided by the call to Set8087CW in TForm1.OnCreate below but I'm
mentioning them mainly in case anyone recognises them and 1 together as symptomatic
of a systemic problem of some sort, but also so google will find this q
for others who run into those symptoms.
Reverting to my q 1b), the "Exception in Safecall method" occurs from StdWndProc->
TWinControl.MainWndProc->[...]->TCustomGeckoBrowser.Paint. Instead of using an
TApplication.OnException handler, is there a way of catching the exception further
up the call-chain, so as to avoid modifying the code of TCustomGeckoBrowser.Paint by
putting a handler in there?
Update: A comment drew my attention to this documentation relating to SafeCall:
ESafecallException is raised when the safecall error handler has not been set up and a safecall routine returns a non-0 HResult, or if the safecall error handler does not raise an exception. If this exception occurs, the Comobj unit is probably missing from the application's uses list (Delphi) or not included in the project source file (C++). You may want to consider removing the safecall calling convention from the routine that gave rise to the exception.
The GeckoBrowser source comes with a unit, BrowserSupports, which looks like a type library import unit, except that it seems to have been manually prepared. It contains an interface which includes the Repaint method which is producing the SafeCall exception.
nsIBaseWindow = interface(nsISupports)
['{046bc8a0-8015-11d3-af70-00a024ffc08c}']
procedure InitWindow(parentNativeWindow: nativeWindow; parentWidget: nsIWidget; x: PRInt32; y: PRInt32; cx: PRInt32; cy: PRInt32); safecall;
procedure Create(); safecall;
procedure Destroy(); safecall;
[...]
procedure Repaint(force: PRBool); safecall;
[...]
end;
Following the suggestion in the quoyed documentation, I changed th "safecall" to StdCall on the Repaint member (but only that member) and, presto!, the exception stopped occurring. If it doesn't reappear in the next couple of days, I'll post that as an answer, unless anyone comes up with a better one.
My project code:
uses
BrowserSupports;
procedure TForm1.FormCreate(Sender: TObject);
begin
Set8087CW($133F);
Application.OnException := HandleException;
end;
procedure TForm1.HandleException(Sender: TObject; E: Exception);
begin
Inc(Errors);
Caption := Format('Errors %d, msg: %s', [Errors, E.Message]);
Screen.Cursor := crDefault;
end;
type
TMyGeckoBrowser = class(TGeckoBrowser);
procedure TForm1.Loaded;
begin
inherited;
GeckoBrowser1.HandleNeeded;
(TMyGeckoBrowser(GeckoBrowser1).WebBrowser as nsIBaseWindow).SetVisibility(True);
end;
procedure TForm1.btnLoadUrlClick(Sender: TObject);
begin
try
GeckoBrowser1.LoadURI(edUrl.Text);
except
end;
end;
Looking at the headers, the prototype for Repaint is effectively as follows:
HRESULT __stdcall Repaint(PRBool force);
and that means that
procedure Repaint(force: PRBool); safecall;
is a reasonable declaration. Remember that safecall performs parameter re-writing to convert COM error codes into exceptions.
This does mean that if the call to Repaint returns a value that indicates failure, then the safecall mechanism will surface that as an exception. If you wish to ignore this particular exception then it is cleaner to do so at source:
try
baseWin.Repaint(True);
except
on EOleException do
; // ignore
end;
If you wish to avoid dealing with exceptions then you could switch to stdcall, but you must remember to undo the parameter re-writing.
function Repaint(force: PRBool): HRESULT; stdcall;
Now you can write it like this:
if Failed(baseWin.Repaint(True)) then
; // handle the error if you really wish to, or just ignore it
Note that Failed is defined in the ActiveX unit.
If you want to troubleshoot the error further then you can look at the error code:
var
hres: HRESULT;
....
hres := baseWin.Repaint(True);
// examine hres
Or if you are going to leave the function as safecall then you can retrieve the error code from the EOleException instance's ErrorCode property.
We're migrating our XE projects to XE5, however, we encountered the access violation exception about teechart during the test.
I've created a test application to recreate the issue. With the test app, it works fine when open the first teechart form but will get the access violation exception when open it second time or open a new form.
Please refer to the attached test app from the following QC (embarcadero).
http://qc.embarcadero.com/wc/qcmain.aspx?d=122729
When debug it with DCUs. The exception happened when notifying TDBChart's OnStateChange event.
procedure TDataSet.DataEvent(Event: TDataEvent; Info: NativeInt);
begin
...
if NotifyDataSources then
begin
for I := 0 to FDataSources.Count - 1 do
FDataSources[I].DataEvent(Event, Info); // <<---- Access Violation
if FDesigner <> nil then FDesigner.DataEvent(Event, Info);
end;
end;
As David Berneda said at Quality Central:
Its related to using an internal TObjectList generic collection inside
DBChart. The code has been improved so the error is fixed now (a new
code takes care of destroying the ObjectList items correctly).
As a workaround, you can add this code at your form's OnClose event:
type
TChartAccess=class(TDBChart);
procedure TOutcomesGraphFm.bbtnCloseClick(Sender: TObject);
begin
TChartAccess(dbcBar).RemovedDataSource(bsTestScores,bsTestScores.DataSource);
Close;
end;
I have Delphi XE3, Windows 7 Pro 64bit.
My application is working fine in my PC but my users told me application crashes upon start on their Win XP and also (!!) on their Win 7.
I tried to run the app on my Win 7 but logged as an ordinary user (no admin) - it works.
So now I have installed virtual machine with Windows XP and really - app crashes upon startup.
I need to find what can be the problem but I'm helpless.
As far as I can't use debugger (I dont have Delphi on that VM installed),
I tried to put some MessageBox(0, 'Hello', 'Test', MB_OK); in various places in my app to catch the place where it happens and this is what I found:
I have this in my project-source:
MessageBox(0, 'Hello', 'Test', MB_OK); // shows OK
Application.CreateForm(TfMain, fMain);
MessageBox(0, 'Hello', 'Test', MB_OK); // doesn't show - crash before this line
And this is in the OnCreate function of my main form called fMain:
procedure TfMain.FormCreate(Sender: TObject);
begin
MessageBox(0, 'Hello', 'Test', MB_OK); // doesn't show - crash before this line
...
So where can this app crash?
Not even first line in the OnCreate executes....
I have no idea... Anybody?
Don't know if this is important: I have some units in fMain uses clause under interface and also under implementation. Should I look there? But what happens just before OnCreate of my main form ?
Finally I got it !
place PRINT DIALOG component on your form (TPrintDialog)
set COPIES = 1 (or more than default zero) in the object inspector during design time
try to run such application on WinXP where NO PRINTERS are installed
Application just crashes upon start and in the details you will see only some kernel32.dll address...
I didn't test it on Win 7 without printers. I have no such system around...
Here's another way to track this down without Delphi on the VM...
Copy your project.
Remove all the units from Project Source except your main form.
Launch your application from XP see if it crashes.
If it crashes...then look at the units being dragged in from your main form...start removing them until your program stops crashing.
If it doesn't crash...start adding units/forms back into your project source until it crashes.
Do you have JCL/JVCL installed(JEDI)?
If so create a Logger...note the Logger needs to be created and hooked before your MainForm code executes...You will also need to set up a detailed Stack Trace from Unhandled Exceptions,
in Delphi select->Project/Options/Linker/Map file/Detailed}
You will need something like this in your Logger unit
procedure HookGlobalException(ExceptObj: TObject; ExceptAddr: Pointer; OSException: Boolean);
var
a_List: TStringList;
begin
if Assigned(TLogger._Instance) then
begin
a_List := TStringList.Create;
try
a_List.Add(cStar);
a_List.Add(Format('{ Exception - %s }', [Exception(ExceptObj).Message]));
JclLastExceptStackListToStrings(a_List, False, True, True, False);
a_List.Add(cStar);
// save the error with stack log to file
TLogger._Instance.AddError(a_List);
finally
a_List.Free;
end;
end;
end;
initialization
Lock := TCriticalSection.Create;
Include(JclStackTrackingOptions, stTraceAllExceptions);
Include(JclStackTrackingOptions, stRawMode);
// Initialize Exception tracking
JclStartExceptionTracking;
JclAddExceptNotifier(HookGlobalException, npFirstChain);
JclHookExceptions;
finalization
JclUnhookExceptions;
JclStopExceptionTracking;
Lock.Free;