需求:
已经知道目标机器的IP地址,管理员级别的用户名和密码,怎样实现通过代码对目标机磁盘信息的访问。
1. 通过使用WMI进行访问
2. 通过调用命令行的命令(net use和dir)来进行访问
3. 通过调用API函数进行反问。
思路:
1. 通过WMI进行访问
2. 通过建立对应的磁盘映射进行访问
优缺点分析:
1. 使用WMI需要对目标机进行一系列的配置,启动一些不安全的服务,不建议使用
2. 在程序中调用命令行,通过命令行命令建立映射,读取映射后磁盘的信息,该方法中需要取得命令行命令的返回结果,需要使用管道等,容易造成阻塞,不容易对执行结果进行判断。
3. 通过调用API函数来建立映射。建议使用。因为是直接调用函数,可以通过判断其返回值来判断映射是否建立成功。
具体实现方法:
1.使用WMI进行访问
①目标机的配置
A启动服务
确认以下service已经被启动
COM+ Event System
Remote Access Auto Connection Manager
Remote Access Connetion Manager
Remote Procedure Call(RPC)
Remote Procedure Call(RPC)Locator
Remote Registry
Server
Windows Management Instrumentation
Windows Management Instrumentation Driver Extensions
WMI Performance Adapter
Workstation
B.检查目标机上DCOM是否可用。
检查注册表中键值HKEY_LOCAL_MACHINE/Software/Microsoft/OLE/EnableDCOM的键值设为Y
C.检查目标机上DCOM是否可用。
检查注册表中键值HKEY_LOCAL_MACHINE/Software/Microsoft/OLE/EnableDCOM的键值设为Y
D.确保WMI的权限设置正确。
在命令行中执行以下三个命令
1)netsh firewall set service RemoteAdmin enable
2)netsh firewall add portopening protocol=tcp port=135 name=DCOM_TCP135
3)netsh firewall add allowedprogramprogram=%windir%/system32/wbem/unsecapp.exe name=UNSECAPP
E.在命令行中执行以下三个命令
cd /d %windir%/system32/wbem
for %i in (*.dll) do RegSvr32 -s %i
for %i in (*.exe) do %i /RegServer
F.在本地安全设置中(运行框中输入命令 secpol.msc)。
打开本地策略-〉安全选项,把 网络访问:本地帐户的共享和安全模式 中设置为经典-本地帐户以自己的身份验证
G.在本地安全设置中(运行框中输入命令 secpol.msc)。
打开本地策略-〉安全选项,把 网络访问:本地帐户的共享和安全模式 中设置为经典-本地帐户以自己的身份验证
②具体代码
'检索语句
PrivateShared ReadOnly SELECTSTR As String ="select FreeSpace ,Size from Win32_LogicalDisk where DeviceID = '?:'"
PrivateFunction GetDiskInfo(ByValIpAddress As String, ByVal netDriveAsString,ByValnetUser AsString,ByValnetPassWord AsString)As Double
'WMI连接
DimconnectOption AsSystem.Management.ConnectionOptions =NewSystem.Management.ConnectionOptions
'network名
connectOption.Username =netUser
'密码
connectOption.Password =netPassWord
Dim manageScopeAs System.Management.ManagementScope =New System.Management.ManagementScope(_"//" + IpAddress + "/root/cimv2", connectOption)
'连接WMI Scope
manageScope.Connect()
'处理检索语句
Dim excuteSelectAs String =SELECTSTR.Replace(Common.ICMtnDataToolConstants.DB_SQL_REPLACE,netDrive)
'检索语句设定
Dim objectQueryAs ObjectQuery =New ObjectQuery(excuteSelect)
'WMI检索内容和WMI的操作范围设定
Dim objectSearcherAs ManagementObjectSearcher =New ManagementObjectSearcher(manageScope,objectQuery)
'调用WMI的检索
Dim returnCollectionAs ManagementObjectCollection =objectSearcher.Get()
'空的大小
Dim freeSizeAs Double = 0
'全体的大小
Dim size As Double = 0
'当前
Dim percentAs Double = 0
For Each returnObj As ManagementObjectIn returnCollection
'取得空白的大小
freeSize = System.Int64.Parse(returnObj("FreeSpace")) / MBSIZE
'取得全体的大小
size = System.Int64.Parse(returnObj("Size")) /MBSIZE
'计算当前的大小
percent = freeSize /size * 100
Next
Return percent
EndFunction
2.使用命令行建立映射进行访问
①具体代码
PrivateFunction GetDiskInfo(ByValIpAddress As String, ByVal netDriveAsString,ByValnetUser AsString,ByValnetPassWord AsString)As Double
'生成disk的命令
Dim dosLine1As String = "net use o: //" + ipAddress + "/" + netDrive_
+ "$ " + netPassWord+" /user:" + netUser
'取得disk的空白大小
Dim dosLine2As String = "dir o: "
'删除disk。
Dim dosLine3As String = "net use o: /del"
GetCmdExecStr(dosLine3,False)
GetCmdExecStr(dosLine1,False)
Dim path As String = "o:/"
If System.IO.Directory.Exists(path)Then
outPutStr = GetCmdExecStr(dosLine2,True)
End If
GetCmdExecStr(dosLine3,False)
'对取得的结果进行解析,得到映射磁盘的剩余空间
EndFunction
PrivateFunction GetCmdExecStr(ByValcmdStr As String, ByVal isReadOutPutAs Boolean) _
As String
'执行命令
Dim pros As Process = NewProcess()
pros.StartInfo.FileName ="cmd.exe"
pros.StartInfo.UseShellExecute =False
pros.StartInfo.RedirectStandardInput =True
pros.StartInfo.RedirectStandardOutput =True
pros.StartInfo.RedirectStandardError =True
pros.StartInfo.CreateNoWindow =True
pros.Start()
pros.StandardInput.WriteLine(cmdStr)
Dim rtnstrAs String = ""
IfisReadOutPut Then
rtnstr=pros. StandardOutput.ReadToEnd()
EndIf
Return rtnstr
End Function
3. 调用API函数得到剩余空间
① 具体代码
'常数
ConstCONNECT_UPDATE_PROFILE = &H1
ConstRESOURCETYPE_ANY = &H0
ConstRESOURCE_CONNECTED = &H1
ConstRESOURCEUSAGE_CONNECTABLE = &H1
SharedReadOnly MBSIZE As Integer = 1024 * 1024
'网络结构体
PrivateStructure NETRESOURCE
Public dwScopeAs Integer
Public dwTypeAs Integer
Public dwDisplayTypeAs Integer
Public dwUsageAs Integer
Public lpLocalNameAs String
Public lpRemoteNameAs String
Public lpCommentAs String
Public lpProviderAs String
EndStructure
'定义API的函数的NetAddConnection2A
PrivateDeclare Function WNetAddConnection2 Lib "Mpr.dll" Alias "WNetAddConnection2A"_
(ByReflpNetResource AsNETRESOURCE, _
ByVallpPassword As String, _
ByVallpUsername As String, _
ByValdwFlags As Integer) As Integer
'定义API的函数WNetCancelConnection2A
PrivateDeclare Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" _
(ByVal lpNameAs String, _
ByVal dwFlagsAs Long, _
ByVal fForceAs Long) As Integer
FunctionCreatMapping(ByValipAddress As String, ByVal driveAs String, _
ByVal netUseAs String, ByVal netPassWord As String, ByVallocalDrive _
As String)As Integer
'返回值
Dim statusAs Integer = 0
'
Dim net As NETRESOURCE
'设定netsource
net.dwScope =RESOURCE_CONNECTED
net.dwType =RESOURCETYPE_ANY
net.dwDisplayType =RESOURCETYPE_ANY
net.dwUsage =RESOURCEUSAGE_CONNECTABLE
net.lpLocalName =localDrive + ":"
net.lpRemoteName ="//" + ipAddress +"/" + drive + "$"
net.lpComment =""
net.lpProvider =""
'连接netsource
status = WNetAddConnection2(net,netPassWord, netUse, 0)
Return status
EndFunction
FunctionCancelMapping(ByVallocalDrive As String) As Integer
'返回值
Dim statusAs Integer = 0
Dim localNameAs String = localDrive + ":"
'关闭netsource
status = WNetCancelConnection2(localName,CONNECT_UPDATE_PROFILE, True)
Return status
EndFunction
PrivateFunction GetDiskSizeInfo(B ByValIpAddress As String, ByVal netDriveAsString,ByValnetUser AsString,ByValnetPassWord AsString)As Long
Dim statusAs Integer = 0
Dim errmsgAs String = ""
DimfreeSize As Long = 0
Try
'
status = CreatMapping(ipAddress,diskInfo.NetDrive,diskInfo.NetUser,passWord, “z”)
'
If status <> 0Then
errmsg = String.Format("连接失败。返回值= {0} 原因= IP:{1}, Drive:{2},User:{3}",_
status, ipAddress,diskInfo.NetDrive,diskInfo.NetUser)
Logger.Err(errmsg)
Throw New Common.ICMtnDataAppException(errmsg)
End If
'取得空白的大小
Dim mappingDriveAs System.IO.DriveInfo =New System.IO.DriveInfo(“z” + ":")
freeSize = mappingDrive.AvailableFreeSpace /MBSIZE
'
status = CancelMapping(mark)
If status <> 0Then
errmsg = String.Format("关闭失败。返回值= {0} mark:{1}", status,mark)
Logger.Err(errmsg)
Throw New Common.ICMtnDataAppException(errmsg)
End If
Catch ex As Exception
Logger.Err("disk的容量取得失败",ex)
Throw New Common.ICMtnDataAppException("disk的容量取得失败",ex)
End Try
Return freeSize
EndFunction
② 注意
当映射到本地的盘符已经存在时,映射会失败。所以应该先对本地所有的盘符进行判断,取出一个本地没有的盘符来进行映射。