 |
|
|
 |
|
|
Hi, would you mind providing an example of how you would use the command line switches to set properties of the underlying ServiceProcessInstaller object.
Thanx...
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
First of all, THANK YOU for your article. It is really useful.
I have one little improvement. In case of your code user must know what switches service executable accepts. I suppose it's a good idea to show all acceptable switches to user when the service was started from console, not from SCM. The method that I use to determine how service was started is quite simple — checking the value of Environment.UserInteractive.
Code:
static void Main(string[] args) { // Started by user if (Environment.UserInteractive) { // Show version information Console.Write(Environment.NewLine + System.Reflection.Assembly.GetExecutingAssembly().FullName + ".");
// Parsing command line if (args != null && args.Length >= 1) { if (args[0].ToLower() == "/i") { // InstallHelper with /u switch set adds CRLF here, but with /i switch set it does not. So... Console.WriteLine(); installMyService(); return; } if (args[0].ToLower() == "/u") { uninstallMyService(); return; } }
// Show usage Console.WriteLine(Environment.NewLine + Environment.NewLine + "Usage: MyService.exe [/i | /u]" + Environment.NewLine + Environment.NewLine + "Where:"); Console.WriteLine(" /i - install service;"); Console.WriteLine(" /u - uninstall service."); } // Started by SCM else { ServiceBase.Run(new MyService()); } }
static void installMyService() { try { // "/LogFile=" - to suppress install log creation ManagedInstallerClass.InstallHelper(new string[] { "/LogFile=", Assembly.GetExecutingAssembly().Location }); } catch { } }
static void uninstallMyService() { try { // "/LogFile=" - to suppress uninstall log creation ManagedInstallerClass.InstallHelper(new string[] { "/u", "/LogFile=", Assembly.GetExecutingAssembly().Location }); } catch { } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
Firstly, very nice simple solution - thanks for sharing that tip. I decided to try it out and came up with the idea of installing the service if it's not already installed (i.e. just double click it in Explorer, and confirm whether or not to install it). Worked well for me, using this code:
if (args.Length == 0) { ServiceController sc = new ServiceController("AshFMS2"); try { string s = sc.Status.ToString(); // throws exception if service does not exist } catch { if (System.Windows.Forms.MessageBox.Show("Install this service? ", "Confirm", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes) { SelfInstaller(SelfInstallOptions.Install); return; } } } else { switch (args[0]) { case "-i" : case "/i" : SelfInstaller(SelfInstallOptions.Install); return; case "-u" : case "/u" : SelfInstaller(SelfInstallOptions.Uninstall); return; } }
BTW SelfInstaller is my method containing code based on yours.
------------------------------ My Latest CP article: SmartPager - a Flickr-style pager control with go-to-page popup layer.
modified on Saturday, December 22, 2007 12:01:11 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Very good, Ashley. Nice extension of the concept. It would be interesting to make your code detect the version of the installed service and upgrade it on demand.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I think if you stop the service you can replace the .exe no problem.
cheers Ashley
"For fifty bucks I'd put my face in their soup and blow." - George Costanza CP article: SmartPager - a Flickr-style pager control with go-to-page popup layer.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
..When I try to start the command line installed service from the Computer Management tool, I get a Services message box (!), quoting "Could not start the MyCLI_Service on Local Computer. Error 3: The system cannot find the path specified." Huh? ..The CLI Install appears to have gotten the correct path, so what gives? ..The Uninstall appears to work. (I have done it several times. ..The original project was setup as a Windows Service project and the solution included a setup/deployment project which got the service into the Services list of the Computer Management tool. This original version of the service could be started, paused (required a property setting change), and stopped.
Look sharp, be sharp, see sharp!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I suppose I would start by looking around in the registry at HKLM\System\CurrentControlSet\Services to see how your service got registered. Is the ImagePath value OK for your service?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The ImagePath appears okay. However, I am using a fake drive/path, that is, I have substituted a C: path with J: drive. I will try placing all the files in a real path on the C: drive. Will update results. Thanks for feedback. Ricky
Look sharp, be sharp, see sharp!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It works!!! No substituted drive pathing allowed. *.msi files have similar problems. Now I can breathe and thank you for a great article. Ricky
Look sharp, be sharp, see sharp!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The EXE takes command line parameters. If the first parameter is "INSTALL" then it does:
System.Diagnostics.Process.Start ( "INSTALLUTIL" , "\"" + System.Windows.Forms.Application.ExecutablePath + "\"" ) ;
With similar code for UNINSTALL. START and STOP can also be done from the command line.
(I chose this method when I wrote my first Windows service three years ago and haven't revisited the code since, I guess I'll have to now.)
-- modified at 9:33 Thursday 29th November, 2007
SWEET! Thanks!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Good job.
I do agree with all your reasons for improving standard service installation approach. Using InstallUtil.exe in the way MS intended is a pain. I think your approach is great however you can go even further (and in "more standard" way) by directly addressing the issue of "not knowing" InstallUtil.exe path. After all you have already guessed where to get help - Reflection.
The following code represents complete solution for service self-installation. It uses InstallUtil.exe thus all its functionality (e.g. logging to file) is still available.
I've been using this approach for more than a year and I had no problems with it. It is no surprise as it is exactly the way of service installation, which is regarded as a standard service installation. I just use a couple of tricks to get path information at runtime and one of these tricks is the same as yours.
BTW AppDomain.ExecuteAssembly even allows you to see InstallUtil.exe console output as yours. Also note that InstallUtil.exe is executed in the same process space as the service application so no new (external) process is started.
string installUtil = Path.Combine(Path.GetDirectoryName(typeof(string).Assembly.Location), "InstallUtil.exe");
AppDomain dom = AppDomain.CreateDomain("temp");
if (args[0].ToLower() == "/i") { dom.ExecuteAssembly(installUtil, null, new string[] { "/LogFile=", "/LogToConsole=false", Application.ExecutablePath }); } else if (args[0].ToLower() == "/u") { dom.ExecuteAssembly(installUtil, null, new string[] { "/u", "/LogFile=", "/LogToConsole=false", Application.ExecutablePath }); }
Cheers, Oleg
|
| Sign In·View Thread·PermaLink | 4.20/5 (3 votes) |
|
|
|
 |
|
|
launching an external exe is ALWAYS inferior to a direct API call. I'd go with the article author's approach long before these fragile "launch the command line tool" approach.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
>launching an external exe is ALWAYS inferior to a direct API call.
You have just missed the point. You ARE NOT launching an external exe. AppDomain loads the assembly in the same process space.
However I do recognise that you may feel that direct API call is better.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Oleg,
Thanks for sharing your idea as well. Personally, I have never used the AppDomain (inexperience with the namespace is the reason) however, this is a good example of the use.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks, Oleg. The best part about posting a new article is that I always seem to learn more than I teach.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I added you suggestion to a service and when I use the -i command line argument the method runs succesfully. However, the service never shows up in the services list and can't be started uing net start servicename.exe.
What am I missing?
This method doesn't give the service a name or tell is how to start ie manual auto
thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Two things to do, SMESSER:
1. Make sure that the output type of your service executable is a Console application. 2. When you run with the -i switch in a CMD console, you should see the output of the installer.
Is the installation rolling back for some reason? The ManagedInstallerClass does a transacted installation so if something goes wrong, you should see the reason in the console window. Look for the word "rollback" in the text.
Kevin Kevin Hazzard's Brain Spigot
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Update: I just reread your assumption. I thought that you were inplying that the service installer code was not needed with your method. I am sure once I add that it will work as expected.
First, just in case it makes a difference I am running on Vista. I still don't see the installed service show up in the service manager.
Here are the contents of both log files.
1.Running a transacted installation.
Beginning the Install phase of the installation. See the contents of the log file for the C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe assembly's progress. The file is located at C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.InstallLog.
The Install phase completed successfully, and the Commit phase is beginning. See the contents of the log file for the C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe assembly's progress. The file is located at C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.InstallLog.
The Commit phase completed successfully.
The transacted install has completed.
2.Installing assembly 'C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe'. Affected parameters are: logtoconsole = assemblypath = C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe i = logfile = C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.InstallLog No public installers with the RunInstallerAttribute.Yes attribute could be found in the C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe assembly. Committing assembly 'C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe'. Affected parameters are: logtoconsole = assemblypath = C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe i = logfile = C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.InstallLog No public installers with the RunInstallerAttribute.Yes attribute could be found in the C:\WindowsService1\WindowsService1\bin\Debug\WindowsService1.exe assembly. Remove InstallState file because there are no installers.
Thanks
-- modified at 11:13 Saturday 24th November, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Looks like you don't have a ProjectInstaller included in your project. Do you have code anywhere in the project that looks like this?
[RunInstaller( true )] public partial class ProjectInstaller : Installer { public ProjectInstaller() { InitializeComponent(); } }
If not, see the reference to Mr. Nasr's article in my text. He shows you how to include such an installer. This is what the InstallHelper locates in your executable to begin the installation. I ran a service install on Vista to be sure it wasn't a problem on that OS. Everything was OK for me. Hope this helps.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
One of those little gems that leaves me wondering , why didn't i think of Lutz Roeder'ing the damn installutil!! This changes many things, believe me.
I always knew that, one day I would wake up and decide to live forever or die in the attempt.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Deploying services will finally stop being PITA
Thanks for sharing with the community!
--- http://sprdsoft.cmar-net.org - We Sprd You Softly Our site features contents and several images. All of this is very weird. In the end, war is not about who's right, it's about who's left.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |