Change the Description of my Windows Service - c#

According to this answer it seems that there is no official way to set a version for a Windows Service. However this can be done by inserting it into its Description or DisplayName.
I would like to be able to change that version number without needing to delete and reinstall the service. But I couldn't find a way to set the Description except for in the installation itself.
So, is there a way, and what is it, to change a Service's Description without reinstalling it?
Preferably using .Net. The Service itself is also .Net if that matters.

This can be accomplished using the SC.exe utility with the command:
sc description <ServiceName> "Any Description you like."
This command could be called from a command window opened as administrator or from a .Net application provided that the service has already been created.

Though this is not a pure .NET solution, it can be implemented in .NET, and it is one of the only MS-supported methods of reconfiguring a service. Plus, it doesn't require direct registry manipulation (best avoided if possible).
You can change the description of a Windows service by using the Windows command-line service controller utility, SC.exe.
You can exec the command you need to execute from your .NET code, or call it from a shell or script, such as CMD.exe or PowerShell.
sc.exe config YourServiceName displayName= "Your service description..."
Note:
Detailed information on the SC config command can be found here: MS Docs SC Config man page
YourServiceName is the actual service name of your application, not it's current DisplayName (unless, of course, they're identical)
If your DisplayName is more than one word, it needs to be wrapped in quotes
There must be no space between the word "displayName" and the equals sign
There must be one or more spaces between equals sign and the beginning of your desired service description

If what you need is the version number of the executable for the Windows service, and the executable is a .NET assembly, then retrieve the path to the service executable, and then retrieve the version from that executable/assembly.

Related

How to uninstall MSI using its Product Code in c#

I know We can uninstall a windows application using its MSI by passing command arguments as follows,
Process p = new Process();
p.StartInfo.FileName = "msiexec.exe";
p.StartInfo.Arguments = "/x \"C:\\MyApplication.msi\"/qn";
p.Start();
But what i want to know is how can we uninstall the application without using MSI ? In the above scenario I should have the MSI in the specific location to uninstall this application, If i could unstaill using product code then I dont need to have the MSI in the target machine.
According to MSDN, You can uninstall it using the product code:
msiexec.exe /x {your-product-code-guid}
When you use the product code, it uses the cached MSI from C:\WINDOWS\Installer.
Along the lines of PhilmE's answer, Windows Installer XML (WiX) ships the Microsoft.Deployment.WindowsInstaller interop library as part of Deployment Tools Foundation (DTF). This skips the COM interop and encapsulates the Win32 API instead.
using Microsoft.Deployment.WindowsInstaller;
public static void Uninstall( string productCode)
{
Installer.ConfigureProduct(productCode, 0, InstallState.Absent, #"REBOOT=""R"" /l*v uninstall.log");
}
Probably for your case, knowing the "/x" Parameter was sufficient. Two remarks on that:
More secure is adding a "REBOOT=R" part to your commandline. And you can add a logfile path:
msiexec /x "..." /qn REBOOT=R /L*v "c:\mylogdir\mymsi.log"
Second, don't try to change anything to "the caching". You don't need even to understand it. If the cached package would be broken, a regular uninstallation is no longer possible, which could bring the computer in a "support needed" state.
Because your question was originally talking about C# .. You don't have to use msiexec for it:
a) Use the original C/C++ API with the function MsiInstallProduct() or MsiConfigureProduct().
MSDN ref:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa370315(v=vs.85).aspx
You have to use interop to use that in C#.
or b)
Use the Windows Installer Object.
For example, this related case was already answered here in stackoverflow:
Programmatically installing MSI packages
But using this function needs the physical package, also for uninstallation.
With a slight indirection, here is the better code for uninstallation:
First, add a reference to COM object "Microsoft Windows Installer Object Library" to your project.
using WindowsInstaller;
public static class MyMsiLib
{
public static void Uninstall(string productCode)
{
Type type = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installer = (Installer)Activator.CreateInstance(type);
installer.UILevel=msiUILevelNone;
installer.ConfigureProduct(productCode, 0, msiInstallStateAbsent);
}
}
The UILevel property before is set here hardcoded to determine the UI level silent as you seem to want. Same for other properties. See MSDN documentation e.g. mentioned in the link above.
Of course "real programmers" work with the original API instead of the "Installer Object" :-)
But for small purposes it is sufficient. And easier.
This command works on the command line:
msiexec /x {3A40307D-6DF2-4412-842F-B1D848043367} /quiet
I haven't tried it in C#, but replacing your arguments with the key shown above should work. You can find the GUID in the registry key for the app you are trying to uninstall.

