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

问题描述 投票:0回答:3

问题:是否有一种编程方式可以阻止 Windows 10 在更新后自动重新启动?

我们致力于开发在 Windows 中运行的“关键任务”软件。 一般来说,如果 Windows 自动更新中断了我们的流程,那就不好了,因为这可能意味着报废材料造成金钱损失(您无法停止并稍后恢复,工作必须从头到尾不间断地进行)。

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

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

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

c# windows delphi winapi restart
3个回答
8
投票

尝试关闭阻止原因 API。 ShutdownBlockReasonCreate

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

应用程序应在开始不可中断的操作(例如刻录 CD 或 DVD)时调用此函数。当操作完成后,调用ShutdownBlockReasonDestroy函数表明系统可以关闭了。

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

NB:记得检查功能是否成功;并在进程完成时销毁关闭原因。


根据您的评论,您似乎需要使用 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;

4
投票

注册表项

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings
包含两个条目:
ActiveHoursStart
ActiveHoursEnd
。根据需要在程序中更改这些条目以禁止重新启动。通过这种方式,您可以控制程序运行时不进行重新启动。请注意,您需要提升权限才能更改这些设置。


0
投票

我用于 Windows 11 的解决方案遵循 @UweRaabe 提出的思路。我使用任务计划程序每小时运行这个命令行批处理程序:

for /f "tokens=1 delims=:" %%a in ('time/t') do set currentHour=%%a
    
if %currentHour% gtr 17 goto after6pm
if %currentHour% gtr 5 goto after6am
    
set /a startHour = %currentHour%+18
set /a endHour = %currentHour%+6
goto SetActiveHours
    
:after6pm
set /a startHour = %currentHour%-6
set /a endHour = %currentHour%-18
goto SetActiveHours
    
:after6am
set /a startHour = %currentHour%-6
set /a endHour = %currentHour%+6
    
:SetActiveHours
   
set "activeHours=%startHour%,%endHour%" 
     
reg add "HKLM\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" /v "ActiveHoursStart" /t REG_DWORD /d %startHour% /f 
reg add "HKLM\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" /v "ActiveHoursEnd" /t REG_DWORD /d %endHour% /f 
© www.soinside.com 2019 - 2025. All rights reserved.