2014-10-09 6 views
1

TLDR: мое консольное приложение запускается, если я нажимаю на него вручную, однако оно не запускается при вызове службой при использовании StartProcess или Shell.Служба не запускает консольное приложение

Это может быть вопрос разрешения?

Подробности: Я написал небольшое приложение для работы с Windows, которое проверяет папку удаленного места для ключа продукта и обновляет локальную машину, если ключ продукта отличается от введенного. Я думал, что это будет простой проект для моего первого набега на услуги Windows.

Служба работает с использованием таймера каждый час (для проверки интервала каждые 30 секунд). Первоначально служба выполнила обновление, но я столкнулся с более сложной проблемой доступа к UNC-пути (мне пришлось бы использовать классы олицетворения).

Поэтому, проверяя код в консольной версии приложения, я заметил, что он смог получить доступ к сетевому местоположению без предоставления учетных данных. Поэтому я переписал службу, чтобы вместо нее называть консольное приложение. Но как бы я ни писал, я не могу запустить консольное приложение из службы.

Если вам нужна дополнительная информация, не стесняйтесь спрашивать!

Спасибо за ваше время.

+2

Служба не предназначена для взаимодействия с пользователем, поэтому намеренно изолирована от настольных компьютеров пользователей. Используйте диспетчер процессов, чтобы узнать, не вызвал ли этот процесс процесс - не ожидайте, что он появится на вашем рабочем столе. –

+1

Работает из консольного приложения, потому что работает под управлением * you *. Он не работает из службы, потому что служба не имеет необходимых разрешений. Если служба запускает консольное приложение, консольное приложение будет работать как служба, а * еще * не будет иметь необходимых разрешений. Запустите службу под учетной записью с правом разрешения или получите разрешения, измененные на пути UNC, и код должен работать нормально из службы. –

ответ

0

Damien ударил ноготь по голове, проблема в том, что при запуске консольного приложения вы запускаете его как вы, у которого есть доступ к 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 x as New ImpersonationFNF("MyDomain", "User","Password") 
    'Copy, read, whatever the stuff you need to do here 
End Using 
Смежные вопросы