Friday, December 21, 2007

Delphi and C++Builder IDE Tip of the Day

One of the most useful features and I believe least used is CTRL + F12. This brings up a list of all the units in the project manager, allows you to type one in and open it. Very handy. It turns out that the little down arrow on the right side of the edit view also has a shortcut key, CTRL + ALT + F12. This allows you to quickly view the open units, especially useful if there are more units than can be shown on the screen at once.

So there you have it, a quick tip before the Christmas break. I won't be posting here again until the new year so everyone have a great Holiday, Christmas and New Years!

Reading Info From a Package Part IV

Well this week really became package week. I posed part I here, part II here and part III here.

For this version I wrapped up the previous package cracking code into a class for easy consumption by any program. Notice I used the previously unused second parameter on GetPackageInfo which is just passed to PackageInfoProc via the Param parameter. This allows us to pass the Self pointer to remove globals. I also added error checking and removed some hard coded constants readers had commented on.


program pdump;

{$APPTYPE CONSOLE}

uses
SysUtils,
Classes;

type
TPackageProducer = (ppOld, ppUndefined, ppBCB, ppDelphi);
TPackageConsumer = (pcCompat, pcDelphi, pcBCB);

TPackage = class
private
FProducer: TPackageProducer;
FConsumer: TPackageConsumer;
FRequiresList: TStrings;
FImplicitUnits: TStrings;
FContainsList: TStrings;
FNeverBuild: Boolean;
FDesignOnly: Boolean;
FRunOnly: Boolean;
public
constructor Create;
destructor Destroy; override;
function LoadFromFile(const FileName: string): Boolean;

property RequiresList: TStrings read FRequiresList;
property ImplicitUnits: TStrings read FImplicitUnits;
property ContainsList: TStrings read FContainsList;
property Producer: TPackageProducer read FProducer;
property Consumer: TPackageConsumer read FConsumer;
property NeverBuild: Boolean read FNeverBuild;
property DesignOnly: Boolean read FDesignOnly;
property RunOnly: Boolean read FRunOnly;
end;

procedure WriteStrings(Strings: TStrings);
var
Index: Integer;
begin
for Index := 0 to Strings.Count - 1 do
WriteLn(Strings[Index]);
end;

procedure PackageInfoProc(const Name: string;
NameType: TNameType; Flags: Byte;
Param: Pointer);
begin
if NameType = ntContainsUnit then
begin
TPackage(Param).ContainsList.Add(Name);

if (Flags and ufImplicitUnit <> 0) and
(Flags and ufWeakPackageUnit = 0) then
begin
TPackage(Param).ImplicitUnits.Add(Name);
end;
end
else if NameType = ntRequiresPackage then
TPackage(Param).RequiresList.Add(Name);
end;

{ TPackage }

constructor TPackage.Create;
begin
FRequiresList := TStringList.Create;
FImplicitUnits := TStringList.Create;
FContainsList := TStringList.Create;
end;

destructor TPackage.Destroy;
begin
FRequiresList.Free;
FImplicitUnits.Free;
FContainsList.Free;
inherited;
end;

function TPackage.LoadFromFile(const FileName: string): Boolean;
var
Module: HMODULE;
Flags: Longint;
begin
Result := False;
Module := LoadPackage(FileName);

try
if Module <> 0 then
begin
GetPackageInfo(Module, Self, Flags, PackageInfoProc);

FNeverBuild := (Flags and pfNeverBuild) <> 0;
FDesignOnly := (Flags and pfDesignOnly) <> 0;
FRunOnly := (Flags and pfRunOnly) <> 0;

case Flags and pfProducerMask of
pfV3Produced: FProducer := ppOld;
pfProducerUndefined: FProducer := ppUndefined;
pfBCB4Produced: FProducer := ppBCB;
pfDelphi4Produced: FProducer := ppDelphi;
else
FProducer := ppUndefined;
end;

case Flags and pfConsumerMask of
pfConsumerDelphi: FConsumer := pcDelphi;
pfConsumerBCB: FConsumer := pcBCB;
else
if FProducer <> ppBCB then
FConsumer := pcCompat
else
FConsumer := pcBCB;
end;

Result := True;
end;
finally
UnloadPackage(Module);
end;
end;

var
Package: TPackage;
FileName: string;
begin
if ParamCount <> 1 then
begin
WriteLn('Usage: PDUMP [PackageFileName]');
Exit;
end;

FileName := ParamStr(1);

if not FileExists(FileName) then
begin
WriteLn(Format('File %s does not exist.', [FileName]));
Exit;
end;

Package := TPackage.Create;

try
if Package.LoadFromFile(FileName) then
begin
if Package.NeverBuild then
WriteLn('Never Build');

if Package.DesignOnly then
WriteLn('Design Only');

if Package.RunOnly then
WriteLn('Run Only');

case Package.Producer of
ppOld: WriteLn('Old Producer');
ppUndefined: WriteLn('Undefined Producer');
ppBCB: WriteLn('BCB Producer');
ppDelphi: WriteLn('Delphi Producer');
end;

