By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
464,733 Members | 1,155 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 464,733 IT Pros & Developers. It's quick & easy.

Installing a Windows Service Programmatically

P: n/a
Hi all:
I read an article from
http://www.c-sharpcorner.com/Code/20...mmatically.asp
about how to install a windows service programmatically.
Based ont the code sample, it provides the feature to install service
under LocalSystem account.
What I need is to install service under some other certian account. By
further studying the code, and MSDN
(http://msdn.microsoft.com/library/de...-us/dllproc/ba
se/createservice.asp) ,
public static extern IntPtr CreateService(IntPtr SC_HANDLE,string
lpSvcName,string lpDisplayName,
int dwDesiredAccess,int dwServiceType,int dwStartType,int
dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string
lpServiceStartName,string lpPassword);
is the core API to create a service. And the last two parameters should be
name and password of account under wihcih service should run. But when I
tried to pass values to these two parameters bu calling:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);
This piece of code is just a bit different from original, but sv_handle
return is 0, which means failure.

Anybody has idea how to install a service under some certain account?
Thanks for any suggestion.
--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
Nov 15 '05 #1
Share this Question
Share on Google+
9 Replies

P: n/a
Hardy,

If the return value is IntPtr.Zero, then throw a new instance of the
Win32Exception class. It will detail what the error from the call to
GetLastError is and it will give you more information about what went wrong
with the call.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:Oo**************@TK2MSFTNGP11.phx.gbl...
Hi all:
I read an article from
http://www.c-sharpcorner.com/Code/20...mmatically.asp about how to install a windows service programmatically.
Based ont the code sample, it provides the feature to install service
under LocalSystem account.
What I need is to install service under some other certian account. By
further studying the code, and MSDN
(http://msdn.microsoft.com/library/de...-us/dllproc/ba se/createservice.asp) ,
public static extern IntPtr CreateService(IntPtr SC_HANDLE,string
lpSvcName,string lpDisplayName,
int dwDesiredAccess,int dwServiceType,int dwStartType,int
dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string
lpServiceStartName,string lpPassword);
is the core API to create a service. And the last two parameters should be
name and password of account under wihcih service should run. But when I
tried to pass values to these two parameters bu calling:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);
This piece of code is just a bit different from original, but sv_handle
return is 0, which means failure.

Anybody has idea how to install a service under some certain account?
Thanks for any suggestion.
--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy

Nov 15 '05 #2

P: n/a
I adding some code like:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);

if (sv_handle.ToInt32() == 0) {
CloseServiceHandle(sc_handle);
int err = GetLastError();
return false;
}

I tried to capture the error by reading return from GetLastError(), I got
997, where to find the definition of error code?

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote
in message news:eW**************@TK2MSFTNGP10.phx.gbl...
Hardy,

If the return value is IntPtr.Zero, then throw a new instance of the
Win32Exception class. It will detail what the error from the call to
GetLastError is and it will give you more information about what went wrong with the call.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:Oo**************@TK2MSFTNGP11.phx.gbl...
Hi all:
I read an article from

http://www.c-sharpcorner.com/Code/20...mmatically.asp
about how to install a windows service programmatically.
Based ont the code sample, it provides the feature to install service under LocalSystem account.
What I need is to install service under some other certian account. By further studying the code, and MSDN

(http://msdn.microsoft.com/library/de...-us/dllproc/ba
se/createservice.asp) ,
public static extern IntPtr CreateService(IntPtr SC_HANDLE,string
lpSvcName,string lpDisplayName,
int dwDesiredAccess,int dwServiceType,int dwStartType,int
dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string lpServiceStartName,string lpPassword);
is the core API to create a service. And the last two parameters should be name and password of account under wihcih service should run. But when I
tried to pass values to these two parameters bu calling:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);
This piece of code is just a bit different from original, but sv_handle
return is 0, which means failure.

Anybody has idea how to install a service under some certain account?

