0

嗨,我无法让卷影复制服务为我用 QT 用 C++ 编写的程序工作。快照已成功创建,但是我无法通过我的程序或 Windows 运行提示访问它(不确定这是否可能首先出现)。我尝试使用 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy27\ 和 \Device\HarddiskVolumeShadowCopy28\ 作为前缀访问快照(从我的程序生成,最后带有正确的数字)。即使我使用 VSS_BT_COPY 和 VSS_BT_FULL 作为状态,快照看起来也像是差异快照。我一直在尝试将 VSS_CTX_NAS_ROLLBACK 作为创建持久快照的上下文,因此我尝试在再次尝试访问程序中的快照之前将它们全部删除,但这次使用上下文 VSS_CTX_FILE_SHARE_BACKUP,但没有成功。这是快照创建代码(删除了错误处理):

void Worker::setupVSS(BackupJob &job)
{
    HRESULT result;
    //backupComponents is a class member variable
    //IVssBackupComponents *backupComponents;

    result = CreateVssBackupComponents(&backupComponents);

    VSS_ID snapshotSetId;
    result = backupComponents->InitializeForBackup();

    //tried both of these
    //result = backupComponents->SetBackupState(FALSE, FALSE, VSS_BT_COPY);
    result = backupComponents->SetBackupState(FALSE, FALSE, VSS_BT_FULL);

    //tried both of these
    //result = backupComponents->SetContext(VSS_CTX_NAS_ROLLBACK);
    result = backupComponents->SetContext(VSS_CTX_FILE_SHARE_BACKUP);

    result = backupComponents->StartSnapshotSet(&snapshotSetId);

    VSS_ID snapshotId;
    wchar_t *source;
    //this line gets the drive letter with : and \
    QString driveLetter = job.getSource().mid(0,3);
    driveLetter.toWCharArray(source);
    //QString("D:\\").toWCharArray(source);
    result = backupComponents->AddToSnapshotSet(source, GUID_NULL, &snapshotId);

    IVssAsync *async;
    result = backupComponents->DoSnapshotSet(&async);

    result = async->Wait();
    async->Release();

    VSS_SNAPSHOT_PROP prop;
    result = backupComponents->GetSnapshotProperties(snapshotId, &prop);

    QString vssPrefix = QString::fromWCharArray(prop.m_pwszSnapshotDeviceObject);
    job.setVSSPrefix(vssPrefix);
}

这是文件打开代码:

QString sourceFileString = job.getCurrentFileSource(fileCount);
if (job.getVSS())
{
    QString prefix = job.getVSSPrefix();
    //tried this comment to remove ? and globalroot from prefix without success
    //prefix = prefix.mid(prefix.indexOf("\\Device"));
    prefix.append("\\");
    prefix = QDir::fromNativeSeparators(prefix);
    sourceFileString.replace(0,3,prefix);
}
QFile sourceFile(sourceFileString);
if (!sourceFile.open(QIODevice::ReadOnly))
{
    updateStatus("<font color=\"red\">ERROR: Couldn't open source file " + QDir::toNativeSeparators(sourceFile.fileName()) + ".</font>");
    updateStatus("<font color=\"red\">ERROR: " + sourceFile.errorString() + "</font>");
    errorsFound = true;
    break;
}

以下是 QT 从失败的文件打开尝试中给我的错误:

2017 年 1 月 13 日 01:42 PM 错误:无法打开源文件 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy38\Users\Josh\Desktop\awef\awef3\awefawefawef - 复制 (10)waefawefawefawwefawefawef - Copyawefawwefawefawefawefwefawefawef.docx。

01-13-2017 01:42 PM 错误:找不到网络路径。

2017 年 1 月 13 日 01:44 PM 错误:无法打开源文件 \Device\HarddiskVolumeShadowCopy40\Users\Josh\Desktop\awef\awef3\awefawefawef - 复制 (10)waefawefawwefawefawefawef - Copyawefawefawwefawefawefwefawefawef.docx。

01-13-2017 01:44 PM 错误:系统找不到指定的路径。

当我尝试从运行提示打开相同的文件时,它只是说 Windows 找不到文件名等。

我验证了快照是使用 vssadmin list shadows 创建的,输出如下:

卷影副本集 ID 的内容:{968d9034-3aee-494b-ae78-82af04a15686} 创建时包含 1 个卷影副本:2017 年 1 月 13 日下午 1:40:09 卷影副本 ID:{1109bad9-7d01-40f2-9141- cda25b313810} 原始卷:(C:)\?\Volume{b3fc9fb7-0000-0000-0000-100000000000}\ 卷影复制卷:\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy38 原始机器:joshdesktop10 服务机器:joshdesktop10 提供者:'Microsoft Software Shadow Copy provider 1.0' 类型:FileShareRollback 属性:No writers,Differential

卷影副本集 ID 的内容:{d6519b09-8325-4c1c-90bc-935a39f2189a} 创建时包含 1 个卷影副本:2017 年 1 月 13 日下午 1:44:07 卷影副本 ID:{21e1b83e-db79-4a29-95b0- 65cc5c7d08a8} 原始卷:(C:)\?\Volume{b3fc9fb7-0000-0000-0000-100000000000}\ 卷影复制卷:\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy40 原始机器:joshdesktop10 服务机器:joshdesktop10 提供者:'Microsoft Software Shadow Copy provider 1.0' 类型:FileShareRollback 属性:No writers,Differential

如您所见,它们是差异备份……这可能是问题所在吗?

有任何想法吗??谢谢!

4

1 回答 1

0

谷歌启发了我......因为在这里,如果不使用 Win32 API 函数 FindFirstFile/FindNextFile,您将无法访问 VSS 快照卷。有一种解决方法...将快照卷挂载为符号链接并使用该链接访问文件。这是我使用的代码:

VSS_SNAPSHOT_PROP prop;
result = backupComponents->GetSnapshotProperties(snapshotId, &prop);    
wchar_t *snapVol = prop.m_pwszSnapshotDeviceObject;
wcsncat(snapVol, L"\\", 1);
if (QDir("C:\\repVSSVol").exists())
    RemoveDirectory(L"C:\\repVSSVol");
if (CreateSymbolicLink(L"C:\\repVSSVol", snapVol, SYMBOLIC_LINK_FLAG_DIRECTORY) == 0)
    win32Error(TEXT("CreateSymbolicLink"));

还要小心删除符号目录链接,如此所述。

于 2017-01-26T20:55:53.390 回答