Click here to Skip to main content
15,891,136 members
Articles / Web Development / ASP.NET

Control your Distributed Application using Windows and Web Service

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
15 Aug 2010CPOL4 min read 23K   606   19  
Control your distributed application using Windows and web service
/*	 /--==###################==--\
 *	 |	Ini File Handler  
 *	 \--==###################==--/
 * 
 * This handles Ini files and all their content.
 * 
 * Some explanation:
 * Categories are in fact sections, but i didn't think
 * "sections" so i wrote "categories". Sorry.
 * 
 * comment lines in ini files begin with #, ; or //
 * multi-line are not supported (Because I've never seen such)
 * 
 * It ignores comments on reading but can write them
 * 
 * How it works:
 * All data is saved in one System.Collections.SortedList which
 * contains the category names as keys, and all key-value pairs
 * as values, saved as SortedList too:
 * 
 * explanation sheet
 * 
 * SortedList Categories
 * {
 *		{"Category1", {Key1, value1}
 *					  {Key2, value2}
 *					  ...
 *								   }
 *		{"Category2", {Key1, value1}
 *					  {Key2, value2}
 *					  ...
 *								   }
 *		...
 * }
 * 
 * that behaves like an array in an array (array[][]), but with dynamic bounds
 * and strings as indexers.
 * 
 */

using System;
using System.IO;
using System.Text;
using System.Collections;

namespace winServiceAndWindowsInterface
{
	/// <summary>
	/// Handles Ini categories, keys and their associated values, static methods implemented for file
	/// handling (saving and reading)
	/// </summary>
	public class IniStructure
	{
		#region Ini structure code
		private SortedList Categories = new SortedList();

		/// <summary>
		/// Initialies a new IniStructure
		/// </summary>
		public IniStructure()
		{
			return; // There's nothing to do...
		}

		/// <summary>
		/// Adds a category to the IniStructure
		/// </summary>
		/// <param name="Name">Name of the new category</param>
		public bool AddCategory(string Name)
		{
			if (Name == "" | Categories.ContainsKey(Name))
				return false;
			if (Name.IndexOf('=') != -1
				| Name.IndexOf('[') != -1
				| Name.IndexOf(']') != -1) // these characters are not allowed in a category name
				return false;

			Categories.Add(Name, new SortedList());
			return true;
		}

		/// <summary>
		/// Deletes a category and its contents
		/// </summary>
		/// <param name="Name">category to delete</param>
		public bool DeleteCategory(string Name)
		{
			if (Name == "" | !Categories.ContainsKey(Name))
				return false;
			Categories.Remove(Name);
			return true;
		}

		/// <summary>
		/// Renames a category
		/// </summary>
		/// <param name="Name">Category to rename</param>
		/// <param name="NewName">New name</param>
		public bool RenameCategory(string Name, string NewName)
		{ //		Or rather moves a category to a new name
			if (Name == "" | !Categories.ContainsKey(Name) | NewName == "")
				return false;

			if (NewName.IndexOf('=') != -1
				| NewName.IndexOf('[') != -1
				| NewName.IndexOf(']') != -1) // these characters are not allowed in a category name
				return false;

			SortedList Category = (SortedList)(Categories[Name]);
			Categories.Add(NewName, Category);
			this.DeleteCategory(Name);
			return true;
		}

		/// <summary>
		/// Returns the names of all categories
		/// </summary>
		/// <returns></returns>
		public string[] GetCategories()
		{
			string[] CatNames = new string[Categories.Count];
			IList KeyList = Categories.GetKeyList();
			int KeyCount = Categories.Count;
			for (int i = 0; i < KeyCount; i++)
			{
				CatNames[i] = KeyList[i].ToString();
			}
			return CatNames;
		}

		/// <summary>
		/// Returns the name of a category by specifying the index.
		/// Useful to enumerate through all categories.
		/// </summary>
		/// <param name="Index">The category index</param>
		/// <returns></returns>
		public string GetCategoryName(int Index)
		{
			if (Index < 0 | Index >= Categories.Count)
				return null;
			return Categories.GetKey(Index).ToString();
		}

