今天是第二次发文章了,难得啊,没办法,眼睛痛的要死,但是还是秉着“辛苦我一个,服务千万家”的精神,我还是继续写我的文章吧。讲座ing...
//--------------------------------------------------------------------//
上一次我写到了使用标准的c++来实现显示程序的当前路径,但是如果是windows应用程序呢?这个完全不必担心,因为windows程序有很多很多的函数给我们利用呢。
首先我们使用的是GetCommandLine()函数。选择这个函数是因为这个函数很简单,不用带参数。这个函数的声明是:
#define GetCommandLine GetCommandLineA
WINBASEAPI __out LPSTR WINAPI GetCommandLineA( VOID );
这里编辑一个小程序,我们可以看到,只需要调用这个函数,我们就可以看到当前程序所在的路径了。
- #include<windows.h>
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show)
- {
- MessageBox( NULL, GetCommandLine(), "程序消息", MB_OK);
- return 0;
- }
- 示例1
运行的结果如图:
但是这里还有一个问题。调用这个函数有一些问题,就是除了包含当前程序的名字以外,这个函数还有一对双引号,这该怎么办呢?在第一讲中我们已经写出可以进行截取路径来对名字除去,那么双引号怎么除去呢?很简单。我们知道,后面的双引号在截取的时候已经不在了,我们只需要对前面的双引号进行处理就行了。如果只是对路径进行显示的话,可以这样写。
- #include<windows.h>
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show)
- {
- char *p1,*p2;
- int i;
- p1 = p2 = (char*)GetCommandLine()+1;//从去掉双引号处开始
- for ( ; *p2 != 0; p2++ )
- if ( *p2 == '//' )
- i = p2 - p1;//标记最后一个“/”号
- p1[i] = 0;//将原来是“/”的地方置0
- MessageBox( NULL, p1, "程序消息", MB_OK);
- return 0;
- }
- 示例2
运行结果如图:
怎么样,容易吧。其实这种方法的效率是最高的,甚至不用什么strlen()、strcpy()、strcat()就可以解决。
接下来我要介绍另外一个函数GetCurrentDirectory(),这个函数有两个参数,它的原型为:
#define GetCurrentDirectory GetCurrentDirectoryW
WINBASEAPI DWORD WINAPI GetCurrentDirectoryW( __in DWORD nBufferLength, __out_ecount_part_opt(nBufferLength, return + 1) LPWSTR lpBuffer );
这个函数有两个参数,第一个参数是缓冲区的长度,第二个参数是装在当前路径的字符串。这样的函数需要用一个字符串来存储,所以比起上一个稍有麻烦。但是它不带双引号,也算是简单的。请看下面这个程序:
- #include<windows.h>
- #define MAX_BUFFER_SIZE 255
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show)
- {
- char str[MAX_BUFFER_SIZE];
- GetCurrentDirectory(MAX_BUFFER_SIZE, str);
- MessageBox( NULL, str,"程序消息", MB_OK);
- return 0;
- }
- 示例3
它的运行结果如图
要除去程序的名字,可以对已经赋值的str进行截取处理,修改后的程序如下:
- #include<windows.h>
- #define MAX_BUFFER_SIZE 255
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show)
- {
- char str[MAX_BUFFER_SIZE];
- char* p = str;
- int i;
- GetCurrentDirectory(MAX_BUFFER_SIZE, str);
- for ( ; *p != 0; p++ )
- if ( *p == '//' )
- i = p - str;
- str[i] = 0;
- MessageBox( NULL, str,"程序消息", MB_OK);
- return 0;
- }
- 示例4
它的运行结果如下图
怎样,也很简单吧。但是此方法需要注意,必须将MAX_BUFFER_SIZE定义得足够大,如果MAX_BUFFER_SIZE过小,那么就会出现路径显示不完整和其它意想不到的问题。
然后我们就要介绍的函数是GetModuleFileName(),这个函数带有三个参数,它的原型如下:
#define GetModuleFileName GetModuleFileNameW
WINBASEAPI DWORD WINAPI GetModuleFileNameW( __in_opt HMODULE hModule, __out_ecount_part(nSize, return + 1) LPWCH lpFilename, __in DWORD nSize );
第一个参数表示的是装载一个程序实例的句柄。如果该参数为NULL,该函数返回该当前应用程序全路径。第二个参数表示的是存放返回的名字的内存块的指针,是一个输出参数,第三个参数是缓冲区的最大值,和GetCurrentDirectory()函数一样,如果缓冲区过小,也会出现显示不完整和其它的问题。
下面请看这个程序:
- #include<windows.h>
- #define MAX_BUFFER_SIZE 255
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show)
- {
- char str[MAX_BUFFER_SIZE];
- GetModuleFileName( NULL, str, MAX_BUFFER_SIZE );
- MessageBox( NULL, str, "程序消息", MB_OK );
- return 0;
- }
- 示例5
程序的结果如图
同样的,使用截取也可以将当前路径显示出来,请看下面的程序:
- #include<windows.h>
- #define MAX_BUFFER_SIZE 255
- int WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevhInst, LPSTR cmd, int show)
- {
- char str[MAX_BUFFER_SIZE];
- GetModuleFileName( NULL, str, MAX_BUFFER_SIZE);
- char* p = str;
- int i;
- GetCurrentDirectory(MAX_BUFFER_SIZE, str);
- for ( ; *p != 0; p++ )
- if ( *p == '//' )
- i = p - str;
- str[i] = 0;
- MessageBox( NULL, str,"程序消息", MB_OK);
- return 0;
- }
- 示例6
程序的结果如图
这里我还想说一点,如果将上述程序第五行的GetModuleFileName( NULL, str, MAX_BUFFER_SIZE);改为GetModuleFileName( hInst, str, MAX_BUFFER_SIZE);这样也会得出同样的结果,那是否意味着两者等同呢?不。如果在WinMain()函数中进行多线程的操作,那么每一个线程都会有一个实例句柄,这样的话如果使用GetModuleFileName()函数,它就会得到实例句柄的路径。这样对于获知线程的来源和删除某些木马程序是有帮助的。
温馨提醒:如果出现诸如“error C2664: “MessageBoxW”: 不能将参数 2 从“char [255]”转换为“LPCWSTR””之类的错误(通常是vs系列),请点击菜单->项目-><项目名称> 属性(P),再在弹出的对话框中左边的树状图中选择配置属性->常规,然后在右边的字符集中选择“使用多字节字符集”,这样做就是使类型转换能够顺利地进行,于是就不会报错了。
//---------------------/
好了,获取当前路径到这里就要告一段落了,欢迎大家评论,我们共同切磋windows编程的知识!(第二讲完)