问题:是否有一种编程方式可以阻止Windows 10在更新后自动重启?
我们致力于"任务关键型"在Windows中运行的软件。一般来说,如果Windows自动更新中断了我们的流程,这很糟糕,因为它可能意味着报废材料中的损失(您无法停止并在以后恢复,工作必须从头到尾不间断地工作)。
过去,我们可以通过让我们的软件安装程序在Windows注册表中设置一个参数(在用户安装程序的同意下)来避免在用户自动更新后自动重启因此,不会自动更新,而是会通知用户有需要重新启动的更新,并在准备好时单击按钮。这适用于Windows Vista,7和8 / 8.1。但是,对于最新的Windows 10(我正在使用Creators'更新),该参数似乎不再有效,因为我观察到我的计算机经历了自动更新,我知道注册表项是已经生效。
在我的研究中,我发现似乎是一个希望的地方,可以选择一个设置,其中Windows将为用户提供安排更新的机会,而不是仅在Windows认为合适时自动执行此操作(信息here)。但是,我不确定如何以编程方式设置Windows,以便安排更新的选项成为默认选项。
是否有一种以编程方式设置Windows 10(最好以友好的方式),以便它不会自动重启?
答案 0 :(得分:6)
尝试关闭阻止原因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。注意:注意错误检查。我已经演示了如何获取错误信息。你用它做什么取决于你。
要指出的另一个重要的事情(在评论中重复)是你不应该阻止主线程。有关详细信息,请参阅Microsoft文档,了解这些更改何时首次在Vista here中引入。
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;
答案 1 :(得分:4)
注册表项HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings
包含两个条目:ActiveHoursStart
和ActiveHoursEnd
。在程序中根据需要更改这些条目以禁止重新启动。这样,您可以控制重启不会在程序运行时发生。请注意,您需要提升权限才能更改这些设置。
答案 2 :(得分:-1)
我不知道它的强度如何,但是打开“另存为”对话框时,记事本似乎阻止了自动重启。如果可接受的修补程序在将来的版本中中断,可能会很有用。