miércoles, 14 de octubre de 2009
Windows Service + Threading
//This code goes in the Service.cs:
// My class that contains all the service logic
MyThread myThread;
// the thread that will do the work private
Thread workerThread;
...
protected override void OnStart(string[] args) {
// set flag to indicate worker thread is active
myThread.ExecuteService = true;
// Create worker thread; this will invoke the WorkerFunction
workerThread = new Thread(new ThreadStart(myThread.WorkerFunction));
// start the thread workerThread.Start();
}
protected override void OnStop() {
// flag to tell the worker process to stop
myThread.ExecuteService = false;
// give it a little time to finish any pending work
workerThread.Join();
}
//This code goes on myThread class:
public void WorkerFunction() {
do{
...
} while(ExecuteService);
}
However with this code everytime after the service just started the service got stopped. Without a clue about what could the problem be I decided to get some wisdom from Google and run into this page: Windows Service Basics
The article (no so basic by the way) presents three different approches (2 of them includes threads =) ) when creating a Windows Service.With a couple of modifications to my code everything run as supposed to:
// This is a flag to indicate the service status
private bool executeService = false;
// My class that contains all the service logic
MyServiceClass myService;
// the thread that will do the work
private Thread workerThread;
...
protected override void OnStart(string[] args) {
// set flag to indicate worker thread is active
executeService = true;
// Create worker thread
workerThread = new Thread(new ThreadStart(DoWorkFunction));
// start the thread
workerThread.Start();
}
protected override void OnStop() {
// flag to tell the worker process to stop
executeService = false;
// give it a little time to finish any pending work
workerThread.Join(new TimeSpan(0,2,0));
}
public void DoWorkFunction() {
do{
myService.WorkerFunction();
} while(executeService);
Thread.CurrentThread.Abort();
}
The way I like it... nice & easy!
I really recommend to read the whole article from the en.csharp-online.net guys. It helped me with my problem and learned a couple of things I wasn't aware of.
viernes, 18 de septiembre de 2009
Telerik Reporting Integration to Silverlight
This time I'd like to talk about how to successfully integrate Telerik Reporting features to your Silverlight Solution. However I'd like get into more detail and give you the real thing, not only the nice picture as shown in Telerik site.
What I'd like to cover here is not only integrate the Reporting but also how successfully configure the whole thing and have it ready to deploy to your Preview / Production server.
Let's start... you will need three projects in your solution. One is the Silverlight project, another is the ASP.Net project that will be hosting the whole thing and finally a Library Application project for your reports.
I will assume you have already added a new report to your Report library and you followed the wizard and had your report filled with some data.
In your Silverlight project you will need to add a new page to show your report and to do so, you'll need to add a RadHtmlPlaceHolder Control (also from Telerik) and set the SourceUrl attribute to something like this:
<telerik:RadHtmlPlaceHolder SourceUrl="MySalesReport.aspx"> </telerik:RadHtmlPlaceHolder>
Add a new WebForm control to your ASP.NET project and named as "MySalesReport.aspx". Add a ReportViewer Control and add your report by populating the Report property in the Properties Panel (be sure to add a reference to your Report library project first). That's it!
That's it? What are you talking about? Here comes the tricky stuff...
Notice in the video that you need to add style properties for your form, body and html elements. But you also need to be sure your div tag has also width = 100%. If you don't do it, your report won't be 100% width in some browser like IE 8.
If you deploy the project as it is right now you'll notice you won't get any data. In order to fix this, first be sure to set "Copy Local" property equals true for your Telerik.Reporting.dll and Telerik.ReportViewer.WebForms.dll
If you used the report wizard that means your connection string is contained within your DataSetTableAdapter. One solution for this problem is to overwrite your connection string with the one specified in your web.config (in your ASP.NET project).
How to do that? You'll first need to add this to your Constructor after the InitializeComponents calling:
this.DataSource = null;Then add a new handler for the event NeedDataSource. Here you will need to get your connection string and set it to your DataSetTableAdapter and then have it fill your DataSetTable and set this object as your report data source:
ConnectionStringSettings connSettings = ConfigurationManager.ConnectionStrings["SampleDB"];if ((connSettings != null) && (connSettings.ConnectionString != null)) {this.myDataSetTableAdapter1.Connection.ConnectionString = connSettings.ConnectionString;}this.myDataSetTableAdapter1.Fill(this.myDataSet.MyDataSetTable);this.DataSource = this.myDataSet.MyDataSetTable;One more thing, you'll notice that you can´t access to your DataSetTableAdapter's ConnectionString property to change it.
This is because this property is a private property. However your DataSetTableAdapter class definition is partial. That means you can add modify this class, so add a new partial class for you Adapter after your Report class definition and add a new property to get access to your ConnectionString.
Now, that's really it. You are good to go.
martes, 15 de septiembre de 2009
All about App.Config
While working, I've found out an interesting challenge. How to access another's application app.config file and be able to read and write to it?
Think in this scenario for a second, you have a Windows Service (not UI if you are not familiar with Windows Services) that needs to read some parameters from the configuration file. And the configuration is really complex that you prefer to have a Windows Form Application to help you set all the values.
That's exactly what I want to accomplish. So here we go. You'll need to add System.Configuration to your project's reference.
To read a value from the app.config it's the basic thing and it's very easy:
string value = ConfigurationManager.AppSetttings["key"];To write a value it's not so easy, at least it doesn't work the other way around. You cannot do something like:
ConfigurationManager.AppSettings["key"] = "this is wrong" <- WRONG!
// Open App.Config
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
// Add an Application Setting.
config.AppSettings.Settings.Add("date", DateTime.Now.ToShortString());
// Update an Application Setting.
config.AppSettings.Settings["key"] = "this is correct";
// Save the configuration file.
config.Save(ConfigurationSaveMode.Modified);
// Force a reload of a changed section.
ConfigurationManager.RefreshSection("appSettings");
In order to access another's application app.config you need to know the file location. For the problem I have exposed I'm writing the Windows Service location to Registry using System.Reflection.Assembly.GetExecutingAssembly().Location. Then in my configuration application I retrieve this value and use it this way:
ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
filemap.ExeConfigFilename = Location; //(this is the location of the app.config I'm trying to access)
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
AppSettingsSection appsettings = config.AppSettings;
appsettings.Settings["key"] = "value";
config.Save();
So now we are able to access the app.config, read and write to it even if it's another's application config file.
domingo, 23 de agosto de 2009
Good Practices for Windows Services
This time I'd like to give some general guidelines you might like to take in count when creating a Windows Service Project.
Let's talk about distribution. I think a good distribution and order can make your life easier. When talking about windows service I like to have all the logic separate in a Class Library Project. This will make my life easy and you will know why further.
So when I create a Windows Service Project I also create a Class Library that contains all the logic. My Windows Service Project then will have a class (a Thread usually so I start and stop when neccesary) that will perform the action (what my windows service will do) by synchronizing and coordinating the access to the multiple classes and services in my Class Library Project.
I also add a Console Project for debugging and testing purposes. The main method will perfom exactly the same as the OnStart method in the windows service. I just need to copy our main class from the windows service and change the namespace and that's it.
When I start coding I usually need to throw messages, exceptions, etc. I like to have a shared interface in my shared Code Library project ILogger. ILogger will have the definition of only one method: void WriteEntry(string message); .
This way Windows Service Project will have a class that implements this interface and will use the EventLog while my Console Project will have a class that will write the entry using System.Console. All the clases in the Code Library Project will use the ILogger interface to log an message or a exception. I think this is called DependencyInjection and it's useful!
So at the end, when writing a windows service you'll end up with at least 4 projects in the solution if you add a Setup Project for installation. Having this distribution will make your life easier than putting everything in your Windows Service I swear.
Hope this will be helpful for someone!
Start a Windows Service after Installation
Recently I had to deal with this problem: How to start (automatically) a windows service after installing it?
It took me a while to find the answer, so I decided to post this to make it easier for anyone in the same situation.
First, How do I install a windows service? Piece of cake, you have several options: write a script, programatically, using a deployment project. I personally like the last option. This is a step by step guide of how to create setup project for you windows service.
Next step, go to the code view of the Project Installer class and in constructor add a new handler like this:
this.AfterInstall += new InstallEventHandler(ProjectInstaller_AfterInstall);
Now add this function:
private void ProjectInstaller_AfterInstall(object sender, InstallEventArgs e)
{
ServiceController controller = new ServiceController("ServiceName");
try
{
controller.Start();
}
catch (Exception ex)
{
String source = "MyService Installer";
String log = "Application";
if (!EventLog.SourceExists(source))
{
EventLog.CreateEventSource(source, log);
}
EventLog eLog = new EventLog();
eLog.Source = source;
eLog.WriteEntry(@"The service could not be started. Please start the service manually. Error: " + ex.Message, EventLogEntryType.Error);
}
}
And that's it. Check the Event Viewer and if you get an error check the service name parameter when creating the ServiceController.
Don't forget to add these Namespaces: System.ServiceProcess; System.Diagnostics;
I won't take credit for this, this code is part of a set of tutorials related to windows services I found in Grinn Blog. Thanks Grinn!
If you decide to use a script anyway (instead of doing this programatically) you just need to insert this command (net start [service]) after the installing instruction.
sábado, 15 de agosto de 2009
SL 3 + RIA Services (Getting Started)
My intention here is to provide you the links I think are the most valuables to start developing and this way save you a lot of searching time.
What is RIA Services basically about? I'd say three things: Entities, Services and UI (Silverlight).
This is a great tutorial that covers these three subjects. This is the first one you should read since it's very clean, understandable and covers the basic. Link
This tutorial from Brad Adams goes a little bit further. You'll be able to play with styles, data validation and authentication as well. Definetly the next step. Link
In case you want to go deeper on Entities and how they relate to each other (one-to-many, many-to-many, etc). I couldn't find a better explanation on this topic. Link
There you are. You are now ready to develop you first Silverlight 3 application with RIA Services.
