Попытка скопировать файл с одного компьютера XP на другой с помощью WMI, поскольку RPC и UNC недоступны

Я новичок в VBScript. Я не могу найти способ скопировать файлы с одного хоста XP на другой, используя WMI в VBS. Обычный способ копирования файлов (RPC - Удаленный вызов процедур, SMB, UNC) недоступен для нескольких хостов, но WMI доступен для всех хостов, и мне нужно скопировать файлы с моего хоста администратора на целевой хост Windows. Я думал, что найду некоторый пример кода там, но я не нашел информации об этом. Я не нашел ничего, что говорило бы, что это не может быть сделано, либо.

Исходные файлы представляют собой исполняемый файл и test1.txt в папке "F:\TEMP" моего компьютера администратора. Я хочу поместить файлы в папку C:\TEMP удаленного хоста HOST1. У меня есть полные права администратора на обоих хостах. Вот что у меня есть, только для одного файла (для простоты тестирования):

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

5 ответов

Решение

Я узнал, что WMI не может создавать файлы на удаленном хосте и не может копировать файлы по сетевому соединению: http://msdn.microsoft.com/en-us/library/windows/desktop/aa389288%28v=vs.85%29.aspx

Однако он может запустить процесс cmd. Вот код Фрэнка Уайта до-диез, сопровождаемый его примером: /questions/4992135/wmi-udalennyij-protsess-dlya-kopirovaniya-fajla/4992146#4992146

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

Вам понадобятся четыре вещи, чтобы использовать все следующие скриптлеты, которые основаны друг на друге, чтобы использовать psexec для запуска "нормального" VBScript или пакетного скрипта на удаленном хосте:

  1. права администратора на удаленном хосте;
  2. WMI включен на удаленном хосте
  3. общий сетевой ресурс (с использованием RPC, UNC, FTP и т. д., но НЕ DFS! ("Распределенная файловая система" - см. примечание), к которому может получить доступ удаленный хост;
  4. psexec.exe и ваши "нормальные" сценарии в сетевой папке.

Важное примечание: НЕ используйте DFS для сопоставления общего сетевого ресурса! Это не удастся, если вы используете распределенную файловую систему для общего сетевого ресурса. Код ошибки, который вы можете получить в зависимости от того, как вы пытаетесь это "Системная ошибка 1312", независимо от того, какую операционную систему (например, XP, Win 7) вы используете.

Если RPC недоступен на удаленном хосте, но есть WMI, то следующий метод создаст локальный файл ASCII в папке c:\temp удаленного хоста, содержащий текст "myTextCommands", без кавычек.

' https://stackru.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

Вы сделали Вы успешно подключили диск, запустили стандартный сценарий для удаленного хоста и загрузили его выходные данные.

Обратите внимание, что этот метод также работает в Windows 7 и Windows 2008 с UAC.

Вот полный "пример" интегрированного скрипта. Не стесняйтесь предлагать исправления, улучшения и т. Д.

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

Во-первых, я думаю, что в вашем коде есть опечатка, в которой вы написали:

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

Я думаю, что вы имели в виду:

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

Во-вторых, я не знаю, возможно ли то, что вы пытаетесь сделать. Я думаю, что полученный код может скопировать файл из каталога на удаленном компьютере в другой каталог на удаленном компьютере.

Однако для решения, если WMI доступен удаленно на всех компьютерах, это означает, что по крайней мере один порт открыт. Если это так, есть ли другие открытые порты? Если это так, возможно, вы могли бы настроить FTP-сервер на хосте администратора через порт X, а затем заставить другие хосты отправлять файл, автоматизируя FTP-клиент по умолчанию для XP.

Я знаю, что этот вопрос старый, но я столкнулся с тем, что когда я пытался найти решение, которое, как я полагал, могло бы направить людей к ответу, который я написал и разместил здесь:

.NET - Копирование исполняемого файла через локальную сеть на другой компьютер и его выполнение

Короче говоря, можно повторить преобразование base64 любого файла (включая exe-файл) с помощью WMI, а затем декодировать его с помощью certutil.

Вы пробовали следующее?

set fso = CreateObject("Scripting.FileSystemObject")
fso.CopyFile "f:\temp\test1.txt", "\\HOST1\C$\temp\test1.txt", true

WMI - это база данных информации. Вы не можете использовать его для копирования файлов.

Другие вопросы по тегам