4

我是 VBScript 的新手。我找不到在 VBS 中使用 WMI 将文件从一台 XP 主机复制到另一台主机的方法。复制文件的常用方法(RPC - 远程过程调用、SMB、UNC)不适用于多个主机,但 WMI 可用于所有主机,我需要将文件从我的管理主机复制到目标 Windows 主机。我以为我会在那里找到一些示例代码,但我没有找到任何信息。也没有找到任何东西告诉我它不能完成。

源文件是我的管理计算机的“F:\TEMP”文件夹中的可执行文件和“test1.txt”。我想将文件放在远程主机 HOST1 的“C:\TEMP”文件夹中。我对两台主机都拥有完全的管理员权限。这是我到目前为止所拥有的,仅用于一个文件(以保持测试简单):

strComputer = "HOST1"
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery( _
    "Select * from Win32_Directory where Name = 'c:\\temp'")
For Each objFiles in colFiles
    errResults  = objFolder.Copy("f:\temp\test1.txt")
    Wscript.Echo errResults
Next
4

5 回答 5

6

我了解到 WMI 无法在远程主机上创建文件,也无法通过网络连接复制文件:http: //msdn.microsoft.com/en-us/library/windows/desktop/aa389288%28v=vs.85% 29.aspx

但是,它可以运行 cmd 进程。这是弗兰克怀特的升 C 代码,后面是他的例子: https ://stackoverflow.com/a/8913231/1569434

InputParameters("CommandLine") = "cmd /c echo myFTPCommands > c:\ftpscript.txt"

您将需要四件事来使用以下所有 scriptlet,它们相互构建以使用 psexec 在远程主机上运行“普通”VBScript 或批处理脚本:

  1. 远程主机的管理员权限;
  2. 在远程主机上启用 WMI
  3. 您的远程主机可以访问的网络共享(使用 RPC、UNC、FTP 等,但不是DFS!(“分布式文件系统” - 见注释);和
  4. psexec.exe 和网络共享上的“正常”脚本。

重要提示:请勿使用DFS映射网络共享!如果您将分布式文件系统用于网络共享,它将失败。无论您使用哪种操作系统(例如,XP、Win 7),根据您的尝试方式,您可能会得到一个错误代码是“系统错误 1312” 。

当远程主机上的 RPC 不可用但 WMI 可用时,以下方法将在远程主机的 c:\temp 文件夹上创建一个本地 ASCII 文件,其中包含文本“myTextCommands”,不带引号。

' https://stackoverflow.com/questions/8884728/wmi-remote-process-to-copy-file
strCommand = "cmd /c echo myTextCommands > c:\temp\testscript.txt"
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" _
    & strComputer & "\root\cimv2")
Set objProcess = objWMIService.Get("Win32_Process")
errReturn = objProcess.Create(strCommand, null, null, intProcessID)
' See following link for error codes returned by errReturn
' http://msdn.microsoft.com/en-us/library/windows/desktop/aa389388(v=vs.85).aspx

请注意上面脚本中的重要限制:它只能创建 ASCII 文件 - 而不是二进制文件。

让我们使用该技术来映射驱动器号:

strCommand = "cmd /c net use z: " & MyShare & " /user:%USERDOMAIN%\%USERNAME% " _
    & strPassword & ">" & strRemoteLog
Set objProcess = objWMIService.Get("Win32_Process")
Call errProcess

其中“strRemoteLog”设置为“c:\temp\MyLog.txt”,提示“strPassword”(参见底部的完整脚本示例和参考),“errProcess”是一个子例程,使用上面提到的“cmd /c”技巧:

Sub errProcess
errReturn = objProcess.Create(strCommand, null, null, intProcessID)
If errReturn = 0 Then
    Wscript.Echo "Process was started with a process ID: " & intProcessID
    WScript.Sleep 5000
Else
    Wscript.Echo "Process could not be started due to error: " & errReturn
End If
End Sub

映射网络驱动器后,将脚本复制到主机:

strCommand="cmd /c xcopy Z:\scripts\SCRIPT1.bat c:\temp\ >>" & strRemoteLog
Call errProcess

SCRIPT1.bat 已准备就绪,因此在远程主机上针对它启动 psexec,向您的脚本传递一个变量 strUserID,该变量将在之前获得,例如:

strCommand="cmd /c Z:\psexec \\%COMPUTERNAME% /accepteula -s -n 120 " _
    & cmd /c c:\temp\SCRIPT1.bat " & strUserID & ">>" & strRemoteLog
Call errProcess

psexec 完成后,您可能希望保存结果。所以你重命名日志文件,上传它,取消映射你的驱动器,并清理残留文件:

strCommand="cmd /c REN " & strRemoteLog & " SCRIPT1-%COMPUTERNAME%.txt"
Call errProcess
strCommand="cmd /c MOVE /Y c:\temp\SCRIPT1*.txt Z:\scripts\LOGS\"
Call errProcess
strCommand="cmd /c net use * /del /Y"
Call errProcess
strCommand="cmd /c del c:\temp\SCRIPT1*.bat /q"
Call errProcess

你完成了。您已成功映射驱动器、针对远程主机运行例程脚本并上传其输出。

请注意,此方法也适用于带有 UAC 的 Windows 7 和 Windows 2008。

这是完整的“示例”集成脚本。随时提出修复、改进等建议。

On Error Resume Next

 MyShare="\\SHARE1"
 strRemoteLog="c:\temp\MapZ.txt"

' Set remote hostname
strComputer="HOST2"
'strComputer = InputBox("Enter Computer name", _
'"Find PC", strComputer)

' Set remote userid
strUserID="USERID1"
'strComputer = InputBox("Enter userid", _
'"Find User", strComputer)

