服务不会启动控制台应用程序

时间:2014-10-09 13:07:32

标签: vb.net windows service cmd

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

这可能是权限问题吗?

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

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

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

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

感谢您的时间。

1 个答案:

答案 0 :(得分:0)

达米恩击中头部,问题是当你运行控制台应用程序时,你正在运行它,你可以访问UNC。当服务运行您的控制台应用程序时,它将以您绑定到服务的用户身份运行它。你有几个选择:

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

无论哪种方式,从控制台应用程序而不是您的服务运行它都是无用的。

我已经创建了一个让我很容易模仿的课程:

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