Tuesday, July 15, 2008

Lookout for Outlook 2007

For those of you that have used Lookout for Outlook 2003 and earlier and have upgraded to Outlook 2007, you have no doubt figured out that Lookout 1.3 does not run or if you are running Lookout 1.2 that it doesn't even load. The reason is that Lookout is looking for a particular COM file that is now the wrong name even though it does actually work with it.

First thing I recommend is downloading the latest release (there will not be anymore because technically MS owns it now and this software is not longer supported by either the original author or MS). One place you can download Lookout 1.3 from is:

http://www.majorgeeks.com/Lookout_d4808.html

To the rescue comes a couple of people. The author says you can just rename the dll it is looking for so that it can find it. That runs the chance of messing up other things if you ask me. However, you can try it if you prefer that solution:

http://www.belshe.com/2007/12/06/how-to-install-lookout-on-outlook-2007/


Another techie figured out the dll that does the dll check and tricked into always being true. Pretty clever. You can download the patched file and replace the one that is installed with Lookout 1.3.

http://www.wirwar.com/blog/2008/01/22/search-e-mail-at-lightspeed-using-lookout-with-outlook-2007/

Apparently there is an issue with dates when .NET Framework 2.0 is installed. Here is a description and fix to the issue.

http://ewbi.blogs.com/develops/2006/04/outlook_lookout.html

You can fix this by checking out the following link on how to patch it Lookout for this issue.

http://www.scw.us/win/FixingLookout/


If you want more background on the issues, etc there is actually a lot of good stuff on the issues at:

http://www.lockergnome.com/windows/2004/07/26/microsoft-lookout-for-outlook/


As you can see Lookout is limited life left in it. Though I imagine clever folks will continue to patch it until a product that is good enough comes along.

Outlook launch error regarding MSOC.DLL

I just upgraded from Outlook 2003 to Outlook 2007. I opened Outlook 2007 and I get a message that says "MAPI was unable to load the information service msoc.dll. Be sure the service is correctly installed and configured." I had to be quick to get it because it oddly disappears and it is not logged to the Windows event log. If you are getting this message it is likely I would say that you are using "Microsoft Office Outlook Connector for IBM Lotus Domino" plug-in for Outlook 2003. When you upgrade to Outlook 2007, the plug-in stays installed. When you open Outlook it tries to connect to the Domino server as it has always, and in Outlook 2007 this plug-in no longer works and appears to not be supported or have a likely shot of being upgraded to work with Outlook 2007. Make sure Outlook 2007 is quit and not hidden process is running (can use Task Manager to check for process called OUTLOOK.EXE). Do yourself a favor, go to Add / Remove Programs and remove "Microsoft Office Outlook Connector for IBM Lotus Domino". It does NOT work in Outlook 2007.This should uninstall the plug-in from Outlook I think. If that doesn't work you can do what I did before I uninstalled it. I just removed the plug-in from Outlook 2007 using Start Menu | Control Panel | Mail and then click the Email Accounts... button. This will take you to a tabbed window. Make sure the E-mail tab is selected. In the list of connections you should see something that indicates the Domino connection (sorry already deleted it so I can't reference the exact text). Highlight it and click the Remove button. Close the Windows and restart Outlook. This is in no way part of the solution, but I wanted to share it anyway. Here is some sample code that I toyed with to attempt to write my own .PST reader, but ended up with the same error when my code ran, and forced me to figure out what the real problem was (see above of course).
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;

public partial class Form1 : Form
{
 public Form1()
 {
  InitializeComponent();
 }

 private void Form1_Load(object sender, EventArgs e)
 {
  Outlook.Application app = new Outlook.ApplicationClass();
  Outlook.NameSpace NS = app.GetNamespace("MAPI");
  Outlook.MAPIFolder objFolder = 
     NS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
  Outlook.MailItem objMail;

  Outlook.Items oItems;
  oItems = objFolder.Items;

  try
  {
   for (int i = 1; i < objFolder.Items.Count; i++)
   {
    objMail = (Outlook.MailItem)oItems[i];
    MessageBox.Show(objMail.Body.ToString());
   }
  }
  catch (COMException ex)
  {
   MessageBox.Show(ex.Message);
  }
  finally
  {
   NS.Logoff();
   objFolder = null;
   objMail = null;
   app = null;
  }
 }
}  


