Vista - Starting a Service

  • Thread starter Thread starter Smurfman-MSDN
  • Start date Start date
S

Smurfman-MSDN

Using VB2008 and Vista Ultimate x64

I have an application I have written that is two part - one is a Windows
Service the other is an interface for the settings for that service.

On my XP machine the service installs just fine and the following code works
just fine:

Me.Interface_ServiceController = New System.ServiceProcess.ServiceController
With Me.Interface_ServiceController
.ServiceName = ServiceNameIn
.Start()
End With

ServiceNameIn is defined as a String being passed to my function. If the
service starts the function returns True if not it returns false.

One XP I am able to start the serice from my interface with no issue.

In Vista I am getting an error:

Cannot open XYZService on computer '.'

Here is what I tried.
Net Start XYZService from a CMD prompt - I get an Error 5 Access Denied.

Verified that the service is set to manual run.

Manually starting the service from Service.MSC - works just fine.

I thought Originally the service name was screwing it up - "X Y Z Service"
so I renamed the service to XYZService with a different Display name. This
did not matter.

I tried to define a machineName this too did not matter.

I am back to the permissions thing. Is there something in Vista that is
blocking my ability to programatically start this service?

Interestingly, I can query the service and I can get the status of it either
running or stopped.

Any suggestions?
J
 
Additional Info.

A Quick Watch helped me to see the inner error message and in fact I am
getting the same "Access is Denied" from within my application.

I understand that from a cmd prompt I can run as administrator to get past
the elevated rights thing.

But in my application I am unsure how I am to accomplish this.

Thanks
J
 
Unless you are explicitly elevated you won't have the permission. The
Services applet asks for elevation, right? Your program needs a manifest to
request elevation to Administrator because otherwise you'll be running
limited (unless you start from an elevated prompt).
 
Hello smurfman
I am back to the permissions thing. Is there something in Vista that is
blocking my ability to programatically start this service?

UAC


You can do 2 things

1. dissable UAC
2. Application tab view uac settings , now change
<requestedExecutionLevel level="asInvoker" uiAccess="false" />

to

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



HTH



Michel
 
Hello Smurfman ,


If you want to do this from code and you have the admin username and
password you could try what happens
when you use impersonation to start the service .

i have once created a class wich can do this an posted it ..... well the
heck here it is :-)

'Michel Posseth [MCP] 10-07-2008 , written to run parts of code in another
user context during runtime


Imports System.Security


Imports System.Security.Principal


Imports System.Runtime.InteropServices


Public Class ImpersonateSpecificUser


Implements IDisposable


Private Const LOGON32_LOGON_INTERACTIVE As Integer = 2


Private Const LOGON32_PROVIDER_DEFAULT As Integer = 0


Private impersonationContext As WindowsImpersonationContext


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


Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _


ByVal ExistingTokenHandle As IntPtr, _


ByVal ImpersonationLevel As Integer, _


ByRef DuplicateTokenHandle As IntPtr) As Integer


Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long


Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As
IntPtr) As Long


Public Event eSpecificUserImpersonation(ByVal Success As Boolean)


Private _Impersonated As Boolean


''' <summary>


''' Gets or sets a value indicating whether this <see
cref="ImpersonateSpecificUser" /> is impersonated.


''' </summary>


''' <value><c>true</c> if impersonated; otherwise, <c>false</c>.</value>


Public Property Impersonated() As Boolean


Get


Return _Impersonated


End Get


Private Set(ByVal value As Boolean)


_Impersonated = value


End Set


End Property


''' <summary>


''' Initializes a new instance of the <see cref="ImpersonateSpecificUser" />
class.


''' </summary>


''' Name of the user.


''' The password.


''' The domain.


Public Sub New(ByVal UserName As String, ByVal Password As String, ByVal
Domain As String)


If impersonateValidUser(UserName, Domain, Password) Then


RaiseEvent eSpecificUserImpersonation(True)


Else


'Your impersonation failed. Therefore, include a fail-safe mechanism here.


RaiseEvent eSpecificUserImpersonation(False)


End If


End Sub


''' <summary>


''' Impersonates the valid user.


''' </summary>


''' Name of the user.


''' The domain.


''' The password.


