【问题标题】:windows error argument type c programmingwindows错误参数类型c编程
【发布时间】:2012-10-22 23:10:03
【问题描述】:

我有这个代码,我在 Windows 中没有经验:

#include <windows.h>
#include <stdio.h>


   typedef BOOL (WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER, 
                                  PULARGE_INTEGER, PULARGE_INTEGER);

   void main (int argc, char **argv)
   {
      BOOL  fResult;

      char  *pszDrive  = NULL,
             szDrive[4];

      DWORD dwSectPerClust,
            dwBytesPerSect,
            dwFreeClusters,
            dwTotalClusters;

      P_GDFSE pGetDiskFreeSpaceEx = NULL;

      unsigned __int64 i64FreeBytesToCaller,
                       i64TotalBytes,
                       i64FreeBytes;


      if (argc != 2)
      {
         printf ("usage:  %s <drive|UNC path>\n", argv[0]);
         printf ("\texample:  %s C:\\\n", argv[0]);
         return;
      }

      pszDrive = argv[1];

      if (pszDrive[1] == ':')
      {
         szDrive[0] = pszDrive[0];
         szDrive[1] = ':';
         szDrive[2] = '\\';
         szDrive[3] = '\0';

         pszDrive = szDrive;
      }

     // FIRST ERROR  kernel32.dll
      pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress (
                               GetModuleHandle ("kernel32.dll"),
                                              "GetDiskFreeSpaceExA");
       // SECOND ERROR pszDrive
      if (pGetDiskFreeSpaceEx)
      {
         fResult = pGetDiskFreeSpaceEx (pszDrive,
                                 (PULARGE_INTEGER)&i64FreeBytesToCaller,
                                 (PULARGE_INTEGER)&i64TotalBytes,
                                 (PULARGE_INTEGER)&i64FreeBytes);
         if (fResult)
         {
            printf ("\n\nGetDiskFreeSpaceEx reports\n\n");
            printf ("Available space to caller = %I64u MB\n",
                    i64FreeBytesToCaller / (1024*1024));
            printf ("Total space               = %I64u MB\n",
                    i64TotalBytes / (1024*1024));
            printf ("Free space on drive       = %I64u MB\n",
                    i64FreeBytes / (1024*1024));
         }
      }
      else
      {
         // ERROR 3 pszDrive
         fResult = GetDiskFreeSpace (pszDrive, 
                                     &dwSectPerClust,
                                     &dwBytesPerSect, 
                                     &dwFreeClusters,
                                     &dwTotalClusters);
         if (fResult)
         {
            /* force 64-bit math */ 
            i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust *
                              dwBytesPerSect;
            i64FreeBytes = (__int64)dwFreeClusters * dwSectPerClust *
                              dwBytesPerSect;

            printf ("GetDiskFreeSpace reports\n\n");
            printf ("Free space  = %I64u MB\n", 
                    i64FreeBytes / (1024*1024));
            printf ("Total space = %I64u MB\n", 
                    i64TotalBytes / (1024*1024));
         }
      }

      if (!fResult)
         printf ("error: %lu:  could not get free space for \"%s\"\n",
                 GetLastError(), argv[1]);
   }

我遇到了这些错误(visual studio 2010 终极版):

在 kernel32.dll:

pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress ( GetModuleHandle ("kernel32.dll"), "GetDiskFreeSpaceExA");

错误:const char* 类型的参数与“LPCWSTR”类型的参数不兼容

在 pszDrive:

fResult = pGetDiskFreeSpaceEx (pszDrive,
                                 (PULARGE_INTEGER)&i64FreeBytesToCaller,
                                 (PULARGE_INTEGER)&i64TotalBytes,
                                 (PULARGE_INTEGER)&i64FreeBytes);

错误:char* 类型的参数与“LPCTSTR”类型的参数不兼容

在 pszDrive:

 fResult = GetDiskFreeSpace (pszDrive, 
                                     &dwSectPerClust,
                                     &dwBytesPerSect, 
                                     &dwFreeClusters,
                                     &dwTotalClusters);

错误:char* 类型的参数与“LPCWSTR”类型的参数不兼容

非常感谢

