Highlander: .NET Reference Analyzer Demo
Posted by in Miscellaneous, tags: .net, compression, DelphiMany people are still wondering why to use .NET at all, because they can do all their business fine with Delphi for Win32. This article demos a Reference Analyzer, written in Highlander and meant to be a real world tool. The purpose is to list all .NET assemblies, that an other assembly (dll or executable) depends on.
The ReferenceAnalyzer uses .NET Reflection to load and analyze any .NET assembly. It will show a detailed list of assemblies being referenced. Of course you cannot write this in Win 32, because this a .NET analyzing tool, so this an end in itself – somehow.

However, the demo shows how mighty and easy to use .NET reflection is. In Delphi Win32 we have RTTI, which certainly allows some fancy things, but Reflection is way more powerful and directly built into the .NET system classes.
It all starts with this:
LAssembly := Assembly.ReflectionOnlyLoadFrom(LAssemblyFileName);
ReflectionOnlyLoadFrom() is a static (class) Method of the Assembly class. This tries to load the given file as assembly. Its a new method of .NET2.0 and does not call any initialization code of the assembly being loaded – which may cause unwanted side effects.
After that we obtain a list of all referenced assemblies of that one we have just loaded:
//Get all referenced assemblies for LAssemblyName in LAssembly.GetReferencedAssemblies do begin //Load each assembly LReferencedAssembly := Assembly.ReflectionOnlyLoad(LAssemblyName.FullName);
Now we do that recursivly and we are done. Thats the whole idea.
Now where is the .NET 2.0 beef?
The above has shown some stuff which in theory could have been done with Delphi 2006.NET already. There we did not have the ReflectionOnlyLoad methods (as D2006 was .NET 1.1), but we might have done this somehow …
The demo also utilizes Generics. Look at this class definition:
TAssemblyDetail = record Name:string; FullPath:string; FullInfo:string; Exists:boolean; //used as predicate in List.Exists function Match(AAssemblyDetail:TAssemblyDetail):boolean;end;
We are using that to store assembly details, and we want to keep a list of that. (I could have used a “full class” as well, but I was lazy and wanted to avoid the “create” calls.) Without generics, you would have to cast the items of a TList back and forth to TAssemblyDetail – you all know that.
In Highlander I can go the .NET 2.0 way:
FAssemblies : List<TAssemblyDetail>;
This makes FAssemblies a strongly typed list of TAssemblyDetail. Now look at a sample how to use that:
procedure TForm1.UpdateListView;var LAssemblyDetail: TAssemblyDetail; LNode: TTreeNode;begin TreeView1.Items.Clear; for LAssemblyDetail in FAssemblies do begin LNode := TreeView1.Items.Add(nil, LAssemblyDetail.FullInfo); LNode.Data := LAssemblyDetail; if LAssemblyDetail.Exists then begin LNode.ImageIndex := 0; LNode.Text := LNode.Text + ', ' + LAssemblyDetail.FullPath; end else LNode.ImageIndex := 1; end;end;
No TAssemblyDetail(FAssemblies.items[i]) cast anymore, just clean code…
Using .NET libraries
If you think “well generics are nice, but I can live without them”, then ok, that may be true. If language feature do not convince you, then you might have a look at Google how many libraries there are available for .NET. You can use all of them with Highlander – and you can still happily mix .NET stuff with all your existing code and “skills”. There is no need to start from the scratch, if you don’t want to.
As a very simple example, ReferenceAnalyzer utilizes a .NET ZIP library, which is based on the already built in System.IO.Compression namespace. Just reference the library you need, and start using it:
procedure TForm1.CompressAssemblies;var LZipFileName:string; LZipFile: ZipFile; LAssembly: TAssemblyDetail;begin LZipFileName := EditAssemblyName.Text; LZipFileName := ChangeFileExt(LZipFileName,'.zip'); if FileExists(LZipFileName) then DeleteFile(LZipFileName); LZipFile := ZipFile.Create(LZipFileName); ProgressBar1.Position := 0; ProgressBar1.Max := FAssemblies.Count + 1; for LAssembly in FAssemblies do begin LZipFile.AddFile(LAssembly.FullPath); ProgressBar1.StepBy(1); end; //Save is last progress step LZipFile.Save; ProgressBar1.Position := ProgressBar1.Max;end;
Coming up next, I’ll show how to do WPF stuff with Highlander.





Entries (RSS)