【问题标题】:Could Not Find Path Specified: CreateDirectoryW找不到指定的路径:CreateDirectoryW
【发布时间】:2015-10-08 14:31:05
【问题描述】:

VS2015,Unicode:在列表框中运行以下代码时出现“无法找到指定的路径”错误:

wchar_t *currPath, *cumPath;
int listTotal = 5;
int pathLength = 32760;
listTotal = SendMessageW(hList, LB_GETCOUNT, 0, 0);
wcscpy_s(cumPath, pathLength, L"\\\\?\\C:\\");
//wcscpy_s(cumPath, pathLength, L"C:\\"); //Tried this, no difference
wcscpy_s(currPath, MAX_PATH - 3, L"");
for (int i = 0; i < listTotal; i++) {
    SendMessageW(hList, LB_GETTEXT, i, (LPARAM) currPath); //"My Nested Path" picked up from textbox OK
    wcscat_s(cumPath, pathLength, (wchar_t *) currPath);
    \\OK but doubled backslashes
    wcscat_s(cumPath, MAX_PATH - 3, __TEXT("\\"));
    \\appear in debugger variable contents
}
int errorcode = CreateDirectoryW(cumPath, NULL);
if (errorcode == 0) {
    ErrorExit(TEXT("CreateDirectoryW"));
    //GetLastError courtesy [MSDN][1]

}

,我在这里错过了一些基本的东西吗?
双反斜杠没有从变量名中解析出来。有没有办法使用与 TEXT 或 L 结合使用的逐字或“原样”前缀来构造宏?

Edit1 代码前有以下两行:

currPath = (wchar_t *)calloc(pathLength, sizeof(wchar_t));
cumPath = (wchar_t *)calloc(pathLength, sizeof(wchar_t));

这两个变量都是在模块范围内声明的。 然而,在进入这个子之前有:

 currPath = (wchar_t *)calloc(pathLength, sizeof(wchar_t));
 ...
 free(currPath); 

currPath 的“重新调用”会不会有什么不好的地方?

Edit2:不,尝试使用另一个变量。 CreateDirectoryW之前​​的cumPath的值是否符合预期?

cumPath = 0x005b4fe8 L"\\\\?\\C:\\我的嵌套路径\\我的嵌套路径\\我的嵌套路径\\我的嵌套路径\\我的嵌套路径\\"

尤里卡!注释掉这一行,函数就起作用了!

  //wcscat_s(cumPath, MAX_PATH - 3, __TEXT("\\"));

但现在没有嵌套目录,就像最初的要求一样。

cumPath = 0x00644fe8 L"\\?\C:\我的嵌套路径我的嵌套路径我的嵌套路径我的嵌套路径我的嵌套路径"

【问题讨论】:

  • 这一行:wcscpy_s(cumPath, pathLength, L"\\\\?\\C:\\"); 正在复制到一个没有特别指向任何地方的指针。结果是未定义的行为。
  • 你真正需要的是学习一些调试技巧。首先计算传递给 api 函数的值。
  • 哎呀:我需要的是更好的 SO 问题技能。给 listTotal 一个值。添加了两个变量的 callocs。但是,对 callocs 做了一些可能不合法的事情。问题已更新。

标签: c winapi path nested prefix


【解决方案1】:

第一个问题是 cumPath 没有指向任何分配的内存。

并且 wcscpy_s() 函数期望目标是一个足够大的 char 数组来保存源字节

这是 wcscpy() 手册页的相关摘录

描述 wcscpy() 函数相当于 strcpy(3) 的宽字符 功能。它复制 src 指向的宽字符串, 包括终止空宽字符 (L'\0'),到数组 由dest指向。

   The strings may not overlap.

   The  programmer  must  ensure  that  there  is  room   for   at   least
   wcslen(src)+1 wide characters at dest.  

【讨论】:

    【解决方案2】:

    系统处理 C 编译的嵌套目录字符串的方式似乎有问题。 C++ 中显然没有类似的problem

    这里的解决方案是在每次新目录迭代时更改当前目录:

    #include <Windows.h>
    #include <Strsafe.h>
    
    
    void ErrorExit(LPCTSTR lpszFunction)
    {
    
        DWORD dww = 0;
        LPVOID lpMsgBuf;
        LPVOID lpDisplayBuf;
    
        dww = GetLastError();
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            dww,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),  (LPTSTR)&lpMsgBuf,0, NULL);
    
        lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    
    
        StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %lu: %s"), lpszFunction, dww, lpMsgBuf);
        MessageBox(NULL, (LPCTSTR)lpDisplayBuf, "Error", MB_OK);
        LocalFree(lpDisplayBuf);
        LocalFree(lpMsgBuf);
    }
    
    
    
    int main()
    {
    
    wchar_t *currPathW, *cumPathW;
    int listTotal = 2;
    int errorcode;
    int pathLength = MAX_PATH - 3;
    int stripLen;
    currPathW = (wchar_t *)calloc(pathLength, sizeof(wchar_t));
    cumPathW = (wchar_t *)calloc(pathLength, sizeof(wchar_t));
    wcscpy_s(cumPathW, pathLength, L"\\\\?\\C:\\");
    
    wcscpy_s(currPathW, MAX_PATH - 3, L"NestedPath");
    for (int i = 0; i < listTotal; i++) {
    
        wcscat_s(cumPathW, pathLength, (wchar_t *) currPathW);
        //OK but doubled backslashes
        wcscat_s(cumPathW, MAX_PATH - 3, L"\\");
        //appear in debugger variable contents
        int errorcode = CreateDirectoryW(cumPathW, NULL);
        if (errorcode == 0) ErrorExit("Failed: ");
    
    }
    //wchar_t * currPathWtmp = (wchar_t *)calloc(pathLength, sizeof(wchar_t));
    wchar_t * currPathWtmp;
    currPathWtmp = cumPathW;
    stripLen = wcslen(currPathWtmp)- wcslen(L"NestedPath") - 1;
    
    for (int i = 0; i < listTotal; i++) {
    
        int errorcode = RemoveDirectoryW(currPathWtmp);
        if (errorcode == 0) ErrorExit("Failed: ");
        currPathWtmp [stripLen] = 0; 
    
    }
    //currPathWtmp = NULL;
    
    
    free(currPathW); 
    free(cumPathW); 
    
    }
    

    编辑:该函数在 256 字符屏障上再次失败,并出现“无法找到指定的路径”,因此看起来需要再跳几个编码圈才能使其真正像宣传的那样工作。Edit2:将 PreprocessorDefinition 从 _WIN32 更改为 WIN64(在本例中为 _AMD64)没有任何区别。
    Edit3:现在应该立即编译它.全部工作!实际上,它适用于 listTotal 的许多值。发生了其他事情。

    【讨论】:

    • 可能是您的代码中使用MAX_PATH 有问题吗?只有260 characters long。你自己的pathLength 更大,而且(警告!随机猜测!)可能足够使用未来十年。
    • 这是一个想法:通过将 \\ 放在列表框字符串中来摆脱 wscat。但不,同样的问题。 +1 的想法。 :) 想知道如果 Explorer 被终止,这是否有效。
    猜你喜欢
    • 2020-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 2018-12-12
    相关资源
    最近更新 更多