fuinei 发表于 2012-5-10 17:14:18

[已解决]使用WMI获指列表中PC的硬盘信息

本帖最后由 fuinei 于 2012-5-17 12:08 编辑

各位好,请问如何通过WMI远程获取指定计算机列表的硬盘信息呢?
如:
1、运行帐号已经具备指定PC的本机管理员权限
2、指定的PC列表
PC1
PC2
PC3
...
3、返回结果包括
计算机名,IP地址,当前系统登录用户,硬盘物理空间大小,硬盘分区数量,C盘分区容量/C盘剩余空间,....
如:PC1,192.168.1.1,test,500G,50G/30G,225G/100G,225G/100G....

502762378 发表于 2012-5-10 22:28:33

越写越觉得自己二,那么就二到底吧
开始套用了个用WMI时判断PC情况的框架,为了做到简化,少用了些对象集合
#include <file.au3>
#include <array.au3>
Local $aResult,$aRecord
$file = @ScriptDir&"\result.ini"
If Not _FileReadToArray(@ScriptDir&"\list.txt",$aRecord) Then;读取文件得到数组
   MsgBox(4096,"Error", " Error reading log to Array   error:" & @error)
   Exit
EndIf
For $x = 1 to $aRecord
$size = 0
$DriveTypeoffnumber = 0
If Ping ($aRecord[$x],250)        Then       
    If DriveStatus( "\\"&$aRecord[$x]&"\c$" ) = "UNKNOWN" Then;有些PC可能IP冲突,也有可能没有管理员权限,暂且定义为防火墙
          IniWrite($file,"info",$aRecord[$x],"Firewall")
        Else
                $aResult += 1
                Redim $aResult[$aResult + 1]
      Local $objWMIService = ObjGet("winmgmts:\\" & $aRecord[$x] & "\root\CIMV2")
                $colItems1 = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL")
                $colItems2 = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk where Description='本地固定磁盘'", "WQL")
                For $objItem1 In $colItems1
                        $aResult[$aResult] = $aRecord[$x];电脑名
                        $aResult[$aResult] = TCPNameToIP($aRecord[$x]);解析出的IP
                        $aResult[$aResult] =$objItem1.UserName;登录的user

          Next
                For $objItem2 In $colItems2
                        $Size += $objItem2.Size
                        $DriveTypeoffnumber += $objItem2.DriveType
                        If $objItem2.Caption = "C:" Then
                                $aResult[$aResult] =$objItem2.Size/1024/1024/1024;C盘空间大小
                                $aResult[$aResult] =$objItem2.FreeSpace/1024/1024/1024;C盘剩余空间大小
            EndIf                               
          Next
                $aResult[$aResult] =$Size/1024/1024/1024;硬盘大小
                $aResult[$aResult] =$DriveTypeoffnumber/3;分区数量
        EndIf
Else       
        If TCPNameToIP($aRecord[$x])<>"" Then
          IniWrite($file,"info",$aRecord[$x],"No boot");没开机
        Else
                IniWrite($file,"info",$aRecord[$x],"N/PC");没有的PC在AD中没有即时update
                EndIf
EndIf
Next
_ArrayDisplay($aResult,"")

PC列表list.txt如你所描述

lxwlxwayy 发表于 2012-5-10 23:00:03

好高深,看不懂

fuinei 发表于 2012-5-11 09:21:14

回复 2# 502762378

谢谢502762378兄的指导,基本功能已实现,我希望检测硬盘所有分区的容量及剩余容量,由于水平有限,参考你的代码修改的数组大小和增加检测其它分区的容量(公司的电脑分区数量为1~4个),如有更好的方法请指教,谢谢!#include <file.au3>
#include <array.au3>
Local $aResult,$aRecord
$file = @ScriptDir&"\result.ini"
If Not _FileReadToArray(@ScriptDir&"\list.txt",$aRecord) Then;读取文件得到数组
   MsgBox(4096,"Error", " Error reading log to Array   error:" & @error)
   Exit
