1

I'm very new in .net. I'm trying to build a windows service to monitor an windows form application so that it starts and keeps running from startup.

The app will also monitor the windows service back and forth to check if its not stopped and it will try to start the service if stopped. I was following this stack post (written in c#, I converted it to vb.net. Pastebin) to run the app as current user from windows service and it is successfully running as expected.

But the problem is that, this process is starting without administrative privilege for which service start trigger is not working when the app monitors the service and finds it stopped.

When I manually run the Application as Run As Administrator it successfully triggers the service if its found stopped. Please suggest how can I run the process as current user with administrative privilege from windows service.

Here is my Service Class

Public Class myService
Dim ApplicationLauncher As New ApplicationLauncher
Private aTimer As System.Timers.Timer
Dim exePath As String = "path_to_exe"

Protected Overrides Sub OnStart(ByVal args() As String)
    SetTimer()
    If Not String.IsNullOrEmpty(GetPCUser()) Then
        If Not IsProcessRunning("App_exePath") Then
            ApplicationLauncher.CreateProcessInConsoleSession(exePath, True)
        End If
    End If
End Sub

Protected Overrides Sub OnStop()        
End Sub

Private Sub SetTimer()
    aTimer = New System.Timers.Timer(1000)
    AddHandler aTimer.Elapsed, AddressOf OnTimedEvent
    aTimer.AutoReset = True
    aTimer.Enabled = True
End Sub

Private Sub OnTimedEvent(source As Object, e As ElapsedEventArgs)
    If Not String.IsNullOrEmpty(GetPCUser()) Then
        If Not IsProcessRunning("App_exePath") Then
            ApplicationLauncher.CreateProcessInConsoleSession(exePath, True)
        End If
    End If
End Sub

Private Function GetPCUser()
    Dim strCurrentUser As String = ""
    Dim moReturn As ManagementObjectCollection
    Dim moSearch As ManagementObjectSearcher
    Dim mo As ManagementObject
    moSearch = New ManagementObjectSearcher("Select * from Win32_Process")
    moReturn = moSearch.Get
    For Each mo In moReturn
        Dim arOwner(2) As String
        mo.InvokeMethod("GetOwner", arOwner)
        Dim strOut As String
        strOut = String.Format("{0} Owner {1} Domain {2}", mo("Name"), arOwner(0), arOwner(1))
        If (mo("Name") = "explorer.exe") Then
            strCurrentUser = String.Format("{0}", arOwner(0))
        End If
    Next
    Return strCurrentUser
End Function

Public Function IsProcessRunning(name As String) As Boolean
    Dim Result As Boolean = False
    Dim GetProcess As Process() = Process.GetProcesses()
    For Each pr In GetProcess
        If pr.ProcessName = name Then
            Result = True
        End If
    Next
    Return Result
End Function
End Class 

Here is my Windows Form Application Class

Public Class Form    
Dim sc As New ServiceController("myService")
Private Timer2 As System.Timers.Timer

Private Sub Form_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    SetTimer2()        
    Visible = False
    ShowInTaskbar = False
    'Some other code
End Sub

Public Sub Form_Startup() Handles Me.Load
    'Some other code
End Sub

Private Sub SetTimer2()
    Timer2 = New System.Timers.Timer(1000)
    AddHandler Timer2.Elapsed, AddressOf OnTimedEvent2
    Timer2.AutoReset = True
    Timer2.Enabled = True
End Sub

Private Sub OnTimedEvent2(source As Object, e As ElapsedEventArgs)
    sc.Refresh()
    If sc.Status.Equals(ServiceControllerStatus.Stopped) Or sc.Status.Equals(ServiceControllerStatus.StopPending) Then
        sc.Start()
    End If
End Sub
End Class
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
Hayat Hasan
  • 229
  • 2
  • 14

1 Answers1

1

You need modify the manifest file for your service starter (Windows Form Application)

To customise the manifest that gets embedded in the program.

  1. Project + Add New Item
  2. Select "Application Manifest File".
  3. Change the <requestedExecutionLevel> element to

E.g

 <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

This will make make the application show the UAC prompt when they start the program.

Update

As per your comments

You cannot grant elevated privileges without UAC this violate the basic principle of User Access Control.

There is no way to elevate permissions while avoiding the prompts, by design. If there was a way to do this, UAC would become useless.

You need to read this question

Start / Stop a Windows Service from a non-Administrator user account

You will need to set the Service permissions to do this

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • Thanks, How can I bypass the UAC prompt . I will prompt each time which would be little annoying to user. – Hayat Hasan Feb 06 '18 at 05:21
  • @Hayan it will be annoying! but this is just windows security, you cant just have every application running around with admin privileges (all hell would break loose) you can disable UAC though – TheGeneral Feb 06 '18 at 05:23
  • The purpose of the job is to run both service and app in background to monitor each other and perform tasks without bothering users permission as the user already accepted this through installation (the app will not have UI either, it will just be running by showing a NotifyIcon in task bar). both process will monitor each other through `System.Timer` in every second so that if user closes any of the service or app it will trigger start or vice versa. all of these is to forcefully start both process from pc startup and prevent user from accidentally close the service or app. – Hayat Hasan Feb 06 '18 at 06:01