【问题标题】:Service Does Not Launch Console Application服务不启动控制台应用程序
【发布时间】:2014-10-09 13:07:31
【问题描述】:

TLDR:如果我手动单击控制台应用程序,它就会运行,但是在使用 StartProcess 或 Shell 时被服务调用时它不会运行。

这可能是权限问题吗?

详情: 我编写了一个小型 Windows 服务应用程序,它检查远程位置文件夹中的产品密钥,如果产品密钥与输入的不同,则更新本地计算机。我认为这将是我第一次涉足 Windows 服务的一个简单项目。

服务使用计时器每小时运行一次(测试间隔为每 30 秒一次)。最初该服务将执行更新,但我在访问 UNC 路径时遇到了一个更复杂的问题(我必须使用模拟类)。

因此,在应用程序的控制台版本中测试代码时,我注意到它能够在不提供凭据的情况下访问网络位置。所以我重写了服务,所以它改为调用控制台应用程序。但无论我如何编写它,我都无法从服务中启动控制台应用程序。

如果需要更多信息,请随时询问!

感谢您的宝贵时间。

【问题讨论】:

  • 服务并非旨在与用户交互,因此故意与用户桌面隔离。使用进程管理器查看它是否生成进程 - 不要期望它会在您的桌面上弹出。
  • 它在控制台应用程序中工作,因为它以 you 身份运行。它从服务中失败,因为该服务没有必要的权限。如果服务运行控制台应用程序,那么控制台应用程序将作为服务运行并且仍然没有必要的权限。在具有正确权限的帐户下运行服务或在 UNC 路径上更改权限,代码应该可以在服务内正常工作。

标签: vb.net windows service cmd


【解决方案1】:

Damien 一针见血,问题是当您运行控制台应用程序时,您是在以您的身份运行它,它可以访问 UNC。当服务运行您的控制台应用程序时,它以您绑定到该服务的用户身份运行它。你有几个选择:

  • 1:将服务设置为以有权访问 UNC 的用户身份运行
  • 2:使用 Impersonation 以您想要的用户身份进行连接。

无论如何,从控制台应用程序而不是您的服务运行它是没有用的。

我已经包含了一个我创建的让模拟变得容易的类:

Imports System.Security.Principal
Imports System.Runtime.InteropServices

''' <summary>
''' Used to temporarily impersonate another user
''' Must use a USING block or dispose of instance to undo impersonation
''' </summary>
''' <remarks></remarks>
Public Class ImpersonateFNS
    Implements IDisposable

    Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String, _
                                                ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As IntPtr) As Integer

    Private _impersonatedUser As WindowsImpersonationContext = Nothing
    Private _loggedOn As Boolean = False

    ''' <summary>
    ''' Should call this in a USING block OR, make sure you dispose this object when done impersonating
    ''' </summary>
    Public Sub New(ByVal Domain As String, ByVal UserName As String, ByVal Password As String)
        Dim token As IntPtr = IntPtr.Zero
        'If (LogonUserA(UserName, Domain, Password, 2, 0, token) <> 0) Then
        If (LogonUserA(UserName, Domain, Password, 9, 0, token) <> 0) Then
            _loggedOn = True
            Dim newIdentity As WindowsIdentity = New WindowsIdentity(token)
            _impersonatedUser = newIdentity.Impersonate()
        Else
            Dim ret As Integer = Marshal.GetLastWin32Error()
            'Console.WriteLine("LogonUser failed with error code : {0}", ret)
            'Throw New System.ComponentModel.Win32Exception(String.Format("LogonUser failed with error code : {0}", ret))
            Throw New Security.SecurityException(String.Format("LogonUser failed with error code : {0}", ret))
        End If
    End Sub

    Private ReadOnly Property LoggedOn As Boolean
        Get
            Return _loggedOn
        End Get
    End Property


#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
            End If
            If _impersonatedUser IsNot Nothing Then
                _impersonatedUser.Undo()
            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
    'Protected Overrides Sub Finalize()
    '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class

如上所示创建类,然后调用位于 USING 块中,这样当您完成业务时,它将撤消模拟。像这样:

Using x as New ImpersonationFNF("MyDomain", "User","Password")
    'Copy, read, whatever the stuff you need to do here
End Using

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-30
    • 2017-05-21
    • 1970-01-01
    • 2017-06-27
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多