EndIf
For $x = 1 to $aRecord
$size = 0
$DriveTypeoffnumber = 0
If Ping ($aRecord[$x],250)      Then      
    If DriveStatus( "\\"&$aRecord[$x]&"\c$" ) = "UNKNOWN" Then;有些PC可能IP冲突,也有可能没有管理员权限,暂且定义为防火墙
            IniWrite($file,"info",$aRecord[$x],"Firewall")
      Else
                $aResult += 1
                Redim $aResult[$aResult + 1]
      Local $objWMIService = ObjGet("winmgmts:\\" & $aRecord[$x] & "\root\CIMV2")
                $colItems1 = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL")
                $colItems2 = $objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDisk where Description='本地固定磁盘'", "WQL")
                For $objItem1 In $colItems1
                        $aResult[$aResult] = $aRecord[$x];电脑名
                        $aResult[$aResult] = TCPNameToIP($aRecord[$x]);解析出的IP
                        $aResult[$aResult] =$objItem1.UserName;登录的user

            Next
                For $objItem2 In $colItems2
                        $Size += $objItem2.Size
                        $DriveTypeoffnumber += $objItem2.DriveType
                        If $objItem2.Caption = "C:" Then
                              $aResult[$aResult] =Round($objItem2.Size/1024/1024/1024,2) & "/" & Round($objItem2.FreeSpace/1024/1024/1024,2);C盘空间大小/及剩余空间
                                                EndIf
                                                If $objItem2.Caption = "D:" Then
                              $aResult[$aResult] =Round($objItem2.Size/1024/1024/1024,2) & "/" & Round($objItem2.FreeSpace/1024/1024/1024,2);D盘空间大小/及剩余空间
                                                EndIf
                                                If $objItem2.Caption = "E:" Then
                              $aResult[$aResult] =Round($objItem2.Size/1024/1024/1024,2) & "/" & Round($objItem2.FreeSpace/1024/1024/1024,2);E盘空间大小/及剩余空间
                                                EndIf
                                                If $objItem2.Caption = "F:" Then
                              $aResult[$aResult] =Round($objItem2.Size/1024/1024/1024,2) & "/" & Round($objItem2.FreeSpace/1024/1024/1024,2);F盘空间大小/及剩余空间
                                                EndIf       
                           
                                Next
                $aResult[$aResult] =Round($Size/1024/1024/1024,2);硬盘大小
                                $aResult[$aResult] =$DriveTypeoffnumber/3;分区数量
      EndIf
Else      
      If TCPNameToIP($aRecord[$x])<>"" Then
            IniWrite($file,"info",$aRecord[$x],"No boot");没开机
      Else
                IniWrite($file,"info",$aRecord[$x],"N/PC");没有的PC在AD中没有即时update
                EndIf
EndIf
Next
_ArrayDisplay($aResult,"")

502762378 发表于 2012-5-11 10:51:01

回复 4# fuinei


    好的办法就是不用WMI