' Enumerate cimv2 on remote host strComputer
Set objWMIService = GetObject("winmgmts:" & _
"{impersonationLevel=Impersonate}!//" & strComputer & "\root\cimv2")

' Verify remote host exists on domain
If( IsEmpty( objWMIService ) = True ) Then
    WScript.Echo( "OBJECT_NOT_INITIALIZED :: " & strComputer )
    WScript.Quit( OBJECT_NOT_INITIALIZED )
End If

' Prompt for masked password
strPassword=GetPass

' Build and run command to execute on strComputer
strCommand = "cmd /c net use z: " & MyShare & " /user:%USERDOMAIN%\%USERNAME% " & strPassword & ">" & strRemoteLog
Set objProcess = objWMIService.Get("Win32_Process")
Call errProcess

' Copy script(s) from MyShare to HOST2 since psexec cannot run scripts on shared drives
strCommand="cmd /c xcopy Z:\scripts\cleanpclocal.bat c:\temp\ /V /C /I /Q /H /R /Y>>" & strRemoteLog
Call errProcess

' Change directory to c:\temp
'strCommand="cmd /c cd c:\temp>" & strRemoteLog
'Call errProcess

' Start PSEXEC against script
strCommand="cmd /c Z:\psexec \\%COMPUTERNAME% /accepteula -s -n 120 cmd /c c:\temp\cleanpclocal.bat " & strUserID & ">>" & strRemoteLog
Call errProcess

' Rename logfile to include hostname, upload to share,  unmap networked drive, and delete script
strCommand="cmd /c REN " & strRemoteLog & " cleanpc-%COMPUTERNAME%.txt"
Call errProcess
strCommand="cmd /c MOVE /Y c:\temp\clean*.txt Z:\scripts\LOGS\"
Call errProcess
strCommand="cmd /c net use * /del /Y"
Call errProcess
strCommand="cmd /c del c:\temp\clean*.bat /q"
Call errProcess

WScript.Quit





' ***********
' APPENDIX
' Subroutines, functions
' ***********

' **SUBROUTINES**
'strCommand="cmd /c dir z:\scripts\>" & strRemoteLog ' Works to get dir of z:\scripts\

' Function to handle errReturn
Sub errProcess
WScript.Echo "strCommand=" & strCommand
errReturn = objProcess.Create(strCommand, null, null, intProcessID)

If errReturn = 0 Then
    Wscript.Echo "Process was started with a process ID: " & intProcessID
    WScript.Sleep 5000
Else
    Wscript.Echo "Process could not be started due to error: " & errReturn
End If
WScript.Echo

' Error return codes for Create method of the Win32_Process Class
' http://msdn.microsoft.com/en-us/library/windows/desktop/aa389388(v=vs.85).aspx
' 0=Successful Completion
' 2=Access Denied
' 3=Insufficient Privilege
' 8=Unknown failure
' 9=Path Not Found
' 21=Invalid Parameter

End Sub



' **FUNCTIONS**

' Subroutine to get masked password
Function GetPass
' Mask Passwords Using Internet Explorer
' Ensure you follow the technet.com instructions and create file password.htm
' http://blogs.technet.com/b/heyscriptingguy/archive/2005/02/04/how-can-i-mask-passwords-using-an-inputbox.aspx

Set objExplorer = WScript.CreateObject _
    ("InternetExplorer.Application", "IE_")

objExplorer.Navigate "file:///C:\SCRIPTS\password.htm"   
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Width = 400
objExplorer.Height = 350 
objExplorer.Left = 300
objExplorer.Top = 200
objExplorer.Visible = 1             

Do While (objExplorer.Document.Body.All.OKClicked.Value = "")
    Wscript.Sleep 250                 
Loop 

strPassword = objExplorer.Document.Body.All.UserPassword.Value
strButton = objExplorer.Document.Body.All.OKClicked.Value
objExplorer.Quit
Wscript.Sleep 250

If strButton = "Cancelled" Then
    Wscript.Quit
'Else
'    Wscript.Echo strPassword
End If

' Return the password
GetPass = strPassword

End Function
于 2012-08-14T07:59:50.693 回答
1

首先,我认为您编写的代码中有一个错字:

errResults  = objFolder.Copy("f:\temp\test1.txt")

我想你的意思是:

errResults  = objFiles.Copy("f:\temp\test1.txt")

其次,我不知道您尝试做的事情是否可行。我认为您拥有的代码可能会将文件从远程计算机上的目录复制到远程计算机上的另一个目录。

但是,对于一种解决方案,如果 WMI 在所有计算机上都可以远程使用,则意味着至少有一个端口是打开的。如果是这种情况,是否还有其他开放的端口?如果是这样,也许您可​​以在您的管理主机上的端口 X 上设置一个 FTP 服务器,然后让其他主机通过自动化默认的 XP FTP 客户端来发送文件。

于 2012-08-02T13:56:40.700 回答
1

我知道这个问题很老,但是当我试图找到一个解决方案时,我发现它会引导人们找到我在这里写下并发布的答案:

.NET - 通过 LAN 将可执行文件复制到另一台计算机并执行它

简而言之,可以使用 WMI 回显任何文件(包括 exe)的 base64 转换,然后使用 certutil 对其进行解码。

于 2017-10-24T12:44:56.167 回答
-1

您是否尝试过以下操作?

set fso = CreateObject("Scripting.FileSystemObject")
fso.CopyFile "f:\temp\test1.txt", "\\HOST1\C$\temp\test1.txt", true
于 2012-08-02T15:14:11.700 回答
-3

WMI 是一个信息数据库。您不能使用它来复制文件。

于 2012-08-02T21:54:08.777 回答