MFC中的ini文件

 

INI配置文件的格式  

 

为什么要用INI文件?如果我们程序没有任何配置文件时,这样的程序对外是全封闭的,一旦程序需要修改一些参数必须要修改程序代码本身并重新编译,这样很不好,所以要用配置文件,让程序出厂后还能根据需要进行必要的配置;配置文件有很多如INI配置文件,XML配置文件,还有就是可以使用系统注册表等。

          本文主要是为读者在实现读写INI配置文件模块之前,提供有关INI文件的格式信息。

在早期的windows桌面系统中主要是用INI文件作为系统的配置文件,从win95以后开始转向使用注册表,但是还有很多系统配置是使用INI文件的。其实INI文件就是简单的text文件,只不过这种txt文件要遵循一定的INI文件格式。现在的WINCE系统上也常常用INI文件作为配置文件,这次研究INI文件的目的就是为了我的GPS定位系统客户端写个系统配置文件。“.INI ”就是英文 “initialization”的头三个字母的缩写;当然INI file的后缀名也不一定是".ini"也可以是".cfg",".conf ”或者是".txt"。

 

经典格式:

INI文件的格式很简单,最基本的三个要素是:parameters,sections和comments。

什么是parameters?

INI所包含的最基本的“元素”就是parameter;每一个parameter都有一个name和一个value,name和value是由等号“=”隔开。name在等号的左边。

如:

      name = value

什么是sections ?

所有的parameters都是以sections为单位结合在一起的。所有的section名称都是独占一行,并且sections名字都被方括号包围着([ and ])。在section声明后的所有parameters都是属于该section。对于一个section没有明显的结束标志符,一个section的开始就是上一个section的结束,或者是end of the file。Sections一般情况下不能被nested,当然特殊情况下也可以实现sections的嵌套。

section如下所示:

         [section]

 

什么是comments ?

在INI文件中注释语句是以分号“;”开始的。所有的所有的注释语句不管多长都是独占一行直到结束的。在分号和行结束符之间的所有内容都是被忽略的。

注释实例如下:

;comments text

 

当然,上面讲的都是最经典的INI文件格式,随着使用的需求INI文件的格式也出现了很多变种;

INI实例:

; last modified 1 April 2001 by John Doe  [owner]  name=John Doe  organization=Acme Products     [database]  server=192.0.2.42     ; use IP address in case network name resolution is not working  port=143  file = "acme payroll.dat"  

 

 

 

 

 

INI 文件读写

 

INI文件是Windows系统中一类比较重要的文件,通常用来存放系统或者应用程序的配置信息,以方便系统或者应用 程序在初始化时再次读入。比如Windows系统中的配置文件win.ini和system.ini,它们就主要存放系统启动或用户登陆时的系统信息。这 项功能在方便了系统配置的同时,也为非法程序的自动运行提供了可乘之机。显然,这类文件的重要性应该引起我们的重视。但是对于这样的ini文件的读写操作 却与普通文本文件有着种种的不同,尤其体现在编程实现上。笔者曾经尝试用手动更改的方法在文件中加入一些项,使得自己的程序能够在初始化时自动运行,但是 却没有成功,最后还是藉由编程的方法来实现了。这里主要涉及到一些API函数,而这些函数又往往不被人们所熟知,本文的任务就是在介绍这些函数的同时,用 简单的程序作了示例,下面我们言归正传。
先来看几个往配置文件中写入信息的函数:
(1)WritePrivateProfileSection()用来在ini文件中直接向指定区域写入键和值的信息,其原型如下:
BOOL WritePrivateProfileSection(
             LPCTSTR lpAppName, // 指向指定字段的字符串
             LPCTSTR lpString, // 指向要写入的键与值字符串
            LPCTSTR lpFileName // 指向文件名称字符串,如果不包含完整路径,则在windows目录下创建
);
用法示例:
WritePrivateProfileSection(_T(“windows”),_T(“load=c:\\winnt\\notepad.exe”),_T(“c:\\winnt\\win.ini”));
(2)WritePrivateProfileString()与上一个函数的不同点在于其将键和值分开了,原型如下:
BOOL WritePrivateProfileString(
            LPCTSTR lpAppName, // 指向指定字段的字符串
            LPCTSTR lpKeyName, // 指向指定键的字符串
            LPCTSTR lpString, // 指向指定值的字符串
            LPCTSTR lpFileName // 指向文件名称字符串
);
用法示例:
WritePrivateProfileString(_T(“windows”),_T(load”)_T(“c:\\winnt\\notepad.exe”),_T(“c:\\winnt\\win.ini”));
(3)WritePrivateProfileStruct()与前面两个的不同在于文件尾有校验和,原型如下:
BOOL WritePrivateProfileStruct(
            LPCTSTR lpszSection, //指向指定字段的字符串
            LPCTSTR lpszKey, //指向指定键的字符串
            LPVOID lpStruct, //指向存放要加入的数据的缓冲区,如果为NULL,则删除键
            UINT uSizeStruct, //缓冲区大小,以字节为单位
            LPCTSTR szFile //以零结尾的文件名称字符串,如果为空,则向win.ini写入
);
用法示例:
WritePrivateProfileStruct(_T(“windows”),_T(“load”),pBuffer,sizeof(pBuffer),_T(“c:\\winnt\\win.ini”));

