将WinMain中的cmdLine拆分为旧式main()函数的参数

23
我想将WinMaincmdLine参数转换为argcargv,以便我可以使用我编写的针对控制台应用程序的参数解析函数。这本来很简单,但我也想支持“引号”。例如: test.exe test1 test2 "testing testing" 应该是:
argv[0] = "test.exe"; argv[1] = "test1"; argv[2] = "test2"; argv[3] = "testing testing";

我知道cmdLine没有程序名(argv[0]),这不重要,我可以使用一个虚拟值。

我想用正则表达式来处理它,(("[^"]+")\s+)|(([^\s]+)\s*),但我不确定它能否很好地工作.. 可能效果不太好?在windows api中有什么函数可以做到这一点吗?谢谢

4个回答

33

如果您正在使用微软编译器,则在 stdlib.h 中定义了公共符号 __argc__argv__wargv。这也适用于使用微软运行时库的 MinGW。


5
当这些可用时,我个人更喜欢它们而不是 CommandLineToArgvW,因为你不必担心调用 LocalFree 并且由于 __argv[__argc]__wargv[__argc] 被设置为 NULL - jamesdlin
太棒了!但是envp怎么办?编辑:好的,_CRTIMP extern char** environ;就可以解决了,我相信。 - csl

8

根据Denis K的回答

请参见:https://msdn.microsoft.com/library/dn727674.aspx

这将为您的应用程序添加Windows特定的入口点,以补充其经典启动点:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, char*, int nShowCmd)
{
    return main(__argc, __argv);
}

6

2
请注意,CommandLineToArgvW 不会在数组末尾添加哨兵 NULL 值,因此它的语义与标准 C 中的 argv 不完全相同。 - jamesdlin
2
此外,CommandLineToArgvW 不会扩展通配符。如果 __argc / __argv 不可用,则应改用 __getmainargs__wgetmainargs - Krzysztof Kosiński
@AndrewMedico 自从 C89 以来,语言标准规定 "argv[argc] 应该是一个空指针"。虽然这是冗余信息,但它是标准行为,因此有些人依赖它。 - jamesdlin
3
我记得CommandLineToArgvW处理字符串的方式与__wgetmainargs不完全相同(由于转义或空格,我忘记了哪一个),所以应该使用后者,因为其行为与传递给main的正常argc/argv相同。 - user541686
哎呀,应该先谷歌一下。 - nobody

-2
如果你想使用普通的int argc,char ** argv参数,那么你就需要自己处理。
void fetchCmdArgs(int* argc, char*** argv) {
    // init results
    *argc = 0;

    // prepare extraction
    char* winCmd = GetCommandLine();
    int index = 0;
    bool newOption = true;
    // use static so converted command line can be
    // accessed from outside this function
    static vector<char*> argVector;

    // walk over the command line and convert it to argv
    while(winCmd[index] != 0){
        if (winCmd[index] == ' ') {
            // terminate option string
            winCmd[index] = 0;
            newOption = true;

        } else  {
            if(newOption){
                argVector.push_back(&winCmd[index]);
                (*argc)++;  
            }
            newOption = false;
        }
        index++;
    }

    // elements inside the vector are guaranteed to be continous
    *argv = &argVector[0];
}


// usage
int APIENTRY WinMain(...) {
    int argc = 0;
    char** argv;
    fetchCmdArgs(&argc, &argv);
}

1
-1 这比你在这里展示的要复杂得多。首先,你没有处理引号。 - user541686
同样被踩了...这真的不是人们应该自己编写的东西,特别是当__argc__argv存在时。 - s3cur3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接