Monday, July 14, 2008

Unlocking Windows Desktop Search

If you have Windows Desktop Search installed by your corporate IT or the like, they may have locked it so that you can't tell Windows Desktop Search where (file system paths) and what (file extensions) to index. Thanks to one of my sys admin friends (I won't name any names in case he wasn't supposed to tell me this) I can now tell Windows Desktop Search to search where and what I want it to, and thus make it a little more useful.

The restriction is created using a group policy. The group policy can be removed by deleting two keys from the registry found at:

HKLM\Software\Policies\Microsoft\Windows\Windows Search

This should make the group policy for these items to not configured. You should also be able to just set the values to 0 to have a similar effect.

In case you need to restore, or just want to know what you are deleting a head of time, here is an export of the registry entries prior to the change.

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Windows Search]
"PreventUsingAdvancedIndexingOptions"=dword:00000001
"PreventModifyingIndexedLocations"=dword:00000001

Format GridView column header text automatically

Here is a snippet of code that I use for with GridViews to convert Database column names to User friendly text. This comes in handy when I am too lazy or not enough time to go through and change the names of the automatically generated column names that are shown as the column headers in a GridView. This also makes it easy to keep the text looking nice even when the columns change and the columns get regenerated. I realize there are some downsides, like slight performance hit, etc, but for departmental solutions were development time is the most precious thing I have, this is a time saver.

This method assumes that your column names are in Pascal Case. This means that all columns start with a capital letter, and that each word in the column name starts with a capital as well. Everything else in between should be lowercase. An example of this is FirstName or LastName or or ZipCode or DisplayName.

// assumes that source text is in PascalCase and that it
// should be changed to more human readable capitalization.
// i.e. BrentVermilion is in pascal case and a more human
// readable form is Brent Vermilion
public static string MakeUserFriendly(string text)
{
 StringBuilder sb = new StringBuilder(text);
 int insertAdjustment=0;
 char ch;
 for (int i = 0; i < text.Length; i++ )
 {
  // AND the previous letter wasn't an Uppercase letter
  if (!char.IsUpper(text[i - 1]))
  {
   // insert a space before the uppercase letter
   sb.Insert(i + insertAdjustment, ' ');
   // we need to keep track of how many space we have added
   // so we know what the adjusted index to insert at will be
   insertAdjustment++;
  }
 }
 return sb.ToString();
}

One place you can call this method is in the PageLoad event.

protected void Page_Load(object sender, EventArgs e)
{
 if (!Page.IsPostBack)
 {
  // convert cryptic Pascal Case header column text
  // (what the user sees) to User friendly readable text
  for (int i = 0; i < myGridView.Columns.Count; i++)
  {
   myGridView.Columns[i].HeaderText =
    MakeUserFriendly(myGridView.Columns[i].HeaderText);
  }
 } 
}

Wednesday, July 9, 2008

ASP.NET Session Timeouts

In ASP.NET there are lots of timeouts. In this blog entry I will be covering in great detail Session timeout due to the complexity of the issue and the fact that I can never remember where all the setting are and what they are for. I am not covering other timeouts except Script Timeout.

SIDE NOTE: Web services that you consume have timeouts before ASP.NET stops waiting for a response from a web service, but I am not covering that here. The web services on the server side have timeouts that are independent of the ASP.NET consuming the web service. I am also not covering timeouts associated with database connections or authentication either. It is however important that all these timeouts be be compatible with each other, otherwise you will get undesirable behavior. For example, don't set your execution time to less than the database timeout. Or don't set the application recycle to be less than the session timeout.


