C# Basics: Creating a Windows Service
Windows services are basically executables that performs certain functions that doesn't
require user intervention (runs in the background e.g. the ASP.net State Service) - for example, recently I
created an indexing service, that extracts text from files (using Ifilters) and stores the text within some database.
You can manage these services within your services management console, we can start/stop/pause etc these
services.
The basic structure of a service within the .net realm using C#, looks something like this:
using System.ServiceProcess; using System.Threading; namespace myWebservice { class Service : ServiceBase { static void Main() { ServiceBase.Run(new Service()); } public Service() { Thread thread = new Thread(Actions); thread.Start(); } public void Actions() { Thread.Sleep(500000); } } }
Notice that we inherited from ServiceBase, you can find this class within the System.ServiceProcess assembly & namespace. Within our entry point (void Main), we call a static method named Run from our ServiceBase class and pass a instance of our service to the method, you may also pass multiple(Array) instances of classes derived from ServiceBase to this method e.g. have multiple & different services run within one process.
You will also notice that I've created a thread within the constructor, this becomes necessary since our service needs to start up within a certain time frame, else it will time out - aborting our service - moving logic to a thread will insure that the service starts in a timely manner. Notice what happens when you call the actions method directly from within the constructor without using a thread
There is also a number of methods one can override within the derived class, onstop/onshutdown/onpause/oncontinue etc - relating to actions we can control using the services management console - some relating to system wide events - like shutting down the server/pc, or putting your laptop into sleep mode e.g. onpowerevent.
To deploy/install this service to a server/pc, create a class inherting from the installer class (available within the System.Configuration.Install assembly) like this:
using System.ComponentModel; using System.Configuration.Install; using System.ServiceProcess; [RunInstaller(true)] public class myServiceInstaller : Installer { public myServiceInstaller() { ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller(); ServiceInstaller serviceInstaller = new ServiceInstaller(); serviceProcessInstaller.Account = ServiceAccount.LocalSystem; serviceInstaller.DisplayName = "myService"; serviceInstaller.StartType = ServiceStartMode.Automatic; serviceInstaller.ServiceName = "myService"; this.Installers.Add(serviceProcessInstaller); this.Installers.Add(serviceInstaller); } }
You can create a .net installer app to deploy the service or simply install it via a batch file running the following commands:
Some tips:
Debugging:
I heard a lot of people complaining about how difficult it is to debug a service, since we can't just simply run it from visual studio - it does however becomes rather simple if we add Debugger.Break() (one of the lovely System.Diagnostics methods) to our code, this will open up a window asking us which application we wish to use in debugging our code (Visual Studio for example). (Remember to set interact with desktop within the properties of your service from the services management console)
Registry:
Something else to consider, when using the registry within services, is that generally we use a local system account (the logon for the service), which accesses different keys within the registy, than our current user (Generally you can access keys from the "HKEY_USERS\.DEFAULT" key).
Remote Desktop:
When the "Allow Service to interact with desktop" checkbox is ticked and you're attempting to interact with the desktop via remote desktop the interaction UI will only appear in the console/admin session.
e.g.
mstsc /console (XP/2003)
mstsc -admin (Vista/7/2008)
Date - 2010-02-28 21:48:06
Comments - 0
ASP.net - Ajax.Net: PageMethods
Source Code
PageMethods in Ajax.net allow us to call server-side methods (e.g. C#, VB.net) from within
client-side functions (e.g. JavaScript).
There is one limitation I would like to point out, before continuing with my post - the fact that
one can't access webcontrols (e.g. GridViews, DropDownList), from within the server-side
method we're calling.
Which is an obvious limitation; in regards to maintaining ViewState, ControlState, re-rendering of
controls etc - since we're working with which
is essentially dead objects. (We'd need to pass state to our method, rebuild our page with its various
control collections re-instate it with our background request (Ajax), eventually altering the current page in
view, including its various states - potentially defeating the whole purpose of what Ajax is all about, since
we'd simply be recreating postbacks, not very effective)
Note: we can however access the rendered controls client-side using the DOM, which will be demonstrated
in this post.
In this post, we're going to create a crude little web application, thats going to look something like this:
- The user can delete an item from the listbox, by selecting/highlighting an item and pressing the delete key (on their keyboard) - via PageMethod
- The user can add a new item to the lisbox - via PageMethod & demonstrating JSON (JavaScript object notation)
The first thing you need to do (within your framework 3.5 enabled web application/site), is add a scriptmanager to your page (or masterpage), set the EnablePageMethods property to true.
<asp:ScriptManager runat="server" ID="smAjax" EnablePageMethods="true"></asp:ScriptManager>
In order to make server-side methods callable, you'll need to define them as public static and mark them with the WebMethod attribute (which we generally use in webservices), notice the server-side method responsible for removing items from the database:
[WebMethod] public static void delete_lbxFriends(Int32 friendID) { using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Default"].ConnectionString)) { connection.Open(); using (SqlCommand command = new SqlCommand("removeFriend", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@friendID", friendID); command.ExecuteNonQuery(); } } }
The client-side function will look something like this:
function deleteListItem(sender, e) { if (e.keyCode == 46) { var friendID = sender.options[sender.selectedIndex].value; sender.disabled = true; PageMethods.delete_lbxFriends(friendID, succeededDeletedCallback, failedDeletedCallback, sender); } }
- The keyCode 46 represents the delete key - which we get from our triggered event
- Variable "sender" contains our dropdown/listbox
- The PageMethods object contains our callable server-side methods.
- We disable the listbox while the server is busy processing our ajax request
Notice the last three parameters "succeededDeletedCallback, failedDeletedCallback, sender" from delete_lbxFriends, succeededDeletedCallback and failedDeletedCallback represents event handlers/callbacks, the last parameter contains values that gets passed to our callback functions - in this case I am passing the dropdown/listbox object to the callback functions.
The callback functions:
function succeededDeletedCallback(result, userContext, methodName) { userContext.remove(userContext.selectedIndex); userContext.disabled = false; }
- Remove the selected item from the dropdown/listbox
- Re-enable listbox
function failedDeletedCallback(error, userContext, methodName) { if (error != null) { alert(error.get_message()); } userContext.disabled = false; }
- Inform the user that something went wrong with their request
- Re-enable the dropdown
This is how we attach the delete function to our listbox, don't be fooled by the fact that Visual Studio thinks that the onkeydown event doesn't exist - its definitely there ;)
<asp:ListBox runat="server" ID="lbxFriends" onkeydown="deleteListItem(this, event)" DataValueField="friendID" DataTextField="fullname"></asp:ListBox>
Lets have a quick look at adding an item to the listbox.
Our insert server-side method:
[WebMethod] public static Object insert_lbxFriends(friend f) { using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Default"].ConnectionString)) { connection.Open(); using (SqlCommand command = new SqlCommand("addFriend", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@firstname", f.firstname); command.Parameters.AddWithValue("@lastname", f.lastname); return command.ExecuteScalar(); } } } // Basically the class needed for our JSON "action" public class friend { public String firstname { get; set; } public String lastname { get; set; } }
The client-side function:
function addListItem() { // JSON var friend = { firstname: $get("txtfirstname").value, lastname: $get("txtlastname").value }; PageMethods.insert_lbxFriends(friend, succeededInsertedCallback, failedInsertedCallback, friend); }
And thats the just of how to use PageMethods n Ajax.net, be sure to download the source code.
Date - 2010-02-21 12:31:27
Comments - 0
First 11 12 13 14 15 16 17 18 19 20 Last / 42 Pages (83 Entries)