我需要从MSI数据库打开一些表,阅读这个和使用delphi(在我的例子是delphi7,但允许其他版本,如果需要的话)放在这一些行。
例如,它看起来像ORCA。 Msi必须是开放的,写入到可以编辑并写入msi文件的表格中。
默认情况下,Delphi不能像我那样打开MSI表,但是我发现了JEDI Windows API ,其中存在像JwaMsi和JwaMsiQuery这样的库。 但是我找不到使用函数的文档或例子
function MsiOpenProduct(szProduct: LPCTSTR; var hProduct: MSIHANDLE): UINT; stdcall; {$EXTERNALSYM MsiOpenProduct}
顺便说一下,当我search有关这个信息,我发现这个代码:
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;
什么是更好的使用和我可以看到文档和/或例子?
PS对不起,我的英语
我会使用基于COM的API到MSI。
看到这个线程和MSI API文档
所以,解决方案存在,我做到了! 这不是那么优雅,但它的工作…
起初,从MSDN阅读文章(在我的情况是关于MSI数据库工作的文章)。 第二,你必须明白你需要做什么。 在我的情况是这样的:
在这里我展示了我如何做到三个第一步。
准备
下载JEDI Windows AP (用于msi的更快捷的工作)并添加到项目JwaMsi.pas,JwaMsiDefs.pas和JwaMsiQuery.pas(不要忘记使用列表)。 依赖关系将被自动添加。 接下来,放置所有需要的组件。
让我们编码!
1打开msi数据库和2读取表名
为处理程序和缓冲区定义变量
var msi_handler_DB, msi_handler_view, msi_handler_record:TMSIHandle; txt:PChar; sz:DWORD;
现在我们需要获取一个表格列表( 更多信息在这里 ),并将其放在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和它可以在这里读取的结构: 一 , 二 , 三 ),导入到带有属性MsiDatabaseImport的MSI中(不要忘记打开数据库,然后附加它之后,还要记住关闭处理程序)并删除临时.idt文件。
祝你好运!
PS对不起,我的英文,第二部分:)