Thanks for any suggestion.
--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy


Nov 15 '05 #3

P: n/a
Hardy,

You should never call GetLastError yourself, as it is not guaranteed to
be accurate. The reason for this is that the runtime makes API calls
between your API call and it might set the error state on its own. Because
of this, you should call the static GetLastWin32Error method on the Marshal
class.

However, there is a class that does all of this, the Win32Exception
class in the System.ComponentModel namespace. You should make your call
like this:

// Call CreateService.
IntPtr sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, servicePath, null, 0, null, _UserName, _Password);

// Throw an exception if there is no handle.
try
{
if (sv_handle == IntPtr.Zero)
// Throw an exception.
throw new Win32Exception();
}
finally
{
CloseServiceHandle(sc_handle);
}

This should give you the description of the error. You can also look in
WINERROR.H to find the error the code represents.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
I adding some code like:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);

if (sv_handle.ToInt32() == 0) {
CloseServiceHandle(sc_handle);
int err = GetLastError();
return false;
}

I tried to capture the error by reading return from GetLastError(), I got
997, where to find the definition of error code?

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote in message news:eW**************@TK2MSFTNGP10.phx.gbl...
Hardy,

If the return value is IntPtr.Zero, then throw a new instance of the
Win32Exception class. It will detail what the error from the call to
GetLastError is and it will give you more information about what went wrong
with the call.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:Oo**************@TK2MSFTNGP11.phx.gbl...
Hi all:
I read an article from

http://www.c-sharpcorner.com/Code/20...mmatically.asp
about how to install a windows service programmatically.
Based ont the code sample, it provides the feature to install service under LocalSystem account.
What I need is to install service under some other certian account. By
further studying the code, and MSDN

(http://msdn.microsoft.com/library/de...-us/dllproc/ba se/createservice.asp) ,
public static extern IntPtr CreateService(IntPtr SC_HANDLE,string
lpSvcName,string lpDisplayName,
int dwDesiredAccess,int dwServiceType,int dwStartType,int
dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string lpServiceStartName,string lpPassword);
is the core API to create a service. And the last two parameters should be
name and password of account under wihcih service should run. But when
I tried to pass values to these two parameters bu calling:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);
This piece of code is just a bit different from original, but sv_handle return is 0, which means failure.

Anybody has idea how to install a service under some certain

account?

Thanks for any suggestion.
--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy



Nov 15 '05 #4

P: n/a
I tried your codes, got error message "Control ID not found".

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote
in message news:e$**************@TK2MSFTNGP12.phx.gbl...
Hardy,

You should never call GetLastError yourself, as it is not guaranteed to be accurate. The reason for this is that the runtime makes API calls
between your API call and it might set the error state on its own. Because of this, you should call the static GetLastWin32Error method on the Marshal class.

However, there is a class that does all of this, the Win32Exception
class in the System.ComponentModel namespace. You should make your call
like this:

// Call CreateService.
IntPtr sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, servicePath, null, 0, null, _UserName, _Password);

// Throw an exception if there is no handle.
try
{
if (sv_handle == IntPtr.Zero)
// Throw an exception.
throw new Win32Exception();
}
finally
{
CloseServiceHandle(sc_handle);
}

This should give you the description of the error. You can also look in WINERROR.H to find the error the code represents.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
I adding some code like:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);

if (sv_handle.ToInt32() == 0) {
CloseServiceHandle(sc_handle);
int err = GetLastError();
return false;
}

I tried to capture the error by reading return from GetLastError(), I got
997, where to find the definition of error code?

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote
in message news:eW**************@TK2MSFTNGP10.phx.gbl...
Hardy,

If the return value is IntPtr.Zero, then throw a new instance of the Win32Exception class. It will detail what the error from the call to
GetLastError is and it will give you more information about what went

wrong
with the call.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:Oo**************@TK2MSFTNGP11.phx.gbl...
> Hi all:
> I read an article from
>

