在标准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. C语言 · 积分之迷

    标题:积分之迷 小明开了个网上商店,卖风铃.共有3个品牌:A,B,C. 为了促销,每件商品都会返固定的积分. 小明开业第一天收到了三笔订单: 第一笔:3个A + 7个B + 1个C,共返积分:315 ...

  2. Netty:option和childOption参数设置说明

    Channel配置参数 (1).通用参数 CONNECT_TIMEOUT_MILLIS :   Netty参数,连接超时毫秒数,默认值30000毫秒即30秒. MAX_MESSAGES_PER_REA ...

  3. 我的海外购页面List

    <%@ page language="java" contentType="text/html;charset=UTF-8" %> <%@ t ...

  4. JS 详解对象的继承

    在学习这篇博文前,请先移步我的另外一篇博文:JS 一张图理解prototype.proto和constructor的关系,先弄清楚“原型链”,这样对于理解继承会非常有效. 注意:博文中提到的“属性”, ...

  5. Oracle 行列转置

    两种简单的行列转置 1.固定列数的行列转换如student   subject    grade--------- ---------- --------student1  语文       80st ...

  6. git 创建新分支并推送到远程分支

      git branch test git checkout test git push origin test:test git branch --set-upstream-to origin/te ...

  7. 11.13git和redis

    2018-11-13 15:46:40 git完结 redis完结, 还剩一点路飞项目!!!做完回学校!!!! 越努力,越幸运!永远不要高估自己! 关于 redis具体使用可以参考: http://w ...

  8. template.js artTemplate 简洁语法官网下载不了 template.js artTemplate 新下载地址

    参考:https://blog.csdn.net/tavatimsa/article/details/82019792

  9. Codeforces Round 504

    (交互题真神奇,,,我自己瞎写了一发目测样例都没过去就AC了...) (只出了两题的竟然没掉下蓝名真是可怕) A:我的代码太不美观了,放个同学的(因为我是c++63分的蒟蒻所以根本不知道那些函数怎么用 ...

  10. ConfuserEx壳

    前言: 这几天用Rolan的时候出现了点问题,然后发现了这个非常好用的工具居然只有几百k,打算逆向一下,然后发现了ConfuserEx壳 探索: Rolan是用C#写的,刚开始用EXEinfoPE打开 ...