type
PsoftItem = ^TSoftItem;
TSoftItem = packed record
SoftName: string;
SoftVer: string;
Path: string;
end;
procedure ReadLocalSoftByMSI(aList: TList);
var
Index: Integer;
Buf: array [0..38] of char;
PropBuf: PChar;
hr: UINT;
Len: DWORD;
P: PSoftItem;
begin
if not Assigned(aList) then exit;
for Index := aList.Count-1 downto 0 do
begin
P := aList.Items[Index];
if Assigned(P) then DisPose(P);
end;
aList.Clear;
Index := 0;
hr := MsiEnumProducts(Index, Buf);
while hr = ERROR_SUCCESS do
begin
new(P);
len := 0;
MsiGetProductInfo(Buf, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, nil, @len);
Inc(Len);
PropBuf := AllocMem(len);
try
MsiGetProductInfo(Buf, INSTALLPROPERTY_INSTALLEDPRODUCTNAME, PropBuf, @len);
P^.SoftName := PropBuf;
finally
FreeMem(PropBuf);
end;
len := 0;
MsiGetProductInfo(Buf, INSTALLPROPERTY_INSTALLLOCATION, nil, @len);
Inc(Len);
PropBuf := AllocMem(len);
try
MsiGetProductInfo(Buf, INSTALLPROPERTY_INSTALLLOCATION, PropBuf, @len);
P^.Path := PropBuf;
finally
FreeMem(PropBuf);
end;
len := 0;
MsiGetProductInfo(Buf, INSTALLPROPERTY_VERSIONSTRING, nil, @len);
Inc(Len);
PropBuf := AllocMem(len);
try
MsiGetProductInfo(Buf, INSTALLPROPERTY_VERSIONSTRING, PropBuf, @len);
P^.SoftVer := PropBuf;
finally
FreeMem(PropBuf);
end;
if Trim(P^.SoftName) = '' then
begin
DisPose(P);
end
else
begin
aList.Add(P);
end;
Inc(Index);
hr := MsiEnumProducts(Index, Buf);
end;
end;
使用这个函数,可以先在窗体上放置一个memo控件,然后在一个Button的OnClick事件中:
procedure TForm1.BitBtn1Click(Sender: TObject);
var
List: TList;
i: Integer;
P: PSoftItem;
begin
Memo1.Lines.Clear;
List := TList.Create;
try
ReadLocalSoftByMSI(List);
for i := 0 to List.Count-1 do
begin
P := List.Items[i];
Memo1.Lines.Add(P^.SoftName);
Memo1.Lines.Add(P^.SoftVer);
Memo1.Lines.Add(P^.Path);
Memo1.Lines.Add('');
end;
finally
for i := 0 to List.Count-1 do
begin
P := List.Items[i];
DisPose(P);
end;
List.Free;
end;
end;
注意:使用这个函数需要引用jwaMsi单元,jwaMsi.pas文件可以到网上去下载。
此程序在WinXP Sp2+delphi 7 下调试通过