在标准C或者Win32控制台程序的main函数中,它们都有两个参数:"argc" 和 "argv",如下所示:

int main(int argc, char * argv[]) ...

这些参数帮助我们为程序传入命令行参数。"argc"为命令行参数的个数,"argv"则为传入参数的数组列表。但是当我们在Visual Studio中创建Win32 GUI程序的时候,WinMain变成程序的入口函数,而该函数并没有"argc" 和"argv"参数,那我们怎样给Windows程序传入命令行参数呢?Windows程序中又怎样取得这些传入的参数呢?

lpCmdLine 参数

第一个方案就来自WinMain函数自身。让我们看一个典型的WinMain函数声明:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)..

如声明所示,WinMain函数有一个类型为"LPSTR(char*)"的参数"lpCmdLine". 这个变量存放着命令行中除程序自身名字外的剩下所有部分。例如,我们有一个名字为"test.exe"的应用程序,当用下面的命令行运行该程序时

test.exe Some arguments here

变量lpCmdLine的值即为"Some arguments here"。尽管该方法不像"argc"和"argv"一样非常方便,但它是获取命令行参数的方法之一。我们需要自己写程序去分析lpCmdLine字符串,这增加了程序的复杂度。

【译注:Windows程序代码同时ANSI版本和UNICODE版本接口。其中WinMain函数为ANSI版本,wWinMain为UNICODE版本。从Visual Studio创建出来的代码主函数命名为_tWinMain。这个函数名会根据当前工程有没有定义_UNICODE宏而在编译时翻译成上面两个不同版本。当翻译成WinMain函数时候,lpCmdLine的类型为LPSTR,而当翻译成wWinMain函数时候,lpCmdLine的类型为LPWSTR,即宽字符数组】

GetCommandLine()函数

另外一个方法就是使用GetCommandLine() API。这个函数返回整个命令行,它把程序自身名称(包括程序的绝对路径)和所有参数放在一个字符串中。该函数非常类似于对lpCmdLine的直接访问。但它的一个好处是能够根据你当前工程的设置自动映射到GetCommandLineA()或者GetCommandLineW()函数。因此解决了访问Unicode命令行输入的问题。但是它还是既没有提供命令行参数数目,也没有类似argv那样把参数自动分割成独立变量的能力。

CommandLineToArgvW()函数

最后一个我要讨论的方法是CommandLineToArgvW函数。这个函数只有Unicode宽字符版本,没有对应的CommandLineToArgvA函数。它的声明如下:


LPWSTR *CommandLineToArgvW(LPCWSTR lpCmdLine, int *pNumArgs)

该函数和'argc'/'argv'一样简单,但是它并不是在Windows程序中直接访问argc和argv变量。如声明所示,函数接受两个参数,一个是需要解析的Unicode命名行字符串,另外一个是指向整型变量的指针。函数在返回时把参数数目存到这个整型变量中。

函数返回一个类似于'argv'的字符串数组。让我们看一个例子:

 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPSTR lpCmdLine, int nShowCmd)
{
LPWSTR *szArgList;
int argCount;
szArgList = CommandLineToArgvW(GetCommandLine(), &argCount); if (szArgList == NULL)
{
MessageBox(NULL, L"Unable to parse command line", L"Error", MB_OK);
return ;
} for(int i = ; i < argCount; i++)
{
MessageBox(NULL, szArgList[i], L"Arglist contents", MB_OK);
} LocalFree(szArgList); return ; }

如上所示,通过这个函数,我们可以取得命令行参数的数目(argc)和一个字符串列表(argv)。这里唯一要注意的事情是该函数会给返回参数列表分配一块内存。当我们用完列表后需要手动地释放该内存,否则就会有内存泄露

EDIT: Variables __argc and __argv

另外,微软提供了全局变量__argc 和__argv。这两个变量由Windows在运行时自动赋值。其中__argv有ASCII和Unicode版本,分别为__argv和__wargv。要使用这两个全局变量,需要引用"stdlib.h"头文件(该头文件已经在windows.h中引用)。为了根据工程设置来自动选择ASCII还是Unicode版本变量,我们可以引用"TCHAR.h"头文件并访问__targv变量。代码如下

extern int __argc;

extern TCHAR* __targv;

这个方法是所有方法中最简单的一个。但它的代价是程序需要链接VC++运行时库(例如"msvcrt.dll")。当然99%的Windows程序几乎都要使用这个运行库:)

Del.icio.us : 命令行参数 WinMain

