防止 Windows 10 在以编程方式更新后自动重启



问题:有没有一种编程方法可以防止Windows 10在更新后自动重启?

我们开发在Windows中运行的"关键任务"软件。 一般来说,如果 Windows 自动更新中断我们的流程,那就很糟糕了,因为它可能意味着报废材料中的钱损失(您不能停止并稍后恢复,作业必须从头到尾不间断地工作(。

过去,我们能够通过让我们的软件安装程序在 Windows 注册表中设置一个参数(经用户安装程序同意(来解决此问题,该参数将防止在用户登录时自动更新后自动重新启动。 因此,将通知用户有更新需要重新启动,并在准备好时单击按钮,而不是自动更新。 这适用于Windows Vista,7和8/8.1。 但是,对于最新的 Windows 10(我正在使用创作者的更新(,该参数似乎不再有效,因为我观察到我的计算机经历了自动更新,我知道注册表项已经生效。

在我的研究中,我发现了一个似乎充满希望的地方,可以选择一个设置,Windows将为用户提供计划更新的机会,而不仅仅是在Windows认为合适的时间自动进行更新(信息在这里(。 但是,我不确定如何以编程方式设置 Windows,以便计划更新的选项成为默认值。

有没有一种编程方法来设置 Windows 10(最好以友好的方式(,使其不会自动重启?

尝试关闭块原因 API。关机块原因创建

API 文档引用 CD 刻录作为示例,但这同样适用于您的"任务关键型"过程。

应用程序应在开始无法中断的操作(如刻录 CD 或 DVD(时调用此函数。操作完成后,调用 ShutdownBlockReasonDestroy 函数以指示系统可以关闭。

请注意,文档特别引用了用户关闭,但我不明白为什么它不应该也适用于更新重启。

注意:请记住检查函数是否成功;并在该过程完成时销毁关机原因。


根据您的评论,您似乎需要帮助使用 Windows API 例程。我建议您在适当的库中声明外部函数。(但您可以放心地在同一单元中进行测试。

function ShutdownBlockReasonCreate(hWnd: HWND; Reason: LPCWSTR): BOOL; stdcall; external user32;
function ShutdownBlockReasonDestroy(hWnd: HWND): BOOL; stdcall; external user32;

下面演示如何使用 API。注意:注意错误检查。我已经演示了如何获取错误信息。你用它做什么取决于你。

要指出的另一件重要事情(在注释中重复(是你不应该阻塞主线程。有关详细信息,请参阅此处的 Vista 首次引入这些更改时的Microsoft文档。

procedure TForm1.JobStartClick(Sender: TObject);
var
LErr: Cardinal;
begin
ListBox1.Items.Add('Attempting to block shutdown:');
if (not ShutdownBlockReasonCreate(Application.MainForm.Handle, 
'Super Critical Job')) then
begin
LErr := GetLastError;
ListBox1.Items.Add('... failed: ' + SysErrorMessage(LErr));
//Probably not safe to start your job in this case, but perhaps you
//choose to give it a shot anyway.
Exit;
end;
ListBox1.Items.Add('... success');
FJobRunning := True;
//Start the job.
//However, NB do not run the job here.
//If it takes a long time and is not asynchronous, you should probably
//run your job on a separate thread.   ***Do not block the main thread
//  otherwise Windows will still kill your app for not responding***
end;
procedure TForm1.JobEndClick(Sender: TObject);
var
LErr: Cardinal;
begin
if (not FJobRunning) then Exit;
//End the job.
//Again, do not block the main thread, so perhaps this is rather something
//to do after you already know the job is done.
FJobRunning := False;
ListBox1.Items.Add('Allow shutdown');
if (not ShutdownBlockReasonDestroy(Application.MainForm.Handle)) then
begin
LErr := GetLastError;
ListBox1.Items.Add('... failed: ' + SysErrorMessage(LErr));
end;
end;
//Declare the handler for the WM_QUERYENDSESSION message as follows.
//procedure WMQueryEndSession(var AMsg : TWMQueryEndSession); message WM_QUERYENDSESSION;
procedure TForm1.WMQueryEndSession(var AMsg: TWMQueryEndSession);
begin
ListBox1.Items.Add('WMQueryEndSession');
if (FJobRunning) then
//NB: This is very important.
//You still need to confirm that your application wants to block
//shutdown whenever you receive this message.
AMsg.Result := 0
else
inherited;
end;

注册表项HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsUpdateUXSettings包含两个条目:ActiveHoursStartActiveHoursEnd。根据需要在程序中更改这些条目以禁止重新启动。这样,您可以控制在程序运行时不重新启动。请注意,需要提升的权限才能更改这些设置。

相关内容

最新更新