http://www.c-sharpcorner.com/Code/20...mmatically.asp
> about how to install a windows service programmatically.
> Based ont the code sample, it provides the feature to install

service
> under LocalSystem account.
> What I need is to install service under some other certian account.
By
> further studying the code, and MSDN
>

(http://msdn.microsoft.com/library/de...-us/dllproc/ba
> se/createservice.asp) ,
> public static extern IntPtr CreateService(IntPtr SC_HANDLE,string > lpSvcName,string lpDisplayName,
> int dwDesiredAccess,int dwServiceType,int dwStartType,int
> dwErrorControl,string lpPathName,
> string lpLoadOrderGroup,int lpdwTagId,string

lpDependencies,string
> lpServiceStartName,string lpPassword);
> is the core API to create a service. And the last two parameters should
be
> name and password of account under wihcih service should run. But when I > tried to pass values to these two parameters bu calling:
> sv_handle = CreateService(sc_handle, serviceName,
serviceDisplayName, > SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
> SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
> servicePath, null, 0, null, _UserName, _Password);
> This piece of code is just a bit different from original, but

sv_handle > return is 0, which means failure.
>
> Anybody has idea how to install a service under some certain

account?
>
>
> Thanks for any suggestion.
>
>
> --
> WWW: http://hardywang.1accesshost.com
> ICQ: 3359839
> yours Hardy
>
>



Nov 15 '05 #5

P: n/a
Hardy,

Are you sure that this is the error that the call to CreateService gave?
If you replace the "throw" part with a call to GetLastWin32Error, what does
that return?
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:uu**************@tk2msftngp13.phx.gbl...
I tried your codes, got error message "Control ID not found".

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote in message news:e$**************@TK2MSFTNGP12.phx.gbl...
Hardy,

You should never call GetLastError yourself, as it is not guaranteed to
be accurate. The reason for this is that the runtime makes API calls
between your API call and it might set the error state on its own.

Because
of this, you should call the static GetLastWin32Error method on the

Marshal
class.

However, there is a class that does all of this, the Win32Exception
class in the System.ComponentModel namespace. You should make your call
like this:

// Call CreateService.
IntPtr sv_handle = CreateService(sc_handle, serviceName,

serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, servicePath, null, 0, null, _UserName, _Password);

// Throw an exception if there is no handle.
try
{
if (sv_handle == IntPtr.Zero)
// Throw an exception.
throw new Win32Exception();
}
finally
{
CloseServiceHandle(sc_handle);
}

This should give you the description of the error. You can also look in
WINERROR.H to find the error the code represents.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
I adding some code like:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);

if (sv_handle.ToInt32() == 0) {
CloseServiceHandle(sc_handle);
int err = GetLastError();
return false;
}

I tried to capture the error by reading return from GetLastError(), I

got 997, where to find the definition of error code?

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com>

