PathGetArgs/PathRemoveArgs与CommandLineToArgvW有区别吗
PathGetArgs/PathRemoveArgs vs. CommandLineToArgvW - is there a difference?
我正在进行一些路径解析C++代码,并为此尝试了许多Windows API。PathGetArgs
/PathRemoveArgs
和轻微按摩的CommandLineToArgvW
之间有区别吗?
换句话说,除了长度/清洁度之外,这是吗
std::wstring StripFileArguments(std::wstring filePath)
{
WCHAR tempPath[MAX_PATH];
wcscpy(tempPath, filePath.c_str());
PathRemoveArgs(tempPath);
return tempPath;
}
与此不同:
std::wstring StripFileArguments(std::wstring filePath)
{
LPWSTR* argList;
int argCount;
std::wstring tempPath;
argList = CommandLineToArgvW(filePath.c_str(), &argCount);
if (argCount > 0)
{
tempPath = argList[0]; //ignore any elements after the first because those are args, not the base app
LocalFree(argList);
return tempPath;
}
return filePath;
}
这是吗
std::wstring GetFileArguments(std::wstring filePath)
{
WCHAR tempArgs[MAX_PATH];
wcscpy(tempArgs, filePath.c_str());
wcscpy(tempArgs, PathGetArgs(tempArgs));
return tempArgs;
}
与不同
std::wstring GetFileArguments(std::wstring filePath)
{
LPWSTR* argList;
int argCount;
std::wstring tempArgs;
argList = CommandLineToArgvW(filePath.c_str(), &argCount);
for (int counter = 1; counter < argCount; counter++) //ignore the first element (counter = 0) because that's the base app, not args
{
tempArgs = tempArgs + TEXT(" ") + argList[counter];
}
LocalFree(argList);
return tempArgs;
}
在我看来,PathGetArgs
/PathRemoveArgs
只是为CommandLineToArgvW
解析提供了一个更干净、更简单的特殊情况实现,但我想知道是否有API表现不同的情况。
函数相似但并不完全相同,主要与如何处理带引号的字符串有关。
CCD_ 7返回指向输入字符串中第一个空格后面的第一个字符的指针。如果在第一个空格之前遇到引号字符,则在函数再次开始查找空格之前,需要另一个引号。如果找不到空格,函数将返回一个指向字符串末尾的指针。
PathRemoveArgs
调用PathGetArgs
,然后使用返回的指针终止字符串。如果遇到的第一个空间恰好在行的末尾,它也会剥离尾部空间。
CommandLineToArgvW
获取所提供的字符串并将其拆分为一个数组。它使用空格来描绘数组中的每个项。数组中的第一个项可以加引号以留出空格。第二项和后续项也可以被引用,但它们支持稍微复杂一点的处理——参数也可以通过在它们前面加一个反斜杠来包括嵌入的引号。例如:
"c:program filesmy appmy app.exe" arg1 "argument 2" "arg "number" 3"
这将生成一个包含四个条目的数组:
argv[0]
-c:\program files\my app\my app.exeargv[1]
-arg1argv[2]
-参数2argv[3]
-arg"number"3
有关解析规则的完整描述,包括如何在参数中嵌入反斜杠和引号,请参阅CommandLineToArgVW
文档。
是的,我观察到当前SDK的不同行为(VS2015 Update 3+Windows 1607 Anniversary SDK,SDK版本设置为8.1):
-
使用空的lpCmdLine调用CommandLineToArgvW(当没有传递参数时,您从wWinMain获得的内容)会返回程序路径和文件名,这些路径和文件名将在每个空格上进行拆分。但这并没有在参数中指定,它自己一定做到了,但没有考虑忽略路径本身的间距:
lpCmdLine = "" argv[0] = C:Program argv[1] = FilesVendorMyProgram.exe
-
使用包含参数的lpCmdLine调用CommandLineToArgvW,不包括程序路径和名称,因此工作正常(只要参数中没有其他空格…):
lpCmdLine = "One=1 Two="2"" argv[0] = One=1 argv[1] = Two=2
请注意,在传递时,它还会去掉参数中的任何其他引号。
-
CommandLineToArgvW不喜欢
Text="Quoted spaces"
格式的第一个参数,因此如果您尝试直接将lpCmdLine传递给它,它会错误地拆分键=值对(如果它们有空格):lpCmdLine = "One="Number One" Two="Number Two"" argv[0] = One="Number argv[1] = One" argv[2] = Two="Number argv[3] = Two"
这里有点记录:
https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391(v=vs.85).aspx
但这种在程序路径中有空格的行为是意料之中的。这对我来说似乎是个错误。我更希望在两种情况下都处理相同的数据。因为如果我真的想要可执行文件的路径,我会调用GetCommandLineW()。
在我看来,唯一明智的一致解决方案是完全忽略lpCmdLine并调用GetCommandLineW(),将结果传递给CommandLineToArgvW()然后如果您对程序路径不感兴趣,则跳过第一个参数。这样,就支持所有组合,即带空格和不带空格的路径,带嵌套引号和不含空格的参数。
int argumentCount;
LPWSTR commandLine = GetCommandLineW();
LPWSTR *arguments = CommandLineToArgvW(commandLine, &argumentCount);
- 在 typedef 内部使用 const 关键字和在 typedef 外部使用 const 关键字之间有区别吗?
- 为什么这里的大括号和括号初始化有区别?
- 使用短运算符的字符串连接有区别吗?
- static_cast<unsigned>(签名)与标准::bit_cast<unsigned>(签名)之间有区别吗?
- 在调用函数时,ptr** 和 ptr*& 之间是否有区别,或者首选C++?
- 在类内和类外的定义处执行类转发声明是否有区别
- CRTP:为什么获得嵌套类型和派生类的嵌套方法有区别
- 使用 std::move 将参数传递给函数,如果该参数声明为按值传递或使用移动操作数 &&,是否有区别?
- c++ 类中的静态常量变量和常量变量在存储方面是否有区别
- 为什么 .cpp 文件和 .h 文件之间有区别?
- C++:调用运算符和调用其实现之间有区别吗
- 将全局声明为类声明语句的一部分与使用单独的语句声明全局之间是否有区别
- 用户定义的类和标准类之间有区别吗?
- 这两个数组之间有区别吗?
- 这些在C 中初始化C数组的方式之间有区别吗?
- vector.size()= 0和vector.empty()之间是否有区别
- 显式运算符 = 调用和 = 运算符之间是否有区别
- 这两种初始化成员变量的方法之间有区别吗?
- 忽略内存消耗,使用“int”或“char”是否有区别
- 在DirectX中,深度值中存储了哪些值?这在DX9和DX11之间有区别吗