Delphi XE+ has a "Search for Usages" option. Is there a similar option in Delphi 7 to find function/procedure callers? I either do a plain text search or place a breakpoint and see who the caller was in the Call Stack during run time. Both are time consuming and very inefficient.
Opening the app in Delphi XE and using "Search for Usages" doesn't work. The app doesn't compile.
There is no equivalent to Search for Usages in Delphi 7. That feature was first introduced in XE.
Even the Find References feature was not introduced until Delphi 2005 (when Delphi switched to the Galileo IDE).
There is an anlternate way of find the callers:
Use a debugger that can show the Call Stack (like MadExcept) and make a "fake" exception in your function like this:
function WhereDoYouCallMe;
begin
raise Exception.Create('Called');
...
...
end;
Now every time the function is called, you will get an error box where you can view the Stack and get where it called. You can continue the program or you can set your breakpoints and so on.
You can also mark the method 'deprecated' and you will get a list of usages in your compiler warnings.
Not ideal but alternatively you could
Rename the method
Compile
Check the compiler errors to find all callers (those that can be resolved at compile time).
As mentioned by dummzeug
Renaming the method is the simplest way to find all uses.
Unfortunately you have to rename all uses in turn to find the next
use. And afterwards revert the changes.
Related
Just upgraded from Delphi XE to Tokyo, and was hoping for some updated IDE features.
One nice to have feature would be automatically providing options to add a unit to the uses clause. For example, if you reference something in code that isn't in a uses, it would be nice if the IDE prompted you to add the related unit(s).
For example, keeping it simple, in IntelliJ, you might declare a Button, but not yet have added the associated Library to the Import clause.
When this happens, the offending line is highlighted (just like in Delphi), but the IDE will let you add the necessary library with an Alt-Enter. If there are multiple libraries (it knows about it) it will prompt you for the one you want.
Anything like this for Delphi?
Delphi 2007 and later versions support this for most types that it knows about (in the search or library path). (It may have been available in D2005/2006; I don't have them installed anywhere now to check. I know it was not in Delphi 7.)
Put in the type, and use the Refactor menu (Refactor->Find Unit) or press Ctrl+Shift+A.
Here's an example:
It's not 100% effective, but it's a vast improvement over the old way.
(And yes, I know about TArray<string>, before someone chimes in. I just grabbed a quick type that I knew wouldn't be in the default VCL form uses clause for an example.)
I am writing a Windows 32 bit program that can use one of multiple possible dlls. So it tries to load each dll in turn, using SysUtils.SafeLoadLibrary and if loading succeeds, it uses that dll.
Unfortunately some of these dlls are statically linked to other dlls. These dlls may be missing from the computer. In that case I get dialog telling me
[myprogram]: [myprogram.exe] System Error
The program can't start because [some dll name] is missing from your computer. Try reinstalling the program to fix this problem."
After pressing the OK button on that dialog, the program gets the error code and tries one of the other dlls which then works fine.
Rather than showing that dialog to the user I want my program to silently ignore it.
How can I accomplish that?
In case it matters: My program is written in Delphi 2007. The Windows version is Windows 8.1, but the program should also work with other Windows versions >= Windows XP.
I have tried SetErrorMode(SEM_FAILCRITICALERRORS) but it did not make any difference.
SafeLoadLibrary sets the error mode to the value that you provide as an argument, and then restores it after the call to LoadLibrary returns. Most likely you are not supplying a value for that parameter, in which case a default of SEM_NOOPENFILEERRORBOX is passed. In that case it is probably disabling SEM_FAILCRITICALERRORS which would explain the behaviour that you see.
You could solve the problem by passing SEM_FAILCRITICALERRORS every time you call SafeLoadLibrary. Or, perhaps better would be to pass the current error mode. However this is hard to obtain. In Vista and later you can call GetErrorMode. But in older versions you have to do this:
ErrorMode := SetErrorMode(0);
SetErrorMode(ErrorMode);
Because this is a process wide setting, you have a window of opportunity between the two calls to SetErrorMode, for multi-threaded applications to be caught out.
Frankly, I believe that you should call SetErrorMode exactly once in the lifetime of a process, at startup. With that in mind, I would shun SafeLoadLibrary.
If you wish to take advantage of its other function, namely to protect against changes to floating point control state, then you should implement that functionality yourself, in my opinion.
In a Delphi Project CTRL + Space not working.
Before "uses" when I Press CTRL + Space the code completion is appeared but after "uses" does not appear.
I use Delphi 2009.
I install Fastreport and raize components and vcl Skin.
The most probable cause for your problem is that you have some smal syntactical error like missing semicolom, invalid name, etc. somewhere between the point where CTRL+Space works and where no longer works. This is due the way how Code Insight is checking the code structure.
So I recomend you go to menu Project and then chose Syntax Check.
Another cause for CTRL+Space not working is that your are still debuging your program. Do nte that while debugging sesion is in progress both Code Insight and Error Insight are disabled.
Something that in general wreaks havoc with Code Insight (Ctrl+Space) is conditional compilation.
So watch out for {$IFDEF ...} in your code.
I prefer to avoid conditional compilation in anything except library code that needs to support multiple Delphi versions. However, if you must use it, consider inverting the logic so you can use {$IFNDEF ...}.
Also, the feature doesn't always work if your code cannot compile. This depends on what dependencies are unable to compile at the point where you press Ctrl+Space.
However, in my experience the feature does sometimes just "break". If you're lucky closing and re-opening the project fixes it. But usually I have to close and re-open Delphi and do a full rebuild of the project.
I had the same problem I press Ctrl+Space to all units in uses section and I see one unit Delphi can't recognize. I delete it and type it again with Ctrl+Space; after that everything is ok.
another reason is if exists a special character like a tab character in your unit.
The "So watch out for {$IFDEF ...} in your code." had this. Temporarily did a Ctrl-X on it and then did Ctrl+Spacebar and pasted the code back in. Then... it worked again. Delphi XE10.1 Update 2. Other reasons why it sometimes doesn't work still remain a mystery. Can be very frustrating indeed.
http://en.wikipedia.org/wiki/REPL Read–eval–print_loop
Is there such a thing for Delphi ?
It would be rather useful to explore DLLs such as Windows APi and sketch their usage, when dealing with border cases scarcely documented.
I tried pascal scripts, such as one in Cnwizards, but it is much less comfortable.
For example it cannot use units like Windows.pas and you had to make some strange stubs of your own for it.
And anyway, those scripts are less easy to use for "try this try that" scenario than Repl.
For Delphi objects most clsoe thing it to pause on breakpoint and use Evaluate/Modify window, but it only works with Delphi objects, not DLLs; it cannot make temporary vars to cache values and such.
It's not really what you're looking for, because Delphi is a statically typed, compiled language, but if you really insist on being able to type some pascal in and see if it does anything, you can try the TJvInterpreter component that comes in the Jedi VCL.
Note that the experience is nothing like using python. You can't just type "uses module" and hit enter, because pascal units must be complete before they can even be interpreted by JvInterpreter, and the JvInterpreter needs you to write a wrapper for every single other unit you want to import. You would go crazy. I'm not seriously advising anybody to try to build a REPL around TJvInterpreter.
The "interactive magic" element of Delphi is called the "designtime environment" and the way we build using "components". We don't even do that bit by writing code much, we do it all visually with our mouse and keyboard. It's called RAD (rapid application development) and is powered by the VCL (visual component library) in Delphi, and (like REPL) is one of the many ways of doing very-rapid development.
The other thing we have that is a lot like a REPL is this button in Delphi:
You click it, after creating a new empty project, and whatever code you added to your new empty project is built and running in less than a second. Close enough to a REPL for me. It's kind of like binary executable instant bliss.
Write one line. Build and run (1 second). Instant.
There is a whole host of components that I am trying out to better understand how to detect when a file or folder has changed. I want to write a delphi application to also do this but delphi Unicode(Tiburon) doesn't seem to ship with any component that can accomplish this. At least not anymore. I found a curious component on the palette called shellersources and after just placing it on a form and running it I get an error:
Cmctrls was compiled with a different version of SHLObj.IAutocomplete
I tried virtually all the component listed here: shell resourcehttp://www.torry.net/pages.php?id=252 and interestingly I get the same exact error on compiling them. I am running delphi on Vista, could this be a vista issue? I also tried the SHChangeNotify component from about.com and even it too produced an identical error concerning SHlObj.IAutocomplete. Anyone noticed this? Strange.
There are two Windows API calls that will help you accomplish this in Delphi:
FindFirstChangeNotification
FindNextChangeNotification
The drawback is that these function calls are low-level-non-delphi components. But you can still make those function calls in Delphi. If you ABSOLUTELY need a delphi component, you could always write your own, using the mentioned functions as base.