using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Collections; using System.Globalization; namespace BaseLibRWFile { public class Ini { public const int MaxSectionSize = 32767; // 32 KB private string m_path; private Dictionary _locks = new Dictionary(); #region P/Invoke declares [System.Security.SuppressUnmanagedCodeSecurity] private static class NativeMethods { [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, uint nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, [In, Out] char[] lpReturnedString, int nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern int GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, IntPtr lpReturnedString, uint nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern int GetPrivateProfileInt(string lpAppName, string lpKeyName, int lpDefault, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] public static extern int GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName); [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool WritePrivateProfileSection(string lpAppName, string lpstring, string lpFileName); } #endregion /// /// 实例化Ini /// /// ini文件完整路径 /// public Ini(string path) { m_path = System.IO.Path.GetFullPath(path); if (!_locks.ContainsKey(m_path)) { _locks.Add(m_path, new object()); } } /// /// 读取ini文件指定数据 /// /// 数据标签 /// 数据名称 /// 默认值 /// public string ReadIni(string label, string name, String value) //读配置文件 { try { string ret; ret = GetString(label, name, value); if (ret == value) { WriteValue(label, name, value); } return ret; } catch (Exception ex) { MessageBox.Show(ex.ToString(), "ReadIni Error"); return null; } } /// /// 写入数据到ini文件 /// /// 数据标签 /// 数据名称 /// 要写入的值 /// public void WriteIni(string label, string name, String value) //写配置文件 { try { WriteValue(label, name, value); } catch (Exception ex) { MessageBox.Show(ex.ToString(), "WriteIni Error"); } } public string Path { get { return m_path; } } /// /// 创建文件夹 /// /// 文件夹完整路径 /// public void DirectoryCreate(string DirectoryFileName) { if (!Directory.Exists(DirectoryFileName)) { Directory.CreateDirectory(DirectoryFileName); } } /// /// 创建ini文件 /// /// ini文件完整路径 /// public void CreateFile(string FileName) { if (!(File.Exists(FileName))) { File.Create(FileName).Close(); } } public void CopyFile(string strSourcePath, string strTargetPath, bool IsCoverage) { try { if (!File.Exists(strTargetPath)) { CreateFile(strTargetPath); } File.Copy(strSourcePath, strTargetPath, IsCoverage); } catch { } } #region Get Value Methods public string GetString(string sectionName, string keyName, string defaultValue) { if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); if (keyName == null) throw new ArgumentNullException(nameof(keyName)); lock (_locks[m_path]) { StringBuilder retval = new StringBuilder(Ini.MaxSectionSize); NativeMethods.GetPrivateProfileString(sectionName, keyName, defaultValue, retval, Ini.MaxSectionSize, m_path); return retval.ToString(); } } /// /// Gets the value of a setting in an ini file as a . /// /// The name of the section to read from. /// The name of the key in section to read. /// The default value to return if the key /// cannot be found. /// The value of the key, if found. Otherwise, returns /// . /// /// or are /// a null reference (Nothing in VB) /// public int GetInt16(string sectionName, string keyName, short defaultValue) { int retval = GetInt32(sectionName, keyName, defaultValue); return Convert.ToInt16(retval); } /// /// Gets the value of a setting in an ini file as a . /// /// The name of the section to read from. /// The name of the key in section to read. /// The default value to return if the key /// cannot be found. /// The value of the key, if found. Otherwise, returns /// /// /// or are /// a null reference (Nothing in VB) /// public int GetInt32(string sectionName, string keyName, int defaultValue) { if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); if (keyName == null) throw new ArgumentNullException(nameof(keyName)); lock (_locks[m_path]) { return NativeMethods.GetPrivateProfileInt(sectionName, keyName, defaultValue, m_path); } } /// /// Gets the value of a setting in an ini file as a . /// /// The name of the section to read from. /// The name of the key in section to read. /// The default value to return if the key /// cannot be found. /// The value of the key, if found. Otherwise, returns /// /// /// or are /// a null reference (Nothing in VB) /// public double GetDouble(string sectionName, string keyName, double defaultValue) { string retval = GetString(sectionName, keyName, ""); if (retval == null || retval.Length == 0) { return defaultValue; } return Convert.ToDouble(retval, CultureInfo.InvariantCulture); } #endregion #region GetSectionValues Methods /// /// Gets all of the values in a section as a list. /// /// /// Name of the section to retrieve values from. /// /// /// A containing objects /// that describe this section. Use this verison if a section may contain /// multiple items with the same key value. If you know that a section /// cannot contain multiple values with the same key name or you don't /// care about the duplicates, use the more convenient /// function. /// /// /// is a null reference (Nothing in VB) /// public List> GetSectionValuesAsList(string sectionName) { List> retval; string[] keyValuePairs; string key, value; int equalSignPos; if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); //Allocate a buffer for the returned section names. IntPtr ptr = Marshal.AllocCoTaskMem(Ini.MaxSectionSize); try { //Get the section key/value pairs into the buffer. lock (_locks[m_path]) { int len = NativeMethods.GetPrivateProfileSection(sectionName, ptr, Ini.MaxSectionSize, m_path); keyValuePairs = ConvertNullSeperatedStringToStringArray(ptr, len); } } finally { //Free the buffer Marshal.FreeCoTaskMem(ptr); } //Parse keyValue pairs and add them to the list. retval = new List>(keyValuePairs.Length); for (int i = 0; i < keyValuePairs.Length; ++i) { //Parse the "key=value" string into its constituent parts equalSignPos = keyValuePairs[i].IndexOf('='); key = keyValuePairs[i].Substring(0, equalSignPos); value = keyValuePairs[i].Substring(equalSignPos + 1, keyValuePairs[i].Length - equalSignPos - 1); retval.Add(new KeyValuePair(key, value)); } return retval; } /// /// Gets all of the values in a section as a dictionary. /// /// /// Name of the section to retrieve values from. /// /// /// A containing the key/value /// pairs found in this section. /// /// /// If a section contains more than one key with the same name, /// this function only returns the first instance. If you need to /// get all key/value pairs within a section even when keys have the /// same name, use . /// /// /// is a null reference (Nothing in VB) /// public Dictionary GetSectionValues(string sectionName) { List> keyValuePairs; Dictionary retval; keyValuePairs = GetSectionValuesAsList(sectionName); //Convert list into a dictionary. retval = new Dictionary(keyValuePairs.Count); foreach (KeyValuePair keyValuePair in keyValuePairs) { //Skip any key we have already seen. if (!retval.ContainsKey(keyValuePair.Key)) { retval.Add(keyValuePair.Key, keyValuePair.Value); } } return retval; } #endregion #region Get Key/Section Names /// /// Gets the names of all keys under a specific section in the ini file. /// /// /// The name of the section to read key names from. /// /// An array of key names. /// /// The total length of all key names in the section must be /// less than 32KB in length. /// /// /// is a null reference (Nothing in VB) /// public string[] GetKeyNames(string sectionName) { int len; string[] retval; if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); //Allocate a buffer for the returned section names. IntPtr ptr = Marshal.AllocCoTaskMem(Ini.MaxSectionSize); try { //Get the section names into the buffer. lock (_locks[m_path]) { len = NativeMethods.GetPrivateProfileString(sectionName, null, null, ptr, Ini.MaxSectionSize, m_path); retval = ConvertNullSeperatedStringToStringArray(ptr, len); } } finally { //Free the buffer Marshal.FreeCoTaskMem(ptr); } return retval; } /// /// Gets the names of all sections in the ini file. /// /// An array of section names. /// /// The total length of all section names in the section must be /// less than 32KB in length. /// public string[] GetSectionNames() { string[] retval; int len; //Allocate a buffer for the returned section names. IntPtr ptr = Marshal.AllocCoTaskMem(Ini.MaxSectionSize); try { //Get the section names into the buffer. lock (_locks[m_path]) { len = NativeMethods.GetPrivateProfileSectionNames(ptr, Ini.MaxSectionSize, m_path); retval = ConvertNullSeperatedStringToStringArray(ptr, len); } } finally { //Free the buffer Marshal.FreeCoTaskMem(ptr); } return retval; } /// /// Converts the null seperated pointer to a string into a string array. /// /// A pointer to string data. /// /// Length of the data pointed to by . /// /// /// An array of strings; one for each null found in the array of characters pointed /// at by . /// private static string[] ConvertNullSeperatedStringToStringArray(IntPtr ptr, int valLength) { string[] retval; if (valLength == 0) { //Return an empty array. retval = Array.Empty(); } else { //Convert the buffer into a string. Decrease the length //by 1 so that we remove the second null off the end. string buff = Marshal.PtrToStringAuto(ptr, valLength - 1); //Parse the buffer into an array of strings by searching for nulls. retval = buff.Split('\0'); } return retval; } #endregion #region Write Methods /// /// Writes a value to the ini file. /// /// The name of the section to write to . /// The name of the key to write to. /// The string value to write /// /// The write failed. /// private void WriteValueInternal(string sectionName, string keyName, string value) { lock (_locks[m_path]) { if (!NativeMethods.WritePrivateProfileString(sectionName, keyName, value, m_path)) { throw new System.ComponentModel.Win32Exception(); } } } public void WriteValue(string sectionName) { WriteValueInternal(sectionName, "a", "a"); WriteValueInternal(sectionName, "a", null); //NativeMethods.WritePrivateProfileSection(sectionName, null, m_path); } /// /// Writes a value to the ini file. /// /// The name of the section to write to . /// The name of the key to write to. /// The string value to write /// /// The write failed. /// /// /// or or /// are a null reference (Nothing in VB) /// public void WriteValue(string sectionName, string keyName, string value) { if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); if (keyName == null) throw new ArgumentNullException(nameof(keyName)); if (value == null) throw new ArgumentNullException(nameof(value)); WriteValueInternal(sectionName, keyName, value); } /// /// Writes an value to the ini file. /// /// The name of the section to write to . /// The name of the key to write to. /// The value to write /// /// The write failed. /// public void WriteValue(string sectionName, string keyName, short value) { WriteValue(sectionName, keyName, (int)value); } /// /// Writes an value to the ini file. /// /// The name of the section to write to . /// The name of the key to write to. /// The value to write /// /// The write failed. /// /// /// or are /// a null reference (Nothing in VB) /// public void WriteValue(string sectionName, string keyName, int value) { WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture)); } /// /// Writes an value to the ini file. /// /// The name of the section to write to . /// The name of the key to write to. /// The value to write /// /// The write failed. /// /// /// or are /// a null reference (Nothing in VB) /// public void WriteValue(string sectionName, string keyName, float value) { WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture)); } /// /// Writes an value to the ini file. /// /// The name of the section to write to . /// The name of the key to write to. /// The value to write /// /// The write failed. /// /// /// or are /// a null reference (Nothing in VB) /// public void WriteValue(string sectionName, string keyName, double value) { WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture)); } #endregion #region Delete Methods /// /// Deletes the specified key from the specified section. /// /// /// Name of the section to remove the key from. /// /// /// Name of the key to remove. /// /// /// or are /// a null reference (Nothing in VB) /// public void DeleteKey(string sectionName, string keyName) { if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); if (keyName == null) throw new ArgumentNullException(nameof(keyName)); //ArrayList list = ArrayList.Adapter(GetSectionNames()); //if (!list.Contains(sectionName)) //{ // return; //} //list = ArrayList.Adapter(GetKeyNames(sectionName)); //if (!list.Contains(keyName)) //{ // return; //} WriteValueInternal(sectionName, keyName, null); } /// /// Deletes a section from the ini file. /// /// /// Name of the section to delete. /// /// /// is a null reference (Nothing in VB) /// public void DeleteSection(string sectionName) { if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); ArrayList list = ArrayList.Adapter(GetSectionNames()); if (list.Contains(sectionName)) { WriteValueInternal(sectionName, null, null); } } #endregion } }