''' <returns></returns>


Private Function impersonateValidUser(ByVal userName As String, ByVal domain
As String, ByVal password As String) As Boolean


Dim tempWindowsIdentity As WindowsIdentity


Dim token As IntPtr = IntPtr.Zero


Dim tokenDuplicate As IntPtr = IntPtr.Zero


impersonateValidUser = False


If RevertToSelf() Then


If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) <> 0 Then


If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then


tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)


impersonationContext = tempWindowsIdentity.Impersonate()


If Not impersonationContext Is Nothing Then


impersonateValidUser = True


End If


End If


End If


End If


If Not tokenDuplicate.Equals(IntPtr.Zero) Then


CloseHandle(tokenDuplicate)


End If


If Not token.Equals(IntPtr.Zero) Then


CloseHandle(token)


End If


End Function


''' <summary>


''' Undoes the impersonation.


''' </summary>


Public Sub undoImpersonation()


impersonationContext.Undo()


Impersonated = False


End Sub


Private disposedValue As Boolean = False ' To detect redundant calls


' IDisposable


Protected Overridable Sub Dispose(ByVal disposing As Boolean)


If Not Me.disposedValue Then


If disposing Then


' TODO: free other state (managed objects).


End If


If Impersonated Then 'wees er zeer van dat we weer in een normale context
draaien


undoImpersonation()


End If


' TODO: free your own state (unmanaged objects).


' TODO: set large fields to null.


End If


Me.disposedValue = True


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(ByVal disposing As
Boolean) above.


Dispose(True)


GC.SuppressFinalize(Me)


End Sub


''' <summary>


''' Impersonates the specific user_e specific user impersonation.


''' </summary>


''' if set to <c>true</c> [success].


Private Sub ImpersonateSpecificUser_eSpecificUserImpersonation(ByVal Success
As Boolean) Handles Me.eSpecificUserImpersonation


Me.Impersonated = Success


End Sub


End Class


Usage :


Using UImp As New
UserImpersonate.ImpersonateSpecificUser("Username","Password","Domain")


IF UImp.Impersonated Then


'all code here that must run in the user context or the method calls to
other procedures


End If


End Using


after this point the code runs in "Normall" modus


HTH
Michel Posseth [MCP]
 
Thanks Michel

I did come across that setting in reading something else... and have now
effectly tried a three settings in the app.manifest

My solution has 4 projects in it.
1) Interface
2) Service
3) A dll class
4) setup

This setting was present in both #1 and #2 I made both to read the same as
seen below...
However I am not prompted to elevate the rights.

Any ideas?


<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0"
xmlns="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv1="urn:schemas-microsoft-com:asm.v1"
xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level
replace the
requestedExecutionLevel node with one of the following.

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

If you want to utilize File and Registry Virtualization for
backward
compatibility then delete the requestedExecutionLevel node.
-->
<requestedExecutionLevel level="requireAdministrator"
uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
</asmv1:assembly>
 
Smurfman-MSDN said:
Thanks Michel

I did come across that setting in reading something else... and have now
effectly tried a three settings in the app.manifest

My solution has 4 projects in it.
1) Interface
2) Service
3) A dll class
4) setup

This setting was present in both #1 and #2 I made both to read the same as
seen below...
However I am not prompted to elevate the rights.

Any ideas?

What if you activate this account on Vista? What happens?

<http://www.howtogeek.com/howto/wind...idden-administrator-account-on-windows-vista/>

<http://www.developer.com/net/net/article.php/3695651>
 
Michel,

Try to paste in your code next time in a textbox and then copy back.

That makes it more readable in a message. Armin once wrote even a program
for that to do that direct with the clipboard.

Cor

Michel Posseth said:
Hello Smurfman ,


If you want to do this from code and you have the admin username and
password you could try what happens
when you use impersonation to start the service .

i have once created a class wich can do this an posted it ..... well the
heck here it is :-)

'Michel Posseth [MCP] 10-07-2008 , written to run parts of code in
another
user context during runtime


Imports System.Security


Imports System.Security.Principal


Imports System.Runtime.InteropServices


Public Class ImpersonateSpecificUser


Implements IDisposable


Private Const LOGON32_LOGON_INTERACTIVE As Integer = 2


Private Const LOGON32_PROVIDER_DEFAULT As Integer = 0


Private impersonationContext As WindowsImpersonationContext


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


Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _


ByVal ExistingTokenHandle As IntPtr, _


ByVal ImpersonationLevel As Integer, _


ByRef DuplicateTokenHandle As IntPtr) As Integer


Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long


Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As
IntPtr) As Long


Public Event eSpecificUserImpersonation(ByVal Success As Boolean)


