Self Updating Windows Service

12 08 2009

So, having written a windows service, a neat thing to do is to get it to self-update.

Now, lets say you have installed the service after some work and it is running. The service can probably poll some server/web service and find out if updates are available. If yes, then you need to get the address of the new file/files and use C#’s webclient class to download the files.

Issues – The account under which the service runs can be the bottle neck. In general if you run a service as a particular user, password changes on a domain will not play well. On the other hand, running it as a NETWORK SERVICE (since you need to access network resources) will severely limit the folders you can touch.

The easy way out is to use the all powerful Local System account. You can pretty much do anything here… including writing into the windows folders.

OK, so your service is running under Local System. You download the new files using the service itself. Now comes the updating part. The trick is to simply replace the exe files. That way, you wont really have to bother about unregistering and re-registering the service. The service retains its registration/entry in the windows registry, and the next time the service starts, its a new exe that runs… Magic :)

So, easy thing to do is to generate a simple batch script using the old service. Having downloaded the new files (with some other name), generate the batch script, and start it up (System.Diagnostic.Process.Start). The batch file should

1. Stop the old service.

2. Delete the old service exe

3. Rename the new service exe to match the old exe name (in the same location too)

4. Start the service

5. Delete itself so that the whole procedure is clean :)

Now, service starting and stopping are permissions that Local System account  has… and since it spawned the batch script, this retains those permissions too… in general, each service has its own set of security descriptions (SDDL)… use sddltranslate or something like that to view a nice description of what sc sdshow outputs on the service…

:)





Controlling Windows Services

12 08 2009

This is somewhat interesting because Windows services do not exactly behave like normal programs… meaning you cannot just install/uninstall it with some simple extraction…

A service is effectively a program that can sleep. Now consider a normal program. At any instant of time, you can clearly say that the program is doing something. Services are not like that. They don’t need to do anything. They can do stuff only on some events (like Timer ticks or on some event)… ok, with new threads and asynchronous programming etc, I guess the demarcation becomes rather weak.

Anyways, a service is basically an exe written as a service. A normal CPP file cannot be a service. The easiest way is to simply code it out in C#. Visual Studio has an inbuilt template that you can use and define your own OnStart and OnStop functions etc. Now installing a service involves putting a link to that effect in the registry. Now this installation has information about the exe that is involved with the service and also the account under which the service runs (and if the service starts automatically, delayed or manually).

To install a service – assuming you have the exe… use the sc create command. You can specify the exe path and also the account (LocalSystem is default), along with startup options, name, display name etc. In shot, this is all you need to install a service.

To run/start the service use net start <Servicename>

To stop the service use net stop <servicename>

You can equivalently start/stop the service using the Services control panel thinge. Its simpler and is one click :)

To uninstall the service do a sc delete.

Installing and uninstalling is usually done by software installers on their own… so the technique may not be so popular.

:( I found out about sc create very late in my life… I was using VS’s installutil for some time :( and at other times, using C# code… sometimes even native C dlls :( :(





EWS

29 07 2009

EWS – is exchange web-service. Its a nice little way for ANY application to communicate with an exchange server and do stuff…

How it does it manage to work with ANY application? Why SOAP of-course! Its just basic XML, so anyone can parse it, even me :)

So, if you have an exchange powered Outlook Web Access page, you need to navigate to  https://<your_web_site>/ews/service.asmx

This is basically the service that is used to do stuff. You can add a web-reference to this in your project. But remember, the Exchange server binding must be to /ews/exchange.asmx … I made this mistake today and got an exception with HTML TAGS IN IT!! Cool na? :)

Now, Push Notification. Email is usually pulled – meaning that the website or email client queries the server to check if there is any new mail. It does this a lot of times and in most cases, there is no new mail :( awwwww….

Push mail to the rescue. What you need is a web-service endpoint on your side. (I think the iPhone has this! WOW! or maybe they are doing something else). You register with the exchange server and tell it your end-point. As soon as it receives a mail or something happens in your email space, you will get a cute notification :) so, YOU get told when the mail comes as and when it comes…  neat huh?

There was a small issue that I had. Too bored to write here. Check the msdn forums. I actually found a slightly better solution than an official M$ guy who works on Exchange and even wrote the book on EWS! I feel all happy happy :)





string(Class) has strings attached

29 07 2009

I guess I kinda realized this during my early Matlab days (about a year and a half ago!)… one of the new and most “powerful” features of matlab (we thought) was its ability to dynamically change array sizes and and when more elements were added… eventually of course (thanks to the profiler), we found that this is in fact the MAIN culprit in slow running simulations.

Here’s why

Short answer – The compiler is not God.

Long answer – Well, the compiler is not God. And so, everytime a new element is added, it basically needs to reallocate ALL the data to a new location where it can fit the old array + the one new element. And it does this each time you add one element… :(

So, what do you do? Stop un-learning good old C and CODE IT WITH A CONSTANT SIZE!

Then came C#. string thinge = “my”; thinge+=” my”;

OMG that is soooo awesome! But again, it does the same thing. We didnt do too many of these things to notice the speed difference, but recently I did. Try doing this in a loop and it takes  ~8000ms for my task… preallocate and it takes ~230ms :) :) :)

Alternatives – use StringBuilder. Its kinda like a linked list, so its cool.

