【问题标题】:How to invoke the screen saver in Windows in C#?如何在 C# 中调用 Windows 中的屏幕保护程序?
【发布时间】:2025-12-03 16:10:01
【问题描述】:

如果在 Windows 环境中定义了用户的屏幕保护程序,我想调用它。

我知道它可以使用纯 C++ 代码来完成(然后在 C# 中的包装非常简单),正如 here 所建议的那样。

不过,出于好奇,我想知道这样的任务是否可以通过使用 dot net 框架(2.0 版及更高版本)的纯托管代码来完成,无需 p/invoke 且无需访问 C++ 端(其中,在转,可以很容易地使用 Windows API)。

【问题讨论】:

  • 您也可以非常轻松地从 C# 中调用 Windows API。
  • 重复(有你要找的答案):*.com/questions/267728/…
  • 不是骗子——问题是如何在没有 p/invoke 的情况下做到这一点。

标签: c# .net windows managed screensaver


【解决方案1】:

我有一个想法,我不确定这会持续多久,所以我认为你需要进行一些研究,但希望这足以让你开始。

屏幕保护程序只是一个可执行文件,注册表将这个可执行文件的位置存储在HKCU\Control Panel\Desktop\SCRNSAVE.EXE

在我的 Vista 副本上,这对我有用:

RegistryKey screenSaverKey = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop");
if (screenSaverKey != null)
{
    string screenSaverFilePath = screenSaverKey.GetValue("SCRNSAVE.EXE", string.Empty).ToString();
    if (!string.IsNullOrEmpty(screenSaverFilePath) && File.Exists(screenSaverFilePath))
    {
        Process screenSaverProcess = Process.Start(new ProcessStartInfo(screenSaverFilePath, "/s"));  // "/s" for full-screen mode
        screenSaverProcess.WaitForExit();  // Wait for the screensaver to be dismissed by the user
    }
}

【讨论】:

  • 这可能有效,但 Windows 内置了触发屏幕保护程序的机制。你应该使用这些,而且它比手动更容易实现。
【解决方案2】:

我认为拥有一个 .Net 库函数来执行此操作的可能性极小——我不知道有什么。快速搜索返回此代码项目tutorial,其中包含您在问题中提到的托管包装器的示例。

P/invoke 的存在使您能够访问特定于操作系统的功能,其中屏幕保护程序就是一个示例。

【讨论】:

    【解决方案3】:

    我不确定您是否可以使用完全托管的代码来执行此操作。

    这使用 Windows API 但仍然很简单:Launch System Screensaver from C# Windows Form

    【讨论】:

      【解决方案4】:

      在任何版本的 Windows 上工作...

      using System;
      using System.Collections.Generic;
      using System.Diagnostics;
      using System.Linq;
      using System.Runtime.InteropServices;
      using System.Text;
      using System.Threading.Tasks;
      
      namespace HQ.Util.Unmanaged
      {
          public class ScreenSaverHelper
          {
              [DllImport("User32.dll")]
              public static extern int SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
      
              [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
              private static extern IntPtr GetDesktopWindow();
      
              // Signatures for unmanaged calls
              [DllImport("user32.dll", CharSet = CharSet.Auto)]
              private static extern bool SystemParametersInfo(int uAction, int uParam, ref int lpvParam, int flags);
      
              // Constants
              private const int SPI_GETSCREENSAVERACTIVE = 16;
              private const int SPI_SETSCREENSAVERACTIVE = 17;
              private const int SPI_GETSCREENSAVERTIMEOUT = 14;
              private const int SPI_SETSCREENSAVERTIMEOUT = 15;
              private const int SPI_GETSCREENSAVERRUNNING = 114;
              private const int SPIF_SENDWININICHANGE = 2;
      
              private const uint DESKTOP_WRITEOBJECTS = 0x0080;
              private const uint DESKTOP_READOBJECTS = 0x0001;
              private const int WM_CLOSE = 16;
      
              public const uint WM_SYSCOMMAND = 0x112;
              public const uint SC_SCREENSAVE = 0xF140;
              public enum SpecialHandles
              {
                  HWND_DESKTOP = 0x0,
                  HWND_BROADCAST = 0xFFFF
              }
              public static void TurnScreenSaver(bool turnOn = true)
              {
                  // Does not work on Windows 7
                  // int nullVar = 0;
                  // SystemParametersInfo(SPI_SETSCREENSAVERACTIVE, 1, ref nullVar, SPIF_SENDWININICHANGE);
      
                  // Does not work on Windows 7, can't broadcast. Also not needed.
                  // SendMessage(new IntPtr((int) SpecialHandles.HWND_BROADCAST), WM_SYSCOMMAND, SC_SCREENSAVE, 0);
      
                  SendMessage(GetDesktopWindow(), WM_SYSCOMMAND, (IntPtr)SC_SCREENSAVE, (IntPtr)0);
              }
          }
      }
      

      【讨论】:

      • 确认,在win10上可以使用。
      最近更新 更多