Zayko in the Net

Personal blog of Vitaly Zayko

NAVIGATION - SEARCH

How to give a folder access rights to a particular user and revoke from everyone else? (C#)

Let's say you need to create a folder on behalf of a user and protect it from access by anyone but this user. Use DirectorySecurity.SetAccessRuleProtection procedure like this:

 DirectoryInfo  dir = new  DirectoryInfo (DirPath);
 if  (!dir.Exists)
 {
     dir.Create();
     DirectorySecurity  ds = dir.GetAccessControl();
     ds.SetAccessRuleProtection(true , false );
     ds.AddAccessRule(new  FileSystemAccessRule (DomainName + "\\\\"  + UserName,
         FileSystemRights .FullControl, AccessControlType .Allow));
     dir.SetAccessControl(ds);
 }
 

Please be noted that local administrator could request and get access rights even for protected folders. Admins are admins.

How to bypass self-signed SSL certificate exception? (C#)

When you try to connect your client App to a server through self-signed SSL certificate (which is normal during development, but obviously is not in production), by default you will get a security exception because such certificate could not be validated. The good approach is to warn user and let him choose whatever he wants to take this risk or not. Add the following code to your class/form to give him such choise. The good idea is to store his response in a local variable and use it to skip this warning in future requests.

 ServicePointManager .ServerCertificateValidationCallback = (s, cert, ch, er) =>
 {
     // Check is this case has been valuated:
      if  (Program .IsCertVerified)
         return  true ;
 
     if  (er == System.Net.Security.SslPolicyErrors .None)
         return  true ;
     else
      {
         // Warn user:
          if  (MessageBox .Show(String .Format("Certificate \\"{0}\\" could not be verified! Do you want to continue?" ,
             cert.Subject), "Certificate Warning" ,
             MessageBoxButtons .YesNo, MessageBoxIcon .Warning) == System.Windows.Forms.DialogResult .Yes)
         {
             // Set the local variable to skip this dialog:
              Program .IsCertVerified = true ;
             return  true ;
         }
         else
          {
             Program .IsCertVerified = false ;
             return  false ;
         }
     }
 };
 

Setting Request timeout interval in WebClient (C#)

Most programmers who work with remote HTTP services prefer to use WebClient over WebRequest/WebResponse because of its simplicity. The only WebClient's feature I missed is ability to customize request timeout interval but fortunatelly it is very easy to fix by creating own class derived from WebClient. Here is how....

 public  class  WebClientEx  : WebClient
  {
     // Timeout in milliseconds
      public  int  Timeout { get ; set ; }
 
     /// <summary>
      /// Sets default timeout
      /// </summary>
      public  WebClientEx()
         : base ()
     {
         this .Timeout = 10000;
     }
 
     /// <summary>
      /// Sets custom timeout
      /// </summary>
      /// <param name="timeout">Timeout in milliseconds</param>
      public  WebClientEx(int  timeout)
         : base ()
     {
         this .Timeout = timeout;
     }
 
     /// <summary>
      /// Overriding base method to set timeout
      /// </summary>
      /// <param name="address">Server Url</param>
      /// <returns>A WebRequest with a timeout assigned</returns>
      protected  override  WebRequest  GetWebRequest(Uri  address)
     {
         WebRequest  wr = base .GetWebRequest(address);
         wr.Timeout = this .Timeout;
         return  wr;
     }
 }
 

Impersonalized service calls in C#

As you know, any Windows Service operates under certain rights. It could be Network Service, Local System or a specific user. IIS process is not an exception. However, sometimes it is necessary to refer to the operating system using a different user account. In such cases your calls to the resources should be impersonalized. Below I'm glad to offer a way you can do it.

 class UserImpersonation : IDisposable
 {
     private bool disposed = false;
 
     [DllImport("advapi32.dll")]
     public static extern int LogonUser(String lpszUserName,
         String lpszDomain,
         String lpszPassword,
         int dwLogonType,
         int dwLogonProvider,
         ref IntPtr phToken);
 
     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
     public static extern int DuplicateToken(IntPtr hToken,
         int impersonationLevel,
         ref IntPtr hNewToken);
 
     [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
     public static extern bool RevertToSelf();
 
     [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
     public static extern bool CloseHandle(IntPtr handle);
 
     const int LOGON32_PROVIDER_DEFAULT = 0;
     const int LOGON32_LOGON_INTERACTIVE = 2;
 
     WindowsImpersonationContext wic;
     string _userName;
     string _domain;
     string _passWord;
 
     public UserImpersonation(string userName, string domain, string passWord)
     {
         _userName = userName;
         _domain = domain;
         _passWord = passWord;
     }
 
     public bool ImpersonateValidUser()
     {
         WindowsIdentity wi;
         IntPtr token = IntPtr.Zero;
         IntPtr tokenDuplicate = IntPtr.Zero;
 
         if (RevertToSelf())
         {
             if (LogonUser(_userName, _domain, _passWord, LOGON32_LOGON_INTERACTIVE,
                 LOGON32_PROVIDER_DEFAULT, ref token) != 0)
             {
                 if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                 {
                     wi = new WindowsIdentity(tokenDuplicate);
                     wic = wi.Impersonate();
                     if (wic != null)
                     {
                         CloseHandle(token);
                         CloseHandle(tokenDuplicate);
                         return true;
                     }
                 }
             }
         }
         if (token != IntPtr.Zero)
             CloseHandle(token);
         if (tokenDuplicate != IntPtr.Zero)
             CloseHandle(tokenDuplicate);
         return false;
     }
 
     private void CleanUp(bool disposing)
     {
         if (!this.disposed)
         {
             if (disposing)
             {
                 if (wic != null)
                     wic.Dispose();
             }
 
             RevertToSelf();
         }
 
         disposed = true;
     }
 
     public void Dispose()
     {
         CleanUp(true);
         GC.SuppressFinalize(this);
     }
 
     ~UserImpersonation()
    {
        CleanUp(false);
    }
 }

And here is how to use this class:

 using (UserImpersonation user = new UserImpersonation(UserName, Domain, Password))
 {
     if (user.ImpersonateValidUser())
     {
         // Do your work here.
  }
     else
  {
         // Something goes wrong. Check it here.
  }
 
 }
 

How to calculate distance between two geographical coordinates? (C#)

Geolocation manipulations become quite often programming task. Below is a simple function that calculated distance between two coordinates in kilometers. If you prefer miles, simply multiply results by 0.6214.

 public  static  double  GetDistance(double  Lat1, double  Lon1, double  Lat2, double  Lon2)
 {
     int  R = 6371;
 
     double  rLat1 = ToRadian(Lat1);
     double  rLat2 = ToRadian(Lat2);
 
     double  dLat = rLat2 - rLat1;
     double  dLon = ToRadian(Lon2 - Lon1);
 
     double  a = Math .Pow(Math .Sin(dLat / 2), 2) + 
         Math .Pow(Math .Sin(dLon / 2), 2) *
         Math .Cos(rLat1) * Math .Cos(rLat2);
 
     double  b = 2 * Math .Atan2(Math .Sqrt(a), Math .Sqrt(1 - a));
 
     return  R * b;
 }
 
 public  static  double  ToRadian(double  Grad)
 {
     return  Math .PI * Grad / 180;
 }
 

Enjoy!

Getting the Url to virtual root in ASP.NET (C#)

Use this snippet when you need to get an Url to virtual root path in your ASP.NET projects. You may need this, for example, when you want to call dynamically a REST Web service which is part of the same project (my story). I have found few ways to do this including storing such kind of info in Web.config file. But below is more short and convenient way. Just don’t forget to add trailing slash to the end because this function doesn’t do it by its self.

 string baseUrl = Request.Url.GetLeftPart(UriPartial.Authority);

Hope this helps.

Technorati Tags:

Flash a window in .NET (C#)

For a reason .NET lacks FlushWindowEx function so glad we can PInvoke it.

Declare FlushWindowEx and its dependencies:

 [StructLayout (LayoutKind .Sequential)]
 public  struct  FLASHWINFO
  {
     public  UInt32  cbSize;
     public  IntPtr  hwnd;
     public  Int32  dwFlags;
     public  UInt32  uCount;
     public  Int32  dwTimeout;
 }
 
 [Flags ]
 public  enum  FlashMode
  {
     FLASHW_STOP = 0,
     FLASHW_CAPTION = 1,
     FLASHW_TRAY = 2,
     FLASHW_ALL = (FLASHW_CAPTION | FLASHW_TRAY),
     FLASHW_TIMER = 4,
     FLASHW_TIMERNOFG = 12
 }
 
 [DllImport ("user32.dll" )]
 static  extern  Int32  FlashWindowEx(ref  FLASHWINFO  pwfi);
 

then just call it like this:

 FLASHWINFO  fw = new  FLASHWINFO ();
 fw.cbSize = Convert .ToUInt32(Marshal .SizeOf(typeof (FLASHWINFO )));
 fw.hwnd = this .Handle;
 fw.dwFlags = (Int32 )FlashMode .FLASHW_ALL;
 fw.uCount = 5;
 FlashWindowEx(ref  fw);
 

 

Technorati Tags: ,

 

How to add progress support to an App icon on Windows 7 Taskbar? (C#)

If you ever work with Windows 7, you already noticed that some Applications could show progress of a long process directly in their icon placed on Windows 7 Taskbar. Good example of this functionality is Internet Explorer when it download a file from Internet or Windows Explorer when you copy/move a file from one location to another. Before .NET Framework 4 era you have had to use external libraries to do this or implement PInvoke by yourself. Now, in your WPF 4 Applications you can use .NET 4 functionality. Here is step-by-step guideline how to do this.

1. Open your progress dialog XAML file. Create reference to Windows.TaskbarItemInfo as very top item of your dialog as shown below (lines 7-9):

1: <Window x:Class="IconProgressDemo.MainWindow" 
2:         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
3:         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
4:         Title="MainWindow" Height="130" Width="490"> 
5:      
6:     <!-- Reference to TaskbarItemInfo: --> 
7:     <Window.TaskbarItemInfo> 
8:         <TaskbarItemInfo /> 
9:     </Window.TaskbarItemInfo> 
10:      
11:     <Grid> 
12:         <StackPanel> 
13:             <!-- Regular WPF ScrollBar: --> 
14:             <ProgressBar Name="progressBar" HorizontalAlignment="Stretch" Height="25" /> 
15:              
16:             <!-- Start long process by pushing this button: --> 
17:             <Button HorizontalAlignment="Center" Margin="0,20" Width="65" Height="25" Click="Button_Click">Start!</Button> 
18:         </StackPanel> 
19:     </Grid> 
20: </Window> 
21: 
22: 

2. Switch to code behind of this dialog. Before process start, set a process state (line #52 below). I’ll explain possible states later. Let start with Normal.

3. Pass a process value to TaskbarItemInfo at the same time as to regular progress bar (lines 65-70).

4. When process finishes toy may want to reset both progress bar and TaskbarItemInfo (lines 58-63).

5. Run this example and press Start button. You will see that Task bar icon shows green progress over it self.

TaskbarItemInfo in Normal state

Now, as promised, let see what other ProgressState values for.

TaskbarItemInfo.ProgressState could be one of the following values:

Normal. As you saw above, this value shows regular green progress on App’s icon.

None. This is default value. This is why it’s important to change this value to any other before you start the process. Otherwise you won’t see any progress on your App icon.

Error. Show red progress bar and suitable for emerging cases when, for example, a non-critical error occurs and you don’t want to interrupt the process but let customer know about such case.

Indeterminate. Shows green ‘wave’ or ‘pulse’. Good for processes when you don’t know how long they will take and have to wait until they finish.

Paused. Shows yellow progress and good for interrupted processes. But note that switching to this value doesn’t interrupt the process it self, you still have to do this manually.

The pictures below illustrate Error, Indeterminate and Paused values of ProgressState property:

Error Indeterminate Paused

And here is full code behind of this example:

1: using  System;
2: using  System.Collections.Generic;
3: using  System.Linq;
4: using  System.Text;
5: using  System.Windows;
6: using  System.Windows.Controls;
7: using  System.Windows.Data;
8: using  System.Windows.Documents;
9: using  System.Windows.Input;
10: using  System.Windows.Media;
11: using  System.Windows.Media.Imaging;
12: using  System.Windows.Navigation;
13: using  System.Windows.Shapes;
14: using  System.Threading;
15: using  System.ComponentModel;
16: 
17: namespace  IconProgressDemo
18: {
19:     /// <summary> 
20:     /// Interaction logic for MainWindow.xaml 
21:     /// </summary> 
22:     public  partial  class  MainWindow  : Window 
23:     {
24:         public  MainWindow()
25:         {
26:             InitializeComponent();
27:         }
28: 
29:         private  void  Button_Click(object  sender, RoutedEventArgs  e)
30:         {
31:             // Simulate long process by using BackgroundWorker: 
32:             using  (BackgroundWorker  bw = new  BackgroundWorker ())
33:             {
34:                 bw.WorkerReportsProgress = true ;
35: 
36:                 // Pass process data: 
37:                 bw.ProgressChanged += new  ProgressChangedEventHandler (bw_ProgressChanged);
38: 
39:                 // Reset the counter: 
40:                 bw.RunWorkerCompleted += new  RunWorkerCompletedEventHandler (bw_RunWorkerCompleted);
41: 
42:                 bw.DoWork += (p, ev) =>
43:                     {
44:                         for  (int  i = 0; i <= 100; i += 10)
45:                         {
46:                             Thread .Sleep(1000);
47:                             ((BackgroundWorker )p).ReportProgress(i);
48:                         }
49:                     };
50: 
51:                 // Set the progress state: 
52:                 TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState .Normal;
53: 
54:                 bw.RunWorkerAsync();
55:             }
56:         }
57: 
58:         void  bw_RunWorkerCompleted(object  sender, RunWorkerCompletedEventArgs  e)
59:         {
60:             // The process was finished, reset the counter: 
61:             progressBar.Value = 0;
62:             TaskbarItemInfo.ProgressValue = 0;
63:         }
64: 
65:         void  bw_ProgressChanged(object  sender, ProgressChangedEventArgs  e)
66:         {
67:             // Pass process counter to both ProgressBar and TaskbarItemInfo: 
68:             progressBar.Value = e.ProgressPercentage;
69:             TaskbarItemInfo.ProgressValue = (double )e.ProgressPercentage / 100;
70:         }
71:     }
72: }
73: 
74: 

Have fun!

Technorati Tags: ,

Encoding a string with MD5 in C#

It is a common sense to keep user passwords encoded so they won't be compromised in case of hacker attack. Here is simple function doing this:

 /// <summary>
 /// Encodes a string using MD5. Don't forget to add ref. to System.Security.Cryptography
 /// </summary>
 /// <param name="password">A string to encode</param>
 /// <returns>Encoded string in Hex format</returns>
 public static string EncodeString(string password)
 {
     string md5encoded;
 
     // MD5 is disposable:
     using (MD5 md5 = new MD5CryptoServiceProvider())
         md5encoded = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(password)));
 
     // Removing dashes to shrink result length:
     return md5encoded.Replace("-", String.Empty);
 }
 

This function will return you string similar to this: E10ADC3949BA59ABBE56E057F20F883E.

Doesn't look like common MD5 string, should be like this: 4QrcOUm6Wau+VuBX8g+IPg== isn't it? To convert our result to such view we need just Bas64 it. Use this line instead of on example above:

 md5encoded = Convert.ToBase64String(md5.ComputeHash(Encoding.ASCII.GetBytes(password)));

So the whole function becoming to this:

 public static string EncodeString(string password)
 {
     string md5encoded;
 
     // MD5 is disposable:
     using (MD5 md5 = new MD5CryptoServiceProvider())
         md5encoded = Convert.ToBase64String(md5.ComputeHash(Encoding.ASCII.GetBytes(password)));
 
     // Removing dashes to shrink result length:
     return md5encoded;
 }
 

 

Is Power of 2? (C#)

Continue playing with Integers. Here is how to determine if a number is power of 2 or not:

 /// <summary>
 /// Checks if an integer is power of 2
 /// </summary>
 /// <param name="i">An int number to check</param>
 /// <returns>true if i is power of 2, false if otherwise</returns>
 public static bool IsPower2(int i)
 {
     return (i != 0) && ((i & -i) == i);
 }