SessionState Timeout
This is the number of minutes before an ASP.NET user session is terminated. It must be an integer, and it is in minutes. The default is to terminate the session after 20 minutes and the application will throw an exception when accessing an terminated session. Another way to think of this is that it is the time between requests for a given session (which is per user) before a session is terminated.

I recommend reading Idle Timeout section below to see how these are related.


Using Web.config
<system.web>
<sessionState timeout="20" />
<system.web>


Using IIS
You can get to the setting by: Open IIS | Properties on Web Site | ASP.NET tab | Edit Configuration... (or Edit Global Configuration to change for more than one site) | State Management tab.

Here you will see a textfield with a label that says "Session timeout (minutes) with a default value of 20 minutes.

Session Timeout Event
When the session times out it fires an event called: Session_End and then when the user hits the page again (after it has expired or the first time), it will start a new session and the Session_Start event is called. It is important to know that the only thing you can really do in the Session_End event is do clean up. This is because this event fire even if a user doesn't hit a page again. In other words, if a session times out due to inactivity, the Session_End is fired even if the user never refreshes the page, etc. It is independent of the page lifecycle. These events are defined in the Global.asax file.


Detecting when a session has timed out
The short answer to this is that you have a session time when the following conditions are met:
Context.Session != null
AND Context.Session.IsNewSession == true
AND Page.Request.Headers["Cookie"] != null
AND Page.Request.Header["Cookie"].indexOf("ASP.NET_SessionId") >= 0

The long answer is read this blog for more details and sample code: http://www.eggheadcafe.com/articles/20051228.asp

and http://aspalliance.com/520


Idle Timeout


IIS 6.0 (and probably 7) has a setting that controls how idle processes are handled.

This can also affect the session timeout indirectly. This is the case when let's say you have the Idle timeout set to 10 minutes to save resources. If your site is not used a lot and say that the only user using your site stopped using it 10 minutes ago, this means that your application will get recycled. One of the side effects of an application getting recycled is that all sessions are terminated also. So, in this case even if your session is set to timeout say in 30 minutes, under some conditions (little traffic), it is effectively 10 minutes.

If you have low traffic on your application I strongly recommend you set the Idle Timeout to at least as long as your session timeout, otherwise you will effectively be limiting the session time to the Idle Timeout when there is very little traffic on your site. This is in my cases not the desired behavior.

Here is what the help docs in IIS say:
"Idle timeout limits helps conserve system resources by terminating unused worker processes by gracefully closing idle processes after a specified idle duration. This allows you to better manage the resources on particular computers when the processing load is heavy, when identified applications consistently fall into an idle state, or when new processing space is not available."


Open IIS | Properties on the App Pool you are using | Performance tab
Here you will see a setting that says: "Shutdown worker processes after being idle for 20 (time in minutes)" where 20 is the default.

NOTE: Some shared hosting provider don't allow you to access or change this value. In this case one option is to at a set interval ping your application (from a program running on another computer) to keep it alive and thus not get recycled. Though some providers may change the setting so that all application are recycled at particular times as well. Best of luck working with shared hosting providers. I would love to have feedback on a shared hosting provider that has settings that are good for low traffic sites.


Recycle Worker Processes
IIS 6.0 (and probably 7) has a another setting that you can set that determines when the worker processes are recycled.

Open IIS | Properties on the App Pool you are using | Recycling tab
Here you will see a setting that says:
"Recycle worker processes (in minutes):" with a default value of 1740 which is 29 hours.

Classic ASP - Session State timeout in IIS
There is a setting in IIS 6 (and probably 5 and 7) that controls the session timeout in minutes if the user does not refresh or change pages in the specified number of minutes. This is for Classic ASP pages NOT ASP.NET. So don't worry about this for ASP.NET. I added it here since it can be confusing You can get to the setting by: Open IIS | Properties on Web Site | Home Directory tab | Configuration button | Options tab.The field label is "Session timeout:" and the value is 20 minutes as the default value.


