如何从非提升的 c# 程序更改系统时间

Posted

技术标签:

【中文标题】如何从非提升的 c# 程序更改系统时间【英文标题】:How do I change system time from a non elevated c# program 【发布时间】:2021-01-18 16:21:36 【问题描述】:

我再次需要你的帮助:)

我想做的事: 我有一个 c# 程序,它以普通用户权限运行 - 无法提高 - 我想从该程序更改系统日期(而不是时间)。

[编辑] 更具体一点:我确实有可以嵌入到程序中的管理员凭据(哎呀,我知道),但我想避免 UAC 提示.

当我从 Visual Studio 外部启动 cmd 并尝试更改日期时,它会因“缺少客户端权限”而失败(大致翻译自德语)。当我以管理员身份启动 cmd 时,确认 UAC 提示相同的命令成功。

我是在家写作,所以目前无法提供运行代码。但是我所有的尝试都编译并运行没有错误,但日期没有改变。

我尝试过的:

    创建了一个Process 实例,将管理员凭据应用到ProcessStartInfo,将FileName 设置为c:\windows\system32\cmd.exe,并将参数设置为/C date thedate。我重定向了StandardOutputStandardError,执行后StandardError 包含与上述相同的消息:“缺少客户端权限”

    我已经修改了这个示例MSDN: WindowsIdentity.Impersonate,使用带有AdvAPI32.LogonUser 的PInvoke 来提高权限,并使用Kernel32.SetSystemTime 来更改系统时间。 AdvAPI32.LogonUser 成功,WindowsIdentity.GetCurrent().Name 返回管理员名称,但调用 Kernel32.SetSystemTime 失败并显示“缺少客户端权限”。

    我已经尝试打开当前进程AdvApi32.OpenCurrentProcess 并使用AdvApi32.AdjustTokenPrivileges 按照此示例***: Change system time programmaticaly using datetimepeaker 调整权限,代码运行完全正常,但Kernel32.SetSystemTime 失败...

[编辑] 解决方案: 我最终编写了一个带有嵌入式 app.manifest 的小程序,请求管理员权限。这个应用程序是从主程序调用的,所以它仍然可以由普通用户运行。

【问题讨论】:

我不明白你的问题。当您需要某些任务的权限时,您肯定必须提供一些权限。或者换句话说:您需要管理员权限来更改系统日期。 这能回答你的问题吗? How do you do Impersonation in .NET? 您需要特权。在 Windows 中关闭 UAC 以删除弹出窗口并创建一个快捷方式以始终以管理员身份运行。 @HimBromBeere 我确实有管理员凭据,我用它们来创建进程/模拟但似乎没有 app.manifest/UAC 提示程序,将使用一个不允许的受限令牌我来更改日期。 @Charlieface 感谢您的链接。代码更容易阅读,但来自 MSDN 的代码确实有效。 WindowsIdentity.GetCurrent().Name 确实确认我是管理员,但即使这样也不允许我更改日期。 【参考方案1】:

一旦启动,就无法更改进程的权限。原始进程必须以提升的权限启动另一个进程。第二个进程实际上可以是同一个 .exe 文件,但带有一个命令参数,告诉进程执行一些小操作并立即退出。

如another question 中所述,要以提升的权限启动进程,请使用 Process.Start,但使用 .Verb = "runas"。这当然会导致 UAC 提示弹出,如果它在机器上启用。必须至少显示一个 UAC 提示,因为如果有这种防御机制,UAC 提示就是重点。

如果您想将许多 UAC 提示减少到只有一个,那么您可以将原始应用设置为以管理员身份启动(原始进程启动时显示 UAC 提示)并且只有一个进程。或者在原始进程和提升的进程之间进行一些进程间通信,使提升的进程只启动一次,并在原始进程结束时完成。在第二种情况下,UAC 提示显示第一次需要它。

【讨论】:

我已经投了赞成票,因为它是我最终得到的解决方案,但它不是我正在寻找的解决方案(在没有 UAC 提示的情况下以管理员身份进行身份验证) - 但它似乎是唯一的出路。 【参考方案2】:

请问您为什么需要从非特权应用程序更改系统时间?

如果要影响其他应用程序,那么您将需要管理员权限,因为日期时间对于许多其他应用程序来说是如此重要的系统功能。但是,如果您只需要调整应用程序中的日期,那么我建议您创建自己的日期/时间提供程序,该提供程序可以将日期偏移量返回到您在应用程序中所需的日期。

例如。

 public DateTime GetDateWithOffset(int daysToOffset)
    
        return DateTime.UtcNow.AddDays(daysToOffset);
    

【讨论】:

以上是关于如何从非提升的 c# 程序更改系统时间的主要内容,如果未能解决你的问题,请参考以下文章

从非托管 c++ 调用托管 c# 函数

从非托管 c++ 调用托管 c# 函数

如何将数据从非托管应用程序传递到 C# COM DLL

绕过 UAC 以允许从非提升源拖放到我们提升的应用程序

从非 Google 系统调用时,CloudKMS 加密/解密如何安全工作?

使用 Dispatcher.Invoke 从非主线程更改 WPF 控件