(4) 还有两个函数,是专门用来向win.ini文件写入的,函数原型如下:
BOOL WriteProfileSection(
            LPCTSTR lpAppName, //指向指定字段的字符串
            LPCTSTR lpString //指向指定值的字符串
);
BOOL WriteProfileString(
            LPCTSTR lpAppName, //指向指定字段的字符串
            LPCTSTR lpKeyName, //指向指定键的字符串
            LPCTSTR lpString //指向指定值的字符串
);
下面来看几个对应的从ini文件获取信息的API函数,上面已经说得很详细了,这里只说其中两个:
DWORD GetPrivateProfileString(
            LPCTSTR lpAppName, //指向指定字段的字符串
            LPCTSTR lpKeyName, //指向键的字符串
            LPCTSTR lpDefault, //如果INI文件中没有前两个参数指定的字段名或键名,则将此值赋给变量
            LPTSTR lpReturnedString, //存放INI文件中值的目的缓存区
            DWORD nSize, //目的缓冲区的大小,以字节为单位
            LPCTSTR lpFileName //指向INI文件名称的字符串
);

UINT GetPrivateProfileInt(
            LPCTSTR lpAppName, //指向指定字段的字符串
            LPCTSTR lpKeyName, //指向键的字符串
            INT nDefault, //如果INI文件中没有前两个参数指定的字段名或键名,则将此值赋给变量
            LPCTSTR lpFileName //指向INI文件名称的字符串
);

 


程序示例1: 我们在这里建立了一个应用程序“App Name”,并且使用了一个INI文件“appname.ini”,在此INI文件中,我们写入如下内容:
[Section1]
FirstKey = It all worked out okay.
SecondKey = By golly, it works.
ThirdKey = Another test.
代码分析如下:

 


