- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
创建 VSS 快照后,我希望能够查询 USN 日志。这可能吗?还是无法从 VSS 快照访问 USN 日志?
我的目标是能够在两个 VSS 快照之间的增量备份中使用 USN 日志。备份过程是
我现在失败的是我试图获取 VSS 快照上最高 USN 条目的部分
我可以从命令行模拟这个,如下所示
C:\>vssadmin list shadows
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.
Contents of shadow copy set ID: {54fc99fb-65f2-4558-8e12-9308979327f0}
Contained 1 shadow copies at creation time: 5/10/2012 6:44:19 PM
Shadow Copy ID: {a2d2c155-9916-47d3-96fd-94fae1c2f802}
Original Volume: (T:)\\?\Volume{a420b1fa-9744-11e1-9082-889ffaf52b70}\
Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25
Originating Machine: computer
Service Machine: computer
Provider: 'Microsoft Software Shadow Copy provider 1.0'
Type: Backup
Attributes: Differential
C:\>fsutil usn queryjournal \\?\Volume{a420b1fa-9744-11e1-9082-889ffaf52b70}
Usn Journal ID : 0x01cd2ebe9c795b57
First Usn : 0x0000000000000000
Next Usn : 0x000000000001b5f8
Lowest Valid Usn : 0x0000000000000000
Max Usn : 0x7fffffffffff0000
Maximum Size : 0x0000000000100000
Allocation Delta : 0x0000000000040000
C:\>fsutil usn queryjournal \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25
Error: The volume change journal is not active.
如果可能的话,您知道我做错了什么吗?
最佳答案
这个问题对于我正在从事的项目非常重要,所以我最终(几乎)100% 成功了。
注意:以下所有代码片段均采用 C# 编写
感谢 Hannes de Jager 之前的回答,他为我指明了正确的方向和文档,我现在可以从 VSS 快照或常规 API 无法使用的任何其他特殊设备读取 USN 日志;就我而言,我的意思是使用 VDDK(用于 VM 磁盘的 VMware SDK)安装的 VMware 快照。
我还重用或导入了来自伟大项目的代码:
C# 中的 USN 期刊浏览器,来自 StCroixSkipper ( http://www.dreamincode.net/forums/blog/1017-stcroixskippers-blog/ )。仅使用官方 API 读取 USN(因此此处没有 VSS),但提供有用的 pinvoke 和 Win32 API 结构以及有关 USN 如何工作的一般信息
AlphaFS ( https://github.com/alphaleonis/AlphaFS/ ) ,它模仿 System.IO
的大部分内容命名空间,但允许访问特殊的 Windows 路径(VSS 快照、原始设备)并提供有用的扩展。
如果其他人感兴趣,我分享我现在使用的代码,仍然处于相当粗糙的状态,但可以工作。
它是如何工作的?
首先,您必须访问所需的 Usn 日志组件。它们作为 ADS(备用数据流)位于设备根部的隐藏条目中。无法使用标准 System.IO
访问它们命名空间,这就是为什么我之前告诉我使用 AlphaFS 项目,但 pinvoking CreateFile()
和ReadFile()
应该足够了。
1/2
条目 \$Extend\$UsnJrnl:$Max
拥有有关期刊当前状态的全局信息。最重要的部分是 usn 日志 ID(如果您想比较多个 VSS 快照,可以使用它来检查日志是否未被重置)和最低的有效 USN 日志序列号。
USN 期刊结构:
// can be directly extracted from $MAX entry using Bitconverter.ToUint64
public struct USN_JOURNAL_DATA{
public UInt64 MaximumSize; //offset 0
public UInt64 AllocationDelta; // offset 8
public UInt64 UsnJournalID; // offset 16
public Int64 LowestValidUsn; // offset 24
}
2/2
条目 \$Extend\$UsnJrnl:$J
包含日志记录。它是一个稀疏文件,因此其磁盘使用量远低于其大小。
为了回答第一个问题,如何从先前的 VSS 快照中知道 Max 使用的 USN 序列并将其与另一个快照的序列进行比较?那么,NextUsn 值就等于 $Usnjrnl:$J
的大小。条目。
在"new"vss 快照 USN 日志上,如果您想解析两个快照之间更改的记录,可以在开始解析记录之前查找“引用”VSS 快照最大 USN。
一般来说,每个 USN 日志条目都是一个唯一的 ID(USN 编号),它是 $J
内的偏移量。日记帐分录本身所在的位置。每个条目都有一个可变的大小,因此要顺序读取,我们必须计算:
next entry offset inside $J =
offset of current entry (or its USN sequennce number + length of current entry
幸运的是,记录长度也是 USN 条目记录的一个字段。说得够多了,这是 USN 记录类别:
public class UsnEntry : IComparable<UsnEntry>{
private const int FR_OFFSET = 8;
private const int PFR_OFFSET = 16;
private const int USN_OFFSET = 24;
private const int REASON_OFFSET = 40;
private const int FA_OFFSET = 52;
private const int FNL_OFFSET = 56;
private const int FN_OFFSET = 58;
public UInt32 RecordLength {get; private set;}
public Int64 USN {get; private set;}
public UInt64 FileReferenceNumber {get;private set;}
public UInt64 ParentFileReferenceNumber {get; private set;}
public UInt32 Reason{get; set;}
public string Name {get; private set;}
public string OldName{get; private set;}
private UInt32 _fileAttributes;
public bool IsFolder{
get{
bool bRtn = false;
if (0 != (_fileAttributes & Win32Api.FILE_ATTRIBUTE_DIRECTORY))
bRtn = true;
return bRtn;
}
}
public bool IsFile{
get{
bool bRtn = false;
if (0 == (_fileAttributes & Win32Api.FILE_ATTRIBUTE_DIRECTORY))
bRtn = true;
return bRtn;
}
}
/// <summary>
/// USN Record Constructor
/// </summary>
/// <param name="p">Buffer pointer to first byte of the USN Record</param>
public UsnEntry(IntPtr ptrToUsnRecord){
RecordLength = (UInt32)Marshal.ReadInt32(ptrToUsnRecord); //record size
FileReferenceNumber = (UInt64)Marshal.ReadInt64(ptrToUsnRecord, FR_OFFSET);
ParentFileReferenceNumber = (UInt64)Marshal.ReadInt64(ptrToUsnRecord, PFR_OFFSET);
USN = (Int64)Marshal.ReadInt64(ptrToUsnRecord, USN_OFFSET);
Reason = (UInt32)Marshal.ReadInt32(ptrToUsnRecord, REASON_OFFSET);
_fileAttributes = (UInt32)Marshal.ReadInt32(ptrToUsnRecord, FA_OFFSET);
short fileNameLength = Marshal.ReadInt16(ptrToUsnRecord, FNL_OFFSET);
short fileNameOffset = Marshal.ReadInt16(ptrToUsnRecord, FN_OFFSET);
Name = Marshal.PtrToStringUni(new IntPtr(ptrToUsnRecord.ToInt32() + fileNameOffset), fileNameLength / sizeof(char));
}
public int CompareTo(UsnEntry other){
return string.Compare(this.Name, other.Name, true);
}
public override string ToString(){
return string.Format ("[UsnEntry: RecordLength={0}, USN={1}, FileReferenceNumber={2}, ParentFileReferenceNumber={3}, Reason={4}, Name={5}, OldName={6}, IsFolder={7}, IsFile={8}", RecordLength, USN, (int)FileReferenceNumber, (int)ParentFileReferenceNumber, Reason, Name, OldName, IsFolder, IsFile);
}
}
我尝试隔离可以解析 USN 日志并提取其条目的最小代码部分,从最低的有效条目开始。请记住,记录的长度是可变的;另请注意,某些记录指向下一个空记录(前 4 个字节,通常是记录长度,被清零)。在本例中,我查找 4 个字节并重试解析,直到获得下一条记录。用 Python 编写类似解析工具的人也报告了这种行为,所以我想我在这里并没有太大错。
string vol = @"\\?\path_to_your_VSS_snapshot";
string maxHandle = vol + @"\$Extend\$UsnJrnl:$Max";
string rawJournal= vol + @"\$Extend\$UsnJrnl:$J";
// cannot use regular System.IO here, but pinvoking ReadFile() should be enough
FileStream maxStream = Alphaleonis.Win32.Filesystem.File.OpenRead(maxHandle);
byte[] maxData = new byte[32];
maxStream.Read(maxData, 0, 32);
//first valid entry
long lowestUsn = BitConverter.ToInt64(maxData, 24);
// max (last) entry, is the size of the $J ADS
IntPtr journalDataHandle = Win32Api.CreateFile(rawJournal,
0,
Win32Api.FILE_SHARE_READ| Win32Api.FILE_SHARE_WRITE,
IntPtr.Zero, Win32Api.OPEN_EXISTING,
0, IntPtr.Zero);
Win32Api.BY_HANDLE_FILE_INFORMATION fileInfo = new Win32Api.BY_HANDLE_FILE_INFORMATION();
Win32Api.GetFileInformationByHandle(journalDataHandle, out fileInfo);
Win32Api.CloseHandle(journalDataHandle);
long lastUsn = fileInfo.FileSizeLow;
int read = 0;
byte[] usnrecord;
byte[] usnraw = new byte[4]; // first byte array is to store the record length
// same here : pinvoke ReadFile() to avoid AlphaFS dependancy
FileStream rawJStream = Alphaleonis.Win32.Filesystem.File.OpenRead(rawJournal);
int recordSize = 0;
long pos = lowestUsn;
while(pos < newUsnState.NextUsn){
seeked = rawJStream.Seek(pos, SeekOrigin.Begin);
read = rawJStream.Read(usnraw, 0, usnraw.Length);
recordSize = BitConverter.ToInt32(usnraw, 0);
if(recordSize == 0){
pos = pos+4;
continue;
}
usnrecord = new byte[recordSize];
rawJStream.Read(usnrecord, 4, recordSize-4);
Array.Copy(usnraw, 0, usnrecord, 0, 4);
fixed (byte* p = usnrecord){
IntPtr ptr = (IntPtr)p;
// here we use the previously defined UsnEntry class
Win32Api.UsnEntry entry = new Win32Api.UsnEntry(ptr);
Console.WriteLine ("entry: "+entry.ToString());
ptr = IntPtr.Zero;
}
pos += recordSize;
}
以下是我使用的 pinvoke:
public class Win32Api{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BY_HANDLE_FILE_INFORMATION{
public uint FileAttributes;
public FILETIME CreationTime;
public FILETIME LastAccessTime;
public FILETIME LastWriteTime;
public uint VolumeSerialNumber;
public uint FileSizeHigh;
public uint FileSizeLow;
public uint NumberOfLinks;
/*public uint FileIndexHigh;
public uint FileIndexLow;*/
public FileID FileIndex;
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool
GetFileInformationByHandle(
IntPtr hFile,
out BY_HANDLE_FILE_INFORMATION lpFileInformation);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr
CreateFile(string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
}
这绝对不是地球上最好的代码,但我认为它将为任何必须做同样事情的人提供一个很好的起点。
关于winapi - 如何获取 VSS 快照的 'NextUSN' 日志条目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10544433/
我们是由少数 Delphi 开发人员组成的团队,他们多年来一直在使用 VSS(我知道这很遗憾),但我们没有使用 VCS 的任何高级功能,因此在很多情况下它都工作正常(但有些情况)有时它让我发疯:()。
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我一直在尝试按照说明安装 Windows SDK 附带的示例 VSS 硬件提供程序。我已经能够使用 VS2013 为 64 位平台成功编译代码。但是,当我尝试安装提供程序时,出现以下错误。 注销现有应
我一直在尝试按照说明安装 Windows SDK 附带的示例 VSS 硬件提供程序。不幸的是,COM 拒绝注册 DLL,并给出以下输出: Unregistering the existing appl
谁能澄清一个问题?我在自制备份实用程序*中使用 VSS API(使用 VSS2008 的 C++ 和在 XP SP3 上运行的最新 SDK)。 VSS 快照操作适用于没有子文件夹的文件夹 - 即我的电
我正在研究从 SourceSafe 到 Subversion 的潜在转变,我们正在努力解决编辑/合并/提交与 checkout /更新/ checkin 范式。主要关心的是您如何知道哪些文件被 Sub
我想编写一个应用程序来监视由“客户端”应用程序(及其所有进程)修改的文件,并在客户端应用程序执行完成后将它们恢复到原始状态。这可以使用卷影服务来实现,还是我应该编写一个文件系统过滤器驱动程序,因为我似
如何解锁 VSS 数据库?我们的一位 VSS 管理员运行了“分析和修复”例程,它阻止了用户 check out 文件。 最佳答案 您也可以简单地删除\data\loggedin\Admin.lck 文
如何将我的数据从 VSS 迁移到 SubVersion?? 最佳答案 这取决于您是否要随身携带 VSS 元数据。 如果是,请查看 PowerAdmin或 Vss2SVN在底格里斯河 如果没有,只需搜索
我正在将 Visual SourceSafe 代码存储库迁移到 Subversion,但遇到了问题。 这是我们当前源代码树(在 VSS 中)的简化布局: project_root\ |-libs\
我的工作场所正计划迁移到 Team Foundation Server,现在还为时过早 - 任何可以远离 Visual SourceSafe 的癌症。 但是,我必须问 - TFS 中的源代码控制是否与
我有卷影副本 (VSS) 的问题。这个问题是几天前开始的。我已经尝试了很多来自 Google 的东西,但找不到解决方案。 令人沮丧(且令人惊讶)的是,即使在我将计算机恢复到逐个扇区的镜像备份后,在不存
我正在尝试在 Visual SourceSafe 6 中合并一个分支。 在这里您可以看到“主线”代码库中的错误: 创建了一个修补程序分支,并修复了文件: 现在是时候将修补程序合并回主线开发了。我选择要
任何人都用示例和分步操作来描述我如何分支代码,然后在分支之后如何合并主代码中的更改。 感谢和问候, 侯赛因 最佳答案 要分支,右键单击将要分支的项目拖到新位置。将弹出一个对话框,选择“共享和分支”选项
我需要编写一个脚本来使源代码安全的项目准备好转移到 subversion,到目前为止我能想到的我需要做什么: 删除 .scc 文件 删除 .vspcc 文件 我是否还需要删除所有文件的“只读”属性,或
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在尝试通过 VSS 备份和恢复 MS SQL 服务器。我的备份操作运行良好,我将备份元数据存储在 XML 文件中。 在还原操作期间,我提供了在备份操作期间创建的相同 XML,发生的情况是还原在 P
在 Visual Source Safe 6.0 中,您可以通过将工作文件夹设置为空字符串来“重置”它。这意味着工作文件夹将由父文件夹的工作文件夹确定。 如何在 Visual Source Safe
我正在研究创建可在 Hyper-V 中启动的 .VHD 文件的方法。 我可以使用 Windows 7 和 Win 2k8 中包含的 VSS ASR 编写器来执行此操作吗? 最佳答案 经过进一步研究,似
我看过问题 here , 但我很难理解如何实现一个系统来从我的系统中读取现有的卷影副本。 有人可以提供一个简短的代码示例,让我可以使用 MS API 或 Alpha 的 API 浏览现有的卷影副本吗?
我是一名优秀的程序员,十分优秀!