		/// <summary>
		/// Adds a key-value pair to a specified category
		/// </summary>
		/// <param name="CategoryName">Name of the category</param>
		/// <param name="Key">New name of the key</param>
		/// <param name="Value">Associated value</param>
		public bool AddValue(string CategoryName, string Key, string Value)
		{
			if (CategoryName == "" | Key == "")
				return false;
			if (Key.IndexOf('=') != -1
				| Key.IndexOf('[') != -1
				| Key.IndexOf(']') != -1	// these chars are not allowed for keynames
				| Key.IndexOf(';') != -1
				| Key.IndexOf('#') != -1
				)
				return false;
			if (!Categories.ContainsKey(CategoryName))
				return false;
			SortedList Category = (SortedList)(Categories[CategoryName]);
			if (Category.ContainsKey(Key))
				return false;
			Category.Add(Key, Value);
			return true;
		}

		/// <summary>
		/// Returns the value of a key-value pair in a specified category by specifying the key
		/// </summary>
		/// <param name="CategoryName">Name of the category</param>
		/// <param name="Key">Name of the Key</param>
		/// <returns></returns>
		public string GetValue(string CategoryName, string Key)
		{
			if (CategoryName == "" | Key == "")
				return null;
			if (!Categories.ContainsKey(CategoryName))
				return null;
			SortedList Category = (SortedList)(Categories[CategoryName]);
			if (!Category.ContainsKey(Key))
				return null;
			return Category[Key].ToString();
		}

		/// <summary>
		/// Returns the key-value pair in a specified category by specifying the index
		/// </summary>
		/// <param name="CategoryName">Index of the category</param>
		/// <param name="Key">Index of the Key</param>
		/// <returns></returns>
		public string GetValue(int CatIndex, int KeyIndex)
		{
			if (CatIndex < 0 | KeyIndex < 0
				|CatIndex >= Categories.Count)
				return null;
			SortedList Category = (SortedList)(Categories.GetByIndex(CatIndex));
			if (KeyIndex >= Category.Count)
				return null;
			return Category.GetByIndex(KeyIndex).ToString();
		}

		/// <summary>
		/// Returns the name of the key in a key-value pair in a specified category by specifying the index
		/// </summary>
		/// <param name="CatIndex">Index of the category</param>
		/// <param name="KeyIndex">Index of the key</param>
		/// <returns></returns>
		public string GetKeyName(int CatIndex, int KeyIndex)
		{
			if (CatIndex < 0 | KeyIndex < 0
				|CatIndex >= Categories.Count)
				return null;
			SortedList Category = (SortedList)(Categories.GetByIndex(CatIndex));
			if (KeyIndex >= Category.Count)
				return null;
			return Category.GetKey(KeyIndex).ToString();
		}


		/// <summary>
		/// Deletes a key-value pair
		/// </summary>
		/// <param name="CategoryName">Name of the category</param>
		/// <param name="Key">Name of the Key</param>
		public bool DeleteValue(string CategoryName, string Key)
		{
			if (CategoryName == "" | Key == "")
				return false;
			if (!Categories.ContainsKey(CategoryName))
				return false;
			SortedList Category = (SortedList)(Categories[CategoryName]);
			if (!Category.ContainsKey(Key))
				return false;
			Category.Remove(Key);
			return true;
		}

		/// <summary>
		/// Renames the keyname in a key-value pair
		/// </summary>
		/// <param name="CategoryName">Name of the category</param>
		/// <param name="KeyName">Name of the Key</param>
		/// <param name="NewKeyName">New name of the Key</param>
		public bool RenameKey(string CategoryName, string KeyName, string NewKeyName)
		{
			if (CategoryName == "" | KeyName == "" | NewKeyName == "")
				return false;
			if (!Categories.ContainsKey(CategoryName))
				return false;
			if (NewKeyName.IndexOf('=') != -1
				| NewKeyName.IndexOf('[') != -1
				| NewKeyName.IndexOf(']') != -1	// these chars are not allowed for keynames
				| NewKeyName.IndexOf(';') != -1
				| NewKeyName.IndexOf('#') != -1
				)
				return false;
			SortedList Category = (SortedList)(Categories[CategoryName]);
			if ( !Category.ContainsKey(KeyName))
				return false;
			
			object value = Category[KeyName];
			Category.Remove(KeyName);
			Category.Add(NewKeyName, value);
			return true;
		}

