先看图片:
我的问题是:C#中如何编写代码,让我编写的Windows服务程序安装后,自动将上面属性中,红框“允许服务与桌面交互”选项打勾。拜托各位快来帮帮我,就差这一个问题了,就可以交差了哈!下面的这段非托管代码可生成一个带有Form窗体的Windows服务程序,可与桌面交互,运行后也可以显示出来窗体来,但窗体不是XP风格的,只有把上面图片红框中的“允许服务与桌面交互”选项打勾。才可正常显示XP风格窗体!代码示例:
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
using System.Runtime.InteropServices;
namespace FileWatchService
{
public class Service1 : System.ServiceProcess.ServiceBase
{
/// 
/// 必需的设计器变量。
/// 
private System.ComponentModel.Container components = null;
Thread threadForm=null;
public Service1()
{
// 该调用是 Windows.Forms 组件设计器所必需的。
InitializeComponent();// TODO: 在 InitComponent 调用后添加任何初始化
}#region 组件设计器生成的代码
/// 
/// 设计器支持所需的方法 - 不要使用代码编辑器 
/// 修改此方法的内容。
/// 
private void InitializeComponent()
{
// 
// Service1
// 
this.ServiceName = "JadeWatchService";}
#endregion
[STAThread]
static void Main() 
{
System.ServiceProcess.ServiceBase.Run(new Service1());}
/// 
/// 清理所有正在使用的资源。
/// 
protected override void Dispose( bool disposing ) 
{
if( disposing )
{
if (components != null) 
{
components.Dispose();
}
}
base.Dispose( disposing );
}/// 
/// 设置具体的操作,以便服务可以执行它的工作。
/// 
protected override void OnStart(string[] args)
{
threadForm=new Thread(new ThreadStart(FormShow));
threadForm.Start();
}/// 
/// 停止此服务。
/// 
protected override void OnStop()
{
if(threadForm!=null)
{
if(threadForm.IsAlive)
{
threadForm.Abort();
threadForm=null;
}
}
}void FormShow()
{GetDesktopWindow(); 
IntPtr hwinstaSave = GetProcessWindowStation(); 
IntPtr dwThreadId = GetCurrentThreadId(); 
IntPtr hdeskSave = GetThreadDesktop(dwThreadId); 
IntPtr hwinstaUser = OpenWindowStation("WinSta0", false,33554432); 
if (hwinstaUser == IntPtr.Zero) 

RpcRevertToSelf(); 
return ;

SetProcessWindowStation(hwinstaUser); 
IntPtr hdeskUser = OpenDesktop("Default", 0, false, 33554432); 
RpcRevertToSelf(); 
if (hdeskUser == IntPtr.Zero) 

SetProcessWindowStation(hwinstaSave); 
CloseWindowStation(hwinstaUser); 
return ; 

SetThreadDesktop(hdeskUser); IntPtr dwGuiThreadId = dwThreadId; Form1 f=new Form1(); //此FORM1可以带notifyIcon,可以显示在托盘里,用户可点击托盘图标进行设置
System.Windows.Forms.Application.Run(f);
dwGuiThreadId = IntPtr.Zero; 
SetThreadDesktop(hdeskSave); 
SetProcessWindowStation(hwinstaSave); 
CloseDesktop(hdeskUser); 
CloseWindowStation(hwinstaUser); 
}[DllImport("user32.dll")]
static extern int GetDesktopWindow();[DllImport("user32.dll")]
static extern IntPtr GetProcessWindowStation();[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThreadId();[DllImport("user32.dll")]
static extern IntPtr GetThreadDesktop(IntPtr dwThread);[DllImport("user32.dll")]
static extern IntPtr OpenWindowStation(string a,bool b,int c);[DllImport("user32.dll")]
static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags,
bool fInherit, uint dwDesiredAccess);[DllImport("user32.dll")]
static extern IntPtr CloseDesktop(IntPtr p);[DllImport("rpcrt4.dll", SetLastError=true)]
static extern IntPtr RpcImpersonateClient(int i);
[DllImport("rpcrt4.dll", SetLastError=true)]
static extern IntPtr RpcRevertToSelf();[DllImport("user32.dll")]
static extern IntPtr SetThreadDesktop(IntPtr a);[DllImport("user32.dll")]
static extern IntPtr SetProcessWindowStation(IntPtr a);
[DllImport("user32.dll")]
static extern IntPtr CloseWindowStation(IntPtr a);
}
}

解决方案 »

  1.   

    原理是这样: 
    onstart的时候修改注册表
    [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\你的服务名]  
     
    "Type"=dword:00000010   
     
    key value+256  
    比如现在00000010是16+256=272
    16精制就是00000110具体方法:
    可以用修改注册表实现,我们必须在安装后操作,所以请重写Installer的OnAfterInstall。protected override void OnAfterInstall(System.Collections.IDictionary savedState) {
                RegistryKey rk = Registry.LocalMachine;
                string key = @"SYSTEM\CurrentControlSet\Services\" + this.sInstaller.ServiceName;
                RegistryKey sub = rk.OpenSubKey(key, true);
                int value = (int)sub.GetValue("Type");
                if (value < 256) {
                    sub.SetValue("Type", value | 256);
                }
                base.OnAfterInstall(savedState);
            }但以上方法只能在重启后起到作用若要想立即生效可以用以下代码代之,将此方法放入onAfterInstall即可。设置服务与桌面交互private void SetServiceDesktopInsteract(string serviceName) {
                ManagementObject wmiService = new ManagementObject(string.Format("Win32_Service.Name='{0}'",serviceName));
                ManagementBaseObject changeMethod = wmiService.GetMethodParameters("Change");
                changeMethod["DesktopInteract"] = true;
                ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", changeMethod, null);
            }若想立即启动服务调System.ServiceProcess.ServiceController类来实现请看