【发布时间】:2019-08-06 04:32:38
【问题描述】:
我正在尝试使用安装的服务作为特定用户(在本例中为我)运行来更改壁纸。
这是我的 Wallpaper 类,它有一个 SetWallpaper 函数:
public sealed class Wallpaper
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError=true)]
private static extern Int32 SystemParametersInfo(
UInt32 action, UInt32 uParam, String vParam, UInt32 winIni);
private static readonly UInt32 SPI_SETDESKWALLPAPER = 0x14;
private static readonly UInt32 SPIF_UPDATEINIFILE = 0x01;
private static readonly UInt32 SPIF_SENDWININICHANGE = 0x02;
public static void SetWallpaper(String path)
{
System.IO.Stream s = new System.Net.WebClient().OpenRead(path.ToString());
System.Drawing.Image img = System.Drawing.Image.FromStream(s);
string tempPath = Path.Combine(Path.GetTempPath(), "wallpaper.bmp");
ImgurWallpaperSetter.ImgurWallpaperSetter.log(tempPath);
img.Save(tempPath, System.Drawing.Imaging.ImageFormat.Bmp);
SystemParametersInfo(SPI_SETDESKWALLPAPER, 1, tempPath,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
int error = Marshal.GetLastWin32Error();
ImgurWallpaperSetter.ImgurWallpaperSetter.log("Last error: " + error);
}
}
当我从单元测试中运行SetWallpaper 时,它可以完美运行,但是当我安装并启动该服务时,它根本不起作用。
这里是服务启动代码:
protected override void OnStart(string[] args) {
//WallpaperScheduler.ScheduleWallpaperFetch(DateTime.Now.Hour, DateTime.Now.Minute+1);
//Debugger.Launch();
Uri imageUrl = WallpaperRetriever.mostPopularImgurWallpaper();
log(imageUrl.AbsoluteUri);
Wallpaper.SetWallpaper(imageUrl.AbsoluteUri);
}
我已经确认它正在正确地将图像下载到我的临时目录中,但它没有设置壁纸。它不会出错或在事件日志中记录任何内容。
这是我在本地服务查看器中安装的服务:
运行它什么都不做。
编辑:
添加此代码以在我的 serviceInstaller_Committed 事件上运行,该事件应允许服务与桌面交互,但我发现服务运行与实际切换壁纸之间存在巨大延迟:
ConnectionOptions coOptions = new ConnectionOptions();
coOptions.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope mgmtScope = new ManagementScope(@"root\CIMV2", coOptions);
mgmtScope.Connect();
ManagementObject wmiService;
wmiService = new ManagementObject(
"Win32_Service.Name='" + serviceInstaller1.ServiceName + "'"
);
ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
InParam["DesktopInteract"] = true;
ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
编辑2:
我已经更新了我的服务以记录到系统事件GetLastError()。现在我看到服务抛出错误 1459(“此操作需要交互式窗口站。”)。但是,这并不能解释为什么我的壁纸最终会切换(我认为通常是在从睡眠中醒来之后)。也更新了上面的 Wallpaper 类。
编辑3 我已经确认睡觉后设置了新壁纸。谁能解释这是为什么?是不是我需要重新启动才能设置交互式桌面功能?
编辑4 我正在做的是感觉很hacky。如果我让服务除了下载壁纸什么都不做,并且如果已经下载了新壁纸并且用户已登录,并且可能有另一个非服务应用程序来更改壁纸,那会更好吗?
【问题讨论】:
-
运行该服务的用户是否有权更改壁纸?您可能想添加一些 try catch 并查看是否抛出任何错误。
-
我现在在自己的帐户上运行它只是为了测试应用程序。我的计算机上只有一个帐户,它是我的管理员帐户。
-
我相信 UAC 已启用,但我在管理命令提示符下安装该服务,并且该服务要求我提供凭据,以便它可以充当我的角色。 UAC 是否可以阻止它,即使它在我的权限下运行?
标签: c# windows-services