static void Main(string[] args) { string extractDir = @"D:\HotfixDB\lab"; bool includeExtension = true; string msiFilePath = @"D:\HotfixDB\lab\NDP45-KB3127229-x64\NDP45-KB3127229.msp"; VsInterop.IStorage rootStorage = null; HRESULT hr = NativeMethods.StgOpenStorage(msiFilePath, null, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, null, 0, out rootStorage); if (HResultHelper.IsSucceeded(hr) && rootStorage != null) { // // A Database and Patch Example // https://msdn.microsoft.com/en-us/library/aa367813(v=vs.85).aspx // // http://www.pinvoke.net/default.aspx/msi.msirecordsetstring // http://blogs.msdn.com/b/heaths/archive/2006/03/31/566288.aspx // MsiDbOpenPersist msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY; if (isPatch(rootStorage)) { msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY | MsiDbOpenPersist.MSIDBOPEN_PATCHFILE; } // Release COM object of root storage. Marshal.ReleaseComObject(rootStorage); IntPtr msiDatabaseHandle = IntPtr.Zero; uint err = NativeMethods.MsiOpenDatabase(msiFilePath, new IntPtr((uint)msiDbOpenPersist), out msiDatabaseHandle); if (err == WinError.ERROR_SUCCESS) { IntPtr msiViewHandle = IntPtr.Zero; //err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Streams", out msiViewHandle); err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Storages", out msiViewHandle); //err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Tables", out msiViewHandle); if (err == WinError.ERROR_SUCCESS) { err = NativeMethods.MsiViewExecute(msiViewHandle, IntPtr.Zero); if (err == WinError.ERROR_SUCCESS) { while (true) { IntPtr msiRecordHandle = IntPtr.Zero; err = NativeMethods.MsiViewFetch(msiViewHandle, out msiRecordHandle); if (err != WinError.ERROR_SUCCESS) { break; } saveStream(msiRecordHandle, extractDir, includeExtension); NativeMethods.MsiCloseHandle(msiRecordHandle); } } } // Close MSI view handle. if (msiViewHandle != IntPtr.Zero) { NativeMethods.MsiCloseHandle(msiViewHandle); } } // Close MSI database handle. if (msiDatabaseHandle != IntPtr.Zero) { NativeMethods.MsiCloseHandle(msiDatabaseHandle); } } else { throw new Exception(string.Format(@"Failed: StgOpenStorage(): Failed to open root storage ""{0}""", msiFilePath)); } }
static void Main(string[] args) { string extractDir = @"F:\Takatano\Desktop\experiment\storages"; bool includeExtension = true; string msiFilePath = @"F:\Takatano\Projects\MsixEx\NDP45-KB3037581.msp"; VsInterop.IStorage rootStorage = null; HRESULT hr = NativeMethods.StgOpenStorage(msiFilePath, null, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, null, 0, out rootStorage); if (HResultHelper.IsSucceeded(hr) && rootStorage != null) { // // もしかすると、この辺関係ないかも // (構造を維持して展開できれば、話は違うかも) // //VsInterop.IEnumSTATSTG enumStatStg = null; //rootStorage.EnumElements(0, IntPtr.Zero, 0, out enumStatStg); //if (enumStatStg != null) //{ // while (true) // { // VsInterop.STATSTG[] stg = new VsInterop.STATSTG[1]; // uint fetched; // hr = (HRESULT)enumStatStg.Next(1, stg, out fetched); // if (hr == HRESULT.S_FALSE) // { // break; // } // if (hr != HRESULT.S_OK) // { // throw new Exception(@"Failed: IEnumSTATSTG.Next(): Failed to enumerate next storage status"); // } // Console.WriteLine(@"Name:{0}, Type:{1}", stg[0].pwcsName, stg[0].type); // if ((VsInterop.STGTY)stg[0].type == VsInterop.STGTY.STGTY_STORAGE) // { // saveStorage(rootStorage, extractDir, stg[0].pwcsName, includeExtension ? @".mst" : null); // } // //if (stg.pwcsName) // //{ // // CoTaskMemFree(stg.pwcsName); // これ必要なのかも, Marshal.FreeCoTaskMem(), string になっているし、不要かな。 // // stg.pwcsName = NULL; // //} // } // Marshal.ReleaseComObject(enumStatStg); //} // // A Database and Patch Example // https://msdn.microsoft.com/en-us/library/aa367813(v=vs.85).aspx // // http://www.pinvoke.net/default.aspx/msi.msirecordsetstring // http://blogs.msdn.com/b/heaths/archive/2006/03/31/566288.aspx // MsiDbOpenPersist msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY; if (isPatch(rootStorage)) { msiDbOpenPersist = MsiDbOpenPersist.MSIDBOPEN_READONLY | MsiDbOpenPersist.MSIDBOPEN_PATCHFILE; } // Release COM object of root storage. Marshal.ReleaseComObject(rootStorage); IntPtr msiDatabaseHandle = IntPtr.Zero; uint err = NativeMethods.MsiOpenDatabase(msiFilePath, new IntPtr((uint)msiDbOpenPersist), out msiDatabaseHandle); if (err == WinError.ERROR_SUCCESS) { IntPtr msiViewHandle = IntPtr.Zero; err = NativeMethods.MsiDatabaseOpenView(msiDatabaseHandle, @"SELECT Name, Data FROM _Streams", out msiViewHandle); if (err == WinError.ERROR_SUCCESS) { err = NativeMethods.MsiViewExecute(msiViewHandle, IntPtr.Zero); if (err == WinError.ERROR_SUCCESS) { while (true) { IntPtr msiRecordHandle = IntPtr.Zero; err = NativeMethods.MsiViewFetch(msiViewHandle, out msiRecordHandle); if (err != WinError.ERROR_SUCCESS) { break; } saveStream(msiRecordHandle, extractDir, includeExtension); NativeMethods.MsiCloseHandle(msiRecordHandle); } } } // Close MSI view handle. if (msiViewHandle != IntPtr.Zero) { NativeMethods.MsiCloseHandle(msiViewHandle); } } // Close MSI database handle. if (msiDatabaseHandle != IntPtr.Zero) { NativeMethods.MsiCloseHandle(msiDatabaseHandle); } } else { throw new Exception(string.Format(@"Failed: StgOpenStorage(): Failed to open root storage ""{0}""", msiFilePath)); } }