#include <stdio.h>
#include <windows.h>
//主函数
main()

            //定义局部
            CHAR inBuf[80]; 
            HKEY hKey1, hKey2; 
            DWORD dwDisposition; 
            LONG lRetCode; 
            // 试图创建INI文件的键值
            lRetCode = RegCreateKeyEx ( HKEY_LOCAL_MACHINE, 
            "SOFTWARE\\Microsoft\\Windows NT 
            \\CurrentVersion\\IniFileMapping\\appname.ini", 
            0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, 
            NULL, &hKey1, 
            &dwDisposition); 
            //判断是否出错
            if (lRetCode != ERROR_SUCCESS)

            { 
                        printf ("Error in creating appname.ini key\n"); 
                        return (0) ; 
            }


            //试图设置一个节区的值
            lRetCode = RegSetValueEx ( hKey1, 
            "Section1", 
            0, 
            REG_SZ, 
            "USR:App Name\\Section1", 
            20); 
            //判断是否出错
            if (lRetCode != ERROR_SUCCESS)

             { 
                        printf ( "Error in setting Section1 value\n"); 
                        return (0) ; 
            }


            / /试图创建一个应用名称键值
            lRetCode = RegCreateKeyEx ( HKEY_CURRENT_USER, 
            "App Name", 
            0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, 
            NULL, &hKey2, 
            &dwDisposition); 

            //判断是否出错
            if (lRetCode != ERROR_SUCCESS)

            { 
                        printf ("Error in creating App Name key\n"); 
                        return (0) ; 
            }
            //强制系统重新读取映射区的内容到共享内存中,以便于将来对应用程序的调用可//以找到它,而不需要重新启动系统 


            WritePrivateProfileStringW( NULL, NULL, NULL, L"appname.ini" ); 
            //向INI文件中添加一些键值 
            WritePrivateProfileString ("Section1", "FirstKey", 
            "It all worked out okay.", "appname.ini"); 
            WritePrivateProfileString ("Section1", "SecondKey", 
            "By golly, it works.", "appname.ini");


            WritePrivateProfileSection ("Section1", "ThirdKey = Another Test.", 
            "appname.ini"); 
            //测试一下添加的正确性
            GetPrivateProfileString ("Section1", "FirstKey", 
            "Bogus Value: Get didn't work", inBuf, 80, 
            "appname.ini"); 
            printf ("%s", inBuf); 
            return(0);
}

程序示例2:通过修改win.ini中的字段[windows]中的键load或run,或者是为system.ini中的字段[boot]中的键 shell增加值,可以达到设置程序自动运行的目的。假设我们要自动运行notepad.exe,修改后的win.ini或system.ini文件象这 样就可以:
win.ini
[windows]
load=c:\winnt\notepad.exe
run=c:\winnt\notepad.exe

system.ini
[boot]
shell=c:\winnt\explorer.exe c:\winnt\notepad.exe
注意:system.ini文件的修改要特别注意,如果你单纯改成shell=c:\winnt\notepad.exe,则不能首先运行 explorer.exe,很明显你将看不到桌面和任务栏,呵呵,笔者在做实验时就曾因为粗心造成了这样的后果,不过不用害怕,只要你用我们下面提供的程 序,将它修改过来就可以了,默认时,系统在system.ini中的[boot]下是shell=c:\winnt\explorer.exe。很多非法 程序就是通过修改这两个文件来达到自启动的目的的。
下面这个程序可以在附书光盘中找到,名称为“AutoPlay”,使用VC++6.0写成,核心程序源代码如下:
void CAutoRunDlg::OnBrowse()
{
            //只浏览exe文件
            CfileDialog fileDlg(TRUE,_T("EXE"),_T("*.exe"),OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,(_T("Executable Files (*.exe) |*.exe ||")));//显示打开文件的对话框

            //当操作者选择OK时,程序取得选择文件的全路径名(包括文件的路径及文件名称),并将相应的数值传输给相关的控件变量。
            if(fileDlg.DoModal()==IDOK)
            { 
                        m_strFileName=fileDlg.GetPathName();

                        //向将变量中的数值传输给控件显示出来。 
                        UpdateData(FALSE);
            } 
}
void CAutoRunDlg::OnApply()
{
            //更新数据
            UpdateData(TRUE); 
            //写入ini文件
            LPCTSTR filename; 
            filename=m_strFileName; 
            WritePrivateProfileString(_T("windows"),_T("load"),filename,_T("c:\\winnt\\win.ini"));
}

您如果要更改system.ini,可以将WritePrivateProfileString(_T("windows"),_T("load"),filename,_T("c:\\winnt\\win.ini"));
改为 WritePrivateProfileString(_T("boot"),_T("shell"),filename,_T("c:\\winnt \\system.ini"));并且在输入文件名时输入c:\winnt\explorer.exe c:\winnt\notepad.exe。
写到这里,本文的意图基本达到,如果您可以把某些代码亲自实现,相信读者会有比较大的收获。

 

 

转自

 

 

 

 

学过的东西收藏起来,方便以后查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值