Classic ASP - Script timeout in IIS
There is a setting in IIS 6 (and probably 5 and 7) that controls the script timeout in seconds. This is the time that ASP allows a script to run before it stops the script and records the event in the Event Log. This is for Classic ASP pages NOT ASP.NET. So don't worry about this for ASP.NET. I added it here since it can be confusing. You can get to the setting by: Open IIS | Properties on Web Site | Home Directory tab | Configuration button | Options tab.The field label is "ASP script timeout:" and the value is 90 seconds as the default value.


Alternate Timeout handling Mechanisms
In some cases you want to inform the user about session timeout status or automatically have it renew, or maybe any other sort of action. You can use JavaScript / AJAX to accomplish this. If you have access to IIS configuration and you are something like an Intranet you can set your application pool to not recycle if you have enough resources, and set an extremely long session timeout and then handle the timeout on the client side instead. This appears to be a much better experience for the user in general. However, you can also use these techniques to just improve the experience the user has when a session times out.

This article goes into great detail so I won't. The article (
http://ajaxpatterns.org/Timeout) does such a wonder job of explaining it. It is complete with demos as well.

Here is a nice link (http://www.pascarello.com/AjaxSessionTimer.aspx) to a timeout warning message box that shows when your session is about to expire. It does not get past the issue of the application being recycled so be sure to adjust that as recommended above.

Here is a link to stuff to make your UI look really cool: http://script.aculo.us/



Script Timeout
While this is not really session timeout, it could affect it in rare instances so I am mentioning it here for completeness. This is the maximum time an .aspx page can run before timing out. It can be set in two places. Either the web.config (or machine.config for all sites) or via code using Script.ScriptTimeout. If you have debug enabled in web.config then the Server.ScriptTimeout is set to 30000000 seconds (or 347.2 days). Otherwise the default is 90 seconds. This setting is most important if you have long requests that need processing like file uploads, etc. In general the defaults are probably ok.

Using the web.config
This sets the timeout to 3 minutes.
<compilation debug="false"/>
<httpRuntime executionTimeout="180" />

Using code
Server.ScriptTimeout

Using IIS
You can get to the setting by: Open IIS | Properties on Web Site | ASP.NET tab | Edit Configuration... (or Edit Global Configuration to change for more than one site) | Application tab.

Here you will see a textfield with a label that says "Request Execution timeout (seconds):" with a default value of 110 seconds.

IMPORTANT NOTE: Be sure to uncheck the "Enable debugging" checkbox next to this field, otherwise, the value will be ignored and set to the 30,000,000 seconds that debugging defaults to.










Wednesday, July 2, 2008

Use Google Page Creator to store files for blogger

I must say I think Google does a nice job on most of their interfaces. They remind me of Apple in that regard. I like blogger, though I think it needs some help when pasting text that is code or xml, I have figured out how to work with that for the most part. You can even up upload pictures for use in your blog. This is pretty cool. I want to be able to upload files like source code files or zip files so others can easily download them instead of copying my partially formatted source code displayed through the browser. I noticed Google offers Google Page Creator (see http://pages.google.com for more info). It is a nice graphical end user tool for creating simple web sites. They give you 100MB of space for FREE. They also give you the ability to quickly and easily upload files to your web space you click the Link button in their tool bar. I then upload my source code I want to share using this window. Then I let it put the link to it on the page. When I look at the link of the page it created for me, I see that I now have a nice public url that I can use as a link in my blogger.com blog (or anywhere else for that matter). Pretty nice for FREE! One last note, you can also upload using the Uploaded stuff widget on the right side of the site manager page. This is basically a little file manager that lets you upload and delete the files as well as show you the size of each file.

Thread safety in C# and ASP.NET

When I started ASP.NET and web programming I thought that I was shielded from race conditions that I learned about in college. Wrong! I found out the hard way after trying to track down an intermittent bug that it is a very real problem even in web programming and that includes ASP.NET. This becomes an issue when you use static variables or methods sometimes. Most of the time I have not found there to be issues with race conditions. However, sometimes there is. This is not the only time it is an issue though. Beware.

I found that it can be difficult to consistently reproduce the bug in web code, though I think it can be done. To make things easier, I simulated the web. I created two threads to create the race condition. I didn't use a Threading Pool, but I think this is close enough, and illustrates the point while reliably and consistently reproducing the race condition.

First I guess I should explain a little bit about what a race condition is. Let's assume you have two threads. They could be two web sessions as each connection to the your ASP.NET application is handled by a thread from the thread pool. The issues comes when those two threads try to access any shared resource. Thread-A sets a value for example, has some kind of delay, and while Thread-A is processing / delaying Thead-B comes along and changes the shared resource before Thread-A has a chance to use / retrieve value from the shared resource. Then when Thread-A finally has a chance to access the shared resource without coding for thread-safety, Thread-A will assume it was the only one that had used the shared resource and thus it will get data it was not expecting. It is probably a good idea to always only allow one object access to a shared resource and only allow one calling object at a time actually call the method.

 I think the easiest way to see this is to look at the output of a program I wrote to see what was actually going on.

Thread-A-Starting
Thread-A-Spawned
Thread-A-Entering Critical Section
Thread-A-New
Generated Value is: 1907360620

Set New Value: 1907360620
Thread-A-Waiting.... forcing race condition
Thread-B-Starting
Thread-B-Spawned

Thread-B-Entering Critical Section
Thread-B-New
Generated Value is: 209463673

Set New Value: 209463673
Thread-B-Waiting.... forcing race condition
Get New Value: 209463673
Thread-A-CriticalSection() returns: 209463673 (Important Line *******)
Thread-A-Exiting Critical Section
Get New Value: 209463673
Thread-B-CriticalSection() returns: 209463673 (Important Line *******)
Thread-B-Exiting Critical Section

The important thing to note is that the return value for both threads is the last value that was set, and this is because both threads entered the critical section of code at the same time or near the same time. When this happens, they basically step on each other's feet and you get bad results.

Below is the same output but there is a lock on the critical section of code so that only one thread can enter it at a time.

Thread-A-Starting
Thread-A-Spawned
Thread-A-Entering Critical Section
Thread-A-New Generated Value is: 1483178371
Set New Value: 1483178371
Thread-A-Waiting.... forcing race condition
Thread-B-Starting
Thread-B-Spawned <Press any key to remember>
Get New Value: 1483178371
Thread-A-CriticalSection() returns: 1483178371 (Important Line *******)
Thread-A-Exiting Critical Section
Thread-B-Entering Critical Section
Thread-B-New Generated Value is: 249049990
Set New Value: 249049990
Thread-B-Waiting.... forcing race condition
Get New Value: 249049990
Thread-B-CriticalSection() returns: 249049990 (Important Line *******)
Thread-B-Exiting Critical Section


The important thing to notice is that the values set by each thread are also retrieved by each respective thread. This is what we want to happen. You will also notice that even though the threads start together or close together, they take turns using the shared resource. In fact, one thread uses the shared resource until it is done with it, and while the other thread waits to use it.

In C# there is something called a Monitor class that locks and unlocks shared resources. They have simplified the syntax much in the same way that they have with database connectivity. If you are familiar with the using () block in your code. You know it implicitly handles the closing a connection for example (even if there is an exception). Well, the lock () block does the same thing for the Monitor class. It basically guarantees that the object will be unlocked even if there is an exception. It does NOT handle deadlocks, though you can do so with try-catch-finally and the Monitor class because it has a TryEnter and allows you to specify how long to wait for a lock before giving up (thus breaking a deadlock).

Below is a snippet of how locks work.



private static Object objLock = new Object();

public void CriticalSection()
{
   lock (objLock)
   {
       // use shared resource here
   }
}


Things to note here are that the objLock variable is both static (this extremely important) and it is also private so that no one else can unlock the lock (which would defeat its purpose). You can use different lock variables for locking different parts of your code. The smaller number of lines of code you lock at a time the better your performance will be. So, you may want to create different locks for different methods if they are not accessing the same shared resource.

If you would like a much more in-depth and more technical explanation of the how and why I suggest what I suggest I recommend you check