Windows ServiceInstaller - Runtime Settings

S

Smurfman-MSDN

Using VB2008 SP1 on Vista Ultimate x64 SP1

I have a Service Application that installs a windows service, and an
interface for making settings for the service to execute by.

I would like to capture from the user - either at the point of installation
or on the form - the user credencials that the service needs to run as.

The service cannot run as Local System because it needs to authenticate to
another server share and poll if a file is there.

So I found that if I entered a username and password into the service that
it would work.

Thanks
J
 
H

Hongye Sun [MSFT]

Hello J,

Thanks for your post.

If my understanding is correct, you are going to pass custom user
credentails to a windows service while installation or on your own UI.

Generally, we will do it via installation. After that, user can change the
credentials from service management console. There are two ways for user to
input credentials while installation:

1. Pass from command line
Pass the command line argument to service when install the service by
InstallUtil. The command line should look like:

InstallUtil.exe MyService.exe /username=MyUserName /password=Password

In the ProjectInstaller's event OnBeforeInstall, get the credentails and
pass it to ServiceProcessInstaller. Here is the sample code:
----------------------------------------------
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);

String username = GetContextParameter("username");
String password = GetContextParameter("password");

if (!String.IsNullOrEmpty(username))
serviceProcessInstaller1.Username = username;
if (!String.IsNullOrEmpty(password))
serviceProcessInstaller1.Password = password;
}
----------------------------------------------

For more information, please visit the following blog:
http://menet.name/blog/christophe/archive/2009/03/01/provide-credentials-use
rname-and-password-while-installing-a-service-silently.aspx

2. Pass from Installation UI
This way is similiar with the command line way. The difference is that it
uses MSI to build an UI to pass credentails.
Here are the steps to do it:

1). Create a project installer class that inherits from the Installer class.
Follow the instructions at this link:
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstall
er.aspx

2). Create a setup project in Visual Studio.
Here is an example:
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Note: It is required to add the service DLL as custom actions in setup
project.

3). Add UI for user to input credetials and pass it to project installer
class.
Follow the instructions at:
http://www.c-sharpcorner.com/UploadFile/steve_hall/InstallationPromptForServ
iceAccount10172007152711PM/InstallationPromptForServiceAccount.aspx

In addition, changing user credentails after service installation can also
be done in code.
It is usually implmeneted by WMI or P/Invoke in .NET. Please visit the
following link for details:
http://msmvps.com/blogs/siva/archive/2007/04/19/changing-log-on-credentials-
of-windows-service.aspx

There is also a commandline tool sc.exe, which can be used to change
service configuration. For more information, please visit the following
link:
http://technet.microsoft.com/en-us/library/bb490995.aspx

Please let me know if you need more information.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within?2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Smurfman-MSDN

Hongye, thanks for the great info.

I am interested in option #2
I already have a Solution in place with 4 projects
1) Form - Interface to Service
2) Service
3) DLL with some special code
4) Setup Project

If I wanted to add to what I already have how woudl I do what you
suggesstions are without re-inventing the wheel as it were.

THanks again.
J

"Hongye Sun [MSFT]" said:
Hello J,

Thanks for your post.

If my understanding is correct, you are going to pass custom user
credentails to a windows service while installation or on your own UI.

Generally, we will do it via installation. After that, user can change the
credentials from service management console. There are two ways for user to
input credentials while installation:

1. Pass from command line
Pass the command line argument to service when install the service by
InstallUtil. The command line should look like:

InstallUtil.exe MyService.exe /username=MyUserName /password=Password

In the ProjectInstaller's event OnBeforeInstall, get the credentails and
pass it to ServiceProcessInstaller. Here is the sample code:
----------------------------------------------
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);

String username = GetContextParameter("username");
String password = GetContextParameter("password");

if (!String.IsNullOrEmpty(username))
serviceProcessInstaller1.Username = username;
if (!String.IsNullOrEmpty(password))
serviceProcessInstaller1.Password = password;
}
----------------------------------------------

