Log*_*mon 9 powershell batch windows-8 file-history windows-10
tl; dr:有没有办法通过无人值守的命令行/某些脚本来配置 Windows 8 文件历史记录?
长话短说:我正在配置很多独立(非域)PC,我认为有备份总比没有备份好。在 Windows 7 上,我什至配置了它的标准备份,尽管它被延迟了——默认情况下,它每周一都会显着降低计算机的速度,除非由于某些不明原因用户没有在周末之前关闭他们的电脑,并且它填满了备份介质并停止备份。
我辞职尝试自动化其配置,但至少我可以在那里以管理员身份设置一次,并且它对所有人都有效,包括新用户。而且我正在调度(调度是自动的)自定义脚本以在备份媒体空间不足时删除旧备份,因此之后不需要维护(设置一次即可忘记)。
从 Windows 8 开始,就有了一个叫做文件历史的东西,它对用户的干扰要小得多(它的性能影响几乎不明显),并且它可以自行清理(基于年龄或可用空间的自动历史管理)。这是真正的备份解决方案,现在是真正的:) 但它也需要为每个用户手动配置。这是不可接受的,因为用户会忘记配置它。
我的计划是使用一些 runonce 登录脚本为每个用户配置它。我已经在通过 runonce-logon 脚本做一些事情,所以安装这样的脚本不是问题。但我不知道如何通过脚本配置文件历史记录。
我尝试了一些研究,但我发现的唯一官方(有一些非官方发现,见下面的截图)相关工具是FhManagew.exe,它删除旧文件版本。我需要先通过 GUI 设置它。链接上有完整的API,貌似可以通过该API配置File History。但我认为这是 .NET 应用程序的 API,因此不能通过命令行使用。或者可以吗?
尝试过注册表搜索,但在任何地方都找不到文件历史记录位置:(
具体来说,假设我想设置文件历史记录\\localhost\FileHistory$
并保留文件版本直到需要可用空间(默认情况下它会永远保留)。这是它的外观:
供参考:备份到本地共享是使文件历史记录在单个硬盘上工作的解决方法,否则它声称它是不安全的。
这是我通过评论发现的:配置存储在 .xml 文件中的 xml 文件中%LocalAppData%\Microsoft\Windows\FileHistory\Configuration
。它在注册表项中被引用HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\fhsvc\Parameters\Configs
,值 name = 配置文件夹的路径(如上),值 data = REG_DWORD:1
。
但简单地添加这些文件和注册表值并启动服务(有它的脚本)不会启动备份,控制面板中的配置也不会更新。但是,如果已配置文件历史记录,则 xml 文件的更新会反映在控制面板中。
不幸的是,API是不是很容易使用-大多数有关调用是一个COM对象没有实现IDispatch
。因此,从 PowerShell 调用这些函数将非常困难和混乱。这些是我们需要进行的调用:
CoCreateInstance
获取FhConfigMgr
对象IFhConfigMgr::CreateDefaultConfiguration
创建配置或替换旧配置IFhConfigMgr::ProvisionAndSetNewTarget
设置备份目标文件夹IFhConfigMgr::SetLocalPolicy
将策略设置为仅在需要空间时删除IFhConfigMgr::SetBackupStatus
打开文件历史记录IFhConfigMgr::SaveConfiguration
提交更改FhServiceOpenPipe
获取文件历史服务的句柄FhServiceReloadConfiguration
告诉服务重新加载其设置FhServiceClosePipe
关闭服务的句柄要调用所有这些函数,我们可以使用我的开源应用程序SprintDLL。我为你写了这个脚本,用每个部分的人造 C++ 等价物进行了评论:
// CoCreateInstance(CLSID_FhConfigMgr, NULL, CLSCTX_INPROC_SERVER, IID_IFhConfigMgr, &fh)
newslot native fhPtr
call ole32.dll!CoCreateInstance /return uint (blockptr(guid {ED43BB3C-09E9-498a-9DF6-2177244C6DB4}), nullptr, int 1, blockptr(guid {6A5FEA5B-BF8F-4EE5-B8C3-44D8A0D7331C}), slotptr fhPtr)
newslot native fh
copyslot fh = fhPtr dereferenced
newslot block vtbl = nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
copyslot vtbl = fh dereferenced
// fh->CreateDefaultConfiguration(TRUE)
newslot native createDefaultConfiguration
copyslot createDefaultConfiguration = vtbl field 4
call funcat createDefaultConfiguration /call thiscall /return uint (slotdata fhPtr, int 1)
// fh->ProvisionAndSetNewTarget("\\localhost\FileHistory$\", "Local Disk")
newslot native provisionAndSetNewTarget
copyslot provisionAndSetNewTarget = vtbl field 14
call funcat provisionAndSetNewTarget /call thiscall /return uint (slotdata fhPtr, bstr "\\\\localhost\\FileHistory$\\", bstr "Local Disk")
// fh->SetLocalPolicy(FH_RETENTION_TYPE, FH_RETENTION_UNLIMITED)
newslot native setLocalPolicy
copyslot setLocalPolicy = vtbl field 9
call funcat setLocalPolicy /call thiscall /return uint (slotdata fhPtr, int 1, int 1)
// fh->SetBackupStatus(FH_STATUS_ENABLED)
newslot native setBackupStatus
copyslot setBackupStatus = vtbl field 11
call funcat setBackupStatus /call thiscall /return uint (slotdata fhPtr, int 2)
// fh->SaveConfiguration()
newslot native saveConfiguration
copyslot saveConfiguration = vtbl field 5
call funcat saveConfiguration /call thiscall /return uint (slotdata fhPtr)
// FhServiceOpenPipe(TRUE, &fhPipe)
newslot native fhPipe
call fhsvcctl.dll!FhServiceOpenPipe /return int (int 1, slotptr fhPipe)
// FhServiceReloadConfiguration(fhPipe)
call fhsvcctl.dll!FhServiceReloadConfiguration /return int (slotdata fhPipe)
// FhServiceClosePipe(fhPipe)
call fhsvcctl.dll!FhServiceClosePipe /return int (slotdata fhPipe)
Run Code Online (Sandbox Code Playgroud)
我从文件历史管理器 COM 对象的 C 风格 COM 接口中函数的位置获得了 VTable 字段 ID 。如果脚本成功,它会说每个函数都返回零。
要使用该脚本,请将其保存到一个文件中,例如filehistory.sprint
. 然后,您可以从批处理文件中运行它,如下所示:
sprintdll run filehistory.sprint
Run Code Online (Sandbox Code Playgroud)
如果通过网络进行部署,您可能希望首先包含一个将实用程序和脚本复制到本地计算机上的命令。