case Package.Consumer of
pcCompat: WriteLn('Compat Consumer');
pcBCB: WriteLn('BCB Consumer');
pcDelphi: WriteLn('Delphi Consumer');
end;

if Package.RequiresList.Count > 0 then
begin
WriteLn(#13#10 + 'Requires List:');
WriteStrings(Package.RequiresList);
end;

if Package.ImplicitUnits.Count > 0 then
begin
WriteLn(#13#10 + 'Implicit Uses:');
WriteStrings(Package.ImplicitUnits);
end;

if Package.ContainsList.Count > 0 then
begin
WriteLn(#13#10 + 'Contains List:');
WriteStrings(Package.ContainsList);
end;
end;
finally
Package.Free;
end;
end.

Thursday, December 20, 2007

Reading Info From a Package Part III

This week became package week. I posed part I here and part II here for reading the information contained within a package. Today I'll continue to grow the program and add the ability to read the remaining information contained in the Flags which is is what language built the package and which language the package is designed for. So there you have it, a small utility that can read the information contained in a package.


program pdump;

{$APPTYPE CONSOLE}

uses
SysUtils,
Classes;

var
RequiresList: TStrings;
ImplicitUnits: TStrings;
ContainsList: TStrings;

procedure PackageInfoProc(const Name: string;
NameType: TNameType; Flags: Byte;
Param: Pointer);
begin
if NameType = ntContainsUnit then
begin
ContainsList.Add(Name);

if (Flags and $10 <> 0) and (Flags and $06 = 0) then
ImplicitUnits.Add(Name);
end
else if NameType = ntRequiresPackage then
RequiresList.Add(Name);
end;

procedure WriteStrings(Strings: TStrings);
var
Index: Integer;
begin
for Index := 0 to Strings.Count - 1 do
WriteLn(Strings[Index]);
end;

type
TPackageProducer = (ppOld, ppUndefined, ppBCB, ppDelphi);
TPackageConsumer = (pcCompat, pcDelphi, pcBCB);

var
Module: HMODULE;
Flags: Longint;
Producer: TPackageProducer;
Consumer: TPackageConsumer;
begin
RequiresList := TStringList.Create;
ImplicitUnits := TStringList.Create;
ContainsList := TStringList.Create;

Module := LoadPackage(ParamStr(1));

try
if Module <> 0 then
begin
GetPackageInfo(Module, nil, Flags, PackageInfoProc);

if (Flags and pfNeverBuild) <> 0 then
WriteLn('Never Build');

if (Flags and pfDesignOnly) <> 0 then
WriteLn('Design Only');

if (Flags and pfRunOnly) <> 0 then
WriteLn('Run Only');

case Flags and pfProducerMask of
pfV3Produced: Producer := ppOld;
pfProducerUndefined: Producer := ppUndefined;
pfBCB4Produced: Producer := ppBCB;
pfDelphi4Produced: Producer := ppDelphi;
else
Producer := ppUndefined;
end;

case Producer of
ppOld: WriteLn('Old Producer');
ppUndefined: WriteLn('Undefined Producer');
ppBCB: WriteLn('BCB Producer');
ppDelphi: WriteLn('Delphi Producer');
end;

case Flags and pfConsumerMask of
pfConsumerDelphi: Consumer := pcDelphi;
pfConsumerBCB: Consumer := pcBCB;
else
if Producer <> ppBCB then
Consumer := pcCompat
else
Consumer := pcBCB;
end;

case Consumer of
pcCompat: WriteLn('Compat Consumer');
pcBCB: WriteLn('BCB Consumer');
pcDelphi: WriteLn('Delphi Consumer');
end;

WriteLn('Requires List');
WriteStrings(RequiresList);
WriteLn(#13#10 + 'Implicit Uses');
WriteStrings(ImplicitUnits);
WriteLn(#13#10 + 'Contains List');
WriteStrings(ContainsList);
end;
finally
UnloadPackage(Module);
RequiresList.Free;
ImplicitUnits.Free;
ContainsList.Free;
end;
end.

Wednesday, December 19, 2007

Reading Info From a Package Part II

Yesterday I posted a small program to read some information from a Package. There is more information to get from the package, so here is and updated version with a bit of information you get get from the Flags. Specifically Never Build, Design Only and Run Only.


program pdump;

{$APPTYPE CONSOLE}

uses
SysUtils,
Classes;

var
RequiresList: TStrings;
ImplicitUnits: TStrings;
ContainsList: TStrings;

procedure PackageInfoProc(const Name: string;
NameType: TNameType; Flags: Byte;
Param: Pointer);
begin
if NameType = ntContainsUnit then
begin
ContainsList.Add(Name);

if (Flags and $10 <> 0) and (Flags and $06 = 0) then
ImplicitUnits.Add(Name);
end
else if NameType = ntRequiresPackage then
RequiresList.Add(Name);
end;

procedure WriteStrings(Strings: TStrings);
var
Index: Integer;
begin
for Index := 0 to Strings.Count - 1 do
WriteLn(Strings[Index]);
end;

var
Module: HMODULE;
Flags: Longint;
begin
RequiresList := TStringList.Create;
ImplicitUnits := TStringList.Create;
ContainsList := TStringList.Create;

Module := LoadPackage(ParamStr(1));

try
if Module <> 0 then
begin
GetPackageInfo(Module, nil, Flags, PackageInfoProc);

if (Flags and pfNeverBuild) <> 0 then
WriteLn('Never Build');

if (Flags and pfDesignOnly) <> 0 then
WriteLn('Design Only');

if (Flags and pfRunOnly) <> 0 then
WriteLn('Run Only');

WriteLn('Requires List');
WriteStrings(RequiresList);
WriteLn(#13#10 + 'Implicit Uses');
WriteStrings(ImplicitUnits);
WriteLn(#13#10 + 'Contains List');
WriteStrings(ContainsList);
end;
finally
UnloadPackage(Module);
RequiresList.Free;
ImplicitUnits.Free;
ContainsList.Free;
end;
end.

Tuesday, December 18, 2007

Reading Info From a Package

If you've ever wanted to find out what packages a package depends on (without using tdump.exe), or implicit units a package has or the units the package contains, then take a look at the code below.


program pdump;

{$APPTYPE CONSOLE}

uses
SysUtils,
Classes;

var
RequiresList: TStrings;
ImplicitUnits: TStrings;
ContainsList: TStrings;

procedure PackageInfoProc(const Name: string;
NameType: TNameType; Flags: Byte;
Param: Pointer);
begin
if NameType = ntContainsUnit then
begin
ContainsList.Add(Name);

if (Flags and $10 <> 0) and (Flags and $06 = 0) then
ImplicitUnits.Add(Name);
end
else if NameType = ntRequiresPackage then
RequiresList.Add(Name);
end;

procedure WriteStrings(Strings: TStrings);
var
Index: Integer;
begin
for Index := 0 to Strings.Count - 1 do
WriteLn(Strings[Index]);
end;

var
Module: HMODULE;
Flags: Longint;
begin
RequiresList := TStringList.Create;
ImplicitUnits := TStringList.Create;
ContainsList := TStringList.Create;

Module := LoadPackage(ParamStr(1));

try
if Module <> 0 then
begin
GetPackageInfo(Module, nil, Flags, PackageInfoProc);

WriteLn('Requires List');
WriteStrings(RequiresList);
WriteLn(#13#10 + 'Implicit Uses');
WriteStrings(ImplicitUnits);
WriteLn(#13#10 + 'Contains List');
WriteStrings(ContainsList);
end;
finally
UnloadPackage(Module);
RequiresList.Free;
ImplicitUnits.Free;
ContainsList.Free;
end;
end.

RAD Studio 2007 Update

RAD Studio 2007 is live on the website. Problem is the website appears to be experiencing technical difficulties.

Friday, December 14, 2007

Sysinternals


A while back I listed the tools that I use and then listed the tools that readers use. Of all the tools listed, only one was from Sysinternals. But in reality I actually use many more when the need arises.

"The Sysinternals web site was created in 1996 by Mark Russinovich and Bryce Cogswell to host their advanced system utilities and technical information. Microsoft acquired Sysinternals in July, 2006. Whether you’re an IT Pro or a developer, you’ll find Sysinternals utilities to help you manage, troubleshoot and diagnose your Windows systems and applications. If you have a question about a tool or how to use them, please visit the Sysinternals Forum for answers and help from other users and our moderators."

The tools available at Sysinternals are some of the most useful tools available for developers and they've only gotten better since being acquired by Microsoft. Check out Mark Russinovich blog for some interesting low level reading.

Friday, December 7, 2007

Suggestion Box

Welcome to the Chris Bensen blog suggestion box. Post suggestions for future topics here in the comments. The comments will be read and emptied periodically so don't be surprised if your suggestions vanishes. Suggestions are just that suggestions and I am under no obligation to accept any suggestion.

Since this is a blog focused on things I'm interested in keep the suggestions along those lines:

Delphi programming.
Programming topics.
My personal hobbies.
Issues of general interest.

Keep your suggestion short and to the point.

You can always find a link back here from the sidebar on the right.

Buying A Car

The Missus and I just bought a new car today from CarsDirect and it was the best car buying experience I have ever had. If you are buying a car seriously consider going through these guys. I had a great experience and imagine you would too.

YouTube needs Parental Ratings

My daughter loves kitty cats. When we go on walks around the neighborhood she looks under everything for them. When she spots one she signs cat and say's "mow mow". She loves my photos of animals too. Any animal is good, but cats are her favorite. She say's she's a cat. One day I searched YouTube for cats and I found the dancing kitty cat below.



In my search, I came across some things that I didn't want her to watch so we don't play that game until I've already had time to view them first. Obviously some sort of parental rating system would be really nice to have at YouTube. Maybe there is something I'm just not aware of.