ESENT 在尝试打开 IE 10/11 时总是抛出 EsentPageSizeMismatchException WebCache.dat

ESENT Always throws EsentPageSizeMismatchException when trying to open IE 10/11 WebCache.dat

我正在尝试创建一个 powershell 脚本来读取 IE 10/11 互联网历史记录,该历史记录存储在 AppData\Local\Microsoft\Windows\WebCache\WebCache.dat.

我正在使用 Managed Esent+- 与 .NET 中的 Win32 Jet api 交互。

我的问题是我永远无法真正打开数据库,因为当我调用 JetAttachDatabase 时抛出 EsentPageSizeMismatchException。在对这个错误做了一些研究之后,我发现 IE WebCache 的页面大小为 32K。当我试图通过将 DatabasePageSize 系统参数设置为 0x8000 来纠正这个问题时,JetInit 开始抛出相同的异常。

这是我的代码

#stop the things locking the database
stop-process -name taskhost
stop-process -name dllhost
#give powershell access to the interop dlls
add-type -path "$PSScriptRoot\ManagedEsent 1.6\Esent.Interop.dll"
$instance = [Microsoft.Isam.Esent.Interop.JET_INSTANCE]::Nil
#set page size
[Microsoft.Isam.Esent.Interop.api]::JetSetSystemParameter(
    $instance,
    [Microsoft.Isam.Esent.Interop.JET_SESID]::Nil,
    [Microsoft.Isam.Esent.Interop.JET_param]::DatabasePageSize,
    0x8000,
    $null
)
[Microsoft.Isam.Esent.Interop.Api]::JetCreateInstance([ref]$instance,"testing")
# init the instance, throws EsentPageSizeMismatchException if the page size is not default
[Microsoft.Isam.Esent.Interop.Api]::JetInit([ref]$instance) 
$sesid = [Microsoft.Isam.Esent.Interop.JET_SESID]::Nil
[Microsoft.Isam.Esent.Interop.Api]::JetBeginSession($instance,[ref]$sesid,$null,$null)
# throws EsentPageSizeMismatchException if page size is default
[Microsoft.Isam.Esent.Interop.api]::JetAttachDatabase(
   $sesid,
   "C:\Users\Administrator\AppData\Local\Microsoft\Windows\WebCache\WebCacheV01.dat",
   [Microsoft.Isam.Esent.Interop.AttachDatabaseGrbit]::ReadOnly
)
...

似乎 ESENT 引擎不喜欢非默认页面大小,但我搜索了互联网,似乎没有办法更改引擎页面大小。是什么导致了这个错误?

如果您注意到,在一种情况下是 JetAttachDatabase 失败并出现异常,而在另一种情况下是 JetInit

你确实是正确的,你需要设置DatabasePageSize。 JetInit 实际上是一个糟糕的名字。它应该被称为 JetInitAndReplayLogFiles。它将查看日志目录(默认名称:“.”)中的事务日志文件(默认名称为 edb*.log),并重播事务日志文件中的操作。

您现在可能正在选择使用不同页面大小创建的其他事务日志文件。理论:您正在获取您在第一次尝试时无意中创建的 edb*.log 个文件。

一些可能的解决方案:

-cd 进入包含日志文件的目录。

-更改 LogFileDirectory(您可以将 JetSetSystemParameterJET_param.LogFilePath 一起使用,或者使用包装器 class InstanceParameters.LogFileDirectory)。哦,您还需要将 InstanceParameters.BaseName 设置为 "v01",因为那是 webcache01.dat 文件似乎使用的内容(影响 "edb.log" 与 "v01.log" 的名称).

-使用esentutl.exe -r v01使数据库进入'clean shutdown'状态,然后将InstanceParameters.Recovery设置为false以避免意外创建新的事务日志文件。我看到您已经附加了 AttacheDatabaseGrbit.ReadOnly.

最后,我希望这只是出于好奇。从事 inetcache 工作的人员可以随时更改实施细节。如果用于取证目的,Microsoft 会协助执法机构进行取证工作。

-马丁

您应该使用 JetGetDatabaseFileInfo() 获取所需的页面大小以与 SetSetSystemParameter() 一起使用

这是 C# 中的示例(嘿...这已经很接近了,对吧?)

        int pageSize;
        JET_INSTANCE instance;
        JET_SESID sesId;

        // match the Page size
        Api.JetGetDatabaseFileInfo(databasePath, out pageSize, JET_DbInfo.PageSize);
        Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.DatabasePageSize, pageSize, null);

对于我的情况,每次切换数据库之前,我都必须手动进入 bin/Debug 文件夹并手动删除内容,然后再进行调试。我希望这对面临此问题的人有所帮助。