<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/feed.xslt" media="screen"?>

<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>C# test.net</title>
	<atom:link href="http://csharptest.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://csharptest.net/</link>
	<description>another random site full of random stuff</description>
	<lastBuildDate>Tue, 22 Nov 2011 22:08:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How to build a multi-protocol REST service with protocol buffers, xml, and json in 10 minutes or less using protobuf-csharp-port</title>
		<link>http://csharptest.net/1062/build-a-rest-service-protocol-buffers-xml-json-using-protobuf-csharp-port/</link>
		<comments>http://csharptest.net/1062/build-a-rest-service-protocol-buffers-xml-json-using-protobuf-csharp-port/</comments>
		<pubDate>Tue, 22 Nov 2011 19:19:29 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Home]]></category>
		<category><![CDATA[Protocol Buffers]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[protobuffer]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[rpc]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=1062</guid>
		<description><![CDATA[In this post we are going to explore some great new features introduced in the latest release of the protobuf-csharp-port project. We are going to build both an IIS service to handle requests as well as a sample client. Let&#8217;s get started. Prerequisites Let&#8217;s start by fetching a copy of the protobuf-csharp-port binaries. We can <a href='http://csharptest.net/1062/build-a-rest-service-protocol-buffers-xml-json-using-protobuf-csharp-port/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>In this post we are going to explore some great new features introduced in the latest release of the <a href="http://code.google.com/p/protobuf-csharp-port/" target="_blank">protobuf-csharp-port</a> project.  We are going to build both an IIS service to handle requests as well as a sample client.  Let&#8217;s get started.</p>
<p><strong>Prerequisites</strong><br />
Let&#8217;s start by fetching a copy of the <a href="http://code.google.com/p/protobuf-csharp-port/downloads/list" target="_blank">protobuf-csharp-port binaries</a>.  We can manually download these and unpack them, use NuGet installed in VS2010, or download the <a href="http://nuget.codeplex.com/releases/view/58939" target="_blank">NuGet Bootstrapper</a>.  I&#8217;m going to use the later approach and download NuGet.exe and run the following command:</p>
<pre>
C:\Projects\ProtoService>NuGet.exe install google.protocolbuffers -x
Successfully installed 'Google.ProtocolBuffers 2.4.1.473'.
</pre>
<p><strong>Service Definition</strong><br />
With our only dependencies out of the way we are going to need to define some messages and a service.  We will start with a new project in visual studio, for ease of demonstration I&#8217;ve created an ASP.NET project.  To create our service definition we are going to create an empty text file and save it with a &#8220;.proto&#8221; extension.  Be sure to use the File->Save As&#8230; menu on this text file, click the down arrow next to the Save button and select &#8220;Save with Encoding&#8230;&#8221;.  Near the bottom choose &#8220;US-ASCII &#8211; Codepage 20127&#8243;.  This is required by the protoc compiler as it does not support text BOM (<a href="http://en.wikipedia.org/wiki/Byte_order_mark" target="_blank">Byte order mark</a>).  Now that we have a text file let&#8217;s create a message for the request and response and the service using the <a href="http://code.google.com/apis/protocolbuffers/docs/proto.html" target="_blank">protobuffer definition language</a>:</p>
<pre>
package ProtoService;

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}
message SearchResponse {
  repeated group Result = 1 {
    required string url = 2;
    optional string title = 3;
    repeated string snippets = 4;
  }
}
message ErrorResult {
  required string error_text = 536870911; //max field-id
}
service SearchService {
  rpc Search (SearchRequest) returns (SearchResponse);
}
</pre>
<p><strong>Code Generation</strong><br />
Now with this saved to &#8220;ProtoService.proto&#8221; we can run the ProtoGen.exe command-line tool we downloaded with NuGet earlier.  ProtoGen will automatically detect that it has been given a &#8220;.proto&#8221; text file and run the protoc.exe compiler from the same directory as ProtoGen.exe.  If you&#8217;re including files and setting options defined by google or the csharp port you will need to have the google directory from {Package}\content\protos copied to the location of your proto files.  Since this is a stand-alone proto and not including others we don&#8217;t need to create a directory structure.  Ready to build, let&#8217;s run ProtoGen now to create our generated code:</p>
<pre>
C:\Projects\ProtoService>Google.ProtocolBuffers\tools\ProtoGen.exe -service_generator_type=IRPCDISPATCH ProtoService.proto
</pre>
<p>The service_generator_type tells the ProtoGen what type of service classes/interfaces we are interested in, the value IRPCDISPATCH generates both interfaces and client/server stubs.  There are lots of other options both for protoc and protogen, running ProtoGen.exe /? will list all of them.  In addition this can be done directly from VStudio 2005~2010 via the <a href="http://help.csharptest.net/?CmdToolOverview.html">CmdTool.exe</a> integration <a href="http://help.csharptest.net/?CmdToolIntegrateProtoGen.html">described here for ProtoGen.exe</a>.</p>
<p><strong>Project References</strong><br />
Now we should find that ProtoService.cs has been created for us.  Let&#8217;s now add this generated source file to our project and reference the two assemblies we need.  Both of our required dependencies are located in Google.ProtocolBuffers\lib\net35, called Google.ProtocolBuffers.dll and Google.ProtocolBuffers.Serialization.dll.  After we have added the two references and the generated source file we should able to compile the project.  Note: if you get some warnings about CLSCompliant you can either attribute your project as CLSCompliant(true) or add the option &#8220;-cls_compliance=false&#8221; to the protogen.exe command line above.  </p>
<p><strong>Service Implementation</strong><br />
The first code we will write will be our service implementation.  The code generator has defined an interface for us to implement called ISearchService.  Let&#8217;s stub out that implementation now in a class called ServiceImplementation:</p>
<pre class="brush:csharp">
class ServiceImplmentation : ISearchService
{
    public SearchResponse Search(SearchRequest searchRequest)
    {
        // Create the response builder
        return SearchResponse.CreateBuilder()
            // Add a result to the response
            .AddResult(
                SearchResponse.Types.Result.CreateBuilder()
                .SetUrl("http://example.com")
                .Build()
                )
            // Build the result message
            .Build();
    }
}
</pre>
<p>Of course you&#8217;re service implementation will be a lot more complicated than this, but this will suffice for demonstration purposes.  Go ahead and build your project and then let&#8217;s move on to creating the IIS handler.</p>
<p><strong>IIS Handler</strong><br />
Our <a href="http://msdn.microsoft.com/en-us/library/system.web.ihttphandler.aspx" target="_blank">IHttpHandler</a> implementation could be reduced to a single line call to <a href="http://help.protobuffers.net/?Google.ProtocolBuffers.Serialization~Google.ProtocolBuffers.Extensions~HttpCallMethod.html" target="_blank">HttpCallMethod</a> if we chose.  The following implementation adds handling of GET requests by parsing of uri query string values and some rudimentary exception handling.</p>
<p>Uri encoded requests are allowed for simple messages (non-nested simple types) and allow us to test right from a browser.  This also allows javascript to use a GET request and pass parameters.  The MIME type constant &#8216;ContentFormUrlEncoded&#8217; is defined as &#8220;application/x-www-form-urlencoded&#8221; which is also the mime type used by HTML forms.  This means that web clients can also simply post an HTML form to the service to execute a method, the constraint of simple types remains for forms as well.  </p>
<pre class="brush:csharp">
class ServiceHandler : IHttpHandler
{
    public bool IsReusable { get { return true; } }
    public void ProcessRequest(HttpContext context)
    {
        MessageFormatOptions defaultOptions = new MessageFormatOptions();
        // Capture the request stream and content-type
        Stream requestStream = context.Request.InputStream;
        string requestType = context.Request.ContentType;

        if (context.Request.HttpMethod == "GET")
        {
            // If the call is an HTTP/GET, we will use URI encoding and the query string
            requestType = MessageFormatOptions.ContentFormUrlEncoded;
            requestStream = new MemoryStream(Encoding.UTF8.GetBytes(context.Request.Url.Query));
        }

        // Parse the HTTP accept header to determine the content-type of the response
        context.Response.ContentType = (context.Request.AcceptTypes ?? new string[0])
                                       .Select(m => m.Split(';')[0])
                                       .FirstOrDefault(m => defaultOptions.MimeInputTypes.ContainsKey(m))
                                       ?? defaultOptions.DefaultContentType;

        // Create the server-side stub to dispatch the call by method name
        using (IRpcServerStub stub = new SearchService.ServerStub(new ServiceImplmentation()))
        {
            try
            {
                // The URI's last path segment will be used for the method name
                string[] path = context.Request.Url.Segments;
                // Use the extension method defined in Google.ProtocolBuffers.Extensions to process
                // the request and write the response back to the client.
                stub.HttpCallMethod(
                        path[path.Length - 1],
                        defaultOptions,
                        requestType,
                        requestStream,
                        context.Response.ContentType,
                        context.Response.OutputStream
                    );
            }
            catch(Exception error)
            {
                // If something fails we will create an ErrorResult and serialze it with the requested
                // content-type obtained earlier while returning an HTTP 500 error.
                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                ErrorResult.CreateBuilder()
                    .SetErrorText(error.Message)
                    .Build()
                    .WriteTo(defaultOptions, context.Response.ContentType, context.Response.OutputStream);
            }
        }
    }
}</pre>
<p><strong>IIS Handler Configuration</strong><br />
The IIS 7x handler configuration is very straight-forward.  We are binding the path to be a &#8216;child&#8217; of our service description proto file &#8220;ProtoService.proto&#8221;.  This, combined with the mimeMap below, allows the user to discover our service definition so that they can interact with it.  So it&#8217;s time to get working, build the project and update the web.config with the following:</p>
<pre class="brush:xml">
  &lt;system.webServer>
    &lt;staticContent>
      &lt;mimeMap fileExtension=".proto" mimeType="text/plain"/>
    &lt;/staticContent>
    &lt;handlers>
      &lt;add name="SearchService" preCondition="integratedMode" verb="GET,POST" path="/ProtoService.proto/*"
           type="ProtoService.ServiceHandler, ProtoService, Version=1.0, Culture=neutral" />
    &lt;/handlers>
  &lt;/system.webServer>
</pre>
<p><strong>Getting Results</strong><br />
Make sure you are running in IIS, this will not work in Cassini.  Open up your browser (NOT IE) and enter the URL: <a href="http://localhost/protoservice.proto/Search?query=asdf" target="_blank">http://localhost/protoservice.proto/Search?query=asdf</a> You should see the following XML response:</p>
<pre class="brush:xml">
&lt;root>
  &lt;result>
    &lt;url>http://example.com&lt;/url>
  &lt;/result>
&lt;/root>
</pre>
<p>If you type something that doesn&#8217;t make sense, or generates an error, (ie. http://localhost/protoservice.proto/BadMethodName) you will see an error message like this:</p>
<pre class="brush:xml">
&lt;root>
&lt;error_text>Method 'ProtoService.ISearchService.BadMethodName' not found.&lt;/error_text>
&lt;/root>
</pre>
<p><strong>Client Proxy</strong><br />
Now that we have a working service, building a simple client proxy for C# binary protobuffers is really easy.  First we need an implementation of the client proxy dispatch interface, <a href="http://help.protobuffers.net/?Google.ProtocolBuffers~Google.ProtocolBuffers.IRpcDispatch_members.html" target="_blank">IRpcDispatch</a>.  I&#8217;m going to use the <a href="http://msdn.microsoft.com/en-us/library/system.net.webclient.aspx" target="_blank">WebClient</a> here simply because it&#8217;s easy; however, production systems more often use the <a href="http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx" target="_blank">HttpWebRequest</a> class.</p>
<pre class="brush:csharp">
class HttpProxy : IRpcDispatch
{
    readonly Uri _baseUri;
    public HttpProxy(Uri baseUri) { _baseUri = baseUri; }

    public TMessage CallMethod&lt;TMessage, TBuilder>(string method, IMessageLite request, IBuilderLite&lt;TMessage, TBuilder> response)
        where TMessage : IMessageLite&lt;TMessage, TBuilder>
        where TBuilder : IBuilderLite&lt;TMessage, TBuilder>
    {
        WebClient client = new WebClient();
        client.Headers[HttpRequestHeader.ContentType] = MessageFormatOptions.ContentTypeProtoBuffer;
        client.Headers[HttpRequestHeader.Accept] = MessageFormatOptions.ContentTypeProtoBuffer;
        byte[] result = client.UploadData(new Uri(_baseUri, method), request.ToByteArray());
        return response.MergeFrom(result).Build();
    }
}
</pre>
<p>Once we have this defined we can now instantiate and call the proxy.</p>
<pre class="brush:csharp">
SearchRequest result;
SearchResponse result;
using(SearchService svc = new SearchService(new HttpProxy(new Uri("http://localhost/protoservice.proto/"))))
    result = svc.Search(SearchRequest.CreateBuilder().SetQuery("bar").Build());

foreach (SearchResponse.Types.Result r in result.ResultList)
    Console.WriteLine(r.Url);
</pre>
<p><strong>Alternative Client Formats</strong><br />
This proxy uses protobuffers but it could easily be adapted to use json or xml just by changing the content-type and and accept headers and serializing accordingly.  To Serialize a protobuffer message as xml or json the following extensions can be used:</p>
<pre class="brush:csharp">
//XML
string xmlResult = client.UploadString(new Uri(_baseUri, method), request.ToXml());
return response.MergeFromXml(
    System.Xml.XmlReader.Create(new StringReader(xmlResult)))
    .Build();

//JSON
string jsonResult = client.UploadString(new Uri(_baseUri, method), request.ToJson());
return response.MergeFromJson(jsonResult).Build();
</pre>
<p>Lastly there are two more extension methods that can do this by simply providing a stream and a mime-type.  This is demonstrated above in the catch block of our http handler.  Here are the extension method prototypes that can be used:</p>
<pre class="brush:csharp">
public static void WriteTo(this IMessageLite message, MessageFormatOptions options, string contentType,
                           Stream output);

public static TBuilder MergeFrom&lt;TBuilder>(this TBuilder builder, MessageFormatOptions options,
                                           string contentType, Stream input) where TBuilder : IBuilderLite;
</pre>
<p><strong>Closing Remarks</strong><br />
I&#8217;m very biased here since I wrote most of this capability; however, I am constantly amazed at how easy protobuffers are to use.  Google&#8217;s Protocol Buffers are very powerful and extremely fast.  I&#8217;ve been using them for two years now and I can&#8217;t imagine writing a serialization or remoting solution without them.</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Managed anti-debugging &#8211; how to prevent users from attaching a debugger</title>
		<link>http://csharptest.net/1051/managed-anti-debugging-how-to-prevent-users-from-attaching-a-debugger/</link>
		<comments>http://csharptest.net/1051/managed-anti-debugging-how-to-prevent-users-from-attaching-a-debugger/</comments>
		<pubDate>Sun, 20 Nov 2011 04:43:39 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Home]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=1051</guid>
		<description><![CDATA[Keeping in line with our previous post &#8220;How to prevent users from killing your service or process&#8221; and continuing down the road of securing our service this post looks at the prevention of debugging. There are a lot of anti-debugging posts out there, most of them written in C++ and assembly and are therefor of <a href='http://csharptest.net/1051/managed-anti-debugging-how-to-prevent-users-from-attaching-a-debugger/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Keeping in line with our previous post &#8220;<a href="http://csharptest.net/?p=1043">How to prevent users from killing your service or process</a>&#8221; and continuing down the road of securing our service this post looks at the prevention of debugging.  There are a lot of anti-debugging posts out there, most of them written in C++ and assembly and are therefor of little use to the managed world.  One of the most complete I&#8217;ve seen is from Symantec &#8220;<a href="http://www.symantec.com/connect/articles/windows-anti-debug-reference">Windows Anti-Debug Reference | Symantec Connect Community</a>&#8221; and an interesting one on stackoverflow &#8220;<a href="http://stackoverflow.com/questions/573115">What is your favourite anti-debugging trick?</a>&#8220;.  These both fall short on providing any solution that is both easy to implement and built with managed code.  </p>
<p>Let&#8217;s face it nothing is going to be bullet proof in this arena, and certainly not the solution I&#8217;m going to suggest.  Yet it is easy and will prevent someone from attaching a debugger after the program is running.  I&#8217;m really not concerned with trying to prevent a debug-session from startup.  Why?  Because you can&#8217;t.  The debugger can jump past any code you have that tries to verify that a debugger is not currently active.  Besides this it provides me very little value, I want to protect an actively running process (a service).  If the user has the rights to stop it in the first place (i.e. they are an admin) then there isn&#8217;t anything I can do to stop them from debugging.  </p>
<p>What I want is to prevent someone from attaching a debugger to this service to protect potentially sensitive information.  How?  Well as it turns out the easiest way to prevent a debug session from starting is with a debug session.  So what we need is to debug ourselves!  Oh wait you can&#8217;t :( but what you can do is easily spawn another process to debug this process while we debug that new process.  This reciprocal or circular debug session will prevent either process from being debugged.  Further, any attempt to kill either process will immediately terminate the other process thus thwarting an effort to kill one debugger so that you can attach one.</p>
<p>To accomplish this in managed code we have two choices, either using the managed debugger API or the native win32 debugger API.  It turns out that the managed debugger is excessively complicated and requires an extraordinary amount of COM code to pull it off (<a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&#038;id=19621" target="_blank">see the mdbg sample</a>)  So I chose to go with a raw win32 debug session and see if we could pull that off easily with a few PInvoke calls.  Sure enough, this is really easy.</p>
<p>So let&#8217;s jump in and take a look at the debugging API calls we are going to need&#8230;</p>
<pre class="brush:csharp">
const int DBG_CONTINUE = 0x00010002;
const int DBG_EXCEPTION_NOT_HANDLED = unchecked((int)0x80010001);

enum DebugEventType : int
{
    CREATE_PROCESS_DEBUG_EVENT = 3, //Reports a create-process debugging event. The value of u.CreateProcessInfo specifies a CREATE_PROCESS_DEBUG_INFO structure.
    CREATE_THREAD_DEBUG_EVENT = 2, //Reports a create-thread debugging event. The value of u.CreateThread specifies a CREATE_THREAD_DEBUG_INFO structure.
    EXCEPTION_DEBUG_EVENT = 1, //Reports an exception debugging event. The value of u.Exception specifies an EXCEPTION_DEBUG_INFO structure.
    EXIT_PROCESS_DEBUG_EVENT = 5, //Reports an exit-process debugging event. The value of u.ExitProcess specifies an EXIT_PROCESS_DEBUG_INFO structure.
    EXIT_THREAD_DEBUG_EVENT = 4, //Reports an exit-thread debugging event. The value of u.ExitThread specifies an EXIT_THREAD_DEBUG_INFO structure.
    LOAD_DLL_DEBUG_EVENT = 6, //Reports a load-dynamic-link-library (DLL) debugging event. The value of u.LoadDll specifies a LOAD_DLL_DEBUG_INFO structure.
    OUTPUT_DEBUG_STRING_EVENT = 8, //Reports an output-debugging-string debugging event. The value of u.DebugString specifies an OUTPUT_DEBUG_STRING_INFO structure.
    RIP_EVENT = 9, //Reports a RIP-debugging event (system debugging error). The value of u.RipInfo specifies a RIP_INFO structure.
    UNLOAD_DLL_DEBUG_EVENT = 7, //Reports an unload-DLL debugging event. The value of u.UnloadDll specifies an UNLOAD_DLL_DEBUG_INFO structure.
}

[StructLayout(LayoutKind.Sequential)]
struct DEBUG_EVENT
{
    [MarshalAs(UnmanagedType.I4)]
    public DebugEventType dwDebugEventCode;
    public int dwProcessId;
    public int dwThreadId;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
    public byte[] bytes;
}

[DllImport("Kernel32.dll", SetLastError = true)]
static extern bool DebugActiveProcess(int dwProcessId);
[DllImport("Kernel32.dll", SetLastError = true)]
static extern bool WaitForDebugEvent([Out] out DEBUG_EVENT lpDebugEvent, int dwMilliseconds);
[DllImport("Kernel32.dll", SetLastError = true)]
static extern bool ContinueDebugEvent(int dwProcessId, int dwThreadId, int dwContinueStatus);
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool IsDebuggerPresent();
</pre>
<p>The structure DEBUG_EVENT above is actually only 96 bytes in total and the bytes 12 to 96 are actually a union.  I did not need any real details about the specifics so I chose to use slam a blob here and not worry about it.  The byte array could be reduced in theory to 84 bytes but I really didn&#8217;t care since we are only going to create a single one of these.  The rest is pretty strait-forward PInvoke junk, nothing fancy.  </p>
<p>Using the methods above to debug a process looks something like the following code:</p>
<pre class="brush:csharp">
// Start a thread to perform the debug loop
new Thread(DebuggerThread) { IsBackground = true, Name = "DebuggerThread" }
    .Start(processId);
// Debugging thread main loop
static void DebuggerThread(object arg)
{
    DEBUG_EVENT evt = new DEBUG_EVENT();
    evt.bytes = new byte[1024];
    // Attach to the process we provided the thread as an argument
    if (!DebugActiveProcess((int)arg))
        throw new Win32Exception();

    while (true)
    {
        // wait for a debug event
        if (!WaitForDebugEvent(out evt, -1))
            throw new Win32Exception();
        // return DBG_CONTINUE for all events but the exception type
        int continueFlag = DBG_CONTINUE;
        if (evt.dwDebugEventCode == DebugEventType.EXCEPTION_DEBUG_EVENT)
            continueFlag = DBG_EXCEPTION_NOT_HANDLED;
        // continue running the debugee
        ContinueDebugEvent(evt.dwProcessId, evt.dwThreadId, continueFlag);
    }
}</pre>
<p>Frankly I had no idea how trivial this was to do.  Once I had this working I was able to quickly build a method that takes my program arguments and detects if it is a parent or child process and act appropriately.  For the child we need only debug our parent process, for the parent we need to both spawn the child and debug it.  Ideally this would be done as a single step since it is possible to start a process as a debugee; however, I didn&#8217;t bother to figure out how to do that.  If you know and don&#8217;t mind sharing please drop a comment.  Since I do know how to start a process and I know how to debug an active process I chose that approach.  It doesn&#8217;t seem like it would be any more or less secure, but I could be wrong on that point.  Anyway the following is what my process start-up looks like&#8230;</p>
<pre class="brush:csharp">
static void Main(string[] args)
{
    NativeDebug.DebugSelf(args);
    ... stuff ...
}
public static void DebugSelf(string[] args)
{
    Process self = Process.GetCurrentProcess();
    // Child process?
    if (args.Length == 2 &#038;&#038; args[0] == "--debug-attach")
    {
        int owner = int.Parse(args[1]);
        Process pdbg = Process.GetProcessById(owner);
        new Thread(KillOnExit) { IsBackground = true, Name = "KillOnExit" }.Start(pdbg);
        //Wait for our parent to debug us
        WaitForDebugger();
        //Start debugging our parent process
        DebuggerThread(owner);
        //Now is a good time to die.
        Environment.Exit(1);
    }
    else // else we are the Parent process...
    {
        ProcessStartInfo psi =
            new ProcessStartInfo(Environment.GetCommandLineArgs()[0], "--debug-attach " + self.Id)
                {
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    ErrorDialog = false,
                    WindowStyle = ProcessWindowStyle.Hidden
                };
        // Start the child process
        Process pdbg = Process.Start(psi);
        if (pdbg == null)
            throw new ApplicationException("Unable to debug");
        // Monitor the child process
        new Thread(KillOnExit) {IsBackground = true, Name = "KillOnExit"}.Start(pdbg);
        // Debug the child process
        new Thread(DebuggerThread) {IsBackground = true, Name = "DebuggerThread"}.Start(pdbg.Id);
        // Wait for the child to debug us
        WaitForDebugger();
    }
}
static void WaitForDebugger()
{
    DateTime start = DateTime.Now;
    while (!IsDebuggerPresent())
    {
        if ((DateTime.Now - start).TotalMinutes > 1)
            throw new TimeoutException("Debug operation timeout.");
        Thread.Sleep(1);
    }
}
static void KillOnExit(object process)
{
    ((Process)process).WaitForExit();
    Environment.Exit(1);
}
</pre>
<p>So we&#8217;ve written about 100 lines of code or so and spent almost no time at all getting it up and running, a good ROI for this kind of stuff.  It worked quite well even running under the NETWORK SERVICE account as a service.  It certainly stops me from debugging it although I&#8217;m certainly not what I&#8217;d call an accomplished hacker.  Given the time and effort to put this together I&#8217;d have to call it a win for active debugger prevention.  The down side of course is that there are now two processes running and trying to tell them apart is difficult at first launch.  </p>
<p>If you&#8217;re going to do something like this, I would suggest adding an &#8216;if (!IsDebuggerPresent())&#8217; to the else clause of our DebugSelf method above.  This would allow you to launch with a debugger but not to attach one at a later time.  Have fun with it and as with any code on this site, &#8220;Don&#8217;t blame me&#8221;.  I didn&#8217;t make you use it ;)  </p>
<p>My own intentions for this are to make a reasonable effort to secure a service running in a controlled but insecure environment.  I would never ship something like this to a customer and hope you would not either.  Preventing a consumer from accessing software they purchased is not at all what I&#8217;m after.  IMHO if information is on their machine it is theirs to debug and view all they want. </p>
<p>One more thing, in case you are wondering this was not my idea.  I read about doing this in a security article some years ago but I can&#8217;t seem to locate it.</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to prevent users from killing your service or process</title>
		<link>http://csharptest.net/1043/how-to-prevent-users-from-killing-your-service-process/</link>
		<comments>http://csharptest.net/1043/how-to-prevent-users-from-killing-your-service-process/</comments>
		<pubDate>Sat, 19 Nov 2011 22:53:45 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Home]]></category>
		<category><![CDATA[Other]]></category>
		<category><![CDATA[process]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=1043</guid>
		<description><![CDATA[Before I say another word, I have read &#8220;The arms race between programs and users&#8221; and wholeheartedly agree. You can not, and should not, attempt to stop an Administrator from killing your process or stopping your service. That is not what we are trying to do here, we are trying to prevent Joe User from <a href='http://csharptest.net/1043/how-to-prevent-users-from-killing-your-service-process/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Before I say another word, I have read &#8220;<a href="http://blogs.msdn.com/b/oldnewthing/archive/2004/02/16/73780.aspx" target="_blank">The arms race between programs and users</a>&#8221; and wholeheartedly agree.  You can not, and should not, attempt to stop an Administrator from killing your process or stopping your service.  That is not what we are trying to do here, we are trying to prevent Joe User from disrupting our process.</p>
<p>So let&#8217;s get started, to do this we want to adjust our process&#8217; access control list.  The individual rights we can grant and deny are discussed on MSDN in the articled titled &#8220;<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684880(v=vs.85).aspx" target="_blank">Process Security and Access Rights</a>&#8220;.  Though most of that article is about creating a process with specific rights, in this case we want to modify the rights of our current process.  To do this we are going to PInvoke <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa446641(v=vs.85).aspx" target="_blank">GetKernelObjectSecurity</a> to obtain the DACL (Discretionary Access Control List), modify it using the <a href="http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.rawsecuritydescriptor.aspx" target="_blank">RawSecurityDescriptor</a>, and finally write it back using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa379578(v=vs.85).aspx" target="_blank">SetKernelObjectSecurity</a> API.  This should be somewhat familiar to those of you that followed that part of building our service.</p>
<p><strong>Step 1 &#8211; Obtaining the process DACL</strong></p>
<pre class="brush:csharp">[DllImport("advapi32.dll", SetLastError = true)]
static extern bool GetKernelObjectSecurity(IntPtr Handle, int securityInformation, [Out] byte[] pSecurityDescriptor,
                                           uint nLength, out uint lpnLengthNeeded);

public static RawSecurityDescriptor GetProcessSecurityDescriptor(IntPtr processHandle)
{
    const int DACL_SECURITY_INFORMATION = 0x00000004;
    byte[] psd = new byte[0];
    uint bufSizeNeeded;
    // Call with 0 size to obtain the actual size needed in bufSizeNeeded
    GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, psd, 0, out bufSizeNeeded);
    if (bufSizeNeeded &lt; 0 || bufSizeNeeded > short.MaxValue)
        throw new Win32Exception();
    // Allocate the required bytes and obtain the DACL
    if (!GetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION,
                                        psd = new byte[bufSizeNeeded], bufSizeNeeded, out bufSizeNeeded))
        throw new Win32Exception();
    // Use the RawSecurityDescriptor class from System.Security.AccessControl to parse the bytes:
    return new RawSecurityDescriptor(psd, 0);
}</pre>
<p>And you thought that was going to be hard?  Of course we also need to be able to save the DACL.  So&#8230;</p>
<p><strong>Part 2 &#8211; Updating the process DACL</strong></p>
<pre class="brush:csharp">[DllImport("advapi32.dll", SetLastError = true)]
static extern bool SetKernelObjectSecurity(IntPtr Handle, int securityInformation, [In] byte[] pSecurityDescriptor);

public static void SetProcessSecurityDescriptor(IntPtr processHandle, RawSecurityDescriptor dacl)
{
    const int DACL_SECURITY_INFORMATION = 0x00000004;
    byte[] rawsd = new byte[dacl.BinaryLength];
    dacl.GetBinaryForm(rawsd, 0);
    if (!SetKernelObjectSecurity(processHandle, DACL_SECURITY_INFORMATION, rawsd))
        throw new Win32Exception();
}</pre>
<p>Cool, that was easy, so we are ready now right?  Not quite, we still need to get the process handle.  A simple thing for our own process:</p>
<p><strong>Part 3 &#8211; Getting the current process</strong></p>
<pre class="brush:csharp">[DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess();</pre>
<p>It just gets easier and easier.  Since this is the current process there (AFAIK) is not any reason to duplicate handle and request additional permissions.  This handle should have access to do anything.  So the only thing left before we can modify the permissions is to define what those permissions are.</p>
<p><strong>Part 4 &#8211; Process access rights</strong></p>
<pre class="brush:csharp">[Flags]
public enum ProcessAccessRights
{
    PROCESS_CREATE_PROCESS =0x0080, //	Required to create a process.
    PROCESS_CREATE_THREAD = 0x0002, //	Required to create a thread.
    PROCESS_DUP_HANDLE = 0x0040, //	Required to duplicate a handle using DuplicateHandle.
    PROCESS_QUERY_INFORMATION = 0x0400, //	Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
    PROCESS_QUERY_LIMITED_INFORMATION = 0x1000, //	Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION. Windows Server 2003 and Windows XP/2000:  This access right is not supported.
    PROCESS_SET_INFORMATION = 0x0200, //	Required to set certain information about a process, such as its priority class (see SetPriorityClass).
    PROCESS_SET_QUOTA = 0x0100, //	Required to set memory limits using SetProcessWorkingSetSize.
    PROCESS_SUSPEND_RESUME = 0x0800, //	Required to suspend or resume a process.
    PROCESS_TERMINATE = 0x0001, //	Required to terminate a process using TerminateProcess.
    PROCESS_VM_OPERATION = 0x0008, //	Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
    PROCESS_VM_READ = 0x0010, //	Required to read memory in a process using ReadProcessMemory.
    PROCESS_VM_WRITE = 0x0020, //	Required to write to memory in a process using WriteProcessMemory.
    DELETE = 0x00010000, //	Required to delete the object.
    READ_CONTROL = 0x00020000, //	Required to read information in the security descriptor for the object, not including the information in the SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
    SYNCHRONIZE = 0x00100000, //	The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state.
    WRITE_DAC = 0x00040000, //	Required to modify the DACL in the security descriptor for the object.
    WRITE_OWNER = 0x00080000, //	Required to change the owner in the security descriptor for the object.
    STANDARD_RIGHTS_REQUIRED = 0x000f0000,
    PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF),//	All possible access rights for a process object.
}</pre>
<p><strong>Part 5 &#8211; Put it all together</strong></p>
<pre class="brush:csharp">// Get the current process handle
IntPtr hProcess = GetCurrentProcess();
// Read the DACL
var dacl = GetProcessSecurityDescriptor(hProcess);
// Insert the new ACE
dacl.DiscretionaryAcl.InsertAce(
    0,
    new CommonAce(
        AceFlags.None,
        AceQualifier.AccessDenied,
        (int)ProcessAccessRights.PROCESS_ALL_ACCESS,
        new SecurityIdentifier(WellKnownSidType.WorldSid, null),
        false,
        null)
);
// Save the DACL
SetProcessSecurityDescriptor(hProcess, dacl);</pre>
<p>The ace we&#8217;ve added now will try to deny access to the &#8220;Everyone&#8221; group (aka WorldSid) to do anything with our process.  We need not fear that we are interrupting an administrator&#8217;s ability to perform any action they desire.  They will have any access required that&#8217;s why we call them administrators :)  As I said in the beginning, we are not trying to stop Administrators, we just want to make sure they are an administrator if they plan to modify or kill this process.</p>
<p>We could of course be more discrete about the rights we are trying to deny, that is entirely up to you.</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service &#8211; Part 7: Finishing touches</title>
		<link>http://csharptest.net/990/building-a-windows-service-part-7-finishing-touches/</link>
		<comments>http://csharptest.net/990/building-a-windows-service-part-7-finishing-touches/</comments>
		<pubDate>Sat, 19 Nov 2011 16:07:00 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Home]]></category>
		<category><![CDATA[Other]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=990</guid>
		<description><![CDATA[Continued from &#8220;Building a Windows Service – Part 6: Adding resources and event logging&#8221; So let&#8217;s recap our goals for this project: Building a service that can also be used from the console Proper event logging of service startup/shutdown and other activities Allowing multiple instances by using command-line arguments Self installation of service and event <a href='http://csharptest.net/990/building-a-windows-service-part-7-finishing-touches/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Continued from &#8220;<a href="http://csharptest.net/?p=977">Building a Windows Service – Part 6: Adding resources and event logging</a>&#8221;</p>
<p>So let&#8217;s recap our goals for this project:</p>
<ul>
<li>Building a service that can also be used from the console</li>
<li>Proper event logging of service startup/shutdown and other activities</li>
<li>Allowing multiple instances by using command-line arguments</li>
<li>Self installation of service and event log</li>
<li>Proper event logging of service exceptions and errors</li>
<li>Controlling of start-up, shutdown and restart options</li>
<li>Handling custom service commands, power, and session events</li>
<li>Customizing service security and access control</li>
</ul>
<p>Yep, we are on the mark there and have demonstrated most of these in the past few posts. The goal not stated directly has always been to to create a new project template. We had a bit of cleaning up to do before we could deal with that. I&#8217;m not going to cover this clean up in the same level of detail as before, but here are a few words about how this has changed from the previous posts:</p>
<ol>
<li>I&#8217;ve added an application icon and manifest. This brought to light that the generator for the win32 resources was not preserving the manifest, nor was it correctly locating the icon when I moved the resources file. To get this working I&#8217;ve built a custom version of the CSharpTest.Net.Generators executable.</li>
<li>For all the good it does, I&#8217;ve added an UnhandledException event listener on the AppDomain to attempt to log the exception. As you probably know this is unreliable at best ;)</li>
<li>I&#8217;ve split all the resources into three parts, messages that are written, exceptions that log, and normal non-logging string resources. These have been to a Resources folder and all resource/event specific stuff is now located there.</li>
<li>The remainder of the service stub class, &#8220;ServiceImplementation&#8221; has been filled out to include power and session events, custom commands, etc. The appropriate logging and plumbing has been introduced into the ServiceProcess class to support these new methods.</li>
<li>There are a couple of other small changes and always bugs, and I&#8217;ve had to fix a few from the previous posts.</li>
</ol>
<p>The end result is a clean easy to use project template for Visual Studio 2008. This can easily be upgraded to 2010 if you desire. The project is currently using the 2.0 Framework to allow the greatest flexibility, but obviously once you create the project from the template it can be changed.</p>
<table>
<tbody>
<tr>
<td width="75"><img src="http://csharptest.net/images/winzip.png" alt="zip" width="50" height="50" /></td>
<td><a title="/downloads/projects/ServiceTemplate.zip" href="http://csharptest.net/downloads/projects/ServiceTemplate.zip">Download the Visual Studio Service Project Template</a><br />
To use the template place it in the following path for 2008:<br />
<span style="font-family:courier new; courier">%UserProfile%\My Documents\Visual Studio 2008\Templates\ProjectTemplates\Visual C#</span>
</td>
</tr>
</tbody>
</table>
<p>Once installed, create a new project, locate the template &#8220;ServiceTemplate&#8221; and create a project.  Since the project name is used heavily throughout the template you should avoid names that contain non-alpha-numeric text or are longer than 64 characters.  You can always rename the project file, assembly, and default namespace later, but start with a simple name.  After the project has been created there are two things to do from the command line.  Assuming a working directory at the root of the project the following commands should be run:</p>
<pre>C:\Projects\MyService> Tools\CmdTool.exe register
C:\Projects\MyService> Tools\CmdTool.exe build MyService.csproj
Generating C:\Projects\MyService\Resources\Exceptions.resx
Generating C:\Projects\MyService\Resources\FormatString.resx
Generating C:\Projects\MyService\Resources\Messages.resx
</pre>
<p>Now you can build and run the project with the &#8216;install&#8217; command and away you go.  Modify the ServiceImplementation class to provide the service implementation.  Adjust the default IsolateDomain, and ShadowCopy settings to your desired defaults.  Don&#8217;t forget if you want to debug service start-up you can run the command &#8220;start {servicename} DEBUG!&#8221; and, if the service is not running, a debug break-point will be triggered.</p>
<p>It&#8217;s not often I have to create a windows service, yet each time it takes me several days to work all this out.  I hope this will save you some time as well, enjoy.</p>
<p>
PS: If you&#8217;ve missed any of the previous posts, here they are:</p>
<ul>
<li><a href="http://csharptest.net/?p=837">Building a Windows Service – Part 1: Getting started</a></li>
<li><a href="http://csharptest.net/?p=850">Building a Windows Service – Part 2: Adding a Service to a Console Application</a></li>
<li><a href="http://csharptest.net/?p=858">Building a Windows Service – Part 3: Creating a Service Installer</a></li>
<li><a href="http://csharptest.net/?p=955">Building a Windows Service – Part 4: Extending the Service Installer</a></li>
<li><a href="http://csharptest.net/?p=968">Building a Windows Service – Part 5: Adding command-line installation</a></li>
<li><a href="http://csharptest.net/?p=977">Building a Windows Service – Part 6: Adding resources and event logging</a></li>
<li><a href="http://csharptest.net/?p=990">Building a Windows Service &#8211; Part 7: Finishing touches</a></li>
</ul>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service – Part 6: Adding resources and event logging</title>
		<link>http://csharptest.net/977/building-a-windows-service-part-6-adding-resources-and-event-logging/</link>
		<comments>http://csharptest.net/977/building-a-windows-service-part-6-adding-resources-and-event-logging/</comments>
		<pubDate>Sat, 19 Nov 2011 16:06:45 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=977</guid>
		<description><![CDATA[Continued from &#8220;Building a Windows Service – Part 5: Adding command-line installation&#8221; So we have a working service it&#8217;s time to start adding some logging. Proper event logging is critical to monitoring services so we are not going to use .NET&#8217;s typical excuse for events. Rather we are going to build a &#8216;real&#8217; message dll <a href='http://csharptest.net/977/building-a-windows-service-part-6-adding-resources-and-event-logging/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Continued from &#8220;<a href="http://csharptest.net/?p=968">Building a Windows Service – Part 5: Adding command-line installation</a>&#8221;</p>
<p>So we have a working service it&#8217;s time to start adding some logging.  Proper event logging is critical to monitoring services so we are not going to use .NET&#8217;s typical excuse for events.  Rather we are going to build a &#8216;real&#8217; message dll from our server, register it as a message event source, and have a real event log.  Sounds crazy I know, but all the hard work has already been done by <a href="http://help.csharptest.net/?CSharpTest.Net.GeneratorsOverview.html" target="_blank">CSharpTest.Net.Generators.exe</a>.  We are also going to use <a href="http://help.csharptest.net/?CmdToolOverview.html" target="_blank">CmdTool.exe</a> to integrate integrate into Visual Studio.</p>
<p>The first thing we are going to need to do is to pull three binaries from my library (<a href="http://code.google.com/p/csharptest-net/downloads/list" title="CSharpTest.Net Library Downloads" target="_blank">available here</a>).  The three we are after are CmdTool.exe, CSharpTest.Net.Generators.exe, and CSharpTest.Net.Library.dll which the Generators assembly depends upon.  I&#8217;m going to just create a folder in the project directory called &#8220;Tools&#8221; and add these files there.  If you&#8217;ve never used CmdTool before you will need to register it by running &#8220;CmdTool.exe Register&#8221; from an administrative command prompt.</p>
<p><strong>Creating CmdTool.config</strong><br />
To use CmdTool for our resources we need a configuration file that tells it what to do.  This is fairly trivial and is explained in some detailed here: &#8220;<a href="http://help.csharptest.net/?CmdToolConfiguration.html" target="_blank">CmdTool.exe Configuration</a>&#8220;.  So we are going to copy/paste <a href="http://help.csharptest.net/?CmdToolIntegrationResX.html" target="_blank">this default configuration</a> and save it into a file called &#8220;CmdTool.config&#8221; in the root of our project.  Here is our configuration file:</p>
<pre class="brush:xml">
&lt;?xml version="1.0" encoding="utf-8" ?>
&lt;CmdTool xsi:noNamespaceSchemaLocation="http://csharptest.net/downloads/schema/CmdTool.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  &lt;match filespec="*.resx">
    &lt;generator debug="false">
      &lt;execute exe=".\Tools\CSharpTest.Net.Generators.exe" />
      &lt;arg value="ResX"/>
      &lt;arg value="-input=$(InputPath)"/>
      &lt;arg value="-namespace=$(Namespace)"/>
      &lt;arg value="-class=$(ClassName)"/>
      &lt;arg value="-public=true"/>
      &lt;arg value="-partial=true"/>
      &lt;arg value="-test=true"/>
      &lt;arg value="-sealed=true"/>
      &lt;arg value="-base=System.ApplicationException"/>
      &lt;arg value="-rxns=$(DefaultNamespace)"/>

      &lt;std-output extension=".Designer.cs"/>
    &lt;/generator>
  &lt;/match>
&lt;/CmdTool>
</pre>
<p><img src="http://csharptest.net/wp-content/uploads/2011/11/SolutionExplore1.png" alt="" title="SolutionExplore1" width="341" height="376" class="alignright size-full wp-image-981" /><br />
Once our configuration is there we need to create standard Resources.resx file just as you always would.  In order for CmdTool to find the configuration file above it must be in the same directory, or a parent directory, of the resource file.  I&#8217;m just adding the Resources.resx file in the root of the project.</p>
<p>After we&#8217;ve added the Resources.resx file to the project we now need to modify the &#8220;Custom Tool&#8221; property for the solution item.  Right-click on the resx file and select &#8220;Properties&#8221;.  You should the option there, just type &#8216;CmdTool&#8217; in the value next to Custom Tool.  Make sure you&#8217;ve registered CmdTool or you will get an error.  The end result should look like this:<br />
<img src="http://csharptest.net/wp-content/uploads/2011/11/CustomToolSetting.png" alt="" title="CustomToolSetting" width="341" height="170" class="alignnone size-full wp-image-983" /></p>
<p>Once this is changed, you&#8217;re output window should display &#8220;Generating C:\{some path}\Resources.resx&#8221; with the full path to the location of the resx file.  Once that is working we already have a lot of bang for our buck.  Creating a resource string like &#8220;String1&#8243;, &#8220;{0}&#8221; will now create a static method with the signature &#8216;string Resources.String1(object _0)&#8217;.  That is neat, we can even create exceptions just by renaming &#8220;String1&#8243; to &#8220;String1Exception&#8221; and presto-magic happens and you have a complete exception class.  I can&#8217;t live without this thing, I&#8217;ve used it sparingly in the open but I use it extensively in my day job as well as private projects.  We have over 250 custom exceptions, each have a unique HRESULT that can be written to the Event Log and monitored.  This is what we are after, Adding support for the event logging part.</p>
<p>Before we go any farther with this you should be very familiar with <a href="http://msdn.microsoft.com/en-us/library/bb401631.aspx" target="_blank">what is an HRESULT</a>, what it&#8217;s composite parts are, and what their constraints are.  Most of this is documented in the help for <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd996906(v=vs.85).aspx" target="_blank">Message Text Files</a> which is exactly what we are going to be generating.</p>
<p>So let&#8217;s get started turning our resx into an event log writer.  Step 1, we need to add some information, the easiest way is to just copy/paste the following settings into the &#8220;View Source&#8221; xml view:</p>
<pre class="brush:xml">
  &lt;assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  &lt;data name=".EventCategory" type="System.Int32, mscorlib">
    &lt;value>1&lt;/value>
    &lt;comment>General&lt;/comment>
  &lt;/data>
  &lt;assembly alias="System" name="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  &lt;data name=".EventSource" type="System.Uri, System">
    &lt;value>ServiceTemplate/ServiceTemplate&lt;/value>
  &lt;/data>
  &lt;data name=".AutoLog" type="System.Boolean, mscorlib">
    &lt;value>True&lt;/value>
  &lt;/data>
  &lt;data name=".AutoLogMethod" type="System.Uri, System">
    &lt;value>EventLogging.WriteEvent&lt;/value>
  &lt;/data>
  &lt;data name=".Facility" type="System.Int32, mscorlib">
    &lt;value>256&lt;/value>
    &lt;comment>General&lt;/comment>
  &lt;/data>
  &lt;data name=".HelpLink" type="System.Uri, System">
    &lt;value>http://example.com/?HResult={0:x8}&lt;/value>
  &lt;/data>
  &lt;data name=".NextMessageId" type="System.Int32, mscorlib">
    &lt;value>2&lt;/value>
  &lt;/data>
  &lt;data name=".EventMessageFormat" xml:space="preserve">
    &lt;value>
More Information: {1}
Excpetion Type: {2}
Base Type: {3}
Stack Trace: {4}
{5}&lt;/value>
  &lt;/data>
</pre>
<p>Once the above has been inserted into the resx file you can verify proper behavior by adding any resource string.  When you save the resx file, a Comment value should magically appear, something like &#8220;#MessageId=1&#8243;.  Do not change or remove, these ids should not be reused to avoid confusion with old event logs, the &#8220;.NextMessageId&#8221; controls the next id that will be assigned.  Occasionally, if you&#8217;re custom exception crazy, you may run into source merge conflicts.  At that point you need to make sure all messages have a unique id (it will fail if this is not the case) and that the &#8220;.NextMessageId&#8221; value is higher than all existing ids.  </p>
<p>The &#8220;.AutoLogMethod&#8221; above, &#8220;EventLogging.WriteEvent&#8221; is to allow us to customize the values provided to the event log.  This method is called when either a method is called to format a string, or when an exception is constructed (not thrown).  Because we are augmenting the data in the message with the &#8220;.EventMessageFormat&#8221; above we are required to write this method.  We could simply remove both the &#8220;.AutoLogMethod&#8221; and &#8220;.EventMessageFormat&#8221; and it would just create the log and write it for us.  By customizing this however we can get some fixed fields on our exceptions that will help in monitoring and triggering of alerts.  So here is our custom EventLogging class that will provide some fixed values and also provide a serialized exception as the binary data for the event.</p>
<pre class="brush:csharp">
public class EventLogging
{
    private static readonly Dictionary&lt;string, EventLog> _logs = new Dictionary&lt;string,EventLog>(StringComparer.Ordinal);

    public static void WriteEvent(string eventLog, string eventSource, int category, EventLogEntryType eventType, long eventId, object[] arguments, Exception error)
    {
        EventLog log;
        lock(_logs)
        {
            if(!_logs.TryGetValue(eventLog + '.' + eventSource, out log))
                _logs.Add(eventLog + '.' + eventSource, log = new EventLog(eventLog, ".", eventSource));
        }

        const int fixedCount = 6;
        object[] fullargs = new object[arguments.Length + fixedCount];
        int ix = 0;
        fullargs[ix++] = eventId.ToString("x8");
        fullargs[ix++] = error == null ? null : error.HelpLink;
        fullargs[ix++] = error == null ? null : error.GetType().ToString();
        fullargs[ix++] = error == null ? null : error.GetBaseException().GetType().ToString();
        fullargs[ix++] = error == null ? null : error.StackTrace;
        fullargs[ix++] = new StackTrace(3).ToString();
        Array.Copy(arguments, 0, fullargs, fixedCount, arguments.Length);

        byte[] data = null;
        if (error != null)
        {
            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    BinaryFormatter ser = new BinaryFormatter();
                    ser.Serialize(ms, error);
                    data = ms.ToArray();
                }
            }
            catch { }
        }

        lock(log)
            log.WriteEvent(new EventInstance(eventId, category, eventType), data, fullargs);
    }
}
</pre>
<p>Now we can build again, and the biggest thing left is getting these .NET resources turning into Win32 message resources.  We have two options here, option 1 is to produce a stand-alone message dll.  This can work well in some cases, but I really want an all-in-one approach here so I&#8217;m going to embed the messages into this managed assembly.  File versions, app icons, etc should survive; however, be aware that this tool builds a win32 resource that must later be bound to this project.  To get the generator producing resources we just need to add a pre-build event.</p>
<pre>
$(ProjectDir)Tools\CSharpTest.Net.Generators.exe ProjectResX "$(ProjectPath)" /name=Messages\Resources "/tools=$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows@CurrentInstallFolder)Bin"
</pre>
<p>Here I&#8217;m using the Windows SDK versions of RC.exe and MC.exe which are both required.  You could optionally change the tools path to another location if desired so long as both of these tools exist.  After you define the pre-build event above build the project.  Assuming that worked there is a new directory below the project file called &#8220;Messages&#8221;.  This Messages directory contains two C# files we need to add to this project, Resources.Constants.cs, and Resources.InstallUtil.cs.  Include these by clicking the &#8220;Show All Files&#8221; option and right-click to select &#8220;Include in Project&#8221;.  Now we need to manually add an entry to our project.  First right-click the project and select &#8220;Unload Project&#8221;.  Then right-click again and select &#8220;Edit XXX.csproj&#8221; to view the file in XML.  At the end of the first PropertyGroup element we need to add the following:</p>
<pre class="brush:xml">
  &lt;PropertyGroup>
    ...
    &lt;Win32Resource>$(ProjectDir)Messages\Resources.res&lt;/Win32Resource>
  &lt;/PropertyGroup>
</pre>
<p><img src="http://csharptest.net/wp-content/uploads/2011/11/ExeWithMessages.png" alt="" title="ExeWithMessages" width="335" height="154" class="alignright size-full wp-image-985" /> This can be done in the project properties dialog, however, if you have assigned an icon, manifest, or something it will be erased.  This ensures those properties remain although you will not be able to edit them.  Now rebuild the project.  You can verify that the resources are properly being created by using the File -> Open -> File&#8230; command and selecting the .exe file you just built.  You should see at least the resources depicted to the right.</p>
<p>Now that we&#8217;ve built it we can simply run the .exe file with the &#8216;install&#8217; argument to register both the service and the event log/source.  Before we do that it would be nice to have something in that event log to see.  So let&#8217;s start with adding a resource string for service startup and shutdown.  I&#8217;m going to start with the following messages in the resources.resx file:</p>
<pre>
<table>
<tr>
<td>ServiceStartFailedException</td>
<td>The service {0} failed to start.</td>
<td>#MessageId=1</td>
</tr>
<tr>
<td>ServiceStarted</td>
<td>The service {0} started successfully.</td>
<td>#MessageId=2</td>
</tr>
<tr>
<td>ServiceStopped</td>
<td>The service {0} has stopped.</td>
<td>#MessageId=3</td>
</tr>
</table>
</pre>
<p>Now we are going to update the service process to add the logging:</p>
<pre class="brush:csharp">
protected override void OnStart(string[] args)
{
    try
    {
        OnStop();
        _service = new ServiceImplementation();

        List<string> allarguments = new List</string><string>(_arguments);
        if (args != null &#038;&#038; args.Length > 0)
            allarguments.AddRange(args);

        _service.Start(allarguments);
        Resources.ServiceStarted(ServiceName);
    }
    catch(Exception e)
    {
        throw new ServiceStartFailedException(ServiceName, e);
    }
}

protected override void OnStop()
{
    if (_service == null)
        return;
    try
    {
        _service.Stop();
        _service.Dispose();
        _service = null;
    }
    finally
    {
        Resources.ServiceStopped(ServiceName);
    }
}
</string></pre>
<p>Once this has been added we will build and run the following to install, start, and stop the service.  After that we are going to the Win7/Win2008 command-line tool to export the log to xml so we can peek at the events.</p>
<pre>
ServiceTemplate.exe
net start ServiceTemplate
net stop ServiceTemplate
Wevtutil.exe qe ServiceTemplate /f:RenderedXml
</pre>
<p>The output of Wevtutil.exe should display something like the following:</p>
<pre class="brush:xml">
&lt;Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>
  &lt;System>
    &lt;Provider Name='ServiceTemplate'/>
    &lt;EventID Qualifiers='16640'>3&lt;/EventID>
    &lt;Level>4&lt;/Level>
    &lt;Task>1&lt;/Task>
    &lt;Keywords>0x80000000000000&lt;/Keywords>
    &lt;TimeCreated SystemTime='2011-11-17T22:10:47.000000000Z'/>
    &lt;EventRecordID>3&lt;/EventRecordID>
    &lt;Channel>ServiceTemplate&lt;/Channel>
    &lt;Computer>HOSTNAME&lt;/Computer>
    &lt;Security/>
  &lt;/System>
  &lt;EventData>
    &lt;Data>41000003&lt;/Data>
    &lt;Data>&lt;/Data>
    &lt;Data>&lt;/Data>
    &lt;Data>&lt;/Data>
    &lt;Data>&lt;/Data>
    &lt;Data>
      at ServiceTemplate.Service.ServiceProcess.OnStop()
      at System.ServiceProcess.ServiceBase.DeferredStop()
      at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]&amp; outArgs)
      at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
      at System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(Object o)
      at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
      at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
      at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
    &lt;/Data>
    &lt;Data>ServiceTemplate&lt;/Data>
  &lt;/EventData>
  &lt;RenderingInfo Culture='en-US'>
    &lt;Message>
      The service ServiceTemplate has stopped.

      More Information:
      Excpetion Type:
      Base Type:
      Stack Trace:
      at ServiceTemplate.Service.ServiceProcess.OnStop()
      at System.ServiceProcess.ServiceBase.DeferredStop()
      at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]&amp; outArgs)
      at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
      at System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(Object o)
      at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
      at System.Threading._ThreadPoolWaitCallback.PerformWaitCallbackInternal(_ThreadPoolWaitCallback tpWaitCallBack)
      at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback(Object state)
    &lt;/Message>
    &lt;Level>Information&lt;/Level>
    &lt;Task>General&lt;/Task>
    &lt;Opcode>&lt;/Opcode>
    &lt;Channel>&lt;/Channel>
    &lt;Provider>&lt;/Provider>
    &lt;Keywords>
      &lt;Keyword>Classic&lt;/Keyword>
    &lt;/Keywords>
  &lt;/RenderingInfo>
&lt;/Event>
</pre>
<p>Of course you may not want that much detail in your event log for informational messages like this one.  The easiest way to achieve that is to separate the errors from the exceptions by creating another resx file with a different facility id (It can use the same event log/source, or a new one).  For some uses this much detail is more than you want even for exceptions, but it should be obvious enough now how to modify this to prune out the data you don&#8217;t want.  Our service is fairly complete now, it installs, run, logs, etc.  We have a little more work to do in the service behavior itself to support some nice-to-have things like pause/continue, custom messages, etc.  </p>
<p>Continued on &#8220;<a href="http://csharptest.net/?p=990">Building a Windows Service – Part 7: Finishing touches</a>&#8220;</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service – Part 5: Adding command-line installation</title>
		<link>http://csharptest.net/968/building-a-windows-service-part-5-adding-command-line-installation/</link>
		<comments>http://csharptest.net/968/building-a-windows-service-part-5-adding-command-line-installation/</comments>
		<pubDate>Sat, 19 Nov 2011 16:05:41 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=968</guid>
		<description><![CDATA[Continued from &#8220;Building a Windows Service – Part 4: Extending the Service Installer&#8221; So with our installer working it would be nice to have a way to just run the install right from the command-line. There are several options here, one way would be to use the Process object, set the start parameters to not <a href='http://csharptest.net/968/building-a-windows-service-part-5-adding-command-line-installation/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Continued from &#8220;<a href="http://csharptest.net/?p=955">Building a Windows Service – Part 4: Extending the Service Installer</a>&#8221;</p>
<p>So with our installer working it would be nice to have a way to just run the install right from the command-line.  There are several options here, one way would be to use the <a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx" target="_blank">Process</a> object, set the start parameters to not use shell execute, and just run and wait for exit.  The other option, though a little &#8216;hackish&#8217; is to leverage the fact that InstallUtil itself is a managed application.  Because it is managed we can simply take the Assembly&#8217;s full path and hand it over to the <a href="http://msdn.microsoft.com/en-us/library/sxx9f4c2.aspx" target="_blank">AppDomain.ExecuteAssembly</a> method.  The nice thing about this approach is that we can capture and redirect output (via <a href="http://msdn.microsoft.com/en-us/library/system.console.setout.aspx" target="_blank">Console.SetOut</a>()) or just let it do it&#8217;s thing.  In addition, we have the luxury of not needing to encode and escape the command-line arguments, instead we just supply them as a string array.  So let&#8217;s build a little utility class to deal with this for us:</p>
<pre class="brush:csharp">
class InstallUtil
{
    private readonly AssemblyName _assemblyName;
    private readonly string _baseDirectory;
    private readonly string _fileName;
    private readonly string _installUtilExe;

    public InstallUtil(Assembly assembly)
    {
        _assemblyName = assembly.GetName();
        _fileName = Path.GetFullPath(assembly.Location);
        _baseDirectory = Path.GetDirectoryName(_fileName);

        _installUtilExe = Path.GetFullPath(Path.Combine(RuntimeEnvironment.GetRuntimeDirectory(), "InstallUtil.exe"));
        if (!File.Exists(_installUtilExe))
            throw new FileNotFoundException("InstallUtil.exe not found.", _installUtilExe);
    }

    public void Install(IEnumerable&lt;string> moreargs)
    {
        if (0 != Run(true, moreargs))
            throw new ApplicationException(String.Format("InstallUtil failed to install {0}.", _assemblyName.Name));
    }

    public void Uninstall(IEnumerable&lt;string> moreargs)
    {
        if (0 != Run(false, moreargs))
            Console.Error.WriteLine("InstallUtil failed to uninstall {0}.", _assemblyName.Name);
    }

    private int Run(bool install, IEnumerable&lt;string> moreargs)
    {
        string apppath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
        string appdata = Path.Combine(apppath, _assemblyName.Name);
        if (!Directory.Exists(appdata))
            Directory.CreateDirectory(appdata);

        List&lt;string> arguments = new List&lt;string>(moreargs);
        if (!install)
            arguments.Add("/uninstall");
        arguments.AddRange(new []
                               {
                                   "/ShowCallStack=true",
                                   String.Format("/LogToConsole=true"),
                                   String.Format("/LogFile={0}", Path.Combine(appdata, "install.log")),
                                   String.Format("/InstallStateDir={0}", _baseDirectory),
                                   String.Format("{0}", _fileName),
                               });

        int result = AppDomain.CurrentDomain.ExecuteAssembly(
                _installUtilExe,
                AppDomain.CurrentDomain.Evidence,
                arguments.ToArray()
                );

        return result;
    }
}
</pre>
<p>And then we can simply crack open our Commands class from part 1 and add two more static methods:</p>
<pre class="brush:csharp">
public static void Install(ICollection&lt;string> args)
{
    new InstallUtil(typeof (Program).Assembly)
        .Install(args);
}

public static void Uninstall(ICollection&lt;string> args)
{
    new InstallUtil(typeof(Program).Assembly)
        .Uninstall(args);
}
</pre>
<p>Following that we add these methods to Program&#8217;s Actions dictionary and we are done.  Now we can simply run our service exe with the commands we defined:</p>
<pre>
C:\Projects\ServiceTemplate> ServiceTemplate.exe install
C:\Projects\ServiceTemplate> ServiceTemplate.exe uninstall
</pre>
<p>Continued on &#8220;<a href="http://csharptest.net/?p=977">Building a Windows Service – Part 6: Adding resources and event logging</a>&#8221;</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service – Part 4: Extending the Service Installer</title>
		<link>http://csharptest.net/955/building-a-windows-service-part-4-extending-the-service-installer/</link>
		<comments>http://csharptest.net/955/building-a-windows-service-part-4-extending-the-service-installer/</comments>
		<pubDate>Sat, 19 Nov 2011 16:04:26 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=955</guid>
		<description><![CDATA[Continued from &#8220;Building a Windows Service &#8211; Part 3: Creating a Service Installer&#8221; In the previous post we created a rough draft of our service installer. In this post we will focus on extending the capabilities of the default ServiceInstaller class and enhancing the behavior of the default class. Here are the goals: Use declarative <a href='http://csharptest.net/955/building-a-windows-service-part-4-extending-the-service-installer/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Continued from &#8220;<a href="http://csharptest.net/?p=858">Building a Windows Service &#8211; Part 3: Creating a Service Installer</a>&#8221;</p>
<p>In the previous post we created a rough draft of our service installer.  In this post we will focus on extending the capabilities of the default ServiceInstaller class and enhancing the behavior of the default class.  Here are the goals:</p>
<ol>
<li>Use declarative attributes on our service to define display name, description etc</li>
<li>Add the ability to control the services command-line arguments during install</li>
<li>Add the ability to set the DelayAutoStart flag on the service (already available in .NET 4.0)</li>
<li>Add the ability to control the ShutdownTimeout for the service</li>
<li>Add the ability to control the failure auto-restart options of the service</li>
<li>Customize the service&#8217;s access control during installation</li>
<li>Allow settings to be controlled by the command-line when appropriate</li>
<li>Extend the command-line help text to provide help information for the settings available</li>
</ol>
<p>So that is a big to-do list so let&#8217;s get started.  First up we need a simple attribute to define some service specific things.  Currently I&#8217;m using the following to define the default startup mode for the service and just reusing the System.ComponentModel&#8217;s attributes for DisplayName and Description.  The ServiceAccessAttribute currently depends on a custom enumeration, <a href="http://csharptest.net/wp-content/uploads/2011/11/ServiceAccessRights.cs_.txt" target="_blank">ServiceAccessRights</a>, created from <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx#access_rights_for_the_service_control_manager" target="_blank">these values</a>.  </p>
<pre class="brush:csharp">
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ServiceAttribute : Attribute
{
    public readonly string ServiceName;
    public ServiceStartMode StartMode = ServiceStartMode.Manual;
    public int AutoRestartAttempts = 0;
    public int AutoRestartDelayMilliseconds = 1000;
    public int ResetFailureDelaySeconds = 86400;

    public ServiceAttribute() : this(null) { }
    public ServiceAttribute(string serviceName)
    {
        ServiceName = serviceName;
    }
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class ServiceAccessAttribute : Attribute
{
    public readonly WellKnownSidType Sid;
    public readonly AceQualifier Qualifier;
    public readonly ServiceAccessRights AccessMask;

    public ServiceAccessAttribute(WellKnownSidType sid, AceQualifier qualifier, ServiceAccessRights accessMask)
    {
        Sid = sid;
        Qualifier = qualifier;
        AccessMask = accessMask;
    }
}

//And apply the attributes on our service class as follows:
[DisplayName("My Service Name")]
[Description("This is a description of the service")]
[Service("testSvc", StartMode = ServiceStartMode.Automatic, AutoRestartAttempts = 2)]
[ServiceAccess(WellKnownSidType.BuiltinAdministratorsSid, AceQualifier.AccessAllowed, ServiceAccessRights.SERVICE_ALL_ACCESS)]
[ServiceAccess(WellKnownSidType.BuiltinUsersSid, AceQualifier.AccessAllowed, ServiceAccessRights.GENERIC_READ | ServiceAccessRights.GENERIC_EXECUTE)]
class ServiceImplementation : IDisposable
{
    ...
</pre>
<p>The ServiceAttribute exposes a default constructor as well as one that takes a service name.  Using the default constructor no service name will be defined unless the command-line option is specified.  Now that we have the attributes defined we can create a derivation of the ServiceInstaller to handle our customization.  Unfortunately installers are not compatible with generics as so we can&#8217;t use that, but a simple type argument for the constructor will suffice.  During construction we will use reflection to interrogate the service type for the attributes we defined.  The values found in those attributes will be copied to properties of this class, or it&#8217;s base class for use during installation.  </p>
<pre class="brush:csharp" style="max-height:100px">
    public class CustomServiceInstaller : ServiceInstaller
    {
        public CustomServiceInstaller(Type serviceType)
        {
            foreach (ServiceAttribute attr in serviceType
                .GetCustomAttributes(typeof(ServiceAttribute), true))
            {
                if (!String.IsNullOrEmpty(attr.ServiceName))
                    ServiceName = attr.ServiceName;

                StartType = attr.StartMode;
                AutoRestartAttempts = attr.AutoRestartAttempts;
                AutoRestartDelayMilliseconds = attr.AutoRestartDelayMilliseconds;
                ResetFailureDelaySeconds = attr.ResetFailureDelaySeconds;
            }

            foreach (DisplayNameAttribute attr in serviceType
                .GetCustomAttributes(typeof(DisplayNameAttribute), true))
                DisplayName = attr.DisplayName;

            foreach (DescriptionAttribute attr in serviceType
                .GetCustomAttributes(typeof(DescriptionAttribute), true))
                Description = attr.Description;

            List<serviceaccessattribute> aces = new List</serviceaccessattribute><serviceaccessattribute>();
            foreach (ServiceAccessAttribute attr in serviceType
                .GetCustomAttributes(typeof(ServiceAccessAttribute), true))
                aces.Add(attr);

            if (aces.Count > 0)
                ServiceAccess = aces.ToArray();
        }

        [DefaultValue("")]
        [Description("Gets or sets the command-line arguments provided to the service executable.")]
        public string ServiceArguments { get; set; }

        [DefaultValue(false)]
        [Description("Gets or sets a value to delay the service startup.")]
        public bool DelayAutoStart { get; set; }

        [DefaultValue(300)]
        [Description("Gets or sets the timeout in seconds for a service shutdown.")]
        public int ShutdownTimeoutSeconds { get; set; }

        [Description("Gets or sets the access control entries to be defined for the service.")]
        public ServiceAccessAttribute[] ServiceAccess { get; set; }

        [DefaultValue(0)]//no restart
        [Description("Gets or sets the number of times to automatically reset the service, 0, 1, 2, or 3.")]
        public int AutoRestartAttempts { get; set; }

        [DefaultValue(1000)]//1 second
        [Description("Gets or sets the milliseconds to delay between failure and automatic restart.")]
        public int AutoRestartDelayMilliseconds { get; set; }

        [DefaultValue(86400)]//24 hours
        [Description("Gets or sets the time in seconds after which to reset the failure count to zero if there are no failures.")]
        public int ResetFailureDelaySeconds { get; set; }
</serviceaccessattribute></pre>
<p>So now for the install right?  Well not exactly, we are going to need a few helpers to get there.  The first thing we want to do is to build a routine to populate all the properties on this class from the Context.Parameters collection.</p>
<pre class="brush:csharp">
private void FillSettings(StringDictionary arguments)
{
    foreach (PropertyInfo pi in GetType().GetProperties())
    {
        if(arguments.ContainsKey(pi.Name))
        {
            object value = Convert.ChangeType(arguments[pi.Name], pi.PropertyType,
                                              System.Globalization.CultureInfo.InvariantCulture);
            pi.SetValue(this, value, null);
        }
    }
}
</pre>
<p>Then of course we actually need to enforce the service name exists and is not empty.  Normally this value would always be provided on the command-line for a service install and pulled from the savedState collection when performing a Rollback or Uninstall.  The reality is that InstallUtil&#8217;s data store is not the most trustworthy of things.  As such, we will always allow the command-line to override the service name for install and uninstall.  There might be a danger here of using this as a generic service removal tool; however, if they have admin rights they could accomplish the same from regedit so the user get&#8217;s what he asks for :).  If we were truly worried about it we could verify that the service was indeed bound to the executable path for the assembly. Anyway here is our GetServiceName routine.</p>
<pre class="brush:csharp">
public string GetServiceName(StringDictionary parameters) { return GetServiceName(parameters, null, ServiceName); }
private string GetServiceName(IDictionary savedState) { return GetServiceName(Context.Parameters, savedState, ServiceName); }
private static string GetServiceName(StringDictionary parameters, IDictionary savedState, string defaultValue)
{
    string name = parameters["ServiceName"];
    if (String.IsNullOrEmpty(name) &#038;&#038; savedState != null)
        name = (string)savedState["ServiceName"];
    if (String.IsNullOrEmpty(name))
        name = defaultValue;

    if (String.IsNullOrEmpty(name))
        throw new ArgumentException("Missing required parameter 'ServiceName'.");
    return name;
}
</pre>
<p>The public overload for this allows us to use the same routine from the parent installer to obtain the correct service name.  The other private overload is going to be used by us during install.  First let&#8217;s look at the easy stuff, here are the overloads that use the above routines to make this install work.</p>
<pre class="brush:csharp">
public override void Install(IDictionary stateSaver)
{
    FillSettings(Context.Parameters);
    stateSaver["ServiceName"] = ServiceName = GetServiceName((IDictionary)null);

    //run the install to completion
    base.Install(stateSaver);

    //now we need to augment the installation options
    using (ServiceController svc = new ServiceController(ServiceName))
    {
        Win32Services.SetServiceExeArgs(svc, Context.Parameters["assemblypath"], ServiceArguments);
        Win32Services.SetDelayAutostart(svc, DelayAutoStart);
        Win32Services.SetShutdownTimeout(svc, TimeSpan.FromSeconds(ShutdownTimeoutSeconds));
        if (ServiceAccess != null)
            Win32Services.SetAccess(svc, ServiceAccess);
        if (AutoRestartAttempts > 0)
            Win32Services.SetRestartOnFailure(svc, AutoRestartAttempts, AutoRestartDelayMilliseconds, ResetFailureDelaySeconds);
    }
}

public override void Commit(IDictionary savedState)
{
    ServiceName = GetServiceName(savedState);
    base.Commit(savedState);
}

public override void Uninstall(IDictionary savedState)
{
    ServiceName = GetServiceName(savedState);
    base.Uninstall(savedState);
}

public override void Rollback(IDictionary savedState)
{
    ServiceName = GetServiceName(savedState);
    base.Rollback(savedState);
}
</pre>
<p>Yep easy and clean with the exception of those Win32Services methods&#8230;  Not wanting to bloat this post with a bunch of pinvoke junk, I&#8217;ve just uploaded it so you can <a href="http://csharptest.net/wp-content/uploads/2011/11/Win32Services.cs_.txt" target="_blank">click here to view Win32Services.cs</a>.</p>
<p>So this wraps up most of our installer work with the EventLog stuff still remaining.  We will deal with that at a later time, but right now we can build, install and uninstall service and finally it should all run with a few small changes to the main installer.  So cracking open the installer we wrote in the last post we will start by removing the Rollback and Uninstall methods.  Then we need to change the type of the _installService property to be our new CustomServiceInstaller passing in the type of our decorated service (ServiceImplementation) to the constructor.  The assignment of the StartType property can also be removed from the constructor.  Finally we need to retool the Install method a little.  We are going to remove the assignment of the ServiceName and DisplayName properties as well as the manipulation of the savedState.  We will still need to obtain the service name so that we can inject it onto the command-line.  So here is what our new Install method looks like:</p>
<pre class="brush:csharp">
public override void Install(IDictionary stateSaver)
{
    if (Context.Parameters.ContainsKey("username"))
        _installProcess.Account = ServiceAccount.User;

    string svcName = _installService.GetServiceName(Context.Parameters);
    _installService.ServiceArguments = ("-service " + svcName + " " + _installService.ServiceArguments).Trim();

    //run the install
    base.Install(stateSaver);
}
</pre>
<p>Now when our service is run by the SCM it always runs the &#8216;-service&#8217; command we added at the end of part 2 and always provides the service name to run as.  We now have a working service and installer!  The next thing to do is to modify those command-line options again so that we can install and uninstall by simply running the executable.</p>
<p>Continued on &#8220;<a href="http://csharptest.net/?p=968">Building a Windows Service – Part 5: Adding command-line installation</a>&#8220;</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service &#8211; Part 3: Creating a Service Installer</title>
		<link>http://csharptest.net/858/building-a-windows-service-part-3-creating-a-service-installer/</link>
		<comments>http://csharptest.net/858/building-a-windows-service-part-3-creating-a-service-installer/</comments>
		<pubDate>Sat, 19 Nov 2011 16:03:56 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=858</guid>
		<description><![CDATA[Continued from &#8220;Building a Windows Service &#8211; Part 2: Adding a Service to a Console Application&#8221; We are going to take this in two steps, first the minimal we need to do to make something *sorta* work, then we are going to get fancy. This post will focus on the first part, making something work. <a href='http://csharptest.net/858/building-a-windows-service-part-3-creating-a-service-installer/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Continued from &#8220;<a href="http://csharptest.net/?p=850">Building a Windows Service &#8211; Part 2: Adding a Service to a Console Application</a>&#8221;</p>
<p>We are going to take this in two steps, first the minimal we need to do to make something *sorta* work, then we are going to get fancy.  This post will focus on the first part, making something work.  To build a service install there are two choices, you can simply open the service in the designer view and right-click to select &#8220;Add Installer&#8221;.  This really doesn&#8217;t do much to benefit you IMO, so we are just going to write one from scratch.  The first thing we need is just a basic installer&#8230;</p>
<pre class="brush:csharp">
[RunInstaller(true)]
public class Installer : System.Configuration.Install.Installer
{
}
</pre>
<p>During the construction of this installer we need to create and initialize our installers.  This is pretty easy to do, we add a few variables to store our child installers and add those to the Installers collection.  For a service you need two installers, the first is a <a href="http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceprocessinstaller.aspx" target="_blank">ServiceProcessInstaller</a> to define the credentials the service will use.  Next we will need to add a <a href="http://msdn.microsoft.com/en-us/library/system.serviceprocess.serviceinstaller.aspx" target="_blank">ServiceInstaller</a> to define the service name, display name, description, etc.  This class is pretty weak in it&#8217;s abilities and we will look at extending it in the next post.  Until then we&#8217;ll just use what we have for a bit.  </p>
<pre class="brush:csharp">
private readonly ServiceProcessInstaller _installProcess;
private readonly ServiceInstaller _installService;

public Installer()
{
    _installProcess = new ServiceProcessInstaller();
    _installProcess.Account = ServiceAccount.NetworkService;

    _installService = new ServiceInstaller();
    _installService.StartType = ServiceStartMode.Automatic;

    //Remove built-in EventLogInstaller:
    _installService.Installers.Clear(); 

    Installers.Add(_installProcess);
    Installers.Add(_installService);
}
</pre>
<p>You&#8217;ll notice a couple of odd things here.  The first is that we did not assign the ServiceName or DisplayName to a value.  This is because we actually want this value to come from the command-line during installation.  The second is that we clear all child installers of the ServiceInstaller class.  This is due to the rather poor default event log installer, we are going to deal with that later.  </p>
<p>So how can we install a service without a value for ServiceName?  Well, put simply you can&#8217;t, we aren&#8217;t done yet.  We want to retrieve this from the context parameters during install.  This is easy to do, we just need to override the various install methods (Install, Uninstall, and Rollback).  Let&#8217;s first look at the Install routine as it will differ slightly from the Uninstall and Rollback.</p>
<pre class="brush:csharp">
public override void Install(IDictionary stateSaver)
{
    if (Context.Parameters.ContainsKey("username"))
        _installProcess.Account = ServiceAccount.User;

    string svcName = Context.Parameters["ServiceName"];
    if (String.IsNullOrEmpty(svcName))
        throw new ArgumentException("Missing required parameter 'ServiceName'.");
    _installService.ServiceName = svcName;
    _installService.DisplayName = svcName;
    stateSaver.Add("ServiceName", svcName);

    //run the install
    base.Install(stateSaver);
}
</pre>
<p>There you have it, let&#8217;s take it apart for a second.  The first thing we do is check the parameters for the existence of a &#8216;username&#8217; argument.  This argument (along with the &#8216;password&#8217; argument) is for specifying the credentials used to run the service.  We initialized the ServiceProcessInstaller&#8217;s Account setting to be the NetworkService account.  Obviously if the user supplied a username they don&#8217;t want that account, unfortunately the installer is too dumb to figure that out so we change the account type here to a user-defined account.</p>
<p>The next thing we need from the parameters is our service&#8217;s name, the &#8216;ServiceName&#8217; argument.  This isn&#8217;t an option for us since we did not define a default (although you could if you desired).  Once we have a service name we have to use that weird &#8216;stateSave&#8217; thing we were given.  We must place our service name in this bag in order to retrieve it later during uninstall and rollback.  Let&#8217;s look at those now&#8230;</p>
<pre class="brush:csharp">
public override void Rollback(IDictionary savedState)
{
    _installService.ServiceName = (string)savedState["ServiceName"];
    base.Rollback(savedState);
}

public override void Uninstall(IDictionary savedState)
{
    _installService.ServiceName = (string)savedState["ServiceName"];
    base.Uninstall(savedState);
}
</pre>
<p>We now have something we can install, but we need to provide the service name when installing:</p>
<pre>
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /ServiceName=foo ServiceTemplate.exe
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /uninstall ServiceTemplate.exe
</pre>
<p>So now we can install this service, but we can not run it.  Why?  Because our service that we wrote in the last post requires specific arguments to run as a service, and it must be told what service name it will be responding to.  To make all that work we need to seriously overhaul the default service installer.  </p>
<p>Continued on &#8220;<a href="http://csharptest.net/?p=955">Building a Windows Service – Part 4: Extending the Service Installer</a>&#8220;</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service &#8211; Part 2: Adding a Service to a Console Application</title>
		<link>http://csharptest.net/850/building-a-windows-service-part-2-adding-a-service-to-a-console-application/</link>
		<comments>http://csharptest.net/850/building-a-windows-service-part-2-adding-a-service-to-a-console-application/</comments>
		<pubDate>Sat, 19 Nov 2011 16:02:09 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=850</guid>
		<description><![CDATA[Continued from &#8220;Building a Windows Service &#8211; Part 1: Getting started&#8221; So now that we&#8217;ve built ourselves a console application it&#8217;s time to add the service. Doing this is strait-forward and we can use the Visual Studio template for both the service and a basic installer. The first thing I&#8217;ve done is to create a <a href='http://csharptest.net/850/building-a-windows-service-part-2-adding-a-service-to-a-console-application/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Continued from &#8220;<a href="http://csharptest.net/?p=837">Building a Windows Service &#8211; Part 1: Getting started</a>&#8221;</p>
<p><a class="alignright" href="http://csharptest.net/wp-content/uploads/2011/11/CreateServiceItem.png"><img class="alignnone size-medium wp-image-840" title="CreateServiceItem" src="http://csharptest.net/wp-content/uploads/2011/11/CreateServiceItem-300x164.png" alt="" width="300" height="164" /></a> So now that we&#8217;ve built ourselves a console application it&#8217;s time to add the service. Doing this is strait-forward and we can use the Visual Studio template for both the service and a basic installer. The first thing I&#8217;ve done is to create a folder called &#8220;Service&#8221; in my project where I intend to keep all the service specific aspects of this project. Right-clicking that folder and adding a &#8220;Windows Service&#8221; will give us a basic shell to work within. The first thing you should see is a grey designer window, if not you can select the project item for the service we created and select &#8220;View Designer&#8221;. Right-clicking on this grey designer window, selecting properties allows you to configure several aspects of the service, &#8220;CanShutdown&#8221;, &#8220;CanStop&#8221;, etc, etc&#8230; Set these up as desired, I just turn them all on except for &#8220;AutoLog&#8221; which I disable. The reason is that I want to control when and how the log is written rather than using the default.</p>
<p>We have a lot of work to do here and to start with we are going move the generated methods in the .Designer.cs file to the actual source file.  Then we will delete all the files below the service (the .Designer.cs, and .resx if it exists).  We are not going to hard-code our service name so that we can support multiple instances and this is the primary reason for removing the designer files.  Allowing the service name to be changed dynamically by command-line options means that we can install multiple named instances on a single host.  This, just like the console option, is primarily a development aid; however, it can also be very useful in a production environment.  So here is what my service looks like:</p>
<pre class="brush:csharp">class ServiceProcess : ServiceBase
{
    private readonly string[] _arguments;
    private ServiceImplementation _service;

    public ServiceProcess(IEnumerable arguments)
    {
        _arguments = arguments.ToArray();
        if (_arguments.Length == 0 || String.IsNullOrEmpty(_arguments[0]))
            throw new ArgumentException("Required parameter service name not provided.");

        AutoLog = false;
        CanStop = true;
        CanShutdown = true;
        CanHandlePowerEvent = true;
        CanHandleSessionChangeEvent = true;
        CanPauseAndContinue = true;

        ServiceName = _arguments[0];
    }

    private void InitializeComponent()
    {
        // For Designer only:
        ServiceName = "ServiceName";
    }

    protected override void Dispose(bool disposing)
    {
        if (_service != null)
            _service.Dispose();
        _service = null;

        base.Dispose(disposing);
    }

    protected override void OnStart(string[] args)
    {
        OnStop();
        _service = new ServiceImplementation();

        List allarguments = new List(_arguments);
        if(args != null &amp;&amp; args.Length &gt; 0)
            allarguments.AddRange(args);

        _service.Start(allarguments);
    }

    protected override void OnStop()
    {
        if(_service != null)
        {
            _service.Stop();
            _service.Dispose();
            _service = null;
        }
    }
}
</pre>
<p>You will probably notice the InitializeComponent() method has been left so as to initialize the service name for the designer.  This really is not required as we aren&#8217;t planning to use the designer to change properties.  The reason for still wanting to use the designer will be obvious in the next step as we build the installer.  Without the service name the designer will fail to generate an installer for us.</p>
<p>Now that we have a ServiceBase derived class, we need a way to run this service from the command-line.  To do this we will add a new method to the Commands class we created in step 1 and then add an entry to the dictionary map.  The new method we will add first called &#8220;RunAsService&#8221;:</p>
<pre class="brush:csharp">public static void RunAsService(ICollection<string> args)
{
    ServiceBase.Run(new Service.ServiceProcess(args));
}
</string></pre>
<p>Then as I said we need to add a command name and entry for this method into the Actions map.  I chose to use &#8220;-service&#8221; as the command name, you can choose anything you like.</p>
<pre class="brush:csharp">
              {"-service", Commands.RunAsService},
</pre>
<p>We now have a working service that can&#8217;t be installed.  The default .NET service installer will not be able to install this service either so we need a good bit of work in the install.  Let&#8217;s take a look at getting the installer together in the next step.</p>
<p>Continued on &#8220;<a href="http://csharptest.net/?p=858">Building a Windows Service &#8211; Part 3: Creating a Service Installer</a>&#8220;</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a Windows Service &#8211; Part 1: Getting started</title>
		<link>http://csharptest.net/837/building-a-windows-service-part-1-getting-started/</link>
		<comments>http://csharptest.net/837/building-a-windows-service-part-1-getting-started/</comments>
		<pubDate>Sat, 19 Nov 2011 16:01:33 +0000</pubDate>
		<dc:creator>roger</dc:creator>
				<category><![CDATA[Other]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://csharptest.net/?p=837</guid>
		<description><![CDATA[This is the first of what I hope to be a multi-part deep-dive into building managed Windows services. As with any task the first thing we need to discover is the why and what for. Services can be very useful for a number of situations. On the client side of things one might be using <a href='http://csharptest.net/837/building-a-windows-service-part-1-getting-started/'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>This is the first of what I hope to be a multi-part deep-dive into building managed Windows services. As with any task the first thing we need to discover is the why and what for. Services can be very useful for a number of situations. On the client side of things one might be using them for a memory cache or offline cache of remote service calls. On the server side they are often used to move long-running or high-risk processes out of the IIS environment. In either the client or server they can also be used to elevate or suppress the access rights of the current user. Another use is running non-stop tasks that occur even when all users are signed out on the client. Regardless of your reasons for moving code OOP (Out-of-Process) into a service there are a few things that are difficult to get right. This series of posts attempts to address those not-so-obvious things that need to be done for a service. The following outline is what I intend to address:</p>
<ol>
<li>Building a service that can also be used from the console</li>
<li>Proper event logging of service startup/shutdown and other activities</li>
<li>Allowing multiple instances by using command-line arguments</li>
<li>Self installation of service and event log</li>
<li>Proper event logging of service exceptions and errors</li>
<li>Controlling of start-up, shutdown and restart options</li>
<li>Handling custom service commands, power, and session events</li>
<li>Customizing service security and access control</li>
</ol>
<p>Getting started on this rough sketch is really fairly easy. If you&#8217;ve been working in .NET for any period of time you have probably already created a service at some time. We are going to do that. Instead we are going to build the service project rather manually giving us the opportunity to discuss things as we go.<br />
<a class="alignright" href="http://csharptest.net/wp-content/uploads/2011/11/CreateConsoleApp.png"><img class="alignnone size-medium wp-image-838" title="CreateConsoleApp" src="http://csharptest.net/wp-content/uploads/2011/11/CreateConsoleApp-300x178.png" alt="" width="300" height="178" /></a></p>
<p>So let&#8217;s first just create a plain-old &#8220;Console Application&#8221;. By using a console application instead of the project template for a service we miss out on some of the built-in defaults.  That IMHO is not all bad.  Once created we are first going to focus on two primary concerns, 1) being able to &#8216;run&#8217; the service in a console app, and 2) getting help on the command-line.  To accomplish this we are going to insist on at least one argument being provided, the command to run.  So we need a little help to dispatch those commands into the appropriate method to handle the request.  We will accomplish this by using a name/value lookup (IDictionary&lt;,&gt;) to turn command names into an action delegate.  Before we can do that however, we first need those action delegate methods.  So before we do anything with the Program class or Main function we are going to create a &#8220;Commands&#8221; class and stub out some methods like so:</p>
<pre class="brush:csharp">static class Commands
{
    public static void Help(ICollection&lt;string&gt; args)
    { /* todo */ }

    public static void Run(ICollection&lt;string&gt; args)
    { /* todo */ }
}</pre>
<p>I chose to use an ICollection&lt;string&gt; here instead of a string[] as it allows me to avoid a few unnecessary ToArray() calls. Now that we have this we can go back to the Program class and declare a static lookup table for dispatching commands. This is trivial with C#3&#8242;s dictionary initializer:</p>
<pre class="brush:csharp">class Program
{
    private static readonly Dictionary&lt;string, Action&lt;ICollection&lt;string&gt;&gt;&gt; Actions
        = new Dictionary&lt;string, Action&lt;ICollection&lt;string&gt;&gt;&gt;(StringComparer.OrdinalIgnoreCase)
              {
                  {"Help", Commands.Help},
                  {"Run", Commands.Run},
              };</pre>
<p>Easy enough right?  Should be obvious where I&#8217;m going with this to most of you.  All I need now is the Main function to lookup the command and dispatch to it.  If the lookup fails we will fall-back to the &#8220;Help&#8221; command.  The first thing to do withe the Main function is change it&#8217;s return type to int.  I&#8217;m not sure what got me in the habit of this, I guess it&#8217;s just my unease with using static data like Environment.ExitCode.  Anyway this is what my Main routine will look like for a while:</p>
<pre class="brush:csharp">static int Main(string[] rawArgs)
{
    int exitCode = 1;
    try
    {
        List&lt;string&gt; args = new List&lt;string&gt;(rawArgs);
        string cmdName = String.Empty;
        if(args.Count &gt; 0)
        {
            cmdName = args[0];
            args.RemoveAt(0);
        }

        Action&lt;ICollection&lt;string&gt;&gt; cmdAction;
        if (!Actions.TryGetValue(cmdName, out cmdAction))
            cmdAction = Commands.Help;

        cmdAction(args);

        exitCode = 0;
    }
    catch (System.Threading.ThreadAbortException)
    { }
    catch (Exception ex)
    {
        Console.Error.WriteLine(ex.ToString());
    }

    Environment.ExitCode = exitCode;
    return exitCode;
}</pre>
<p>Next up is getting a stub implementation of the service class itself. Unfortunately ServiceBase is not always a very pleasant thing to work with from our console application. Due to this we are going to introduce our own class to mirror the service behavior&#8217;s available in the ServiceBase class. For starters though we will keep it simple and just get start/stop working. First we add a new C# class with the following methods:</p>
<pre class="brush:csharp">class ServiceImplementation : IDisposable
{
    public void Start(ICollection&lt;string> arguments)
    { /* todo */ }

    public void Stop()
    { /* todo */ }

    public void Dispose()
    { /* todo */ }
}</pre>
<p>With this to stub the service calls we can now implement that Run method we added to the Commands class. This will be our entry-point when running from the console:</p>
<pre class="brush:csharp">public static void Run(ICollection&lt;string> args)
{
    using(Service.ServiceImplementation svc = new Service.ServiceImplementation())
    {
        svc.Start(args);

        Console.WriteLine("Press [Enter] to exit...");
        Console.ReadLine();

        svc.Stop();
    }
}</pre>
<p>You should be able to compile and run at this point, not that there is any point in doing that :)</p>
<p>Continued on &#8220;<a href="http://csharptest.net/?p=850">Building a Windows Service &#8211; Part 2: Adding a Service to a Console Application</a>&#8220;</p>
]]></content:encoded>
			
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
