none
32位(XP)升级64位(Server 2008 R2)时,PdhGetFormattedCounterValue不正常 RRS feed

  • 常规讨论

  • 原由:

          之前的一个系统性能监视程序的运行环境由原来的32位XP换成了64位的Server 2008 R2。由于要求,不使用WOW64,所以需要进行代码升级。

    现象:

          程序挺简单,功能很单一,就是通过命令行参数将需要Query的Counter传进来。然后将Counter取到的值printf

          现共有下面3个Counter需要监视

              \System\Processes
              \System\Processor Queue Length
              \LogicalDisk(_Total)\Avg. Disk Queue Length

          直接编译没问题,于是只是修改了一下变量类型。运行时出问题,【\System\Processes】和【\System\Processor Queue Length】监视正常,但是【\LogicalDisk(_Total)\Avg. Disk Queue Length】失败。

          失败函数为:PdhGetFormattedCounterValue

          返回值为:PDH_INVALID_DATA

          进一步DEBUG后得到,函数返回后PDH_FMT_COUNTERVALUE中的CStatus为PDH_CSTATUS_INVALID_DATA

          针对64位修改后的同一程序编译为32位后,在XP上一切正常。

    代码:

    void main(int Argc, char **Argv){
     int Ir = 99;

     HQUERY   hQuery = NULL;
     HCOUNTER  hCounter;
     char* CounterQuery = NULL;
     PPDH_COUNTER_INFO pInfo = NULL;
     DWORD SizeOrg = 10000;
     DWORD Size = SizeOrg;
     PDH_FMT_COUNTERVALUE  pValue;
     PDH_STATUS  PdhIr;
     int iLoop;
     __int64  i64Ir;
     __int64  i64Temp = (__int64)0;
     __int64  i64Para = (__int64)0;


     while( 1 ){
      if( Argc < 2 ) {
       Ir = 91;
       break;
      };
      CounterQuery = Argv[1];

      PdhIr = PdhOpenQuery( NULL, 0, &hQuery );
      if( PdhIr != ERROR_SUCCESS ){
       Ir = 1;
       break;
      }

      PdhIr = PdhAddCounter( hQuery, CounterQuery, 0, &hCounter );
      if( PdhIr != ERROR_SUCCESS ){
       Ir = 2;
       break;
      }

      PdhIr = PdhCollectQueryData( hQuery );
      if( PdhIr != ERROR_SUCCESS ){
       Ir = 3;
       break;
      }

      PdhIr = PdhGetFormattedCounterValue(hCounter, PDH_FMT_LARGE|PDH_FMT_NOSCALE, NULL, &pValue);
      if( PdhIr != ERROR_SUCCESS ){
       Ir = 4;
       break;
      }
      i64Ir = pValue.largeValue;
      Ir = 0;
      for( iLoop = 2;iLoop < Argc;iLoop++ ){
       if( strcmp( Argv[iLoop],"u=KB" ) == 0 ) {
        i64Para = (__int64)1024;
        i64Temp = pValue.largeValue / i64Para;
        i64Ir = i64Temp;
        continue;
       }
       if( strcmp( Argv[iLoop],"u=MB" ) == 0 ) {
        i64Para = (__int64)1024 * (__int64)1024;
        i64Temp = pValue.largeValue / i64Para;
        i64Ir = i64Temp;
        continue;
       }
       if( strcmp( Argv[iLoop],"u=GB" ) == 0 ) {
        i64Para = (__int64)1024 * (__int64)1024 * (__int64)1024;
        i64Temp = pValue.largeValue / i64Para;
        i64Ir = i64Temp;
        continue;
       }
       if( strcmp( Argv[iLoop],"u=TB" ) == 0 ) {
        i64Para = (__int64)1024 * (__int64)1024 * (__int64)1024 * (__int64)1024;
        i64Temp = pValue.largeValue / i64Para;
        i64Ir = i64Temp;
        continue;
       }
       if( strncmp( Argv[iLoop],"u=",2 ) == 0 ) {
        i64Para = _atoi64(Argv[iLoop]+2);
        if( i64Para == (__int64)0 ){
         Ir = 11;
         break;
        }
        i64Temp = pValue.largeValue / i64Para;
        i64Ir = i64Temp;
        continue;
       }
      }
      if( Ir != 0 ) break;
      printf( "%I64d\n",i64Ir );
      break;
     }

     if( hQuery != NULL ){
      PdhIr = PdhCloseQuery( hQuery );
     }

     exit( Ir );
    }

    在大家回答前,先谢谢各位关注

    2010年9月5日 12:12

全部回复

  • 是不是权限问题。用WOW64,运行看看
    麻烦把正确答案设为解答。
    2010年9月7日 14:18
    版主
  • 应该不是权限问题,同一用户下,用perfmon(未使用管理员身份)能正常监视\LogicalDisk(_Total)\Avg. Disk Queue Length

    在32位XP下能正常跑的程序拿到64位底下也不行。按我的理解来说,直接拿来跑的话应该会自动用WOW64了吧?

    另:CPU忘说了:Intel Core 2 Duo E6550  编译时使用目标机器是x64

    现在有3种lib,IA64  AMD64  X64,查了一下IA64是给安腾用的。总不能用AMD64吧?用了以后还报错说Module Computer是X86和目标机器AMD64有冲突(环境日文的,翻译过来大概就这么个意思)。IA64一样的报错。

    再另:编译环境是VS2010+WINSDK 7.0

    2010年9月8日 5:39