老问题了,在网上搜了一些方法,但还是不行。
window服务是装载着WCF服务的,窗体是用来观察和控制停止或再启动WCF服务。
要求在winXP、Win2003、Win2008下能弹出窗体。
问题:
1、如何在服务启动时,把窗体也show出来?另做一个EXE也行。(但Process.Start("notepad.exe"); //记事本也调不出来!)
2、如何实在不能Show窗体的前提,window服务启动时,如何让WCF服务也不中止在启动着?停止服务时,WCF也停止。我原先的做法部分代码如下。服务启动时用了线程:        /// <summary>
        /// 启动服务
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            uiThread = new Thread(new ThreadStart(StartService.FormShow));
            uiThread.Start();
            //this.StartProcessor();
        }线程里的方法:#region 服务启动窗体        public static 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;            CtrlForm f = new CtrlForm();
            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);        #endregion
窗体Load时启动WCF服务:#region 启动WCF服务        private void LoadService()
        {
            if (dicHost == null || dicHost.Count == 0)
            {
                dicHost = new Dictionary<string, ServiceHost>();                Configuration conf = ConfigurationManager.OpenExeConfiguration(Assembly.GetEntryAssembly().Location);
                ServiceModelSectionGroup svcmod = (ServiceModelSectionGroup)conf.GetSectionGroup("system.serviceModel");                foreach (ServiceElement el in svcmod.Services.Services)
                {
                    Type svcType = Type.GetType(el.Name + "," + "Services");
                    //Type svcType = Type.GetType(el.Name + "," + el.Name.Split('.')[0]);                    ListViewItem lvItem = new ListViewItem(el.Name);
                    if (svcType == null)
                    {
                        lvItem.SubItems.Add("已停止");
                        lvItem.SubItems.Add("服务类型无效" + el.Name + "配置文件中。");
                    }
                    else
                    {
                        ServiceHost aServiceHost = new ServiceHost(svcType);
                        aServiceHost.Open();
                        dicHost.Add(el.Name, aServiceHost); //启动的服务保存在字典
                        lvItem.SubItems.Add("已启动");
                        lvItem.SubItems.Add("");
                    }
                    this.lvList.Items.Add(lvItem);
                }
            }
            else
            {
                HG.WinAPI.Win32.ShowWindow(this.Handle, HG.WinAPI.Win32.SW_SHOWNORMAL);
                SetMid(this);
                HG.WinAPI.Win32.SetForegroundWindow(this.Handle);
                //HG.WinAPI.Win32.SendMessage(this.Handle, HG.WinAPI.Win32.WM_NCACTIVATE, HG.WinAPI.Win32.WA_ACTIVE, 0);
            }
        }        #endregion