从Win32程序中的主函数中获取命令行参数的更多相关文章

  1. Python中random模块在主函数中设置随机种子是否对于调用的函数中的随机值产生影响?

    一个问题,加入我有一个工程文件,在main函数里面调用random模块,设置随机种子,主函数中的随机种子的设置是否会影响主函数所调用的函数中的随机值? 实际上这个问题非常重要,比如你在跑网络的时候,初 ...

  2. django变量使用-在模板中使用视图函数中的变量

    DTL语言,即django template language 第一次使用时,需要修改项目的setting.py文件,将其中TEMPLATES中的DIRS修改为os.path.join(BASE_DI ...

  3. MFC中获取命令行参数的几种方法

    在MFC程序中,可以用以下几种方法来获取命令行参数. 为方便说明,我们假设执行了命令:C:\test\app.exe -1 -2 方法一 ::GetCommandLine(); 将获取到 " ...

  4. C程序获取命令行参数

    命令行参数 命令行界面中,可执行文件可以在键入命令的同一行中获取参数用于具体的执行命令.无论是Python.Java还是C等等,这些语言都能够获取命令行参数(Command-line argument ...

  5. 重新认识Java中的程序入口即主函数各组成部分

    主函数各组成部分深入理解 public static void main(String[] agrs) 主函数:是一个特殊的函数,作为程序的入口,可以被JVM调用 主函数的定义: public:代表着 ...

  6. java的主函数中各个词的作用

    主函数 public static void main(String[] args){} public: main主方法是由jvm(虚拟机)来调用,jvm实际也是一程序,为了保证jvm能在任何情况下调 ...

  7. 我的第一个Python程序,定义主函数,eval、format函数详解,

    程序实例: #第一个py小程序 def main(): f = eval(input("输入一个数值:")) p=f*(5/9) print("现在的值为:{0:3.3f ...

  8. 《On Lisp》第四章第三节图4.6中的rmapcar函数中展现的apply陷阱

    (defun rmapcar (fn &rest args) (if (some #'atom args) (apply fn args) (apply #'mapcar #'(lambda ...

  9. MSSQL AlwaysOn中的“主角色中的连接”和“可读辅助副本”初探

    一.开篇 在进行配置只读路由的时候,需要进行配置可用性组中的可用性副本,如下如所示: 每一项都是啥意思可以看看这个链接 https://msdn.microsoft.com/zh-cn/library ...

随机推荐

  1. ant 通配符

    ant 通配符 我们常用的匹配模式有ANT模式,比如acegi可以用PATTERN_TYPE_APACHE_ANT来使用ANT匹配模式,那什么是ANT匹配模式呢.   ANT通配符有三种:     通 ...

  2. MongoDB GridFS 存储文件

    使用MongoDB的GridFS方式. CSDN: https://blog.csdn.net/qq_32657967/article/details/81534259官方文档: https://do ...

  3. centos7配置固定ip

    查看本机gateway netstat -rn (以0.0.0.0开始的行的gateway是默认网关) vi /etc/sysconfig/network-scripts/ifcfg-enp0s3 T ...

  4. nohup.out文件过大解决方法 定时任务清空

    0.1和2分别表示标准输入.标准输出和标准错误信息输出,可以用来指定需要重定向的标准输入或输出. 在一般使用时,默认的是标准输出,既1.当我们需要特殊用途时,可以使用其他标号.例如,将某个程序的错误信 ...

  5. Netty 学习笔记(1)通信原理

    前言 本文主要从 select 和 epoll 系统调用入手,来打开 Netty 的大门,从认识 Netty 的基础原理 —— I/O 多路复用模型开始.   Netty 的通信原理 Netty 底层 ...

  6. myeclipse及Eclipse中.classpath、.project、.settings、.mymetadata(myeclipse特有)介绍

    引言 今天在创建java项目的时候遇到了很多的错误,在解决的过程中遇到了一些根本不知道什么作用的文件,然后按照网上的一些做法可以将问题解决,但是这也说明我们在学习的时候很多基础和细节的地方是我们薄弱的 ...

  7. java web (sevlet)请求之get,post,forward,redirect

    [参考]web请求之get,post,forward,redirect 1,form表单:可以采用post或者get请求,客户端主动跳转,url地址会改变为提交后的地址 2,forward:forwa ...

  8. GoLang之反射

    反射 反射(reflect) 所谓反射(reflect)就是能检查程序在运行时的状态. 使用反射的三条定律: 反射可以将“接口类型变量”转换为“反射类型对象”: 反射可以将“反射类型对象”转换为“接口 ...

  9. x264_param_default分析

    {     /* 开辟内存空间*/     memset( param, 0, sizeof( x264_param_t ) );              /* CPU自动检测 */     par ...

  10. 可视化展示attention(seq2seq with attention in tensorflow)

    目前实现了基于tensorflow的支持的带attention的seq2seq.基于tf 1.0官网contrib路径下seq2seq 由于后续版本不再支持attention,迁移到melt并做了进一 ...