Powershell 从MSI中提取二进制数据

Powershell 从MSI中提取二进制数据,powershell,windows-installer,Powershell,Windows Installer,我正在尝试使用Powershell从MSI文件中提取二进制数据。 我可以得到任何其他数据,但我似乎无法提取二进制信息 $Query = "SELECT Data FROM Binary WHERE Name = 'bannrbmp'" $View = $Database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $Database, ($Query)) $View.GetType().InvokeMember("Execu

我正在尝试使用Powershell从MSI文件中提取二进制数据。 我可以得到任何其他数据,但我似乎无法提取二进制信息

$Query = "SELECT Data FROM Binary WHERE Name = 'bannrbmp'"
$View = $Database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $Database, ($Query))
$View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
$Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)

$BinaryData = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)
它在最后一行中断,这让我相信“StringData”存在问题,但我可能偏离了目标。这张桌子在奥卡打开时的样子。

如下所示提取文本数据时,此代码将成功完成

$Query = "SELECT Component FROM FeatureComponents WHERE Feature = 'OrcaHelp'"
$View = $Database.GetType().InvokeMember("OpenView", "InvokeMethod", $null, $Database, ($Query))
$View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
$Record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $null, $View, $null)

$Data = $Record.GetType().InvokeMember("StringData", "GetProperty", $null, $Record, 1)


我在网上找不到任何东西,如果有人能帮助它,我们会非常感激。

< P>这是一个C++代码片段,它提取一个二进制文件并将其写入磁盘。您可以使用它,或者至少可以看到流和读取的流。这些是所有脚本语言最终调用的基本Win32 API调用,不需要互操作。它需要一些STDIO。H,Windows .H,MSsiQuang.h和打包在程序或Dll中调用-我不知道你的C++舒适度。这应该可以,即使我最近没有测试过

PMSIHANDLE hDatabase;
PMSIHANDLE hBinaryView;
PMSIHANDLE hBinaryRecord;

//Get the handle to the active database. we need this to do view manipulation
UINT nr = MsiOpenDatabase ("some.msi", MSIDBOPEN_READONLY, &hDatabase);

//Get a view of the binary table based on the SQL Query
char sQuery []  = {"SELECT * FROM Binary WHERE Name='somebinary'"}; // Binary

nr = MsiDatabaseOpenView(hDatabase, sQuery, &hBinaryView);
if (nr!= ERROR_SUCCESS)
   return 1;

//MsiViewExecute Needs to to be called for MsiFetchView.
//We pass it null because the query above is as granular as we can get
//so we do not need to take it further by specifying an additional value.
nr = MsiViewExecute(hBinaryView, NULL);  
if (nr == ERROR_SUCCESS)
    //Fetch the view into a record.  We do this because we can only do
    //streams out of a record and not out of the view.
    nr = MsiViewFetch(hBinaryView, &hBinaryRecord);

//Make sure that the entry was found in the table
if (nr == ERROR_SUCCESS)
{

    //Build the path to write the file to
    TCHAR FileName [MAX_PATH] = {"somefile.ext"}; 
    char bStream [4096] = {0};
    BOOL bOkay=TRUE;

    HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, 0, 
                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (hFile == INVALID_HANDLE_VALUE)
        nr = -1;
    else
    {
        long nTotal = 0;            
        long nattr = 0;
        DWORD nWritten, nBuffer;
        do
        {   // Read the stream into a buffer, 1023 bytes at a time
            nBuffer=1023;
            nr = MsiRecordReadStream(hBinaryRecord, 2, bStream, &nBuffer); // Binary & cab are 2
            if ((ERROR_SUCCESS == nr) && (nBuffer > 0))
            {
                //Write the buffer to a file. 
                nr = WriteFile(hFile, bStream, nBuffer, &nWritten, NULL);

                if (nr != 0)// 0 is bad
                    nTotal = nTotal + nBuffer; // debug only
                else
                    bOkay = FALSE;
            }
            else
            if (nr != ERROR_SUCCESS)
                bOkay = FALSE;
        } // record record stream
        while (bOkay == TRUE && (nBuffer > 0));

        // done copying file
        CloseHandle(hFile);
        }// create file

    // we only needed one row, so close the view
    MsiViewClose(hBinaryView);

    // done with query
    MsiCloseHandle(hBinaryRecord);
}

// done with binary table
MsiCloseHandle(hBinaryView);
// done with MSI database
MsiCloseHandle(hDatabase);

下面是一个如何提取msi二进制表中嵌入的每个二进制数据项的示例。 原始文件名将丢失,但嵌入数据的“名称”列将用作输出文件的名称

在我的例子中,选择标志“msiReadStreamAnsi”提取的文件与嵌入的文件完全相同,但还有其他标志:

*需要msi文件的完整路径,否则会出现异常:

Exception calling "InvokeMember" with "5" argument(s): "OpenDatabase,DatabasePath,OpenMode" 使用“5”参数调用“InvokeMember”时出现异常:“OpenDatabase、DatabasePath、OpenMode”
你说它在最后一行中断是什么意思?是否伴随有错误?bannerbmp(基于横幅和bmp)很可能是位图。还有其他几个包括ico,这表明它们是图标。为什么希望位图或图标支持
StringData
?既然如此,为什么您希望任何二进制数据自动支持
StringData
?这不是字符串数据,而是二进制数据。但老实说,所有这些COM互操作在我看来都是相当混乱的,而且你没有关闭句柄。如果你感兴趣的话,我可以告诉你其他的方法。马特,这只是一个例外,什么也没说。Ken,我正试图从MSI中的exe中提取图标,我知道它不是字符串数据@ChristopherPaint我很想知道我能用什么方法来解决这个问题。其他人都做对了——二进制数据是用ReadStream类型的API提取的。 Exception calling "InvokeMember" with "5" argument(s): "OpenDatabase,DatabasePath,OpenMode"