For more information, please visit the following blog:
http://menet.name/blog/christophe/archive/2009/03/01/provide-credentials-use
rname-and-password-while-installing-a-service-silently.aspx

2. Pass from Installation UI
This way is similiar with the command line way. The difference is that it
uses MSI to build an UI to pass credentails.
Here are the steps to do it:

1). Create a project installer class that inherits from the Installer class.
Follow the instructions at this link:
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstall
er.aspx

2). Create a setup project in Visual Studio.
Here is an example:
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Note: It is required to add the service DLL as custom actions in setup
project.

3). Add UI for user to input credetials and pass it to project installer
class.
Follow the instructions at:
http://www.c-sharpcorner.com/UploadFile/steve_hall/InstallationPromptForServ
iceAccount10172007152711PM/InstallationPromptForServiceAccount.aspx

In addition, changing user credentails after service installation can also
be done in code.
It is usually implmeneted by WMI or P/Invoke in .NET. Please visit the
following link for details:
http://msmvps.com/blogs/siva/archive/2007/04/19/changing-log-on-credentials-
of-windows-service.aspx

There is also a commandline tool sc.exe, which can be used to change
service configuration. For more information, please visit the following
link:
http://technet.microsoft.com/en-us/library/bb490995.aspx

Please let me know if you need more information.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within?2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Smurfman-MSDN

Hongye,
Okay I have an update.

Basically I assumed that the first few steps of solution 2 - were already in
place for my solution -

I used the one doc from c-sharpcorner.com - and while it was in c-sharp I
understood the concept and went with it.

So here is where I am at - perhaps you can assist me further.

I edited the "ProjectInstaller.Designer.vb" and changed the
serviceprocessinstaller.account to be user from localsystem.

I then added the logic
serviceprocessinstaller1.username = context.parameters.item("f1")
serviceprocessinstaller1.password = context.parameters.item("f2")

In the setup project custom actions for the Install node for the service, I
added
/f1=[EDITC1] /f2=[EDITC2]
to the the CustomActionData value.

I then attempted the install.

I received an error - related to the data input on the username field when I
entered "john brown" (no quotes) I got an error specifically related to brown
as part of the error exception thrown.

Then I got an error that said:
Error 1001. Unable to create an instance of the
My_Service_Name.ProjectInstaller installer type. --> Exception has been
thrown by the target of an invocation. --> Object Reference not set to an
instance of an object.

It seems that the space caused an issue.

This also lead me to some other points:
1) suppose I want to hide the password a user types in.
2) What if the username has a space in it
3) What if the password has a space or other special char in it.


Thanks
J

"Hongye Sun [MSFT]" said:
Hello J,

Thanks for your post.

If my understanding is correct, you are going to pass custom user
credentails to a windows service while installation or on your own UI.

Generally, we will do it via installation. After that, user can change the
credentials from service management console. There are two ways for user to
input credentials while installation:

1. Pass from command line
Pass the command line argument to service when install the service by
InstallUtil. The command line should look like:

InstallUtil.exe MyService.exe /username=MyUserName /password=Password

In the ProjectInstaller's event OnBeforeInstall, get the credentails and
pass it to ServiceProcessInstaller. Here is the sample code:
----------------------------------------------
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);

String username = GetContextParameter("username");
String password = GetContextParameter("password");

if (!String.IsNullOrEmpty(username))
serviceProcessInstaller1.Username = username;
if (!String.IsNullOrEmpty(password))
serviceProcessInstaller1.Password = password;
}
----------------------------------------------

For more information, please visit the following blog:
http://menet.name/blog/christophe/archive/2009/03/01/provide-credentials-use
rname-and-password-while-installing-a-service-silently.aspx

2. Pass from Installation UI
This way is similiar with the command line way. The difference is that it
uses MSI to build an UI to pass credentails.
Here are the steps to do it:

1). Create a project installer class that inherits from the Installer class.
Follow the instructions at this link:
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstall
er.aspx

2). Create a setup project in Visual Studio.
Here is an example:
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Note: It is required to add the service DLL as custom actions in setup
project.

3). Add UI for user to input credetials and pass it to project installer
class.
Follow the instructions at:
http://www.c-sharpcorner.com/UploadFile/steve_hall/InstallationPromptForServ
iceAccount10172007152711PM/InstallationPromptForServiceAccount.aspx

In addition, changing user credentails after service installation can also
be done in code.
It is usually implmeneted by WMI or P/Invoke in .NET. Please visit the
following link for details:
http://msmvps.com/blogs/siva/archive/2007/04/19/changing-log-on-credentials-
of-windows-service.aspx

There is also a commandline tool sc.exe, which can be used to change
service configuration. For more information, please visit the following
link:
http://technet.microsoft.com/en-us/library/bb490995.aspx

Please let me know if you need more information.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within?2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Smurfman-MSDN

Now I have met with a new problem.
Editing the Projectinstaller.Designer.vb file as suggested in the link you
gave me - seemed like th ething to do, excpet it clearly states that the code
should not be edited. I found out that in the Project Designer if I were to
move or set a property it re-wrote teh settings for the username and password
fields.

As a reminder I am using VB2008

Thanks
J

"Hongye Sun [MSFT]" said:
Hello J,

Thanks for your post.

If my understanding is correct, you are going to pass custom user
credentails to a windows service while installation or on your own UI.

Generally, we will do it via installation. After that, user can change the
credentials from service management console. There are two ways for user to
input credentials while installation:

1. Pass from command line
Pass the command line argument to service when install the service by
InstallUtil. The command line should look like:

InstallUtil.exe MyService.exe /username=MyUserName /password=Password

In the ProjectInstaller's event OnBeforeInstall, get the credentails and
pass it to ServiceProcessInstaller. Here is the sample code:
----------------------------------------------
protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);

String username = GetContextParameter("username");
String password = GetContextParameter("password");

if (!String.IsNullOrEmpty(username))
serviceProcessInstaller1.Username = username;
if (!String.IsNullOrEmpty(password))
serviceProcessInstaller1.Password = password;
}
----------------------------------------------

For more information, please visit the following blog:
http://menet.name/blog/christophe/archive/2009/03/01/provide-credentials-use
rname-and-password-while-installing-a-service-silently.aspx

2. Pass from Installation UI
This way is similiar with the command line way. The difference is that it
uses MSI to build an UI to pass credentails.
Here are the steps to do it:

1). Create a project installer class that inherits from the Installer class.
Follow the instructions at this link:
http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstall
er.aspx

2). Create a setup project in Visual Studio.
Here is an example:
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
Note: It is required to add the service DLL as custom actions in setup
project.

3). Add UI for user to input credetials and pass it to project installer
class.
Follow the instructions at:
http://www.c-sharpcorner.com/UploadFile/steve_hall/InstallationPromptForServ
iceAccount10172007152711PM/InstallationPromptForServiceAccount.aspx

In addition, changing user credentails after service installation can also
be done in code.
It is usually implmeneted by WMI or P/Invoke in .NET. Please visit the
following link for details:
http://msmvps.com/blogs/siva/archive/2007/04/19/changing-log-on-credentials-
of-windows-service.aspx

There is also a commandline tool sc.exe, which can be used to change
service configuration. For more information, please visit the following
link:
http://technet.microsoft.com/en-us/library/bb490995.aspx

Please let me know if you need more information.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within?2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
H

Hongye Sun [MSFT]

Hi J,

Thanks for your reply.

If you are using VB 2008 and VS setup project to deploy your service, I
want to introduce you another way to you. This is the easiest way. You just
need to:

