我需要从MSI数据库中打开一些表,阅读本文并使用Delphi放置一些行(在我的例子中是Delphi 7,但如果需要则允许其他版本)。
例如它看起来像ORCA。 Msi必须是开放的,写入表格,可以编辑并写入msi文件。
默认情况下,Delphi无法打开MSI表,但我找到了一个JEDI Windows API,其中存在像JwaMsi和JwaMsiQuery这样的库。但我找不到使用
等功能的文档或示例function MsiOpenProduct(szProduct: LPCTSTR; var hProduct: MSIHANDLE): UINT; stdcall;
{$EXTERNALSYM MsiOpenProduct}
顺便说一下,当我搜索有关此信息时,我发现了这段代码:
const msilib = 'msi.dll';
type
MSIHANDLE = DWORD;
TMsiHandle = MSIHANDLE;
function MsiCloseHandle(hAny: MSIHANDLE):UINT;stdcall;external msilib name 'MsiCloseHandle';
function MsiOpenProduct(szProduct:LPCSTR;var hProduct:MSIHANDLE):UINT;stdcall;external msilib name 'MsiOpenProductA';
function MsiGetProductProperty(hProduct:MSIHANDLE;szProperty:LPCSTR;lpValueBuf:LPSTR;pcchValueBuf:LPDWORD):UINT;stdcall; external msilib name 'MsiGetProductPropertyA';
function MsiSetInternalUI(dwUILevel:INSTALLUILEVEL;phWnd:LPHWND):INSTALLUILEVEL;stdcall; external msilib name 'MsiSetInternalUI';
function GetMSIProperty(aProductCode:string):string;
var
msi:TMSIHandle;
t:string;
function _getmsiproperty(_name:string):string;
var
txt:PChar;
sz:DWORD;
begin
sz:=MAX_PATH;
txt:=AllocMem(sz+1);
if MsiGetProductProperty(msi,PChar(_name),txt,@sz)=ERROR_MORE_DATA then
begin
ReAllocMem(txt,sz+1);
MsiGetProductProperty(msi,PChar(_name),txt,@sz);
end;
SetString(Result,txt,sz);
FreeMem(txt,sz+1);
end;
begin
MsiSetInternalUI(2,nil); // скрываем GUI/hide GUI
if MsiOpenProduct(PChar(aProductCode),msi)=ERROR_SUCCESS then
begin
t:=_getmsiproperty('ARPPRODUCTICON'); // главная иконка приложения/main program icon
if t='' then t:=_getmsiproperty('ProductIcon');
if t='' then t:=_getmsiproperty('CompleteSetupIcon');
if t='' then t:=_getmsiproperty('CustomSetupIcon');
if t='' then t:=_getmsiproperty('InfoIcon');
if t='' then t:=_getmsiproperty('InstallerIcon');
if t='' then t:=_getmsiproperty('RemoveIcon');
if t='' then t:=_getmsiproperty('RepairIcon');
Result:=t;
MsiCloseHandle(msi);
end;
end;
什么是更好的使用和我可以看到文档和/或示例?
P.S。对不起我的英文
答案 0 :(得分:1)
我会将基于COM的API用于MSI。
答案 1 :(得分:0)
所以,解决方案存在,我做到了!它不是那么优雅,但它正在发挥作用......
首先,阅读MSDN中的文章(在我的例子中是关于使用MSI数据库的文章)。 第二,你必须明白你需要做什么。就我而言,它是:
这里我将展示如何完成前三个步骤。
准备
下载JEDI Windows AP(以便更轻松地使用msi)并添加到项目JwaMsi.pas,JwaMsiDefs.pas和JwaMsiQuery.pas(不要忘记USES列表)。将自动添加依赖项。 接下来,在表单上放置所有需要的组件。
我们的代码!
1打开msi数据库和2个读取表名
定义处理程序和缓冲区的变量
var msi_handler_DB, msi_handler_view, msi_handler_record:TMSIHandle;
txt:PChar;
sz:DWORD;
现在我们需要获取表格列表(more info here)并将其放在ListBox中,例如
begin
sz:=MAX_PATH; //initialise
txt:=AllocMem(sz+1); //variables
OpenDialog1.Execute; //select file
If MsiOpenDatabase(PChar(OpenDialog1.FileName), MSIDBOPEN_DIRECT, msi_handler_DB)=ERROR_SUCCESS //check if DB is open
then begin //start reading
Listbox1.Clear; //prepare listbox for filling
MsiDatabaseOpenView(msi_handler_DB, 'SELECT * FROM _Tables',msi_handler_view); //prepare query to _Table
MsiViewExecute(msi_handler_view, msi_handler_record); //execute...
While not MsiViewFetch(msi_handler_view, msi_handler_record)=ERROR_NO_MORE_ITEMS //and fetch it in cycle until end of table
do begin
MsiRecordGetString(msi_handler_record,1,txt,sz); //read string
ListBox1.Items.Add(txt); //and write to listbox
end; //end of fetch cycle
MsiCloseAllHandles; //close handles (we don't need they more)
end; //stop reading
end;
3阅读所需表并显示
这很容易!
begin
edit1.text:=Listbox1.Items.ValueFromIndex[ListBox1.ItemIndex];
If MsiOpenDatabase(PChar(OpenDialog1.FileName), MSIDBOPEN_DIRECT, msi_handler_DB)=ERROR_SUCCESS //open database again
then begin
MsiDatabaseExport(msi_handler_DB, pchar(ListBox1.Items.Strings[ListBox1.ItemIndex]), 'C:\Windows\Temp', Pchar(ListBox1.Items.Strings[ListBox1.ItemIndex]+'.idt')); //export table to .idt
MsiCloseAllHandles; //and close handler again
//...
//here must be placed code for
//parsing .idt as tabulation separated file
//with wordwrap and show it.
//for example - in StringGrid
//...
DeleteFile('C:\Windows\Temp\'+ ListBox1.Items.Strings[ListBox1.ItemIndex]+'.idt'); //do not forget delete temporary .idt file. save our planet! :)
end;
end;
4如果需要 - 进行更改并保存
从头到尾重复第三步:将StringGrid导出到文件(关于.idt及其结构,你可以在这里阅读:one,two,three),导入到具有属性MsiDatabaseImport的MSI(不要忘记之前打开数据库并追加它,还要记住关闭处理程序)并删除临时.idt文件。
祝你好运!P.S。对不起,我的英文,第二部分:)