Private _Impersonated As Boolean


''' <summary>


''' Gets or sets a value indicating whether this <see
cref="ImpersonateSpecificUser" /> is impersonated.


''' </summary>


''' <value><c>true</c> if impersonated; otherwise, <c>false</c>.</value>


Public Property Impersonated() As Boolean


Get


Return _Impersonated


End Get


Private Set(ByVal value As Boolean)


_Impersonated = value


End Set


End Property


''' <summary>


''' Initializes a new instance of the <see cref="ImpersonateSpecificUser"
/>
class.


''' </summary>


''' Name of the user.


''' The password.


''' The domain.


Public Sub New(ByVal UserName As String, ByVal Password As String, ByVal
Domain As String)


If impersonateValidUser(UserName, Domain, Password) Then


RaiseEvent eSpecificUserImpersonation(True)


Else


'Your impersonation failed. Therefore, include a fail-safe mechanism here.


RaiseEvent eSpecificUserImpersonation(False)


End If


End Sub


''' <summary>


''' Impersonates the valid user.


''' </summary>


''' Name of the user.


''' The domain.


''' The password.


''' <returns></returns>


Private Function impersonateValidUser(ByVal userName As String, ByVal
domain
As String, ByVal password As String) As Boolean


Dim tempWindowsIdentity As WindowsIdentity


Dim token As IntPtr = IntPtr.Zero


Dim tokenDuplicate As IntPtr = IntPtr.Zero


impersonateValidUser = False


If RevertToSelf() Then


If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) <> 0 Then


If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then


tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)


impersonationContext = tempWindowsIdentity.Impersonate()


If Not impersonationContext Is Nothing Then


impersonateValidUser = True


End If


End If


End If


End If


If Not tokenDuplicate.Equals(IntPtr.Zero) Then


CloseHandle(tokenDuplicate)


End If


If Not token.Equals(IntPtr.Zero) Then


CloseHandle(token)


End If


End Function


''' <summary>


''' Undoes the impersonation.


''' </summary>


Public Sub undoImpersonation()


impersonationContext.Undo()


Impersonated = False


End Sub


Private disposedValue As Boolean = False ' To detect redundant calls


' IDisposable


Protected Overridable Sub Dispose(ByVal disposing As Boolean)


If Not Me.disposedValue Then


If disposing Then


' TODO: free other state (managed objects).


End If


If Impersonated Then 'wees er zeer van dat we weer in een normale context
draaien


undoImpersonation()


End If


' TODO: free your own state (unmanaged objects).


' TODO: set large fields to null.


End If


Me.disposedValue = True


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(ByVal disposing As
Boolean) above.


Dispose(True)


GC.SuppressFinalize(Me)


End Sub


''' <summary>


''' Impersonates the specific user_e specific user impersonation.


''' </summary>


''' if set to <c>true</c> [success].


Private Sub ImpersonateSpecificUser_eSpecificUserImpersonation(ByVal
Success
As Boolean) Handles Me.eSpecificUserImpersonation


Me.Impersonated = Success


End Sub


End Class


Usage :


Using UImp As New
UserImpersonate.ImpersonateSpecificUser("Username","Password","Domain")


IF UImp.Impersonated Then


'all code here that must run in the user context or the method calls to
other procedures


End If


End Using


after this point the code runs in "Normall" modus


HTH
Michel Posseth [MCP]









Smurfman-MSDN said:
Additional Info.

A Quick Watch helped me to see the inner error message and in fact I am
getting the same "Access is Denied" from within my application.

I understand that from a cmd prompt I can run as administrator to get
past
the elevated rights thing.

But in my application I am unsure how I am to accomplish this.

Thanks
J
 
Thanks everyone.
The manifest is the key.
In Visual Studio 2008 everything is done for you.

Funny - but after making the changes I did yesterday it just didn't matter.
But today, after a fresh start - the program automatically prompted me to run
as Administrator (by Program I mean VS2008) and it restarted.

I re-installed my program, and poof the whole manifest thing was working as
expected.

I found this link that helped me to understand that VS2008 does everything
for you.
I suspect that I just needed to close the project and re-open it.

http://www.professionalvisualstudio.com/blog/2007/10/05/enabling-your-application-for-uac-on-vista/

Also, I found another link to add the Shield to my Service Button -

http://www.vb-helper.com/howto_2008_uac_shield.html

( I extend my Thanks to the Author)

Thanks everyone.
J
 
Back
Top