What is the easiest language to build Windows services in?
Easiest in this case would be defined as least amount of code, and lowest point of entry into the language.
At the risk of stating the obvious, if you have any C/C++/Java background, I think C# offers you the lowest point of entry.
Assuming you're using Visual Studio 2008, you can follow these steps:
Open Visual Studio 2008, and select the File|New|Project menu option.
In the New Project dialog...
Select the Visual C#|Windows node in Project types
Select the Windows Service template
Enter a name and location for your project
Press OK
At this point, you have all the basics for your Windows service. The Program.cs file contains the Main() method for your service, and Service1.cs defines the System.ServiceProcess.ServiceBase component that is your new Windows service.
In the Property Grid for your Service1 component, consider setting the following properties at a minimum:
(Name) - give your object an intuitive name, e.g., ServiceExample
AutoLog - set to false to prevent events from being written by default to the Application event log (Note: I'm not saying you shouldn't log service events; I just prefer writing to my own event log instead of the Application log - see below)
CanShutdown - set to true if you want to handle system shutdowns
ServiceName - defines the name by which your service will be known to the Service Control Manager (SCM)
In the code for ServiceExample, the OnStart() and OnStop() virtual functions are stubbed out. You'll need to fill these in with whatever your service needs to do obviously. If you changed the CanShutdown property to true, you'll want to override the OnShutdown method as well. I've created an example below illustrating the use of these functions.
At this point, the ServiceExample service is essentially complete, but you still need a way to install it. To do this, open the ServiceExample component in the designer. Right-click anywhere in the designer panel, and select the Add Installer menu option. This adds a ProjectInstaller component to your project, which contains two additional components - serviceProcessInstaller1 and serviceInstaller1.
Select the serviceProcessInstaller1 component in the designer. In the Property Grid, consider setting the following properties:
(Name) - give your object an intuitive name, e.g., serviceProcessInstaller
Account - select the LocalService account as a minimum, but you may have to use the NetworkService or LocalSystem account if your service requires more privileges
Select the serviceInstaller1 component in the designer. In the Property Grid, consider setting the following properties:
(Name) - give you object an intuitive name, e.g., serviceInstaller
Description - the service's description which will show up in the SCM for your service
DisplayName - the friendly name for your service which will show up in the SCM for your service
ServiceName - make sure this is the same name that you selected for the ServiceName property of your ServiceExample component (see Step 4)
StartType - indicate if you want the service to start automatically or manually
Remember that I said I prefer writing events to my own event log instead of the Application event log. To do this, you'll need to replace the default EventLogInstaller in your ProjectInstaller with a custom one. Make your code for your ProjectInstaller look like this:
using System.Diagnostics;
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
public ProjectInstaller()
{
InitializeComponent();
EventLogInstaller installer = FindInstaller(this.Installers);
if (installer != null)
{
installer.Log = "ServiceExample"; // enter your event log name here
}
}
private EventLogInstaller FindInstaller(InstallerCollection installers)
{
foreach (Installer installer in installers)
{
if (installer is EventLogInstaller)
{
return (EventLogInstaller)installer;
}
EventLogInstaller eventLogInstaller = FindInstaller(installer.Installers);
if (eventLogInstaller != null)
{
return eventLogInstaller;
}
}
return null;
}
}
At this point, you can build your project to get your Windows service executable. To install your service, open the Visual Studio 2008 command prompt, and navigate to the Debug or Release directory where your executable is. At the command prompt, type the following: InstallUtil ServiceExample.exe. This will install your service on the local machine. To uninstall it, type the following at the command prompt: InstallUtil /u ServiceExample.exe
As long as your service is not running, you can make changes to your service and re-build, i.e., you do not have to uninstall your service to make changes to it. However, you will be unable to overwrite the executable with your fixes and enhancements as long as it is running.
To see your service in action, open the ServiceExample.cs file and make the following changes:
using System.Diagnostics;
public partial class ServiceExample : ServiceBase
{
public ServiceExample()
{
// Uncomment this line to debug the service.
//Debugger.Break();
InitializeComponent();
// Ties the EventLog member of the ServiceBase base class to the
// ServiceExample event log created when the service was installed.
EventLog.Log = "ServiceExample";
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("The service was started successfully.", EventLogEntryType.Information);
}
protected override void OnStop()
{
EventLog.WriteEntry("The service was stopped successfully.", EventLogEntryType.Information);
}
protected override void OnShutdown()
{
EventLog.WriteEntry("The service was shutdown successfully", EventLogEntryType.Information);
}
}
Once you run your service with these changes, you can look at the ServiceExample event log in the Event Viewer and see the messages logged there.
EDIT: If you prefer to use the Application event log for your event logging instead of a custom one, simply make no changes to the ProjectInstaller.cs file. In addition, leave out the line that sets the Log property of the EventLog in the ServiceExample constructor. When you run your service, your log messages will appear in the Application event log.
I agree with everyone that has responded elsewhere, but I would say don't focus too much on the actual language, as long as you're working in the .NET framework, and there's a starter project for you, you're good to go. I've done several "Windows services" in the past, and developed them both in VB.NET and C#, with minimal code.
What I would recommend the OP to do is to learn how to build the installer package for it. Installing the service is as easy as executing "installutil.exe {drive}\path\to\file.exe", but when you have to do anything larger than deploying a "hello world" Windows service, it's good to know and understand how do deploy the service in a meaningful way.
Not to start a flame war, but I've "standardized" on using WiX for all my deployment packages, outside of doing old-school COM interop type stuff, since that's a brunt of work to get to install correctly. I'm anxious for the WiX team to develop the bootstrapper piece that allows you to put the prerequisites and the main msi into an EXE file which can be downloaded. They have it slated for 3.5, so I'll patiently wait, and use WinZip Self-Extracting executables for now.
For me, and I've only tried it a couple of ways, Visual Studio and C# was the easiest.
Visual Studio did all of the necessary service plumbing setup for the framework and I found C# very easy to learn, migrating from VB6, VB.NET and C.
With Visual C#, you'll find the most code samples on the net.
Combined with Visual Studio, and it's a walk in the park to get a basic Windows Service up and running.
Visual Studio also makes it a snap to create a MSI installer package.
That would be my pick
A windows service project in C# will give you a fully deployable service from the Visual Studio template with the click of a button. You just need to add your payload code.
Use the Visual Studio Service type project, use C# or VB.NET.
I personally prefer C#, but in general it's easy to understand the life cycle and code the logic at the desired stage.
Building an installer is also very easy.
Related
I need to build a vdproj on a jenkins machine (Windows Server 2012 R2)- which requires devenv.exe and not msbuild. I cannot install Visual Studio.
Devenv.exe is required for a MSI package.
I've used process monitor and determined I require one more file for devenv.exe to work : api-ms-win-core-heap-l2-1-0.dll
This file does not exist on any developer machine that we have, and devenv.exe/devenv.com works on the dev machines.
Where can I find this file?
Are there other ways to build a vdproj without Visual Studio?
Virtual Machine: This sounds a little hairy I am afraid. Could you use a virtual machine - with Visual Studio on it - to build the Visual Studio Installer project in question?
WiX et al: Converting to WiX or another deployment tool besides Visual Studio Installer Projects would solve the problem? Is this a very complicated installer? Using the WiX decompiler dark.exe to decompile an MSI to WiX markup can help you convert the installer to WiX format. Quite a bit of WiX knowledge will be required to do this successfully. Maybe something a consultant could do quickly? Depends on the complexity.
Windows API-set: As far as I know api-ms-win-core-heap-l2-1-0.dll is a Windows API-set, and not a real file or real dependency as such. These are new constructs in Windows. Try opening such an API-set file with Dependency Walker to see what they redirect to. Pretty mysterious these API-sets:
An API Set is a strong name for a list of Win32 APIs. The convention
for assigning a strong name to an API Set is to use what appears to be
a dll name. But the purpose of an API Set is to provide architectural
separation between the API Set's name and its associated host DLL
implementation for improved portability of your app, so you should
think of an API Set's name as just a unique character string, and not
as a dll name. For delay load, you use the name of the API Set.
API Sets rely on operating system support in the library loader to
effectively introduce a namespace redirection component into the
library binding process. Subject to various inputs, including the API
Set name and the binding (import) context, the library loader performs
a runtime redirection of the reference to a target host binary that
houses the appropriate implementation of the API Set.
The decoupling between implementation and interface contracts provided
by API Sets offers many engineering advantages, but can also
potentially reduce the number of DLLs loaded in a process.
On disk I find most of these API-Sets in %SystemRoot%\WinSxS and %SystemRoot%\System32\downlevel.
Nice article on the technical aspects of this new API-Set feature.
Complex Executable: Though devenv.exe is just an EXE file like any other, I do think there will be dependencies for Visual Studio Installer Projects beyond just dll import tables that will be very hard to set up properly, and what about future releases when all can fail without warning? (if something changes - Visual Studio has been a pretty moving target of late).
WiX Quick Start: Here are some of the best links that I have found over time for WiX:
Some WiX Quick Start Tips - chaotic, but
upvoted. Must have been helpful.
Helge Klein's real-world WiX sample - do check this out.
Rainer Stropek's WiX Samples on Github - can be very helpful.
From MSI to WiX by Alex Schevchuk - aging content, but excellent.
We are trying to install a Java program to run as a windows service. Of the various available options(JSW, YAJSW, Launch4J, procrun, WinRun4J etc etc), we would like to use srvany.exe and install it using InstallShield. The Windows documentation says ...
Using RegEdit : create a "Parameters" key for your service (e.g. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService\Paramaters\ )
Using RegEdit : within the newly created "Parameters" key , create a string value called Application and enter the full path to the application you are wanting to run as a service.
Is there a way to achieve this using InstallShield without using InstallShield's registry editor? Is there an InstallScript call that can take care of adding and removing "Parameters" to the srvany entry in the registry? The solution should to work for Windows 2008R2 & 2003R2.
Any help will be greatly appreciated.
Assuming you are using a Basic MSI project type, I find a combination of the ServiceInstall, ServiceControl and Registry tables to be a good solution. Due to the fact that ServAny is really just a thunking layer, the ServiceInstall table can't fully describe the service without a little assistance from the Registry table. Still, no custom actions should be needed and the MSI will be very solid and robust.
As we were not able to find a favourable solution within available time, we decided to not use the srvany.exe. We decided to use YAJSW and within InstallShield use "Text File Changes" to modify the wrapper.conf for the YAJSW to launch our java application.
I have two projects: Mvc3TestSvcRef & Mvc4TestSvcRef.
Mvc3TestSvcRef is from the ASP.NET MVC 3 template for an intranet application.
Mvc4TestSvcRef is from the ASP.NET MVC 4 template for an intranet application.
I'm trying to add a service reference.
In Mvc3TestSvcRef, I right-click the project (or the References folder) and choose Add Service Reference. I point to the URL, click Go. When the reference is resolved, I enter a namespace and click OK. As expected, I see the section added to config with the bindings and client tags completed.
I can import: "using Mvc3TestSvcRef.MySvcRef;"
And write code like:
using (var cl = new MyServiceClient())
{
cl.DoStuff();
}
In Mvc4TestSvcRef, I follow the same steps, but there is no system.servicemodel added to config. Additionally the import: "using Mvc4TestSvcRef.MySvcRef;" cannot be resolved.
I've tried this for MVC 4 from both Visual Studio 2010 and Visual Studio 2012.
Was there a major change to the process for adding service references in ASP.NET MVC 4 project type, or am I missing something or have corrupt install?
There was no code in Reference.cs, just comments:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.17929
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
I copied the reference.cs from the project that worked and modified the namespace, then added the section from the working project into the MVC 4 project and was still having an issue.
I tried to build and I got several warnings and an error. Failed to generate code for the service reference 'MySvcRef'. Please check other error and warning messages for details.
That led me to this article: Service Reference Error: Failed to generate code for the service reference
So I unchecked the Reuse types in all referenced assemblies from the Advanced section.
This seems to have generated a good service reference. Although, I should point out that if you have something in say System, like System.TimeSpan for example, that is used as a DataMember in one of your DataContracts, the reference will now have TimeSpan in the reference namespace, not from it's origin. So, the client would see any System.Timespan properties as ReferenceNameSpace.Timespan, which may throw off comparisons and such. The better answer here is to include specific assemblies from the reference and don't check the box for System.Web.Http, as pointed out in the comments below
I don't know if it is too late, but here is the solution "When you add the reference, on advanced setting remove the reuse types checkbox."
I am starting out with TDD using Moq to Mock an interface that I have:
public interface IDataService
{
void Commit();
TopListService TopLists { get; }
}
From the samples I have seen I would expect SetupGet (or Setup) to appear in the intellisense when I type
var mockDataService = new Mock<IDataService>();
mockDataService.
But it is missing. Could someone suggest why?
Make sure you are using the latest version of Moq.
It sounds like a problem with your project setup, rather than with Moq.
Check that your source code compiles successfully (or Mock<IDataService> will be meaningless).
Check that your test project is referencing Moq.
Check that the Mock you're using is Moq.Mock and not from another namespace.
Otherwise I'd put money on it being Visual Studio. Close it down, open it up again, see if Intellisense wakes up.
If you can type the code that ought to work and make it build, then it's definitely Visual Studio playing up.
I have a service [C# exe] and I can deploy it using Visual Studio Command Prompt window typing "InstallUtil MyService.exe". Now how to do the same thing from Install Shield 2009 Premier(and also start the service as we do manually)?
There are two main options. The easy one, but not so recommended, is to add MyService.exe as the key file of a component, and mark the component as an Installer Class. This will invoke InstallUtilLib.dll (which functions similarly to InstallUtil.exe) to install this component. However all versions of InstallUtilLib has no handling for rollback, and will yield an incomprehensible message box window if there's any error; these are the reasons to prefer other approaches.
The other option starts the same way, with MyService.exe as the key file of a component. Then open the advanced options of the component and use the Install NT Services and Control NT Services nodes to install and start the service respectively. The potential downsides are that you'll need to know the internal name of the service to do this, and I'm not certain whether it works for all C# services.