wrote
in message news:eW**************@TK2MSFTNGP10.phx.gbl...
> Hardy,
>
> If the return value is IntPtr.Zero, then throw a new instance of the > Win32Exception class. It will detail what the error from the call to > GetLastError is and it will give you more information about what went wrong
> with the call.
>
> Hope this helps.
>
>
> --
> - Nicholas Paldino [.NET/C# MVP]
> - ni**************@exisconsulting.com
>
> "Hardy Wang" <ha********@marketrend.com> wrote in message
> news:Oo**************@TK2MSFTNGP11.phx.gbl...
> > Hi all:
> > I read an article from
> >
>

http://www.c-sharpcorner.com/Code/20...mmatically.asp
> > about how to install a windows service programmatically.
> > Based ont the code sample, it provides the feature to install
service
> > under LocalSystem account.
> > What I need is to install service under some other certian

account.
By
> > further studying the code, and MSDN
> >
>

(http://msdn.microsoft.com/library/de...-us/dllproc/ba
> > se/createservice.asp) ,
> > public static extern IntPtr CreateService(IntPtr SC_HANDLE,string > > lpSvcName,string lpDisplayName,
> > int dwDesiredAccess,int dwServiceType,int dwStartType,int
> > dwErrorControl,string lpPathName,
> > string lpLoadOrderGroup,int lpdwTagId,string
lpDependencies,string
> > lpServiceStartName,string lpPassword);
> > is the core API to create a service. And the last two parameters

should
be
> > name and password of account under wihcih service should run. But when
I
> > tried to pass values to these two parameters bu calling:
> > sv_handle = CreateService(sc_handle, serviceName,

serviceDisplayName, > > SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
> > SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
> > servicePath, null, 0, null, _UserName, _Password);
> > This piece of code is just a bit different from original, but

sv_handle
> > return is 0, which means failure.
> >
> > Anybody has idea how to install a service under some certain
account?
> >
> >
> > Thanks for any suggestion.
> >
> >
> > --
> > WWW: http://hardywang.1accesshost.com
> > ICQ: 3359839
> > yours Hardy
> >
> >
>
>



Nov 15 '05 #6

P: n/a
Yes, I am sure, I used a catch to capure exception thrown by code, and got
that message.
By calling "int err = Marshal.GetLastWin32Error();" I have error number
1421, don't know what does it mean.

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote
in message news:eR****************@TK2MSFTNGP11.phx.gbl...
Hardy,

Are you sure that this is the error that the call to CreateService gave? If you replace the "throw" part with a call to GetLastWin32Error, what does that return?
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:uu**************@tk2msftngp13.phx.gbl...
I tried your codes, got error message "Control ID not found".

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com>

wrote
in message news:e$**************@TK2MSFTNGP12.phx.gbl...
Hardy,

You should never call GetLastError yourself, as it is not guaranteed
to
be accurate. The reason for this is that the runtime makes API calls
between your API call and it might set the error state on its own.

Because
of this, you should call the static GetLastWin32Error method on the

Marshal
class.

However, there is a class that does all of this, the
Win32Exception class in the System.ComponentModel namespace. You should make your call like this:

// Call CreateService.
IntPtr sv_handle = CreateService(sc_handle, serviceName,

serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, servicePath, null, 0, null, _UserName, _Password);
// Throw an exception if there is no handle.
try
{
if (sv_handle == IntPtr.Zero)
// Throw an exception.
throw new Win32Exception();
}
finally
{
CloseServiceHandle(sc_handle);
}

This should give you the description of the error. You can also look
in
WINERROR.H to find the error the code represents.
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
> I adding some code like:
> sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName, > SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
> SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
> servicePath, null, 0, null, _UserName, _Password);
>
> if (sv_handle.ToInt32() == 0) {
> CloseServiceHandle(sc_handle);
> int err = GetLastError();
> return false;
> }
>
> I tried to capture the error by reading return from GetLastError(), I got
> 997, where to find the definition of error code?
>
> --
> WWW: http://hardywang.1accesshost.com
> ICQ: 3359839
> yours Hardy
> "Nicholas Paldino [.NET/C# MVP]"
<ni**************@exisconsulting.com> wrote
> in message news:eW**************@TK2MSFTNGP10.phx.gbl...
> > Hardy,
> >
> > If the return value is IntPtr.Zero, then throw a new instance of the
> > Win32Exception class. It will detail what the error from the call to > > GetLastError is and it will give you more information about what went > wrong
> > with the call.
> >
> > Hope this helps.
> >
> >
> > --
> > - Nicholas Paldino [.NET/C# MVP]
> > - ni**************@exisconsulting.com
> >
> > "Hardy Wang" <ha********@marketrend.com> wrote in message
> > news:Oo**************@TK2MSFTNGP11.phx.gbl...
> > > Hi all:
> > > I read an article from
> > >
> >
>

http://www.c-sharpcorner.com/Code/20...mmatically.asp > > > about how to install a windows service programmatically.
> > > Based ont the code sample, it provides the feature to install > service
> > > under LocalSystem account.
> > > What I need is to install service under some other certian
account.
> By
> > > further studying the code, and MSDN
> > >
> >
>

(http://msdn.microsoft.com/library/de...-us/dllproc/ba
> > > se/createservice.asp) ,
> > > public static extern IntPtr CreateService(IntPtr

SC_HANDLE,string
> > > lpSvcName,string lpDisplayName,
> > > int dwDesiredAccess,int dwServiceType,int dwStartType,int > > > dwErrorControl,string lpPathName,
> > > string lpLoadOrderGroup,int lpdwTagId,string
> lpDependencies,string
> > > lpServiceStartName,string lpPassword);
> > > is the core API to create a service. And the last two parameters
should
> be
> > > name and password of account under wihcih service should run.

But when
I
> > > tried to pass values to these two parameters bu calling:
> > > sv_handle = CreateService(sc_handle, serviceName,

serviceDisplayName,
> > > SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
> > > SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
> > > servicePath, null, 0, null, _UserName, _Password);
> > > This piece of code is just a bit different from original, but
sv_handle
> > > return is 0, which means failure.
> > >
> > > Anybody has idea how to install a service under some certain
> account?
> > >
> > >
> > > Thanks for any suggestion.
> > >
> > >
> > > --
> > > WWW: http://hardywang.1accesshost.com
> > > ICQ: 3359839
> > > yours Hardy
> > >
> > >
> >
> >
>
>



Nov 15 '05 #7

P: n/a
Hardy,

This is truly odd. 1421 is what the exception and the call to
GetLastWin32Error returned. However, I don't know why CreateService is
returning it. What are you doing in the UI when this call is made?
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:e7**************@tk2msftngp13.phx.gbl...
Yes, I am sure, I used a catch to capure exception thrown by code, and got
that message.
By calling "int err = Marshal.GetLastWin32Error();" I have error number
1421, don't know what does it mean.

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> wrote in message news:eR****************@TK2MSFTNGP11.phx.gbl...
Hardy,

Are you sure that this is the error that the call to CreateService gave?
If you replace the "throw" part with a call to GetLastWin32Error, what

does
that return?
--
- Nicholas Paldino [.NET/C# MVP]
- ni**************@exisconsulting.com

"Hardy Wang" <ha********@marketrend.com> wrote in message
news:uu**************@tk2msftngp13.phx.gbl...
I tried your codes, got error message "Control ID not found".

--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy
"Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com>

wrote
in message news:e$**************@TK2MSFTNGP12.phx.gbl...
> Hardy,
>
> You should never call GetLastError yourself, as it is not guaranteed to
> be accurate. The reason for this is that the runtime makes API calls > between your API call and it might set the error state on its own.
Because
> of this, you should call the static GetLastWin32Error method on the
Marshal
> class.
>
> However, there is a class that does all of this, the Win32Exception > class in the System.ComponentModel namespace. You should make your call > like this:
>
> // Call CreateService.
> IntPtr sv_handle = CreateService(sc_handle, serviceName,
serviceDisplayName,
> SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START,
> SERVICE_ERROR_NORMAL, servicePath, null, 0, null, _UserName, _Password); >
> // Throw an exception if there is no handle.
> try
> {
> if (sv_handle == IntPtr.Zero)
> // Throw an exception.
> throw new Win32Exception();
> }
> finally
> {
> CloseServiceHandle(sc_handle);
> }
>
> This should give you the description of the error. You can also

look
in
> WINERROR.H to find the error the code represents.
>
>
> --
> - Nicholas Paldino [.NET/C# MVP]
> - ni**************@exisconsulting.com
>
> "Hardy Wang" <ha********@marketrend.com> wrote in message
> news:%2****************@TK2MSFTNGP10.phx.gbl...
> > I adding some code like:
> > sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName, > > SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
> > SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
> > servicePath, null, 0, null, _UserName, _Password);
> >
> > if (sv_handle.ToInt32() == 0) {
> > CloseServiceHandle(sc_handle);
> > int err = GetLastError();
> > return false;
> > }
> >
> > I tried to capture the error by reading return from GetLastError(), I
got
> > 997, where to find the definition of error code?
> >
> > --
> > WWW: http://hardywang.1accesshost.com
> > ICQ: 3359839
> > yours Hardy
> > "Nicholas Paldino [.NET/C# MVP]" <ni**************@exisconsulting.com> > wrote
> > in message news:eW**************@TK2MSFTNGP10.phx.gbl...
> > > Hardy,
> > >
> > > If the return value is IntPtr.Zero, then throw a new
instance
of the
> > > Win32Exception class. It will detail what the error from the
call
to
> > > GetLastError is and it will give you more information about what

went
> > wrong
> > > with the call.
> > >
> > > Hope this helps.
> > >
> > >
> > > --
> > > - Nicholas Paldino [.NET/C# MVP]
> > > - ni**************@exisconsulting.com
> > >
> > > "Hardy Wang" <ha********@marketrend.com> wrote in message
> > > news:Oo**************@TK2MSFTNGP11.phx.gbl...
> > > > Hi all:
> > > > I read an article from
> > > >
> > >
> >
>

http://www.c-sharpcorner.com/Code/20...mmatically.asp > > > > about how to install a windows service programmatically.
> > > > Based ont the code sample, it provides the feature to

install > > service
> > > > under LocalSystem account.
> > > > What I need is to install service under some other certian
> account.
> > By
> > > > further studying the code, and MSDN
> > > >
> > >
> >
>

(http://msdn.microsoft.com/library/de...-us/dllproc/ba
> > > > se/createservice.asp) ,
> > > > public static extern IntPtr CreateService(IntPtr
SC_HANDLE,string
> > > > lpSvcName,string lpDisplayName,
> > > > int dwDesiredAccess,int dwServiceType,int dwStartType,int > > > > dwErrorControl,string lpPathName,
> > > > string lpLoadOrderGroup,int lpdwTagId,string
> > lpDependencies,string
> > > > lpServiceStartName,string lpPassword);
> > > > is the core API to create a service. And the last two parameters > should
> > be
> > > > name and password of account under wihcih service should run. But when
> I
> > > > tried to pass values to these two parameters bu calling:
> > > > sv_handle = CreateService(sc_handle, serviceName,
serviceDisplayName,
> > > > SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
> > > > SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
> > > > servicePath, null, 0, null, _UserName, _Password);
> > > > This piece of code is just a bit different from original, but
> sv_handle
> > > > return is 0, which means failure.
> > > >
> > > > Anybody has idea how to install a service under some certain > > account?
> > > >
> > > >
> > > > Thanks for any suggestion.
> > > >
> > > >
> > > > --
> > > > WWW: http://hardywang.1accesshost.com
> > > > ICQ: 3359839
> > > > yours Hardy
> > > >
> > > >
> > >
> > >
> >
> >
>
>



Nov 15 '05 #8

P: n/a
Let me post all my codes here, what I like to do is to create a class
library, I can use it by other UI, then add a test Windows Application
Class Library:
----------------------------------------
using System;
using System.Runtime.InteropServices;

/// <summary>
/// Programmatically install / uninstall Windows Service
/// </summary>
/// <example>
/// <code>
/// string svcPath = @"C:\build\service\Debug\Service.exe";
/// string svcDispName="Service Display Name";
/// string svcName= "Service Name";
/// WindowsServiceInstaller c = new WindowsServiceInstaller();
/// c.InstallService(svcPath, svcName, svcDispName);
/// </code>
/// </example>
public class WindowsServiceInstaller {
/// <summary>
/// Default constructor to initialize instance
/// </summary>
public WindowsServiceInstaller() {
_UserName = "";
_Password = "";
}

/// <summary>
/// Username to run account
/// </summary>
private string _UserName;
/// <summary>
/// Password to run account
/// </summary>
private string _Password;

#region DLLImport
/// <summary>
/// Open SC Manager
/// </summary>
[DllImport("advapi32.dll")]
private static extern IntPtr OpenSCManager(string lpMachineName,string
lpSCDB, int scParameter);
/// <summary>
/// Create Service
/// </summary>
[DllImport("Advapi32.dll")]
private static extern IntPtr CreateService(IntPtr SC_HANDLE,string
lpSvcName,string lpDisplayName,
int dwDesiredAccess,int dwServiceType,int dwStartType,int
dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string
lpServiceStartName,string lpPassword);
/// <summary>
/// Close Service Handle
/// </summary>
[DllImport("advapi32.dll")]
private static extern void CloseServiceHandle(IntPtr SCHANDLE);
/// <summary>
/// Start Service
/// </summary>
[DllImport("advapi32.dll")]
private static extern int StartService(IntPtr SVHANDLE,int
dwNumServiceArgs,string lpServiceArgVectors);
/// <summary>
/// Open Service
/// </summary>
[DllImport("advapi32.dll",SetLastError=true)]
private static extern IntPtr OpenService(IntPtr SCHANDLE,string
lpSvcName,int dwNumServiceArgs);
/// <summary>
/// Delete Service
/// </summary>
[DllImport("advapi32.dll")]
private static extern int DeleteService(IntPtr SVHANDLE);

/// <summary>
/// Get last error
/// </summary>
[DllImport("kernel32.dll")]
private static extern int GetLastError();
#endregion DLLImport

//path to the service that you want to install
//servicePath = @"C:\build\service\Debug\Service.exe";
//serviceDisplayName="Service Display Name";
//serviceName= "Service Name";

/// <summary>
/// This method installs and runs the service in the service conrol manager
under LocalSystem account.
/// </summary>
/// <param name="servicePath">The complete path of the service.</param>
/// <param name="serviceName">Name of the service.</param>
/// <param name="serviceDisplayName">Display name of the service.</param>
/// <returns>True if the process went throgh successfully. False if there
was any error.</returns>
public bool InstallService(string servicePath, string serviceName, string
serviceDisplayName) {
#region Constants declaration.
int SC_MANAGER_CREATE_SERVICE = 0x0002;
int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
int SERVICE_DEMAND_START = 0x00000003;
int SERVICE_ERROR_NORMAL = 0x00000001;

int STANDARD_RIGHTS_REQUIRED = 0xF0000;
int SERVICE_QUERY_CONFIG = 0x0001;
int SERVICE_CHANGE_CONFIG = 0x0002;
int SERVICE_QUERY_STATUS = 0x0004;
int SERVICE_ENUMERATE_DEPENDENTS = 0x0008;
int SERVICE_START = 0x0010;
int SERVICE_STOP = 0x0020;
int SERVICE_PAUSE_CONTINUE =0x0040;
int SERVICE_INTERROGATE = 0x0080;
int SERVICE_USER_DEFINED_CONTROL = 0x0100;

int SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL);
int SERVICE_AUTO_START = 0x00000002;
#endregion Constants declaration.

IntPtr sc_handle = OpenSCManager(null,null,SC_MANAGER_CREATE_SERVICE) ;

if (sc_handle.ToInt32() != 0) {
IntPtr sv_handle;
if (_UserName.Trim().Length > 0) {
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);
} else {
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, null, null);
}

if (sv_handle.ToInt32() == 0) {
int err = Marshal.GetLastWin32Error();
CloseServiceHandle(sc_handle);
return false;
} else {
//now trying to start the service
int i = StartService(sv_handle, 0, null);
// If the value i is zero, then there was an error starting the service.
// note: error may arise if the service is already running or some other
problem.
if(i == 0) {
//Console.WriteLine("Couldnt start service");
return false;
}
//Console.WriteLine("Success");
CloseServiceHandle(sc_handle);
return true;
}
} else {
//Console.WriteLine("SCM not opened successfully");
return false;
}
}

/// <summary>
/// This method installs and runs the service in the service conrol manager
under specified account.
/// </summary>
/// <param name="servicePath">The complete path of the service.</param>
/// <param name="serviceName">Name of the service.</param>
/// <param name="serviceDisplayName">Display name of the service.</param>
/// <param name="serviceStartName">The name of the account under which the
service should run</param>
/// <param name="password">The password to the account name specified by
the serviceStartName parameter</param>
/// <returns>True if the process went throgh successfully. False if there
was any error.</returns>
public bool InstallService(string servicePath, string serviceName,
string serviceDisplayName, string serviceStartName, string password) {
_UserName = serviceStartName;
_Password = password;

return InstallService(servicePath, serviceName, serviceDisplayName);
}

/// <summary>
/// This method uninstalls the service from the service conrol manager.
/// </summary>
/// <param name="serviceName">Name of the service to uninstall.</param>
public bool UnInstallService(string serviceName) {
int GENERIC_WRITE = 0x40000000;
IntPtr sc_hndl = OpenSCManager(null,null,GENERIC_WRITE);

if (sc_hndl.ToInt32() !=0) {
int DELETE = 0x10000;
IntPtr svc_hndl = OpenService(sc_hndl,serviceName,DELETE);
//Console.WriteLine(svc_hndl.ToInt32());
if(svc_hndl.ToInt32() !=0) {
int i = DeleteService(svc_hndl);
if (i != 0) {
CloseServiceHandle(sc_hndl);
return true;
} else {
CloseServiceHandle(sc_hndl);
return false;
}
} else {
return false;
}
} else {
return false;
}
}
}
===========================
Test application:
-----------------------------
private void button1_Click(object sender, System.EventArgs e) {
WindowsServiceInstaller c = new WindowsServiceInstaller();
if
(c.InstallService(@"C:\Work\ReportScheduler\Report Scheduler\bin\Debug\Report
Scheduler.exe", "Report", "Report", @"domian\username", "password")) {
MessageBox.Show("OK");
} else {
MessageBox.Show("Bad");
}
}
===============================================
I tried the overload without username and password, the service is created,
but this one failed.
Nov 15 '05 #9

P: n/a
Why not simply use the sc.exe commandline utility (standard on XP and W2K3, resource kit utility for NT4).

Willy.

"Hardy Wang" <ha********@marketrend.com> wrote in message news:Oo**************@TK2MSFTNGP11.phx.gbl...
Hi all:
I read an article from
http://www.c-sharpcorner.com/Code/20...mmatically.asp
about how to install a windows service programmatically.
Based ont the code sample, it provides the feature to install service
under LocalSystem account.
What I need is to install service under some other certian account. By
further studying the code, and MSDN
(http://msdn.microsoft.com/library/de...-us/dllproc/ba
se/createservice.asp) ,
public static extern IntPtr CreateService(IntPtr SC_HANDLE,string
lpSvcName,string lpDisplayName,
int dwDesiredAccess,int dwServiceType,int dwStartType,int
dwErrorControl,string lpPathName,
string lpLoadOrderGroup,int lpdwTagId,string lpDependencies,string
lpServiceStartName,string lpPassword);
is the core API to create a service. And the last two parameters should be
name and password of account under wihcih service should run. But when I
tried to pass values to these two parameters bu calling:
sv_handle = CreateService(sc_handle, serviceName, serviceDisplayName,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
servicePath, null, 0, null, _UserName, _Password);
This piece of code is just a bit different from original, but sv_handle
return is 0, which means failure.

Anybody has idea how to install a service under some certain account?
Thanks for any suggestion.
--
WWW: http://hardywang.1accesshost.com
ICQ: 3359839
yours Hardy

Nov 15 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.