none
如何使用Windows 服务设置桌面背景图片 RRS feed

  • 问题

  • 用C# 写了个服务,在服务中调用 SystemParametersInfo(20,0,"图片路径",1) 函数,总是返回失败,操作系统是win10,但是通过普通的Winform 程序调用此函数却是OK,求教这是什么原因呢?
    2016年5月16日 4:41

答案

  • 谢谢提醒,现在问题已经解决,解决的方式是

    1、允许服务与桌面应用交互

    2、引用的第三方的DLL(Cjwdev.WindowsApi)

    主要代码如下:

    1、允许服务与桌面应用交互

     private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
            {
                //允许服务和用户界面交互
                ConnectionOptions coOptions = new ConnectionOptions();
                coOptions.Impersonation = ImpersonationLevel.Impersonate;
                ManagementScope mgmtScope = new System.Management.ManagementScope(@"root\CIMV2", coOptions);
                mgmtScope.Connect();
                ManagementObject wmiService;
                wmiService = new ManagementObject("Win32_Service.Name='" + this.serviceInstaller1.ServiceName + "'");
                ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
                InParam["DesktopInteract"] = true;
                ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
            }

    2、引用第三方动态库(Cjwdev.WindowsApi.dll),在服务启动后调用我的应用程序,更改桌面代码的逻辑放置在我的应用程序中。

      protected override void OnStart(string[] args)
            {

                //我的应用程序路径
                string appStartPath = @"C:\\SV\\ChangeImageWinFormUI.exe";
                IntPtr userTokenHandle = IntPtr.Zero;
                ApiDefinitions.WTSQueryUserToken(ApiDefinitions.WTSGetActiveConsoleSessionId(), ref userTokenHandle);
                ApiDefinitions.PROCESS_INFORMATION procInfo = new ApiDefinitions.PROCESS_INFORMATION();
                ApiDefinitions.STARTUPINFO startInfo = new ApiDefinitions.STARTUPINFO();
                startInfo.cb = (uint)Marshal.SizeOf(startInfo);
                ApiDefinitions.CreateProcessAsUser(userTokenHandle, appStartPath, "", IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startInfo, out procInfo);
                if (userTokenHandle != IntPtr.Zero)
                    ApiDefinitions.CloseHandle(userTokenHandle);
                int _currentAquariusProcessId = (int)procInfo.dwProcessId;

            }

    • 已标记为答案 xbxc99 2016年5月17日 1:30
    2016年5月17日 1:30

全部回复

  • 每个用户的 桌面背景图片 是不同的吧。 windows service默认不是运行在当前登录用户下的。

    你试一试在Service的属性的log on页中,用的你的当前登录用户运行一下service试一试是不是能调用成功。

    2016年5月16日 5:06
  • 看是不是服务里面

    Allow service to inerract with desktop

    这个没有勾上


    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2016年5月16日 6:08
  • 谢谢,问题已经解决了,不过除了这一项之外还用到了一个第三方的动态库 Cjwdev.WindowsApi.dll

    通过下面的代码,设置服务安装完之后,勾选允许服务于桌面交互

     private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
            {
                //允许服务和用户界面交互
                ConnectionOptions coOptions = new ConnectionOptions();
                coOptions.Impersonation = ImpersonationLevel.Impersonate;
                ManagementScope mgmtScope = new System.Management.ManagementScope(@"root\CIMV2", coOptions);
                mgmtScope.Connect();
                ManagementObject wmiService;
                wmiService = new ManagementObject("Win32_Service.Name='" + this.serviceInstaller1.ServiceName + "'");
                ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
                InParam["DesktopInteract"] = true;
                ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
            }

    2016年5月17日 1:24
  • 谢谢提醒,现在问题已经解决,解决的方式是

    1、允许服务与桌面应用交互

    2、引用的第三方的DLL(Cjwdev.WindowsApi)

    主要代码如下:

    1、允许服务与桌面应用交互

     private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
            {
                //允许服务和用户界面交互
                ConnectionOptions coOptions = new ConnectionOptions();
                coOptions.Impersonation = ImpersonationLevel.Impersonate;
                ManagementScope mgmtScope = new System.Management.ManagementScope(@"root\CIMV2", coOptions);
                mgmtScope.Connect();
                ManagementObject wmiService;
                wmiService = new ManagementObject("Win32_Service.Name='" + this.serviceInstaller1.ServiceName + "'");
                ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");
                InParam["DesktopInteract"] = true;
                ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);
            }

    2、引用第三方动态库(Cjwdev.WindowsApi.dll),在服务启动后调用我的应用程序,更改桌面代码的逻辑放置在我的应用程序中。

      protected override void OnStart(string[] args)
            {

                //我的应用程序路径
                string appStartPath = @"C:\\SV\\ChangeImageWinFormUI.exe";
                IntPtr userTokenHandle = IntPtr.Zero;
                ApiDefinitions.WTSQueryUserToken(ApiDefinitions.WTSGetActiveConsoleSessionId(), ref userTokenHandle);
                ApiDefinitions.PROCESS_INFORMATION procInfo = new ApiDefinitions.PROCESS_INFORMATION();
                ApiDefinitions.STARTUPINFO startInfo = new ApiDefinitions.STARTUPINFO();
                startInfo.cb = (uint)Marshal.SizeOf(startInfo);
                ApiDefinitions.CreateProcessAsUser(userTokenHandle, appStartPath, "", IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref startInfo, out procInfo);
                if (userTokenHandle != IntPtr.Zero)
                    ApiDefinitions.CloseHandle(userTokenHandle);
                int _currentAquariusProcessId = (int)procInfo.dwProcessId;

            }

    • 已标记为答案 xbxc99 2016年5月17日 1:30
    2016年5月17日 1:30