Tuesday, July 06, 2004

As Louis Amstrong's funeral song went "ONE MORE TIME!!!"

This is a dreaded 3rd way to get all the Winforms (OR any other bloody OS handle it seems...) in your application! So this solution has the potential to be used as a resource tracker if you suspected that the CLR was leaking handles. It also has the potential to SLLLOOOWWW your app down.

Add this unit to your delphi.net project
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


unit HookHandleAllocator;

interface
uses System.Collections;

procedure HandleAdded(handleType: string; handleValue: IntPtr; currentHandleCount: integer);
procedure HandleRemoved(handleType: string; handleValue: IntPtr; currentHandleCount: integer);

var
WinformList : System.Collections.ArrayList;

implementation

uses System.Reflection,System.Windows.Forms;
type
THandleChangeEventHandler = procedure (handleType: string; handleValue: IntPtr; currentHandleCount: integer) of object;

var
aDelegate : THandleChangeEventHandler;


procedure HandleAdded(handleType: string; handleValue: IntPtr; currentHandleCount: integer);
begin
if (handleType = 'Window') then WinformList.Add(handleValue);
end;

procedure HandleRemoved(handleType: string; handleValue: IntPtr; currentHandleCount: integer);
begin
if (handleType = 'Window') then WinformList.Remove(handleValue);
end;

procedure HookIntoHandleAllocator;
const
AllBindingFlags : BindingFlags = BindingFlags.Instance or BindingFlags.Static or
BindingFlags.Public or BindingFlags.NonPublic or
BindingFlags.FlattenHierarchy;
type
TObjectArray = array of TObject;
var
SystemModule : Module;
FusionType : System.Type;
HandleType : System.Type;
DelegateType : System.Type;
UnitType : System.Type;
HandleEventInfo : EventInfo;
HandlerMethodInfo : MethodInfo;
WindowHandleCollection : TObjectArray;
ParamArray : array [0..0] of TObject;
begin

SystemModule := TypeOf(System.Windows.Forms.Form).Module;
if not Assigned(SystemModule) then Exit;

FusionType := SystemModule.GetType('System.HandleCollector');
if not Assigned(FusionType) then Exit;

DelegateType := SystemModule.GetType('System.HandleChangeEventHandler');
if not Assigned(DelegateType) then Exit;

HandleEventInfo := FusionType.GetEvent('HandleAdded',AllBindingFlags);
if not Assigned(HandleEventInfo) then Exit;
HandlerMethodInfo := HandleEventInfo.GetAddMethod(true);
if not Assigned(HandlerMethodInfo) then Exit;

UnitType := Assembly.GetExecutingAssembly.
GetModules[0].GetType('HookHandleAllocator.Unit',true);

if not Assigned(UnitType) then Exit;
aDelegate := HandleAdded;

ParamArray[0] := Delegate.CreateDelegate(DelegateType,UnitType,'HandleAdded');
HandlerMethodInfo.Invoke(nil,ParamArray);
HandleEventInfo := FusionType.GetEvent('HandleRemoved',AllBindingFlags);
if not Assigned(HandleEventInfo) then Exit;
HandlerMethodInfo := HandleEventInfo.GetAddMethod(true);
if not Assigned(HandlerMethodInfo) then Exit;
aDelegate := HandleRemoved;
ParamArray[0] := Delegate.CreateDelegate(DelegateType,UnitType,'HandleAdded');
HandlerMethodInfo.Invoke(nil,ParamArray);
end;

initialization
WinformList := System.Collections.ArrayList.Create;
HookIntoHandleAllocator;
finalization

end.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

procedure TWinForm.Button7_Click(sender: System.Object; e: System.EventArgs);
var
i : integer;
FoundControl : Control;
begin
for i := 0 to WinformList.Count - 1 do
begin
FoundControl := Control.FromHandle(IntPtr(WinformList.Item[i]));
if FoundControl is System.Windows.Forms.Form then
MessageBox.Show(FoundControl.Text);
end;
end;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

I hope this is last solution to the WinForm list issue... Now I need to check if all this works in CLR 2.0.

0 Comments:

Post a Comment

<< Home