【问题讨论】:

    标签: c windows winapi


    【解决方案1】:

    最简单的解决方案是将项目设置更改为多字节字符集。

    为此,在解决方案资源管理器中右键单击项目,选择属性。在属性对话框的左侧窗格中选择常规。找到字符集并将其更改为“使用多字节字符集”。

    不过,如果您要进行大量 Windows 编程,您应该习惯 Unicode。基本上这意味着使用 wchar_t(或 TCHAR)而不是 char,包括在常量字符串中:

          pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress (
                                              GetModuleHandle (L"kernel32.dll"),
                                              "GetDiskFreeSpaceExW");
    

    在这种情况下,正如亚当正确指出的那样,您还需要将函数名称从 A 版本更改为 W 版本。

    【讨论】:

    • 嗨,谢谢它的工作,但没有 L"GetDiskFreeSpaceExW" 只是 "GetDiskFreeSpaceExW"
    【解决方案2】:

    将您的代码更改为更能识别TCHAR,因为当您像您一样将 Ansi 和 Unicode 代码混合在一起时,这是 Win2 API 所期望的:

    #include <windows.h> 
    #include <stdio.h> 
    #include <tchar.h>
    
    typedef BOOL (WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER,  
                                  PULARGE_INTEGER, PULARGE_INTEGER); 
    
    void _tmain (int argc, TCHAR **argv) 
    { 
        BOOL  fResult; 
    
        TCHAR *pszDrive = NULL,
              szDrive[4]; 
    
        DWORD dwSectPerClust, 
              dwBytesPerSect, 
              dwFreeClusters, 
              dwTotalClusters; 
    
        P_GDFSE pGetDiskFreeSpaceEx = NULL; 
    
        unsigned __int64 i64FreeBytesToCaller, 
                         i64TotalBytes, 
                         i64FreeBytes; 
    
    
        if (argc != 2) 
        { 
            _tprintf (_T("usage:  %s <drive|UNC path>\n"), argv[0]); 
            _tprintf (_T("\texample:  %s C:\\\n"), argv[0]); 
            return; 
        } 
    
        pszDrive = argv[1]; 
    
        if (pszDrive[1] == TEXT(':')) 
        { 
            _stprintf(szDrive, _T("%s:\\"), pszDrive[0]); 
            pszDrive = szDrive; 
        } 
    
        // FIRST ERROR  kernel32.dll 
        pGetDiskFreeSpaceEx = (P_GDFSE) GetProcAddress ( 
                               GetModuleHandle (TEXT("kernel32.dll")), 
                                              #ifdef UNICODE
                                              "GetDiskFreeSpaceExW"); 
                                              #else
                                              "GetDiskFreeSpaceExA"); 
                                              #endif
                               );
    
        // SECOND ERROR pszDrive 
        if (pGetDiskFreeSpaceEx) 
        { 
            fResult = pGetDiskFreeSpaceEx (pszDrive, 
                                 (PULARGE_INTEGER)&i64FreeBytesToCaller, 
                                 (PULARGE_INTEGER)&i64TotalBytes, 
                                 (PULARGE_INTEGER)&i64FreeBytes); 
            if (fResult) 
            { 
                _tprintf (_T("\n\nGetDiskFreeSpaceEx reports\n\n")); 
                _tprintf (_T("Available space to caller = %I64u MB\n"), 
                    i64FreeBytesToCaller / (1024*1024)); 
                _tprintf (_T("Total space               = %I64u MB\n"), 
                    i64TotalBytes / (1024*1024)); 
                _tprintf (_T("Free space on drive       = %I64u MB\n"), 
                    i64FreeBytes / (1024*1024)); 
            } 
        } 
        else 
        { 
            // ERROR 3 pszDrive 
            fResult = GetDiskFreeSpace (pszDrive,  
                                     &dwSectPerClust, 
                                     &dwBytesPerSect,  
                                     &dwFreeClusters, 
                                     &dwTotalClusters); 
            if (fResult) 
            { 
                /* force 64-bit math */  
                i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust * 
                              dwBytesPerSect; 
                i64FreeBytes = (__int64)dwFreeClusters * dwSectPerClust * 
                              dwBytesPerSect; 
    
                _tprintf (_T("GetDiskFreeSpace reports\n\n")); 
                _tprintf (_T("Free space  = %I64u MB\n"),  
                    i64FreeBytes / (1024*1024)); 
                _tprintf (_T("Total space = %I64u MB\n"),  
                    i64TotalBytes / (1024*1024)); 
            } 
        } 
    
        if (!fResult) 
            _tprintf (_T("error: %lu:  could not get free space for \"%s\"\n"), 
                 GetLastError(), argv[1]); 
    } 
    

    否则,由于您在启用UNICODE 的情况下进行编译,因此只需编写纯Unicode 代码:

    #include <windows.h> 
    #include <stdio.h> 
    
    typedef BOOL (WINAPI *P_GDFSE)(LPCWSTR, PULARGE_INTEGER,  
                                  PULARGE_INTEGER, PULARGE_INTEGER); 
    
    void wmain (int argc, wchar_t **argv) 
    { 
        BOOL  fResult; 
    
        wchar_t *pszDrive = NULL,
              szDrive[4]; 
    
        DWORD dwSectPerClust, 
              dwBytesPerSect, 
              dwFreeClusters, 
              dwTotalClusters; 
    
        P_GDFSE pGetDiskFreeSpaceEx = NULL; 
    
        unsigned __int64 i64FreeBytesToCaller, 
                         i64TotalBytes, 
                         i64FreeBytes; 
    
    
        if (argc != 2) 
        { 
            wprintf (L"usage:  %s <drive|UNC path>\n", argv[0]); 
            wprintf (L"\texample:  %s C:\\\n", argv[0]); 
            return; 
        } 
    
        pszDrive = argv[1]; 
    
        if (pszDrive[1] == L':') 
        { 
            _stprintf(szDrive, _T("%s:\\"), pszDrive[0]); 
            pszDrive = szDrive; 
        } 
    
        // FIRST ERROR  kernel32.dll 
        pGetDiskFreeSpaceEx = (P_GDFSE) GetProcAddress ( 
                               GetModuleHandle (TEXT("kernel32.dll")), 
                                              "GetDiskFreeSpaceExW"
                               ); 
        // SECOND ERROR pszDrive 
        if (pGetDiskFreeSpaceEx) 
        { 
            fResult = pGetDiskFreeSpaceEx (pszDrive, 
                                 (PULARGE_INTEGER)&i64FreeBytesToCaller, 
                                 (PULARGE_INTEGER)&i64TotalBytes, 
                                 (PULARGE_INTEGER)&i64FreeBytes); 
            if (fResult) 
            { 
                wprintf (L"\n\nGetDiskFreeSpaceEx reports\n\n"); 
                wprintf (L"Available space to caller = %I64u MB\n", 
                    i64FreeBytesToCaller / (1024*1024)); 
                wprintf (L"Total space               = %I64u MB\n", 
                    i64TotalBytes / (1024*1024)); 
                wprintf (L"Free space on drive       = %I64u MB\n", 
                    i64FreeBytes / (1024*1024)); 
            } 
        } 
        else 
        { 
            // ERROR 3 pszDrive 
            fResult = GetDiskFreeSpace (pszDrive,  
                                     &dwSectPerClust, 
                                     &dwBytesPerSect,  
                                     &dwFreeClusters, 
                                     &dwTotalClusters); 
            if (fResult) 
            { 
                /* force 64-bit math */  
                i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust * 
                              dwBytesPerSect; 
                i64FreeBytes = (__int64)dwFreeClusters * dwSectPerClust * 
                              dwBytesPerSect; 
    
                wprintf (L"GetDiskFreeSpace reports\n\n"); 
                wprintf (L"Free space  = %I64u MB\n",  
                    i64FreeBytes / (1024*1024)); 
                wprintf (L"Total space = %I64u MB\n",  
                    i64TotalBytes / (1024*1024)); 
            } 
        } 
    
        if (!fResult) 
            wprintf (L"error: %lu:  could not get free space for \"%s\"\n", 
                 GetLastError(), argv[1]); 
    } 
    

    【讨论】:

    • 虽然 GetProcAddress 始终采用 char 字符串,但 GetModuleHandle 的参数是 LPCTSTR。
    【解决方案3】:

    您显然是在UNICODE 模式下编译。更改以下内容:

    void _tmain (int argc, TCHAR **argv)
    

      TCHAR  *pszDrive  = NULL,
             szDrive[4];
    

    这应该会让你走得更远。有关详细信息,请参阅以下问题:What is the difference between _tmain() and main() in C++?

    【讨论】:

    • 这行不通,因为 OP 明确要求使用 GetProcAddress(..., "GetDiskFreeSpaceExA") 的 ANSI 变体。
    • 嗨,非常感谢,我需要阅读很多关于 win 编程的链接,我仍然在 "kernel32" 处出现第一个错误,其他都可以,你能检查我是否需要更改用于 UNICODE
    猜你喜欢
    • 2017-04-14
    • 2021-06-16
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    相关资源
    最近更新 更多