老问题了,在网上搜了一些方法,但还是不行。
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
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
要在服务里show出窗体有两个必要的条件:
1. 允许服务与桌面交互,打勾
2. serviceProcessInstaller1的Account属性要选择LocalSystem
uiThread.Start();线程内直接调用UI
报错了吧
/// 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);
}
{
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();
}
正确的做法是,窗口通过开启启动项注册,服务和窗口分别两个EXE程序。如果只是简单的监视服务状态,只要用DOS命令查看即可,如果需要精确控制服务,你必须在WCF服务内提供管理用的方法,对服务进行消息控制。
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,退一步就是那窗体界面不要了。
如果按照你原先的做法,设置服务于桌面交互,并在服务里面开启窗口,虽然是可以做到的,但是这样就意味着服务将随着窗口的关闭一起关闭了,参考pcAnywhere就是这样,右下角图片关了,服务就消失了,那样才叫不可取。