1. Add service assembly as custom actions in setup project. (Remove all the
CustomActionData)

2. In setup process installer, set account as User.

3. Clear UserName and Password in setup process installer.

After doing above steps, run the setup MSI file and it will bring a dialog
box which can be used to pass account name and password. Please try this
solution first and let me know if it meets your need. Otherwise, I will
continue with you on the previous solution.

Here I provide quick answers to your questions:

1) suppose I want to hide the password a user types in.
VS does not native support it. You have to use other tools to do it, like
ORCA. Here is an example:
http://www.codeproject.com/KB/install/setupprjpwd.aspx

2) What if the username has a space in it?
Use /f1="[EDITC1]\" /f2="[EDITC2]\" instead. For more information, please
visit following page:
http://msdn.microsoft.com/en-us/library/2w2fhwzz(VS.80).aspx

3) What if the password has a space or other special char in it?
Same answer to question 2.

4. What if designer overrides your code to set username and password?
You should not write any code in designer.cs file. You should write it in
installer.cs file. You can open it by pressing F7 when in the installer
designer. Override OnCommitted method from the base installer and put your
code in it.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
S

Smurfman-MSDN

Hongye,
I revamped the project based on your new suggestion.
(of course I already had the setup assembly added to my custom actions for
"install/uninstall/commit/rollback" the only setting that is present is
"InstallerClass" set to true - I did not touch this.)
I was not 100% sure by what you meant by the "setup process installer" but I
managed to find what you were referring in the ProjectInstaller.vb [Design].

In there i have the two installer objects (built by default)
1) ServiceProcessInstaller1
2) ServiceInstaller

I looked at the settings for ServiceProcessInstaller1 and found account as
you mentioned. I think it was already set to user (based on my other steps I
was trying a couple of days ago - where we were attempting to override the
install method in the code).

However - this statement did not hold true -
3. Clear UserName and Password in setup process installer.

There were no such settings.

I compiled and installed to test.

Here is where I am at.

The installer runs, the prompt for Username and Password comes up exactly as
you mentioned.

A few things - and perhaps this is where ORCA can help me you will have to
confirm if this is true.

1) john brown is not a valid name for the installer username, as john brown
is not a user on the computer (even though he is). I found that I MUST enter
john brown as .\john brown and it runs fine. is there a fine tune to this in
orca.

2) The Prompt Box is displayed in the top left corner of the computer screen
and if you were doing something else ie looking at a web page on Internet
Explorer the dialog box is burried behind and sits in the top left corner. I
would like it to come to the front of the install window as its parent - what
I found was that the isntaller was just sitting there waiting for imput, but
if I clicked the installer window the prompt window was not displayed - i had
no idea where it was until I minimized everything. (in other words it was
not tied to the installer package)

3) If I enter the username / password wrong the installer fails and rolls
back. Not giving me a chance to try again. Can I change this behavior.


NOW if all of this means I have to go back to the Custom Install dialog box
ie EDITC1 and EDITC2 (as f1 and f2

I was able to get this logic to work...partially using this logic - which is
now commented out.

'Public Overrides Sub Install(ByVal stateSaver As
System.Collections.IDictionary)
' Dim serviceProcessInstaller1 As
System.ServiceProcess.ServiceProcessInstaller = Nothing

' For Each installer As Object In Me.Installers
' Try
' serviceProcessInstaller1 = DirectCast(installer,
System.ServiceProcess.ServiceProcessInstaller)
' Catch exc As Exception

' End Try
' Next
' If serviceProcessInstaller1 IsNot Nothing Then
' serviceProcessInstaller1.Account =
System.ServiceProcess.ServiceAccount.User
' serviceProcessInstaller1.Username = Context.Parameters("f1")
' serviceProcessInstaller1.Password = Context.Parameters("f2")
' End If

' MyBase.Install(stateSaver)
'End Sub

