VB.net 2010 Window Service 运行实际应用程序而不仅仅是进程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17755444/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
VB.net 2010 Window Service Run the actual application not just the process
提问by Jose Ortiz
Here is what I am trying to do is create a service that checks if Microsoft Lync is running. If it's running then do nothing but write to eventlog. If it's not running run the exe and then log in to Lync. The problem I am getting is when it comes time to run the exe, it would go and start the process but it never actually runs the app. I tried to see if would work with notepad but all it did was create the process in task manager but never opened the actual app.
这就是我想要做的是创建一个检查 Microsoft Lync 是否正在运行的服务。如果它正在运行,那么除了写入事件日志之外什么都不做。如果它没有运行,请运行 exe,然后登录到 Lync。我遇到的问题是,当需要运行 exe 时,它会启动并启动该进程,但它从未真正运行该应用程序。我试图看看是否可以使用记事本,但它所做的只是在任务管理器中创建进程,但从未打开实际的应用程序。
Imports System
Imports System.Data
Imports System.Timers
Imports System.Diagnostics
Imports System.Data.SqlClient
Imports System.ServiceProcess
Imports System.Windows.Forms
Public Class Service1
Protected Overrides Sub OnStart(ByVal args() As String)
EventLog.WriteEntry("In Onstart", "starting timer")
Timer1.Start()
End Sub
Protected Overrides Sub OnStop()
End Sub
Private Sub Timer1_Elapsed(ByVal sender As System.Object,
ByVal e As System.Timers.ElapsedEventArgs) Handles Timer1.Elapsed
If IsProcessRunning("communicator") Then
EventLog.WriteEntry("no problem")
Else
EventLog.WriteEntry("not running")
Dim info As New ProcessStartInfo("C:\Program Files (x86)\Microsoft Lync\communicator.exe")
info.UseShellExecute = False
info.RedirectStandardError = True
info.RedirectStandardInput = True
info.RedirectStandardOutput = True
info.CreateNoWindow = True
info.ErrorDialog = False
info.WindowStyle = ProcessWindowStyle.Hidden
Dim process__1 As Process = Process.Start(info)
End If
End Sub
Public Function IsProcessRunning(ByVal name As String) As Boolean
For Each clsProcess As Process In Process.GetProcesses()
If clsProcess.ProcessName.StartsWith(name) Then
Return True
End If
Next
Return False
End Function
End Class
回答by Alejandro
Problem comes from the fact that in Windows (and specially since versions 6.x) services run in a completely isolated session and desktop, without any chance of user interaction, which is by design and discouraged to do so, for security reasons. The program you're launching actually does starts, but it does so in that hidden desktop (same for notepad) where no users can ever see it.
问题来自这样一个事实,即在 Windows(尤其是 6.x 版之后)服务在完全隔离的会话和桌面中运行,没有任何用户交互的机会,出于安全原因,这是设计使然,不鼓励这样做。您启动的程序确实会启动,但它是在用户永远无法看到的隐藏桌面(记事本也是如此)中启动的。
The quick and dirty workaround is to mark the service as interactive in the control panel, and start the interactive services detectionservice. When doing so, when your service runs the program, a window will flash in the taskbar, telling there is a message from a service, so that you can switch to that parallel desktop and actually see it. That's simply very inconvenient to the user and widely considered a BAD PRACTICE.
快速而肮脏的解决方法是在控制面板中将服务标记为交互式,并启动交互式服务检测服务。这样做时,当您的服务运行程序时,任务栏中会闪烁一个窗口,告诉您有来自服务的消息,以便您可以切换到该并行桌面并实际看到它。这对用户来说非常不方便,并且被广泛认为是一种不良做法。
The real solution is to make the program a regular application and not a service, and run it though some autostart location in Windows for every user. It does not need to have visible UI, but run in the same context as you do. Or to leave the service, but also put some application in user space that communicates with the service just for the sake of running the second program. In any case, the general rule is to never have any kind of user interaction from a service process.
真正的解决方案是使程序成为常规应用程序而不是服务,并通过 Windows 中的某个自动启动位置为每个用户运行它。它不需要具有可见的 UI,而是在与您相同的上下文中运行。或者离开服务,也为了运行第二个程序,将一些与服务通信的应用程序放在用户空间。在任何情况下,一般规则是永远不要与服务进程进行任何类型的用户交互。
Here is an article that explains the problems and some workarounds http://blogs.technet.com/b/askperf/archive/2007/04/27/application-compatibility-session-0-isolation.aspx
这是一篇解释问题和一些解决方法的文章http://blogs.technet.com/b/askperf/archive/2007/04/27/application-compatibility-session-0-isolation.aspx
回答by Jose Ortiz
I was able to create a program that detects whether or not Lync is running and if it's not restart the program.
我能够创建一个程序来检测 Lync 是否正在运行以及它是否没有重新启动程序。
Imports System.Diagnostics
Imports Microsoft.Lync
Imports Microsoft.Lync.Model
Imports Microsoft.Lync.Model.Conversation
Imports Microsoft.Lync.Model.Group
Public Class frmCheckLync
Private _lyncClient As LyncClient
Private _contactManager As ContactManager
Private _conversationManager As ConversationManager
Private _self As Self
Private _groups As Dictionary(Of String, Group)
Private _contactSubscriptions As Dictionary(Of String, ContactSubscription)
Public Event StateChanged As EventHandler(Of ClientStateChangedEventArgs)
Public _signIn As IAsyncResult
Public asyncState As Object() = {_lyncClient}
Public clsProcess As Process
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
Timer1.Enabled = True
AddHandler Timer1.Elapsed, AddressOf Timer1_Tick
Timer1.Interval = 600
Timer1.Start()
Catch ex As Exception
Diagnostics.EventLog.WriteEntry("This is a test" + ex.Message.ToString, "This is a test")
End Try
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
Try
Timer1.Stop()
GetClient()
Try
CheckClient()
Catch ex As Exception
End Try
Catch ex As Exception
Finally
Timer1.Start()
End Try
End Sub
Public Function IsProcessRunning(ByVal name As String) As Boolean
For Each Me.clsProcess In Process.GetProcesses()
If Me.clsProcess.ProcessName.StartsWith(name) Then
Return True
End If
Next
Return False
End Function
Public Sub GetClient()
If IsProcessRunning("communicator") = False Then
Try
Dim info As New ProcessStartInfo("C:\Program Files\Microsoft Lync\communicator.exe")
info.UseShellExecute = False
info.RedirectStandardError = True
info.RedirectStandardInput = True
info.RedirectStandardOutput = True
info.CreateNoWindow = True
info.ErrorDialog = False
info.WindowStyle = ProcessWindowStyle.Normal
Dim process__1 As Process = Process.Start(info)
Catch ex1 As Exception
End Try
Try
Dim info1 As New ProcessStartInfo("C:\Program Files (x86)\Microsoft Lync\communicator.exe")
info1.UseShellExecute = False
info1.RedirectStandardError = True
info1.RedirectStandardInput = True
info1.RedirectStandardOutput = True
info1.CreateNoWindow = True
info1.ErrorDialog = False
info1.WindowStyle = ProcessWindowStyle.Normal
Dim process__2 As Process = Process.Start(info1)
Catch ex2 As Exception
End Try
End If
End Sub
Public Sub CheckClient()
Try
_lyncClient = LyncClient.GetClient()
Catch
GetClient()
End Try
If _lyncClient.State = ClientState.SignedOut Then
_signIn = _lyncClient.BeginSignIn(Nothing, Nothing, Nothing,
Function(result)
If result.IsCompleted Then
_lyncClient.EndSignIn(result)
' Setup application logic
' could not sign in
Else
End If
End Function, TryCast("Local user signing in", Object))
End If
End Sub
End Class

