.NET tip: Getting the Users Home, Temp or My Documents Directory by Charlie Calvert

Posted on April 15, 2008 by ZDima.
Categories: ASP.NET, C#.

A common need for programmers is to get the users home directory and other commonly used directories. In .NET, this involves using a combination of the Environment.SpecialFolders enumeration, and the Environment.GetEnvironmentVariable() function. The code in this article is written in C#, but it should be easy to translate it into Pascal code.

Special Folders

Here is the Environment.SpecialFolder enumeration:

  1. Environment.SpecialFolder.ApplicationData
  2.     Environment.SpecialFolder.System
  3.     Environment.SpecialFolder.CommonApplicationData
  4.     Environment.SpecialFolder.CommonProgramFiles
  5.     Environment.SpecialFolder.Cookies
  6.     Environment.SpecialFolder.Desktop
  7.     Environment.SpecialFolder.DesktopDirectory
  8.     Environment.SpecialFolder.Favorites
  9.     Environment.SpecialFolder.History
  10.     Environment.SpecialFolder.InternetCache
  11.     Environment.SpecialFolder.LocalApplicationData
  12.     Environment.SpecialFolder.MyComputer
  13.     Environment.SpecialFolder.MyMusic
  14.     Environment.SpecialFolder.MyPictures
  15.     Environment.SpecialFolder.Personal
  16.     Environment.SpecialFolder.ProgramFiles
  17.     Environment.SpecialFolder.Programs
  18.     Environment.SpecialFolder.Recent
  19.     Environment.SpecialFolder.SendTo
  20.     Environment.SpecialFolder.StartMenu

Here is how to use this enumeration:

  1. String PersonalFolder =
  2.     Environment.GetFolderPath(Environment.SpecialFolder.Personal);

After executing this code, the variable PersonalFolder should contain the value of your My Documents directory.

Special Folders, Integer value of Enum, Dir on My System

In Listing 1 you see the values of all the special folders on my system. Note that this enumeration is not sequential. In particular, the integer value for the first member of the enumeration in .NET 1.1 is 0, the next is 2, then 5, then 6, etc. I got these values by writing this code: int i = (int)sp. If someone sees a pattern here, let me know!
Listing 1: The values of the SpecialFolder enumeration on my system. The number in the first column is the integer value of the particular SpecialFolder member shown in the second column.

  1. 0   Desktop            C:Documents and SettingsCharlieDesktop
  2. 2   Programs      C:Documents and SettingsCharlieStart MenuPrograms
  3. 5   Personal      D:documents
  4. 6   Favorites    C:Documents and SettingsCharlieFavorites
  5. 8   Recent   C:Documents and SettingsCharlieRecent
  6. 9   SendTo   C:Documents and SettingsCharlieSendTo
  7. 11  StartMenu  C:Documents and SettingsCharlieStart Menu
  8. 13  MyMusic         D:documentsMy Music
  9. 16  DesktopDirectory  C:Documents and SettingsCharlieDesktop
  10. 17  MyComputer
  11. 26  ApplicationData      C:Documents and SettingsCharlieApplication Data
  12. 28  LocalApplicationData  C:Documents and SettingsCharlieLocal SettingsApplication Data
  13. 32  InternetCache  C:Documents and SettingsCharlieLocal SettingsTemporary Internet Files
  14. 33  Cookies         C:Documents and SettingsCharlieCookies
  15. 34  History         C:Documents and SettingsCharlieLocal SettingsHistory
  16. 35  CommonApplicationData C:Documents and SettingsAll UsersApplication Data
  17. 37  System            C:WINDOWSSystem32
  18. 38  ProgramFiles    C:Program Files
  19. 39  MyPictures        D:documentsMy Pictures
  20. 43  CommonProgramFiles    C:Program FilesCommon Files

Listing 2 shows the code for getting the values found in the previous listing. Note the use of the IList interface to access the list of strings stored in a ListBox. Becoming comfortable with interfaces is one of the core tasks for programmers migrating from Win32 to .NET. Java programmers should already be familiar with this paradigm.
Listing 2: The code for retrieving the values displayed in Listing 1.

  1. private static void ShowSpecialFolder(Environment.SpecialFolder sp, IList list)
  2.     {
  3.         int i = (int)sp;
  4.         String S1 = String.Format("{1} {0} {2} {0}{0}{0} {3}", 't', i,
  5.             sp.ToString(), Environment.GetFolderPath(sp));
  6.         list.Add(S1);
  7.     }
  8.  
  9.     public static IList GetAllSpecialFolders(IList list)
  10.     {
  11.         ShowSpecialFolder(Environment.SpecialFolder.ApplicationData, list);
  12.         ShowSpecialFolder(Environment.SpecialFolder.System, list);
  13.         ShowSpecialFolder(Environment.SpecialFolder.CommonApplicationData, list);
  14.         ShowSpecialFolder(Environment.SpecialFolder.CommonProgramFiles, list);
  15.         ShowSpecialFolder(Environment.SpecialFolder.Cookies, list);
  16.         ShowSpecialFolder(Environment.SpecialFolder.Desktop, list);
  17.         ShowSpecialFolder(Environment.SpecialFolder.DesktopDirectory, list);
  18.         ShowSpecialFolder(Environment.SpecialFolder.Favorites, list);
  19.         ShowSpecialFolder(Environment.SpecialFolder.History, list);
  20.         ShowSpecialFolder(Environment.SpecialFolder.InternetCache, list);
  21.         ShowSpecialFolder(Environment.SpecialFolder.LocalApplicationData, list);
  22.         ShowSpecialFolder(Environment.SpecialFolder.MyComputer, list);
  23.         ShowSpecialFolder(Environment.SpecialFolder.MyMusic, list);
  24.         ShowSpecialFolder(Environment.SpecialFolder.MyPictures, list);
  25.         ShowSpecialFolder(Environment.SpecialFolder.Personal, list);
  26.         ShowSpecialFolder(Environment.SpecialFolder.ProgramFiles, list);
  27.         ShowSpecialFolder(Environment.SpecialFolder.Programs, list);
  28.         ShowSpecialFolder(Environment.SpecialFolder.Recent, list);
  29.         ShowSpecialFolder(Environment.SpecialFolder.SendTo, list);
  30.         ShowSpecialFolder(Environment.SpecialFolder.StartMenu, list);
  31.  
  32.         return list;
  33.     }
  34.  
  35.     private void button1_Click_1(object sender, System.EventArgs e)
  36.     {
  37.         GetAllSpecialFolders(listBox1.Items);
  38.     }

This code begins with the last method, button1_Click_1, which will be called when the user clicks on a button. The button click method calls the GetAllSpecialFolders() method. GetAllSpecialFolders() has one call to ShowSpecialFolders for each of the special folders that the C# API tracks for you. Each call to ShowSpecialFolders creates one of the strings shown in Listing 1:

  1. 0   Desktop            C:Documents and SettingsCharlieDesktop

The ShowSpecialFolders method begins by getting the integer value of the member of the SpecialFolders enumeration that is passed in as a parameter:

  1. int i = (int)sp;

This integer value appears at the beginning of the strings shown in Listing 1. For instance, it is the 0 before the word Desktop. This value is normally not important to developers, but I am showing it to you in case you are curious about the declaration of the SpecialFolders enumeration.In Microsoft’s implementation of C#, we never see the source, so it is interesting to guess how it must be declared. For instance, in this case, the enumeration might look something like this:

  1. enum SpecialFolder {Desktop=0, Programs=2, Personal=5, Favorites=6, Recent=8, etc);

The next line of my ShowSpecialFolders method begins with a call to String.Format. The String.Format() method has a peculiar, but useful, syntax I have only seen in C#. Each of the instances of code that appears in curly braces is replaced by one of the latter parameters passed to the method. For instance {0}, {1} and {2} get replaced with one of the parameters such as ‘\t’ or sp.ToString() which is passed to String.Format. Note that ‘\t;’ is the second parameter. It is the tab character, and will replace all instances of {0}. The variable i is the third parameter, and the value stored in that variable will replace each instance of {1}.

The code {2} is replaced by each instance of sp.ToString(). sp is a member of the SpecialFolder enumeration, and the ToString() method conveniently converts sp into a string representation of the enumeration member. That is, it converts sp into a string such as “Desktop”, “Programs”, “Personal”, etc. In the String shown above, the value of i appears as 0, and sp.ToString() appears as Desktop. Again, programmers don’t normally need to make a call to find out the string value of an enumeration, but it is interesting to know that you can do it if you so desire.

The last parameter, the one that goes into {3}, is the path, such as C:\Documents and Settings\Charlie\Desktop. I retrieved the path string by making the following call: Environment.GetFolderPath(sp). Note that I place three tabs in front of the path, to separate it from the rest of the code:

  1. String S1 = String.Format("{1} {0} {2} {0}{0}{0} {3}", 't', i,
  2.     sp.ToString(), Environment.GetFolderPath(sp));

I still had to manually edit some of the tabbing to make it come out as evenly as it appears in Listing 1.

Useful Methods

Listing 3 shows some other useful methods. Note that I use the GetEnvironmentVariable call to retrieve the Home Directory and in the call to GetEnvTempDir(). Since environment variables are mutable, these calls are probably less reliable than other calls. Also, they may be OS dependant. In particular, I have only tested them on XP. Note, however, the GetTempDir() call, which uses what should be a more reliable method of retreiving the temporary directory. In particular, it uses the Path object. The GetMyDocumentsDir() method is a wrapper around the Environment.SpecialFolder enumeration.
Listing 3: Routines for getting the users home directory, their My Documents directory, and the temp directory.

  1. public static String GetHomeDir()
  2.     {
  3.         return Environment.GetEnvironmentVariable("USERPROFILE");
  4.     }
  5.  
  6.     public static String GetMyDocumentsDir()
  7.     {
  8.         return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
  9.     }
  10.  
  11.     public static String GetEnvTempDir()
  12.     {
  13.         return Environment.GetEnvironmentVariable("TEMP");
  14.     }
  15.  
  16.     public static String GetTempDir()
  17.     {
  18.         return System.IO.Path.GetTempPath();
  19.     }

Summary

In this article you have learned a few simple tricks for getting system dependant information while using .NET. In particular, you learned about the Environment.SpecialFolder enumeration, and about the Environment.GetEnvironmentVariable method. The Environment class is part of the System namespace, so you should not have to add any special Using statements to your code other than the default Using System reference which should appear at the top of all C# files.

By Charlie Calver Ref from: CodeGear

Pushing Data to a Silverlight Client with Sockets: Part IIDan Wahlin's WebLog

Posted on April 13, 2008 by dwahlin.
Categories: C#, Contributors.

In Part 1 of this two part series on socket support in Silverlight 2 I discussed how a server could be created to listen for clients using classes in the System.Net.Sockets namespace.  In that post the TcpListener class was used to listen for client connections and the client stream was accessed using the TcpClient class's GetStream() method.  In this post I'll cover how a Silverlight client can connect to a server using sockets and receive data pushed by the server asynchronously.

Creating a Silverlight Socket Client

Silverlight 2 provides a Socket class located in the System.Net.Sockets namespace (a Silverlight namespace...not the .NET Framework namespace mentioned earlier) that can be used to connect a client to a server to send and/or receive data.  The Socket class works in conjunction with a SocketAsyncEventArgs class to connect and send/receive data.  The SocketAsyncEventArgs class is used to define asynchronous callback methods and pass user state between those methods (such as the Socket object that originally connected to the server).  An example of using the Socket and SocketAsyncEventArgs classes is shown next:

  1. <span >private void Page_Loaded(<span >object sender, <span >RoutedEventArgs e)
  2. {
  3.     <span >DnsEndPoint endPoint = <span >new <span >DnsEndPoint(<span >Application.Current.Host.Source.DnsSafeHost, 4530);
  4.     <span >Socket socket = <span >new <span >Socket(<span >AddressFamily.InterNetwork, <span >SocketType.Stream, <span >ProtocolType.Tcp);
  5.  
  6.     <span >SocketAsyncEventArgs args = <span >new <span >SocketAsyncEventArgs();
  7.     args.UserToken = socket;
  8.     args.RemoteEndPoint = endPoint;
  9.     args.Completed += <span >new <span >EventHandler&lt;<span >SocketAsyncEventArgs&gt;(OnSocketConnectCompleted);
  10.     socket.ConnectAsync(args);   
  11. }


This code first identifies the application's host server along with a port of 4530 (Silverlight can only connect to servers on a port between 4502 and 4532).  A Socket object capable of communicating using the TCP protocol is then created.  Once the Socket object is created, a SocketAsyncEventArgs object is instantiated and the socket object is assigned to the UserToken property so that it is passed through to other methods.  The target endpoint of the server is set using the RemoteEndPoint property and the argument object's Completed event is hooked to an asynchronous callback method named OnSocketConnectCompleted.  Once these objects are created and ready to use, the Socket object's ConnectAsync() method can be called which accepts a SocketAsyncEventArgs object as a parameter.

When the client is connected to the server the following method is called which creates a buffer to hold data received from the server and rewires the SocketAsyncEventArgs's Completed event to a different callback method named OnSocketReceive:

  1. <span >private void OnSocketConnectCompleted(<span >object sender, <span >SocketAsyncEventArgs e)
  2. {
  3.     <span >byte[] response = <span >new byte[1024];
  4.     e.SetBuffer(response, 0, response.Length);
  5.     e.Completed -= <span >new <span >EventHandler&lt;<span >SocketAsyncEventArgs&gt;(OnSocketConnectCompleted);
  6.     e.Completed += <span >new <span >EventHandler&lt;<span >SocketAsyncEventArgs&gt;(OnSocketReceive);
  7.     <span >Socket socket = (<span >Socket)e.UserToken;
  8.     socket.ReceiveAsync(e);
  9. }


The Socket object's ReceiveAsync() method is then called to begin the process of accepting data from the server.  As data is received the OnSocketReceive() method is called which handles deserializing XML data returned from the server into CLR objects that can be used in the Silverlight client. 

  1. <span >private void OnSocketReceive(<span >object sender, <span >SocketAsyncEventArgs e)
  2. {
  3.     <span >StringReader sr = <span >null;
  4.     <span >try
  5.     {
  6.         <span >string data = <span >Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
  7.         sr = <span >new <span >StringReader(data);
  8.         <span >//Get initial team data
  9.         <span >if (_Teams == <span >null &amp;&amp; data.Contains(<span >&quot;Teams&quot;))
  10.         {
  11.             <span >XmlSerializer xs = <span >new <span >XmlSerializer(<span >typeof(<span >Teams));
  12.             _Teams = (<span >Teams)xs.Deserialize(sr);
  13.             <span >this.Dispatcher.BeginInvoke(UpdateBoard);
  14.         }
  15.  
  16.         <span >//Get updated score data
  17.         <span >if (data.Contains(<span >&quot;ScoreData&quot;))
  18.         {
  19.             <span >XmlSerializer xs = <span >new <span >XmlSerializer(<span >typeof(<span >ScoreData));
  20.             <span >ScoreData scoreData = (<span >ScoreData)xs.Deserialize(sr);
  21.             <span >ScoreDataHandler handler = <span >new <span >ScoreDataHandler(UpdateScoreData);
  22.             <span >this.Dispatcher.BeginInvoke(handler, <span >new object[] { scoreData });
  23.         }
  24.     }
  25.     <span >catch { }
  26.     <span >finally
  27.     {
  28.         <span >if (sr != <span >null) sr.Close();
  29.     }
  30.     <span >//Prepare to receive more data
  31.     <span >Socket socket = (<span >Socket)e.UserToken;
  32.     socket.ReceiveAsync(e);
  33. }


The deserialization process is handled by the XmlSerializer class which keeps the code nice and clean.  Alternatively, the XmlReader class could be used or the LINQ to XML technology that's available in Silverlight.  Notice that data is routed back to the UI thread by using the Dispatcher class's BeginInvoke() method.  If you've worked with Windows Forms before then this should look somewhat familiar.  That's all there is to work with sockets in a Silverlight client.  There's certainly some work involved, but many of the complexities are hidden away in the Socket and SocketAsyncEventArgs classes which both minimize the need to work with threads directly.  I've already shown what the client interface looks like as data is updated but here it is one more time (click the image to see an animated gif of the application in action):

The complete code for the Silverlight client and server application can be downloaded here.

Using Silverlight 2 ItemsControl TemplatesDan Wahlin's WebLog

Posted on April 3, 2008 by dwahlin.
Categories: C#, Contributors.

Building Silverlight 2 applications reminds me of the first time I built an ASP.NET application.  There are so many new features and controls that it takes a little time to get up-to-speed with what's available and how it can be used.  It's definitely fun but at times you just want to throw the monitor out the window when something doesn't work like you think it should (disclaimer:  I've never actually thrown a monitor anywhere...but I'm definitely guilty of wanting to do it).  The good news is that the learning curve flattens out pretty quickly once you grasp a few key concepts which probably makes my monitor feel much better.  :-)

I was building a sample application for a Silverlight 2 book I'm working on and after I finished a particular feature I realized that there was an easier way to do what I wanted without writing much C# code.  I needed to dynamically output Rectangles with images and was doing it all programmatically mainly because it was comfortable and easy to do.  Here's an example of the code I initially wrote:

  1. <span >foreach (Model.<span >Photo photo <span >in photos)
  2. {
  3.     <span >Rectangle rect = <span >new <span >Rectangle();
  4.     rect.Stroke = <span >new <span >SolidColorBrush(<span >Colors.Gray);
  5.     rect.StrokeThickness = 2D;
  6.     rect.RadiusX = 15D;
  7.     rect.RadiusY = 15D;
  8.     rect.Height = 75D;
  9.     rect.Width = 75D;
  10.     <span >ImageBrush imgBrush = <span >new <span >ImageBrush();
  11.     imgBrush.ImageSource = <span >new <span >BitmapImage(<span >new <span >Uri(photo.Url));
  12.     imgBrush.Stretch = <span >Stretch.Fill;
  13.     rect.Fill = imgBrush;
  14.     rect.Tag = photo.Url;
  15.     rect.MouseLeftButtonDown += <span >new <span >MouseButtonEventHandler(rect_MouseLeftButtonDown);
  16.     rect.Margin = <span >new <span >Thickness(10D);
  17.     <span >this.wpImages.Children.Add(rect);
  18. }


The code worked fine and I was able to generate the desired output for the interface.  It never felt quite right though....it seemed too code intensive for such a simple task.

In researching some other controls available in Silverlight 2 I came across ItemsControl which turns out to be what I needed in the first place.  ItemsControl allows a panel template to be defined (StackPanel, Canvas, Grid, etc.) as well as an items template.  It's like the DataList in ASP.NET in some ways.  Using it allows a collection of objects to be data bound and output without having to write custom looping code with C# or VB.NET.  Here's an example of using ItemsControl in XAML:

  1. <span >&lt;<span >ItemsControl <span >x<span >:<span >Name<span >=&quot;icPhotos&quot; <span >Grid.Row<span >=&quot;1&quot;&gt;
  2.     &lt;<span >ItemsControl.ItemsPanel<span >&gt;
  3.         &lt;<span >ItemsPanelTemplate<span >&gt;
  4.             &lt;<span >wp<span >:<span >WrapPanel <span >x<span >:<span >Name<span >=&quot;wpImages&quot; <span >Margin<span >=&quot;10&quot; <span >Orientation<span >=&quot;Horizontal&quot; /&gt;
  5.         &lt;/<span >ItemsPanelTemplate<span >&gt;
  6.     &lt;/<span >ItemsControl.ItemsPanel<span >&gt;
  7.     &lt;<span >ItemsControl.ItemTemplate<span >&gt;
  8.         &lt;<span >DataTemplate<span >&gt;
  9.             &lt;<span >Rectangle <span >Stroke<span >=&quot;LightGray&quot; <span >Tag<span >=&quot;{<span >Binding <span >Url<span >}&quot; <span >Fill<span >=&quot;{<span >Binding <span >ImageBrush<span >}&quot; <span >StrokeThickness<span >=&quot;2&quot;
  10.                        <span >RadiusX<span >=&quot;15&quot; <span >RadiusY<span >=&quot;15&quot; <span >Margin<span >=&quot;15&quot;
  11.                        <span >Height<span >=&quot;75&quot; <span >Width<span >=&quot;75&quot; <span >Loaded<span >=&quot;Rectangle_Loaded&quot; <span >MouseLeave<span >=&quot;Rectangle_MouseLeave&quot;
  12.                       <span >MouseEnter<span >=&quot;Rectangle_MouseEnter&quot;  <span >MouseLeftButtonDown<span >=&quot;Rectangle_MouseLeftButtonDown&quot;&gt;
  13.                 &lt;<span >Rectangle.RenderTransform<span >&gt;
  14.                     &lt;<span >TransformGroup<span >&gt;
  15.                         &lt;<span >ScaleTransform <span >ScaleX<span >=&quot;1&quot; <span >ScaleY<span >=&quot;1&quot; <span >CenterX<span >=&quot;37.5&quot; <span >CenterY<span >=&quot;37.5&quot; /&gt;
  16.                     &lt;/<span >TransformGroup<span >&gt;
  17.                 &lt;/<span >Rectangle.RenderTransform<span >&gt;
  18.             &lt;/<span >Rectangle<span >&gt;                           
  19.          &lt;/<span >DataTemplate<span >&gt;
  20.     &lt;/<span >ItemsControl.ItemTemplate<span >&gt;
  21. &lt;/<span >ItemsControl<span >&gt;


This code uses a really nice WrapPanel control created by lneir as the panel template.  The WrapPanel control automatically wraps UIElements to the next line once the width of the screen has been exceeded.  The ItemTemplate defines a data template that outputs a Rectangle with an ImageBrush used for the fill as objects are bound.

Once the templates were defined I was able to bind my photo collection to the ItemsControl control (named icPhotos) using the following code.  Very nice and more along the lines of what I'm used to doing with ASP.NET controls.

  1. <span >this.icPhotos.ItemsSource = photos;

In working through the XAML and code I learned a trick about binding an ImageBrush to the Fill property of a UIElement which I'll blog about soon.

VS 2005 ActiveX failed to load in browser windows (Microsoft.mshtml).

Posted on October 29, 2007 by ZDima.
Categories: C#.

Recently I was struggled with issue where ActiveX component developed in Visual Studio 2005 was working on some machines and failed to load into browser window on another.

It was no evidence on what is missing until I spot a message where it was complaint about missing Miscrosoft.mshtml assembly.

It turnout that the Visual Studio 2005 Setup wizard is not adding this assembly into dependency list and therefore into package.

To fix the problem I manually added Miscrosoft.mshtml.dll and stdole.dll to the setup project to copy them into application folder without registration.