However this is where I was not getting the proper results - such as a space
in the username and perhaps understanding now the .\user name versus the user
name

Give me your thoughts.
Much appreciated.

J

"Hongye Sun [MSFT]" said:
Hi J,

Thanks for your reply.

If you are using VB 2008 and VS setup project to deploy your service, I
want to introduce you another way to you. This is the easiest way. You just
need to:

1. Add service assembly as custom actions in setup project. (Remove all the
CustomActionData)

2. In setup process installer, set account as User.

3. Clear UserName and Password in setup process installer.

After doing above steps, run the setup MSI file and it will bring a dialog
box which can be used to pass account name and password. Please try this
solution first and let me know if it meets your need. Otherwise, I will
continue with you on the previous solution.

Here I provide quick answers to your questions:

1) suppose I want to hide the password a user types in.
VS does not native support it. You have to use other tools to do it, like
ORCA. Here is an example:
http://www.codeproject.com/KB/install/setupprjpwd.aspx

2) What if the username has a space in it?
Use /f1="[EDITC1]\" /f2="[EDITC2]\" instead. For more information, please
visit following page:
http://msdn.microsoft.com/en-us/library/2w2fhwzz(VS.80).aspx

3) What if the password has a space or other special char in it?
Same answer to question 2.

4. What if designer overrides your code to set username and password?
You should not write any code in designer.cs file. You should write it in
installer.cs file. You can open it by pressing F7 when in the installer
designer. Override OnCommitted method from the base installer and put your
code in it.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).

This posting is provided "AS IS" with no warranties, and confers no rights.
 
H

Hongye Sun [MSFT]

Hi J,

Thanks for your reply.

The built in dialog for service user name and password is a convenient way
to set service user account. It has no capacity to be customized as you
want. None of your three problems can resolved under this means.

If you go back to the Custom Install dialog box method, it really can solve
most of your problems. However, it still has some limitation. Here are my
explanations:

1. ".\john brown" and "john brown" problem
Actually, this constraint is also required in service management console.
If you want to work around it, you have to write the logic to pre-check the
name and add proper prefix before passing it to service process installer.

Here is a sample code:
-----------------------
Dim username As String = MyBase.Context.Parameters.Item("f1")
If Not (String.IsNullOrEmpty(username) OrElse username.Contains(Of
Char)("\"c)) Then
username = (".\" & username)
End If
-----------------------

In addition, the space problem should already been fixed if you change the
CustomActionData to: /f1="[EDITC1]\" /f2="[EDITC2]\". Please let me know if
it does not work.

2. When username / password wrong, the installer fails and rolls back.
You are still facing this issue in custom install dialog box method. Here
are possible workarounds:

One workaround is to customize the NEXT button event to do the validation.
However, this method is very complicated and it requires you to use C++ and
be familiar with ORCA. For more information, please visit the following web
page:
http://www.codeproject.com/KB/install/vsSetupCustomDialogs.aspx

Another workaround is to pop up a dialog box by yourself, instead of using
MSI dialog box. The general steps are:

1) Add a windows form with user name and password textboxes and OK and
Cancel buttons.

- Set the DialogResult property of both buttons.

- In OK button's click event, check the validity of the user name and
password. If it fails, set form's DialogResult value to None to prevents
the dialog box to return.

- Create two public properties of user name and password in the form to let
installer to get them after dialog returns.

2) In the ProjectInstaller.vb method Install method, instance the form and
invoke its ShowDialog method.

- Get its returned DialogResult, if it is OK, get the user name and
password from form and set it to serviceprocessinstaller.

- If its return value is other than OK, easiest way is to throw an
exception to make installation rollback.

I can send a sample project to you for the second workaround. Please send
an email to my mailbox (e-mail address removed), remove 'online.', if
you need it. Thanks.

Have a nice day.

Regards,
Hongye Sun ([email protected], remove 'online.')
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
(e-mail address removed).


This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top