So, next time, think twice before using that += for strings …





iMovie is crazy

25 07 2009

So, there were these kids who were making a movie on a MAC – using iMovie. They wanted to import some video shot using some camcorder. Problem – iMovie only imports a few formats – very few – 4 to be exact… I like the number, but in my opinion this very very bad :(

I was requested to convert the movie from MPEG2 to something that it could import. Initially I tried with  my standard stuff… you know Virtual Dub and Virtual Dub Mod… but the darn thing just wouldn’t take it in… even though the video could play properly on the MAC

So, I searched… and http://www.squared5.com/ came up (MPEG Stream Clip)… neat free software. Converts to whatever iMovie imports. I used avi with Apple JPEG compression. It could import (DV didnt work. MP4 worked)… but then, the sound wouldnt (it was mp3)… so, the thing that finally worked was an avi container with Apple JPEG compression for the video and UNCOMPRESSED PCM sound (OMG!)

This just adds on to my growing decrease of respect for the MAC… first Apple expects you to PAY for the iPhone SDK… and then they make such a fuss about how easy their softwares are… yeah, I guess things get easy when they import just FOUR formats!

Compare this to Vegas… it’ll probably import EVERYTHING under the sun! Man I like Windows! :)





SqlBulkCopy

25 07 2009

So, (apparently starting a sentence with “so” is rather weird and is a characteristic of M$ employees!) when you want to READ data from an SQL database, you can just as well write your own SQL query string in plain-text on the C# side and then just ExecuteReader. It creates a reader object that can retrieve data for you sequentially in one direction – forward (which is mostly what you want anyway… ). This is rather fast too.

BUT, lets say you want to PUT data into the database. The standard way of doing this is to use INSERT statements. Since SQL 2008, the insert statement supports multiple inserts in a single statement

i.e. you can say INSERT()()()(); and it will put in multiple records. But internally, apparently it still splits it up. But hey, its one query!

Another way to do this is to use SqlBulkCopy (search for class description etc on msdn…) Basically what you do is that you frame your own DataTable with all the data you want to put in and then type-cast it into whatever BulkCopy wants and then write to database. Now, SqlBulkCopy also splits up the entire operation into chunks. There is a parameter that you can set which will do this for you. One way to copy really really large chunks of data is to populate your datatable in chunks that will get written by sqlbulkcopy…

Speed increase over single insert statements is really huge. For some 80,000 entries, the time reduced from something like 5 minutes to under 20 seconds.

Neat.





Impersonation

16 07 2009

I’ll talk of impersonation in the context of a web-application. A similar analogy may be drawn for a client side app too…

Basically, when you are running a web-site, it runs under IIS’s credentials (usually NT AUTHORITY\NETWORK SERVICE). Now this is a service account and is designed to have very limited privileges. Lets say you want to do something with higher privileges. Two possibilities

1. You want to temporarily run code as a different user on the current system (with the user existing on the current system)

2. You want to run as a different user whose account may not exist on the current system but luckily for you, you are on a domain.

Now, there are two broad ways to impersonate. In asp.net, you can mention impersonation in web.config and have the windows authenticated person automatically impersonated when he/she visits a page. But usually, if you have some SQL statements, the permissions may not be enough (hopefully they wont be! otherwise, anyone can meddle with your Database)…

So, the other way to impersonate is in code. There are lots of very simple examples on the web… ideally, it should take less than 4-5 lines of code to fully impersonate someone.  Now, you can impersonate with a User identity object that HttpContext contains. But in this case, when you try to access the person’s computer, you will still be recognized as Anonymous (you can check the target system’s event logs). To circumvent this, you will need the actual password of the person you are trying to impersonate. Use the WinApi LogonUser function. Remember, since you are on a domain, you can run LogonUser for a remote user on your system and the authentication will anyway happen at the LDAP server. So, LogonUser CAN be used for remote authentication. The access token that you get is then used to impersonate.

Doing it this way is better than a few other options. One is adding a network share. This is somewhat slow in my experience.

So, impersonate where ever needed. Its good and saves you a lot of time from worrying about privileges…





Screen Capture the mouse

18 06 2009

OK, this is rather arbit and somewhat stupid. Still…

Press Print Screen. It gives you a capture of the current screen. The mouse is missing.

Open control panel, go to mouse options then cursor options. Print Screen that, and Photoshop the mouse with some outer shadows.

I told you it was kinda arbit.





WnetAddConnection2A

18 06 2009

WNetAddConnection2A is essentially a WinAPI function that allows you to add/mount Windows share connections (Samba shares if you will)… it lets you specify a comp name, username and password. Now the problem is, once in a while, you may encounter 1219 error. This translates to multiple connections from the same comp to the remote comp – which is apparently bad in Windows. Until today, I used to restart both comps to make this go away. Dont do that. Goto command line, do a net use and see who/what is using the connections. Then do a net use * /delete to remove them all… google more to find out how to remove only what you want or better still, experiment.





Aero in Remote Desktop

29 05 2009

YES! Remote Desktop now does AREO!! now = Windows 7

Basically they put in more capabilites into the RDP client. Wanna test it? You need to access a Win 7 (or maybe even vista-not sure) comp FROM a win 7 comp… it works only then.

I need to check out how games will perform through RDP now :)