		/// <summary>
		/// Modifies the value in a key-value pair
		/// </summary>
		/// <param name="CategoryName">Name of the category</param>
		/// <param name="KeyName">Name of the Key</param>
		/// <param name="NewValue">New name of the Key</param>
		public bool ModifyValue(string CategoryName, string KeyName, string NewValue)
		{
			if (CategoryName == "" | KeyName == "")
				return false;
			if (!Categories.ContainsKey(CategoryName))
				return false;
			SortedList Category = (SortedList)(Categories[CategoryName]);
			if ( !Category.ContainsKey(KeyName))
				return false;
			
			Category[KeyName] = NewValue;
			return true;
		}

		/// <summary>
		/// Returns all keys in a category
		/// </summary>
		/// <param name="CategoryName">Name of the category</param>
		/// <returns></returns>
		public string[] GetKeys(string CategoryName)
		{
			SortedList Category = (SortedList)(Categories[CategoryName]);
			if (Category == null)
				return null;
			int KeyCount = Category.Count;
			string[] KeyNames = new string[KeyCount];
			IList KeyList = Category.GetKeyList();
			for (int i = 0; i < KeyCount; i++)
			{
				KeyNames[i] = KeyList[i].ToString();
			}
			return KeyNames;
		}

		#endregion

		#region Ini writing code
		/// <summary>
		/// Writes an IniStructure to a file with a comment.
		/// </summary>
		/// <param name="IniData">The contents to write</param>
		/// <param name="Filename">The complete path and name of the file</param>
		/// <param name="comment">Comment to add</param>
		/// <returns></returns>
		public static bool WriteIni(IniStructure IniData, string Filename, string comment)
		{
			string DataToWrite = CreateData(IniData, BuildComment(comment));
			return WriteFile(Filename, DataToWrite);
		}

		/// <summary>
		/// Writes an IniStructure to a file without a comment.
		/// </summary>
		/// <param name="IniData">The contents to write</param>
		/// <param name="Filename">The complete path and name of the file</param>
		/// <returns></returns>
		public static bool WriteIni(IniStructure IniData, string Filename)
		{
			string DataToWrite = CreateData(IniData);
			return WriteFile(Filename, DataToWrite);
		}