解决方案 »

  1.   

    1、如何在服务启动时,把窗体也show出来?另做一个EXE也行。(但Process.Start("notepad.exe"); //记事本也调不出来!)但代码太长没看,只针对你这个问题:
    要在服务里show出窗体有两个必要的条件:
    1. 允许服务与桌面交互,打勾
    2. serviceProcessInstaller1的Account属性要选择LocalSystem
      

  2.   

    uiThread = new Thread(new ThreadStart(StartService.FormShow));
    uiThread.Start();线程内直接调用UI
    报错了吧
      

  3.   

    /// <summary>
            /// Windows服务类
            /// </summary>
            /// <summary>
                /// 检查服务存在的存在性
                /// </summary>
                /// <param name=" NameService ">服务名</param>
                /// <returns>存在返回 true,否则返回 false;</returns>
                public static bool isServiceIsExisted(string NameService)
                {
                    ServiceController[] services = ServiceController.GetServices();
                    foreach (ServiceController s in services)
                    {
                        if (s.ServiceName.ToLower() == NameService.ToLower())
                        {
                            return true;
                        }
                    }
                    return false;
                }            /// <summary>
                /// 安装Windows服务
                /// </summary>
                /// <param name="stateSaver">集合</param>
                /// <param name="filepath">程序文件路径</param>
                public static void InstallmyService(IDictionary stateSaver, string filepath)
                {
                    AssemblyInstaller AssemblyInstaller1 = new AssemblyInstaller();
                    AssemblyInstaller1.UseNewContext = true;
                    AssemblyInstaller1.Path = filepath;
                    AssemblyInstaller1.Install(stateSaver);
                    AssemblyInstaller1.Commit(stateSaver);
                    AssemblyInstaller1.Dispose();
                }            /// <summary>
                /// 卸载Windows服务
                /// </summary>
                /// <param name="filepath">程序文件路径</param>
                public static void UnInstallmyService(string filepath)
                {
                    AssemblyInstaller AssemblyInstaller1 = new AssemblyInstaller();
                    AssemblyInstaller1.UseNewContext = true;
                    AssemblyInstaller1.Path = filepath;
                    AssemblyInstaller1.Uninstall(null);
                    AssemblyInstaller1.Dispose();
                }            /// <summary>
                /// 检查Windows服务是否在运行
                /// </summary>
                /// <param name="name">程序的服务名</param>
                public static bool IsRunning(string name)
                {
                    bool IsRun = false;
                    try
                    {
                        if (!isServiceIsExisted(name))
                        {
                            return false;
                        }
                        ServiceController sc = new ServiceController(name);
                        if (sc.Status == ServiceControllerStatus.StartPending ||
                            sc.Status == ServiceControllerStatus.Running)
                        {
                            IsRun = true;
                        }
                        sc.Close();
                    }
                    catch
                    {
                        IsRun = false;
                    }
                    return IsRun;
                }            /// <summary>
                /// 启动Windows服务
                /// </summary>
                /// <param name="name">程序的服务名</param>
                /// <returns>启动成功返回 true,否则返回 false;</returns>
                public static bool StarmyService(string name)
                {
                    ServiceController sc = new ServiceController(name);
                    if (sc.Status == ServiceControllerStatus.Stopped || sc.Status == ServiceControllerStatus.StopPending
                            )
                    {
                        sc.Start();
                        sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));
                    }
                    else
                    {
                    }
                    sc.Close();
                    return true;
                }            /// <summary>
                /// 停止Windows服务
                /// </summary>
                /// <param name="name">程序的服务名</param>
                /// <returns>停止成功返回 true,否则返回 false;</returns>
                public static bool StopmyService(string name)
                {
                    ServiceController sc = new ServiceController(name);
                    if (sc.Status == ServiceControllerStatus.Running ||
                        sc.Status == ServiceControllerStatus.StartPending)
                    {
                        sc.Stop();
                        sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 10));
                    }
                    else
                    {
                    }
                    sc.Close();
                    return true;
                }            /// <summary>
                /// 重启Windows服务
                /// </summary>
                /// <param name="name">程序的服务名</param>
                /// <returns>重启成功返回 true,否则返回 false;</returns>
                public static bool RefreshmyService(string name)
                {
                    return StopmyService(name) && StarmyService(name);
                }
      

  4.   

            public void FormShow()
            {
                Form1 StartService = new Form1();
                StartService.ShowDialog(); //不要用Show
            }        protected override void OnStart(string[] args)
            {
                Thread uiThread = new Thread(new ThreadStart(() => FormShow()));
                //Thread uiThread = new Thread(new ThreadStart(FormShow));
                uiThread.Start();
            }
      

  5.   

    额,你的意思就是说,在windows服务里面启动,在界面上显示出来嘛,写个启动小软件,把你需要的启动的软件的路径放进去,再直接监视服务里面如果没有启动,就启动起来啥
      

  6.   

    是你的理解有问题,窗口之所以不能在服务里面开启,因为服务不是由当前用户启动的,未登录系统的时候,服务就先开启了,自然无法带用户界面了。(但是可以勾选服务的一个选项,启用用户交互,但不推荐)
    正确的做法是,窗口通过开启启动项注册,服务和窗口分别两个EXE程序。如果只是简单的监视服务状态,只要用DOS命令查看即可,如果需要精确控制服务,你必须在WCF服务内提供管理用的方法,对服务进行消息控制。
      

  7.   

    这个问题我知道,服务程序一般使用的是LocalSystem帐户,拥有自己的window station,和Default桌面,这个window station是不能于用户交互的,也就是说,你不能在上面显示窗口,它也不接受用户的鼠标、键盘等输入。
    C# window服务启动窗体相关文章,一个是博客园的,一个是CSDN的,
    http://www.cnblogs.com/vic_lu/archive/2011/02/18/1957842.html
    http://topic.csdn.net/u/20080513/10/9967ed75-c572-4825-9dbd-7bc487e13dc5.html
    这两个比较有帮助的资料。我上面的代码就是根据这些资料改动的。这方法不可取,公司要求是用WINDOWS服务启动WCF,退一步就是那窗体界面不要了。
      

  8.   

    什么叫不可取?你先看看其它著名的软件是如何实现的吧。比如诺顿杀毒软件,常驻服务别说了,开机自启动,但是管理界面是另一个exe程序,在开机启动项里面注册的,如果那个启动项删除,杀毒服务还是工作的,但是右下角少了一个监视用的管理窗口,也可以后期单独打开那个窗口。
    如果按照你原先的做法,设置服务于桌面交互,并在服务里面开启窗口,虽然是可以做到的,但是这样就意味着服务将随着窗口的关闭一起关闭了,参考pcAnywhere就是这样,右下角图片关了,服务就消失了,那样才叫不可取。