$driver = "\\192.168.0.132\c$"
MsgBox(1,"", _test($driver)&"\"& _test($driver,1))

Func _test ($sdriver,$x =0)
    If FileExists($sdriver) Then
                If $x = 0 Then
                  return DriveSpaceTotal($sdriver)
                else
                  Return DriveSpaceFree($sdriver)
                EndIf
               
        endif
EndFunc


502762378 发表于 2012-5-11 11:07:42

回复 5# 502762378


    另外如果你是手动从AD的OU中手动倒PC得list的话,送你个命令,你会很happy的:dsquery

fuinei 发表于 2012-5-11 12:09:52

回复 5# 502762378

原来想到使用AU3的语句只能在本机执行所以才想使用WMI的,上面的方法很不错
使用WMI代码测试时发现2个问题:
1、个别PC(原因未知)会导致程序异常中止
2、部分没有E盘的PC会把D盘的容量/剩余空间填写到E盘所在的列

fuinei 发表于 2012-5-11 12:11:03

回复 6# 502762378
我们公司刚好使用域管理的,能否给个简单的例子?

502762378 发表于 2012-5-13 20:00:36

回复 7# fuinei


    1:怎么给你说呢,我经常也会用WMI批量搞时出现问题,我这边探测出的一种情况是IP冲突,这个你应该清楚吧。可能还有其他的问题,都不说WIN7了,真心觉得XP高深。
   2;那个你可以先在循环开始定义$driverE=“”、$driverF=“”,然后下边的这样写,专业语言我没办法给你解答,你自己琢磨
If $objItem2.Caption = "F:" Then
        $driverF=Round($objItem2.Size/1024/1024/1024,2) & "/" & Round($objItem2.FreeSpace/1024/1024/1024,2);F盘空间大小/及剩余空间
EndIf   
$aResult[$aResult]= $driverF

关于dsquery的知识你自己上AD的帮助主题中搜吧。。

fuinei 发表于 2012-5-15 15:07:55

回复 9# 502762378
谢谢指导,问题2已解决,根据你的方法使用DriveSapceTotal和DriveSapceFree加默认共享路径的方式也可以成功获取到远程计算机的硬盘分区容量信息,请问不使用WMI情况下可以获取远程计算机当前登录的用户名吗?

502762378 发表于 2012-5-15 20:34:12

回复 10# fuinei


    可以用pstools中的psloggedon,也可以查看所有用户配置文件的最新修改时间

fuinei 发表于 2012-5-16 11:56:13

回复 11# 502762378
谢谢指导,由于水平有限使用psloggedon配合AU3时未能返回需要的结果,但根据配置文件的最新修改时间判断当前用户时也遇到返回结果不准确的情况,代码如下:#include <File.au3>
$Configshare = "\\192.168.1.1\c$\Documents and Settings"
$A_list = _FileListToArray($Configshare, "*", 2)
Local $lastuser = $A_list
Local $modified = FileGetTime($Configshare & "\" & $A_list,0,1)
For $i = 2 To $A_list
        $filemodied = FileGetTime($Configshare & "\" & $A_list[$i],0,1)
        If $filemodied > $modified Then
                $lastuser = $A_list[$i]
        EndIf
Next
MsgBox("","",$lastuser)
希望能指点一下,谢谢!

502762378 发表于 2012-5-16 12:43:44

本帖最后由 502762378 于 2012-5-16 12:54 编辑

回复 12# fuinei


1.可能是你dos回显的练习做的不多,使用psloggedon由于中途有一个停顿时间,所以你回显得不到信息,你可以这样:
c:\pstools\psloggedon \\192.168.0.132 >d:\1.txt
然后处理文本中得到的信息
2 .通过查看所有user配置文件的最后修改时间,判断登陆账户这个理论上肯定是成立的,但是要注意两个问题:1机器是否是注销状态?(如果是我就要判断最后登陆的user的那个修改时间到现在的时间差有没有超过一个时间段,)2:机器是否是锁定状态?如果是这样又要测试锁定状态下user的配置文件修改时间有没有一直在即时更新,我没有测试,解决不了第二个问题,我顿时觉得此方案不靠谱、不严谨了。。

fuinei 发表于 2012-5-16 15:38:41

本帖最后由 fuinei 于 2012-5-16 16:12 编辑

回复 13# 502762378

非常感谢指导,由于水平有限,对文本加工的正则还是没有搞懂,按指导使用psloggedon已基本可返回当前用户信息,但需准确返回结果还是要配套正确的正则表达式,目前测试的代码如下:
Local $test_PC = "PC1"
Local $log = "c:\logonuser.txt"
Local $cmd = "c:\psloggedon.exe \\" & $test_PC & " >" & $log
RunWait(@ComSpec & " /c " & $cmd,"", @SW_HIDE)
Local $file = FileOpen($log,0)
$logonuserinfo = FileReadline($file,8)
$logonuser = StringRegExp($logonuserinfo, '', 1);正则未填写
MsgBox("","",$logonuserinfo)
MsgBox("","",$logonuser)
FileClose($file)
;fileDelete($log)
目前$logonuserinfo结果为   2012-5-16 8:02:31    Domain\users
请问如何写正则表达式可返回Domain\users呢?

第2个方法经测试原代码有问题,比较目录后没有更新修改时间变量,修改为以下代码后可基本达到我的要求,我计划使用该信息来获取该PC的用户#include <File.au3>
$Configshare = "\\192.168.1.1\c$\Documents and Settings"
$A_list = _FileListToArray($Configshare, "*", 2)
Local $lastuser = $A_list
Local $modified = FileGetTime($Configshare & "\" & $A_list,0,1)
For $i = 2 To $A_list
      $filemodied = FileGetTime($Configshare & "\" & $A_list[$i],0,1)
      If $filemodied > $modified Then
                $modified = $filemodied
                $lastuser = $A_list[$i]
      EndIf
Next
MsgBox("","",$lastuser)

502762378 发表于 2012-5-16 16:48:18

回复 14# fuinei


    问道了我的痛处,我不会正则,用字符窜处理倒是没有问题
$string = "2012-5-16 8:02:31    Domain\users"
$suser = StringSplit($string,"\")
MsgBox(1,1," Domain\"&$suser)

页: [1] 2
查看完整版本: [已解决]使用WMI获指列表中PC的硬盘信息