Mega Code Archive

 
Categories / Delphi / COM
 

Enumerate COM Servers

Title: Enumerate COM Servers Question: I needed a Class to Enumerate all Registered COM Objects so that I could Retrieve the Prog ID`s. Answer: The only way to do this, it seems, it to search through the first level of the HKEY_CLASSES_ROOT and look for subkeys of CLSID. If the Key has a CLSID subkey it is a COM object of sorts. Open the CLDID GUID in the CLSID Key and look for PROGID Key and INPROCServer* Key. There are usually a couple of variants to the availabe keys - There might be an InprocServer32 Key and or an InprocServer Key or an InprocHandler Key. In this example I habe only searched for InprocServer32 Keys, as the Sub Class Items will get quite complicated in I was to look for everything. Below is a class that handles this process. One should make it into a component or Com Object, but I'll leave that up to you. unit Class_ComEnum; interface Uses Registry,Classes,Sysutils; Type TComItem = Class Private fProgID : String; fCLSID : String; fInprocServer : String; fTypeLib : String; fVersion : String; Public Published Property ProgID : String Read fProgId Write fProgId; Property CLSID : String Read fCLSID Write fCLSID; Property InprocServer : String Read fInprocServer Write fInprocServer; Property TypeLib : String Read fTypeLib Write fTypeLib; Property Version : String Read fVersion Write fVersion; end; TComEnumProgress = Procedure(Sender : TObject;total,position : Integer) of object; TComEnum = Class Private Reg : TRegistry; ComList : TList; eProgress : TComEnumProgress; function GetComCount: Integer; Public Procedure BuildList; Function GetItem(Index : Integer) : TComItem; Constructor Create; Destructor Destroy;override; Published Property ComCount : Integer Read GetComCount; property OnProgress :TComEnumProgress Read eProgress Write eProgress; End; Var ComEnum : TComEnum; implementation Uses Windows,Dialogs; { TComEnum } procedure TComEnum.BuildList; Var KeyList : TStringList; Count : Integer; fCLSID : String; Temp : TComItem; test : Boolean; KeyToOpen : String; begin KeyList := TStringList.Create; Reg := TRegistry.Create; Reg.RootKey := HKEY_CLASSES_ROOT; test := Reg.OpenKey('',false); Reg.GetKeyNames(KeyList); Reg.CloseKey; For Count := 0 to KeyList.Count -1 do begin if Assigned(eProgress) then eProgress(self,keylist.count,count); // open the first Key in the List KeyToOpen := KeyList.Strings[count]; Test := Reg.OpenKey('\' + KeyToOpen,False); // look to see if it has a CLSID if Reg.KeyExists('CLSID') then Begin Reg.CloseKey; If Reg.OpenKey( '\' + KeyToOpen + '\CLSID',false) then begin fCLSID := Reg.ReadString(''); Reg.CloseKey; if Reg.OpenKey('\CLSID\' + fCLSID,False) then begin // Get The CLSID Temp := TComItem.Create; Temp.CLSID := fCLSID; // Get all the Details Reg.CloseKey; Try If Reg.OpenKey('\CLSID\' + fCLSID + '\' + 'InprocServer32',false) Then Temp.InprocServer := Reg.ReadString(''); if Reg.OpenKey('\CLSID\' + fCLSID + '\' + 'ProgID',false) then Temp.ProgID := Reg.ReadString(''); if Reg.OpenKey('\CLSID\' + fCLSID + '\' + 'Version',false) then Temp.Version := Reg.ReadString(''); If Reg.OpenKey('\CLSID\' + fCLSID + '\' + 'TypeLib',false) then Temp.TypeLib := Reg.ReadString(''); Reg.CloseKey; if (Temp.TypeLib = '') or (Temp.ProgID = '') then begin Temp.Free; end else ComList.Add(Temp); Except on E:Exception do begin Temp.fCLSID := 'ERROR'; ComList.Add(Temp); Reg.CloseKey; end; end; end; end; end; end; End; constructor TComEnum.Create; begin ComList := TList.Create; end; destructor TComEnum.Destroy; begin inherited; ComList.Free; end; function TComEnum.GetComCount: Integer; begin result := ComList.Count; end; Function TComEnum.GetItem(Index: Integer) : TComItem; begin if (Index = 0) AND (Index begin Result := ComList.Items[index]; End Else Result := NIL; end; end. USING THE CLASS For a Test, create a new Application. Put a ListView, button and a progress bar on the screen. Set the ListView Style to Report. Add the following code to the Button procedure TForm1.Button1Click(Sender: TObject); Var count : Integer; Temp : TComItem; Rec : TListItem; begin ComEnum := TComEnum.Create; ComEnum.OnProgress := DoProgress; ComEnum.BuildList; for Count := 0 to ComEnum.ComCount-1 do begin Temp := ComEnum.GetItem(count); Rec := ListView1.Items.add; Rec.Caption := Temp.ProgID; Rec.SubItems.Add(Temp.CLSID); Rec.SubItems.Add(Temp.InprocServer); Rec.SubItems.Add(Temp.Version); Rec.SubItems.Add(Temp.TypeLib); end; end; TEMP is a pointer to the COMITEM sub class. As you loop though the list, assign the pointer (TEMP) to ratuen Result of Get Item. Once you have done this you can add it to any viewable component; REC is a pointer to the ListView Items. The class has one method and one Event OnProgress EVENT Delare this in your Private section of the form class Procedure DoProgress(Sender : TObject;Count,Position : Integer); and insert the following code procedure TForm1.DoProgress(Sender: TObject; Count, Position: Integer); begin progressBar1.Max := count; progressBar1.Position := position; end; The Count Value is the total number of first level keys that the class will search though. The Position the indication of how far it is. BUILDLIST This method will build an Object List of all the registerd COM Objects and store than in the COMITEM sub class. As the method runs, the progress event will trigger if you have assigned it.