Consuming a WCF Service that is hosted in a Windows Service from outside solution

I've set up a WCF Library hosted in a Windows Service using the following walk-through:
http://msdn.microsoft.com/en-us/library/ff649818.aspx
The consumer winforms is in the same solution, which is located locally on my work PC's C: drive.
The walk-through works i.e. the winforms button gives me the correct answer.
If I create a new Solution on the C-Drive with a single Windows Forms project in it I cannot successfully add a service reference to this running service, i get the following message:
The detailed message says the following:
The URI prefix is not recognized. Metadata contains a reference that
cannot be resolved: 'net.tcp://localhost:8526/Service1'. Could not
connect to net.tcp://localhost:8526/Service1. The connection attempt
lasted for a time span of 00:00:02.0020000. TCP error code 10061: No
connection could be made because the target machine actively refused
it 127.0.0.1:8526. No connection could be made because the target
machine actively refused it 127.0.0.1:8526 If the service is defined
in the current solution, try building the solution and adding the
service reference again.
Why can I add this Service Reference ok to a project within the same Solution as the Service but not from a project in a different solution?
EDIT
My colleague found an error in the MSDN article - I have detailed his find HERE
The step by step walkthrough article at MSDN ends unfortunately where it gets interesting, so let's continue here. Because there are many possibilities which may cause the error, I've described several options (= scencarios which may cause the issue) below, which should help troubleshooting:
1st option: Try to specify
net.tcp://localhost:8526/Service1/mex
when you add the service reference to your new client - ensure that the service is installed and running before you do that.
Explanation: The suffix "mex" stands for "metadata exchange" and allows Visual Studio to download details of the WCF contract. This suffix is also used in the walk-through example, it was added automatically (you will see it in the Address field if re-open the added service reference by right-clicking on "Configure Service-Reference...").
2nd option: What I noticed when I tested the walk-through is that it helps sometimes to right-click on the service reference and select in the contect menu "Update Service-Reference".
After a while in the systray you can see the balloon message "Your service(s) have been hosted.", after which you can start the client within the same solution. In this case, the service has been temporarily created but is not deployed permanently - which means, if you stop debugging, it is removed. As a result, you can't use this service from a remote PC, it is just visible within the solution in Visual Studio. Visual Studio internally invokes the tool
WcfSvcHost.Exe /Service:<Service1Binary> /Configuration:<Service1Config>
supporting it with the right parameters to register the service properly (you can find this tool in Visual Studio's Common7\IDE subdirectory, and there is also WcfTestClient.Exe available - a tool which acts as a client, very useful to debug WCF).
For instance, if you have stopped debugging, and launch the client.exe from Windows Explorer outside of Visual Studio, then it does not find the service and you're getting exactly the error message you have described in your question.
There are two interesting links regarding this matter at Microsoft:
Problem with Metadata Exchange and Publishing Metadata
Note that this is different from deploying it as described in the 3rd option.
3rd option: Have you used InstallUtil to deploy the service? In this case it can happen that you have accidently removed the [...]/bin/Debug subdirectory and the service fails to start, because the .EXE file is missing.
Note: This can be avoided if you're using a ServiceInstaller project, which copies the binaries before the service is registered. Or - if you want to use InstallUtil for simplicity - you can copy the service binaries to a target directory (including the .config files and .dlls) before you register it.
4th option: If you run the service on a remote computer, you need to specify the proper host name or IP address of the host instead of localhost, and you need to ensure that the personal firewall (windows firewall or 3rd party) doesn't block the port 8526 (the port number which was used in the example). Specify an exception to allow this port for incoming and outgoing traffic.
5th and final option (UPDATE): Naming conflict - Service1 is the service but also the class name in the Wcf library. Either fully qualify the class name you're using from the WCF library in the service, i.e. WcfServiceLibrary1.Service1 or rename the class. Whytheq has found it himself with a colleague and as posted it here.
More reading: Check out this article, which I've found recently: "WCF: a few tips". It explains very well troubleshooting WCF. The only change I would made to the console hosting example is to replace the using statement by a
ServiceHost host = new ServiceHost(typeof(Service));
try
{
host.Open();
Console.WriteLine("WCF Service is ready for requests." +
"Press any key to close the service.");
Console.WriteLine();
Console.Read();
Console.WriteLine("Closing service...");
}
finally
{
if (host!=null) {
host.Close();
host=null;
}
}
If you want to know more about the reason why, check out this article: "Proxy open and close".
You can get round this as follows:
Browse the service's WSDL URL and save the WSDL to a local file.
Then make the following changes to the file:
Remove the namespace prefix from the name used for the wsdl:binding i.e. change
name="wb:wsclocks-inboundSoapBinding" to be
name="wsclocks-inboundSoapBinding"
Change the binding attribute of the wsdl:port attribute to match, and also remove the namespace prefix from the value of the name attribute, so it is just wsclocks-inbound.
Then run svcutil /o:Client\WBServices /noConfig

Deleting a service

I created an installer and custom actions for a service.
On first install I managed to install the service , but when I tried running the service I got
an Error :Windows installer service cant start Error 193:0xc2
I have tried deleting this service in myriad of ways, yet on install I am still getting an error message 1001 The specified service already exists.
I deleted the service directly from the registry , but this does not seem to have worked.
I have tried
sc delete [service] --> The specified service does not exist as an installed service.
The service is not showing up in the registry nor is it present in installed services.
Any other thoughts or options would be appreciated
I have used this commands in a bat file that runs every time reinstalling. Try this and see.
set path=%path%;%SystemRoot%\Microsoft.NET\Framework\vXXX
InstallUtil /u YourService.exe
InstallUtil /i YourService.exe
net start "Service name"
If you want to delete/uninstall/remove a Windows service, perhaps left from an incomplete installer, you can use the sc command from an Administrator control prompt:
sc delete [servicename]
"sc delete" Deletes a service subkey from the registry. If the service is running or if another process has an open handle to the service, then the service is marked for deletion.
EDIT
I have tried sc delete [service] The specified service does not exist
as an installed service.
Probably restarting the machine would fix this.
sc.exe stop serviceName
sc.exe delete serviceName
and reboot the your VM\PC
This complaint may be coming from the installer, not from Windows.
I had this same issue earlier this year, I installed a service from an MSI file, which fouled up somewhere along the line. I uninstalled the package and tried reinstalling through the installer and got the same message as you did, that the service already existed. Frustrating. It didn't show up as an installed package at all anymore, nor did it show up in the service list.
It ended up that the MSI file did not clean up after itself properly during uninstall, but that I could manually manipulate this database and remove the information myself using MSIZap.exe. You need the Windows SDK to get at this program. There may be other ways, but I don't know of them.
You will need the package guid of your installation package to remove it using MSIZap. In the same directory as MsiZap.exe, you will find another application, MsiDb.exe. Run that, point it at your MSI file, point it to some empty directory to store some exports select the "Property" table, select the "Export" radio button and hit the "OK" button. Open the "Property.idk" file that was generated by MsiDb.exe in any text editor. Look in your text for a line that says "ProductCode". The GUID that follows is what you will feed into MsiZap, brackets and all. Now you will simply (bwahaha... yeah right) enter:
msizap T {product code}
Where "{product code}" is replaced by the GUID you found. This removes all traces of your product from the MSI database in windows, which should shut the installer up.
I realize that all of this is a ridiculous pain in the butt. I don't understand why finding a product code is such a trial. But, I suppose if the uninstaller worked, you wouldn't have to do its job for it now. There really might be a simpler way to do all of this, but I haven't found one. Once I found something that worked, I was over it.
As a final note, what caused this error for me was leaving the services list open during uninstall. An uninstaller which isn't paying attention could ignore some exceptions and leave pieces of itself lying about. I was lucky, the poorly behaving uninstaller was my own. And by the way, to appreciate just how much garbage is left over from uninstallation, check out this article.
I'm not sure if I had the same problem that you had, but if so, I hope this helps. If you need clarification, ask and I'll update the answer. If I'm up a tree and this has nothing to do with your problem, I apologize.
Try with Powershell and Wmi:
(gwmi win32_service -filter "name='yourservicename'").delete()
Make sure services.msc window is closed. Sometime that messes up the service deletion. I am not sure if this will help, you should not have touched the registry!
Perhaps you tried to delete the service while it's running? In that case you might need to reboot to clear things up.

Installed Win Service not displaying in Service Manager

I have a Windows Service created in c#.
It's relatively simple compared to some of the other ones that I've worked on.
I built a setup project to install it for some testing.
I added the primary output from the service project and all the dependencies were added correctly.
I went to View > Custom Actions and added my Primary output to Install, Commit, Rollback, and Uninstall.
The project built and I right clicked the project and clicked Install.
The installation came back successful, I can view the service on the control panel under Add/Remove programs, but when I go into the Service Manager... nothing...
Can anyone provide some insite or anything else that may cause a successfuly installed service to NOT display on the Service Manager.
Forgive me if this goes without saying, but you haven't mentioned what code you are executing in your custom actions. Your service assembly must have a class which derives from System.Configuration.Install.Installer, and that class must have the [RunInstaller(true)] attribute on it. Within that class, you will need to create an instance of System.ServiceProcess.ServiceInstaller and System.ServiceProcess.ServiceProcessInstaller, set the appropriate parameters on those instances, and add them to the Installers collection. The ServiceInstaller and ServiceProcessInstaller MSDN pages have a very basic example, but it should be enough to get you there if this is what is needed.
Make sure you had provided some value in "Display name" property.
Use the following command "sc query <service_name>" from command prompt to see whether your windows service got properly installed. If you are not sure on the service name use the following command "sc query state= all >c:\ServicesList.txt" after executing this command search the ServicesList.txt in your C:\ drive.
If that too doesn't work try looking for the service name in registry under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
You said you added your primary output to Install, etc. But did you create an Installer derived class to do the actual installing of the windows service? I'm not talking the setup project itself, but in your project there should be an installer class that actually does the service install for you.
I had a post on my blog about creating a framework for easy installable services, it has examples on creating the isntaler class.
http://blackrabbitcoder.net/archive/2010/10/07/c-windows-services-2-of-2-self-installing-windows-service-template.aspx
In my case, solution of the problem was simple, i forgot to add access modifier 'Public' to the class. After adding access modifier, service is visible now in services list.

How can i start windows service automatically

i try to develop a windows service. My win service must run if windows 7 stars up. How can i do?
Change the startup type of the service to Automatic.
You should create an installer application for your service (if you haven't already) and you can set this option in there so when its installed it is pre-configured this way. See Walkthrough: Creating a Windows Service Application in the Component Designer
Set the startup type to "Automatic".
You set service startup to "Automatic" in service control manager. Not a programming question, by the way.
Actually make sure your installer sets the startup type on Automatic ;) Add dependencies as needed so that you start after dependent services.
If you want to set this programmatically (i.e. during the development phase) then this is set in the properties for the Installer (StartType), which you will also need.
You could configure the service through the command line using the "SC" utility provided by Windows; it comes with XP and later.
sc create MyServiceName binPath= <path
to service exe file> start= auto
DisplayName= MyServiceDisplayName
sc description MyServiceName "This is
my service's description"
The spaces after arguments (like binPath= ) are important.

Categories

Resources