Friday, December 5, 2008

How to access file share on remote server

In my ASP.NET Application, I must access file share on a remote server by its UNC path, i.e., \\server\folder\subfolder\, using specific username and password.


using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.IO;

namespace RemoteCredentials
{
	class MainClass
	{
		[DllImport( "advapi32.dll", SetLastError = true )]
		private static extern bool LogonUser( string
			lpszUsername, string lpszDomain, string lpszPassword,
			int dwLogonType, int dwLogonProvider, ref IntPtr phToken );

		[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
		private unsafe static extern int FormatMessage(int
			dwFlags, ref IntPtr lpSource,
			int dwMessageId, int dwLanguageId, ref String lpBuffer, 
			int nSize, IntPtr *arguments);

		[DllImport( "kernel32.dll", CharSet = CharSet.Auto, 
			SetLastError = true )]
		private static extern bool CloseHandle( IntPtr handle);

		[DllImport("advapi32.dll", CharSet = CharSet.Auto, 
			SetLastError = true)]
		public extern static bool DuplicateToken( IntPtr
			existingTokenHandle,
			int SECURITY_IMPERSONATION_LEVEL, 
			ref IntPtr duplicateTokenHandle );


		// logon types
		const int LOGON32_LOGON_INTERACTIVE = 2;
		const int LOGON32_LOGON_NETWORK = 3;
		const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

		// logon providers
		const int LOGON32_PROVIDER_DEFAULT = 0;
		const int LOGON32_PROVIDER_WINNT50 = 3;
		const int LOGON32_PROVIDER_WINNT40 = 2;
		const int LOGON32_PROVIDER_WINNT35 = 1;

		/// 
		/// The main entry point for the application.
		/// 
		[STAThread]
		static void Main(string[] args)
		{
			IntPtr token = IntPtr.Zero;
			IntPtr dupToken = IntPtr.Zero;

			bool isSuccess = LogonUser( 
				"userId", "192.168.1.1", "password", 
				LOGON32_LOGON_NEW_CREDENTIALS,
				LOGON32_PROVIDER_DEFAULT, ref token );
			
			if( !isSuccess )
			{
				RaiseLastError();
			}

			isSuccess = DuplicateToken( token, 2, ref dupToken );
			
			if( !isSuccess )
			{
				RaiseLastError();
			}

			WindowsIdentity newIdentity = new WindowsIdentity( dupToken );
			
			WindowsImpersonationContext impersonatedUser 
				= newIdentity.Impersonate();

			DirectoryInfo dirInfo = new DirectoryInfo(
				@"\\192.19.12.46\sharedfolder" );
			FileInfo[] files = dirInfo.GetFiles();

			impersonatedUser.Undo();

			foreach( FileInfo file in files )
			{
				Console.WriteLine( file.FullName );
			}

			isSuccess = CloseHandle( token );
			if( !isSuccess )
			{
				RaiseLastError();
			}
		}

		// GetErrorMessage formats and returns an error message
		// corresponding to the input errorCode.
		public unsafe static string GetErrorMessage( int errorCode )
		{
			int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
			int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
			int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;

			int messageSize = 255;
			string lpMsgBuf = "";
			int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER 
				| FORMAT_MESSAGE_FROM_SYSTEM 
				| FORMAT_MESSAGE_IGNORE_INSERTS;

			IntPtr ptrlpSource = IntPtr.Zero;
			IntPtr ptrArguments = IntPtr.Zero;

			int retVal = FormatMessage(
				dwFlags, ref ptrlpSource, errorCode, 0, 
				ref lpMsgBuf, messageSize, &ptrArguments);
			if( retVal == 0 )
			{
				throw new ApplicationException(
				string.Format( 
					"Failed to format message for error code '{0}'."
					, errorCode ) );
			}

			return lpMsgBuf;
		}

		private static void RaiseLastError()
		{
			int errorCode = Marshal.GetLastWin32Error();
			string errorMessage = GetErrorMessage(errorCode );

			throw new ApplicationException( errorMessage);
		}
	}
}

Tuesday, December 2, 2008

Đếm số dòng có trong một File

Đoạn code sau đưa ra cách để đếm số dòng trong một file. Nó sẽ đếm cả dòng cuối cùng của một file ngay cả khi dòng cuối cùng không phải là kết thúc của dòng mới.

Cách sử dụng:

C:/>CountLine CountLine.cs
lines = 50

Mã nguồn bằng C#:

namespace Sample
{
   static class LineCount
   {
       /// 
       /// The main entry point for the application.
       /// 
       [STAThread]
       static void Main(string[] args)
       {
           if (args.Length == 0)
               Console.WriteLine("Usage: LineCount File Name");
           else
           {
               string fileName = args[0];

               if (!File.Exists(fileName))
                   Console.WriteLine("File '{0} does not exist. Please try again.", fileName);
               else
               {
                   FileStream fileStream = File.OpenRead(fileName);
                  
                   int ch, prev = '\n' /* so empty files have no lines */, lines = 0;

                   while ( (ch = fileStream.ReadByte()) != -1) /* Read all chars in the file. */
                   {
                       if ( ch == '\n' )
                       {
                           ++lines; /* Bump the counter for every newline. */
                       }
                      
                       prev = ch; /* Keep a copy to later test whether... */
                   }
                  
                   fileStream.Close();
                  
                   if ( prev != '\n' ) /* ...the last line did not end in a newline. */
                   {
                       ++lines; /* If so, add one more to the total. */
                   }
                  
                   Console.WriteLine("lines = {0}", lines);
               }
           }
       }
   }
}