		private static bool WriteFile(string Filename, string Data)
		{	// Writes a string to a file
			try
			{
				FileStream IniStream = new FileStream(Filename,FileMode.Create);
				if (!IniStream.CanWrite)
				{
					IniStream.Close();
					return false;
				}
				StreamWriter writer = new StreamWriter(IniStream);
				writer.Write(Data);
				writer.Flush();
				writer.Close();
				IniStream.Close();
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static string BuildComment(string comment)
		{ // Adds a # at the beginning of each line
			if (comment == "")
				return "";
			string[] Lines = DivideToLines(comment);
			string temp = "";
			foreach (string line in Lines)
			{
				temp += "# " + line + "\r\n";
			}
			return temp;
		}

		private static string CreateData(IniStructure IniData)
		{
			return CreateData(IniData,"");
		}

		private static string CreateData(IniStructure IniData, string comment)
		{	//Iterates through all categories and keys and appends all data to Data
			int CategoryCount = IniData.GetCategories().Length;
			int[] KeyCountPerCategory = new int[CategoryCount];
			string Data = comment;
			string[] temp = new string[2]; // will contain key-value pair
			
			for (int i = 0; i < CategoryCount; i++) // Gets keycount per category
			{
				string CategoryName = IniData.GetCategories()[i];
				KeyCountPerCategory[i] = IniData.GetKeys(CategoryName).Length;
			}

			for (int catcounter = 0; catcounter < CategoryCount; catcounter++)
			{
				Data += "\r\n[" + IniData.GetCategoryName(catcounter) + "]\r\n"; 
				// writes [Category] to Data
				for (int keycounter = 0; keycounter < KeyCountPerCategory[catcounter]; keycounter++)
				{
					temp[0] = IniData.GetKeyName(catcounter, keycounter);
					temp[1] = IniData.GetValue(catcounter, keycounter);
					Data += temp[0] + "=" + temp[1] + "\r\n";
					// writes the key-value pair to Data
				}
			}
			return Data;
		}
		#endregion

		#region Ini reading code

		/// <summary>
		/// Reads an ini file and returns the content as an IniStructure. Returns null if an error occurred.
		/// </summary>
		/// <param name="Filename">The filename to read</param>
		/// <returns></returns>
		public static IniStructure ReadIni(string Filename)
		{
			string Data = ReadFile(Filename);
			if (Data == null)
				return null;

			IniStructure data = InterpretIni(Data);
			
			return data;
		}

		public static IniStructure InterpretIni(string Data)
		{
			IniStructure IniData = new IniStructure();
			string[] Lines = RemoveAndVerifyIni(DivideToLines(Data));
			// Divides the Data in lines, removes comments and empty lines
			// and verifies if the ini is not corrupted
			// Returns null if it is.
			if (Lines == null)
				return null;

			if (IsLineACategoryDef(Lines[0]) != LineType.Category)
			{
				return null;
				// Ini is faulty - does not begin with a categorydef
			}
			string CurrentCategory = "";
			foreach (string line in Lines)
			{
				switch (IsLineACategoryDef(line))
				{
					case LineType.Category:	// the line is a correct category definition
						string NewCat = line.Substring(1,line.Length - 2);
						IniData.AddCategory(NewCat); // adds the category to the IniData
						CurrentCategory = NewCat;
						break;
					case LineType.NotACategory: // the line is not a category definition
						string[] keyvalue = GetDataFromLine(line);
						IniData.AddValue(CurrentCategory, keyvalue[0], keyvalue[1]);
						// Adds the key-value to the current category
						break;
					case LineType.Faulty: // the line is faulty
						return null;
				}
			}
			return IniData;
		}

		private static string ReadFile(string filename)
		{		// Reads a file to a string.
			if (!File.Exists(filename))
				return null;
			StringBuilder IniData;
			try
			{
				FileStream IniStream = new FileStream(filename,FileMode.Open,FileAccess.Read);
				if (!IniStream.CanRead)
				{
					IniStream.Close();
					return null;
				}
				StreamReader reader = new StreamReader(IniStream);
				IniData = new StringBuilder();
				IniData.Append(reader.ReadToEnd());
				reader.Close();
				IniStream.Close();
				return IniData.ToString();
			}
			catch
			{
				return null;
			}
		}
		
		private static string[] GetDataFromLine(string Line)
		{
			// returns the key and the value of a key-value pair in "key=value" format.
			int EqualPos = 0;
			EqualPos = Line.IndexOf("=", 0);
			if (EqualPos < 1)
			{
				return null;
			}
			string LeftKey = Line.Substring(0, EqualPos);
			string RightValue = Line.Substring(EqualPos + 1);
			
			string[] ToReturn = {LeftKey, RightValue};
			return ToReturn;
		}

		private enum LineType // return type for IsLineACategoryDef and LineVerify
		{
			NotACategory,
			Category,
			Faulty,
			Comment,
			Empty,
			Ok
		}

		private static LineType IsLineACategoryDef(string Line)
		{
			if (Line.Length < 3)
				return LineType.NotACategory; // must be a short keyname like "k="
            
			if (Line.Substring(0,1) == "[" & Line.Substring(Line.Length - 1, 1) == "]")
				// seems to be a categorydef
			{
				if (Line.IndexOf("=") != -1) 
					//  '=' found -> is incorrect for category def
					return LineType.Faulty;
				if (ContainsMoreThanOne(Line,'[') | ContainsMoreThanOne(Line, ']'))
					// two or more '[' or ']' found -> incorrect
					return LineType.Faulty;
				return LineType.Category;
			}
			return LineType.NotACategory;
		}

		private static string[] DivideToLines(string Data)
		{		// Divides a string into lines
			string[] Lines = new string[Data.Length];
			int oldnewlinepos = 0;
			int LineCounter = 0;
			for (int i = 0; i < Data.Length; i++)
			{
				if (Data.ToCharArray(i,1)[0] == '\n')
				{
					Lines[LineCounter] = Data.Substring(oldnewlinepos, i - oldnewlinepos - 1);
					oldnewlinepos = i + 1;
					LineCounter++;
				}
			}

			// Lines[] array is too big: needs to be trimmed
			
			Lines[LineCounter] = Data.Substring(oldnewlinepos, Data.Length - oldnewlinepos);
			string[] LinesTrimmed = new string[LineCounter + 1];
			for (int i = 0; i < LineCounter + 1; i++)
			{
				LinesTrimmed[i] = Lines[i];
			}
			return LinesTrimmed;
		}

		private static bool ContainsMoreThanOne(string Data, char verify)
		{	// returns true if Data contains verify more than once
			char[] data = Data.ToCharArray();
			int count = 0;
			foreach (char c in data)
			{
				if (c == verify)
					count++;
			}
			if (count > 1)
				return true;
			return false;
		}

		private static LineType LineVerify(string line)
		{		// Verifies a line of an ini
			if (line == "")
				return LineType.Empty;

			if (line.IndexOf(";") == 0 | line.IndexOf("#") == 0 | line.IndexOf("//") == 0)
			{
				return LineType.Comment; // line is a comment: ignore
			}

			int equalindex = line.IndexOf('=');
			if (equalindex == 0)
				return LineType.Faulty; // an '=' cannot be on first place

			if (equalindex != -1) // if = is found in line
			{
				// Verify: no '[' , ']' ,';' or '#' before the '='
				if (line.IndexOf('[', 0, equalindex) != -1
					| line.IndexOf(']', 0, equalindex) != -1
					| line.IndexOf(';', 0, equalindex) != -1
					| line.IndexOf('#', 0, equalindex) != -1)
					return LineType.Faulty;
			}

			return LineType.Ok;
		}

		private static string[] RemoveAndVerifyIni(string[] Lines)
		{
			// removes empty lines and comments, and verifies every line
			string[] temp = new string[Lines.Length];
			int TempCounter = 0; // number of lines to return
			foreach (string line in Lines)
			{
				switch (LineVerify(line))
				{
					case LineType.Faulty: // line is faulty
						return null;
					case LineType.Comment:	//	line is a comment
						continue;
					case LineType.Ok:	// line is ok
						temp[TempCounter] = line;
						TempCounter++;
						break;
					case LineType.Empty: // line is empty
						continue;
				}
			}
			// the temp[] array is too big: needs to be trimmed.
			string[] OKLines = new string[TempCounter];
			for (int i = 0; i < TempCounter; i++)
			{
				OKLines[i] = temp[i];
			}
			return OKLines;
		}
		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader ArabicRobotics.com
Egypt Egypt
Tareq Gamal El-din Mohammed,
---------
Website:
www.ArabicRobotics.com

---------

Graduated from Modern Academy for Computer science and Information Technology. Egypt,
Then flow Microsoft development track Certificates:
MCAD.NET (Microsoft Certified Application Developer)
MCSD.NET (Microsoft Certified Solution Developer)
Microsoft SharePoint Administration, Configuration and Development.

Robotics fields was a Hobby since 2002,
started to develop some applications for "Robosapien", "RoboSapienV2", "RS Media", RoboMe and WowWee Rovio. from WowWee company,

Started working with robots as a professional way at 2014
By using "NAOqi" Robotics from Aldebaran.

By developing some applications and libraries like :
NAO.NET.
https://www.youtube.com/watch?v=oOyy-2XyT-c

OpenCV with NAO Robot:

- NAORobot Vision using OpenCV -TotaRobot P1
https://www.youtube.com/watch?v=MUcj8463x08

- NAO Robot Vision using OpenCV - P2
https://www.youtube.com/watch?v=93k1usaS-QM

NAO Alarm Clock :
https://www.youtube.com/watch?v=djLlMeGLqOU
-----------------------------

also Robotic Arm Project:


Other Projects Developed by Tareq Gamal El-din Mohammed :

Developed and posted some applications in Code Project web site like :

- Control your Distributed Application using Windows and Web Service
http://www.codeproject.com/Articles/101895/Control-your-Distributed-Application-using-Windows


- Quick and dirty directory copy
http://www.codeproject.com/Articles/12745/Quick-and-dirty-directory-copy

- Program Execute Timer(From the Web)
http://www.codeproject.com/Articles/12743/Program-Executer-Timer

Comments and Discussions