By Lizz

2012-08-01 23:43:10 8 Comments

I'm new to VBScript. I cannot find a way to copy files from one XP host to another using WMI in a VBS. The usual way of copying files (RPC - Remote Procedure Call, SMB, UNC) are not available to several hosts but WMI is available to all hosts, and I need to copy files from my admin host to a target Windows host. I thought I'd find some sample code out there but I've found no info on it. Haven't found anything telling me it can't be done, either.

The source files are an executable and 'test1.txt' in my admin computer's 'F:\TEMP' folder. I want to put the files on remote host HOST1's 'C:\TEMP' folder. I have full admin rights on both hosts. Here is what I have so far, just for one file (to keep the testing simple):

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


@Robert MacMillan 2017-10-24 12:44:56

I know this question is old, but came across is when I was trying to find a solution so figured would direct people to an answer I wrote up and posted here:

.NET - Copying an executable across LAN to another computer, and executing it

In short, it is possible to echo base64 conversion of any file (including an exe) using WMI and then decode it with certutil.

@Lizz 2012-08-14 07:59:50

I learned that WMI cannot create files on a remote host, and it cannot copy files over a network connection:

However, it can run a cmd process. Here's Frank White's code in C sharp, followed by his example:

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

You will need four things to use all the following scriptlets, which build on each other to use psexec to run a "normal" VBScript or batch script on the remote host:

  1. admin rights on the remote host;
  2. WMI enabled on the remote host
  3. a network share (using RPC, UNC, FTP, etc., but NOT DFS! ("Distributed File System" - see note) that your remote host can access; and
  4. psexec.exe and your "normal" script(s) on the network share.

Important Note: Do NOT use DFS to map the network share! It will fail if you use Distributed File System for your network share. An error code you might get depending on how you try is "System error 1312", no matter which operating system (e.g., XP, Win 7) you use.

When RPC is not available on a remote host but WMI is, then the following method will create a local ASCII file on the remote host's c:\temp folder, containing the text "myTextCommands", without the quotes.

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

Notice the important limitation in the script above: it can only create ASCII files - not binary.

Let's use that technique to map a drive letter:

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

where "strRemoteLog" is set to something like "c:\temp\MyLog.txt", "strPassword" is prompted (see full script example and reference at bottom), and "errProcess" is a subroutine that runs the following process using the "cmd /c" trick mentioned above:

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
    Wscript.Echo "Process could not be started due to error: " & errReturn
End If
End Sub

With a network drive mapped, copy your script to the host:

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

SCRIPT1.bat is ready, so start psexec against it on the remote host, passing your script a variable strUserID that would be obtained earlier and is here for example:

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

Once psexec finishes, you might want to save the results. So you rename the log file, upload it, unmap your drive, and clean up residual files:

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

You're done. You've successfully mapped a drive, run a routine script against the remote host, and uploaded its output.

Note this method also works on Windows 7 and Windows 2008 with UAC.

Here's the full 'sample' integrated script. Feel free to suggest fixes, improvements, etc.

On Error Resume Next


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

' Set remote userid
'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 )
End If

' Prompt for masked password

' 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


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

'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
    Wscript.Echo "Process could not be started due to error: " & errReturn
End If

' Error return codes for Create method of the Win32_Process Class
' 0=Successful Completion
' 2=Access Denied
' 3=Insufficient Privilege
' 8=Unknown failure
' 9=Path Not Found
' 21=Invalid Parameter

End Sub


' Subroutine to get masked password
Function GetPass
' Mask Passwords Using Internet Explorer
' Ensure you follow the instructions and create file password.htm

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                 

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

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

' Return the password
GetPass = strPassword

End Function

@Jimmy D 2012-08-28 12:22:34

Awesome writeup!

@Lizz 2012-08-28 17:07:25

you were the inspiration, Frank, so thank you! :)

@Vishal D 2012-08-02 21:54:08

WMI is a database of information. You cannot use it to copy files.

@Jimmy D 2012-08-28 12:22:02

@Vishal D - uhm... you really might want to get some more knowledge before making comments like this.

@peter 2012-08-02 15:14:11

Have you tried the following ?

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

@Lizz 2012-08-21 03:47:39

Nope, since that code can copy to hosts with RPC enabled, which ours don't. Thanks, tho.

@Hans Olsson 2012-08-02 13:56:40

Firstly, I think there's a typo in your code where you've written:

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

I think you meant:

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

Secondly, I don't know if what you're trying to do is possible. I think the code you've got might copy a file from a directory on the remote computer to another directory on the remote computer.

For a solution though, if WMI is available remotely on all the computers, that means that at least one port is open. If that's the case, are there any other ports that are open? If so, maybe you could set up a FTP server on your admin host on port X and then have the other hosts send the file by automating the default XP FTP client.

@Lizz 2012-08-03 09:58:01

Thanks, ho1! Your typo correction is correct. Also, I believe you are correct about WMI not being capable (yet?) of copying files without using some external technology, like FTP, RPC, etc. I'm going to update my script to 1) map to a network share and copy file(s) to that shared folder; 2) connect to the remote PC using WMI; and 3) map to the network share and pull the file down. I'll update this question when ready. I just wish Microsoft would clearly define WMI...

Related Questions

Sponsored Content

14 Answered Questions

[SOLVED] Call a function from another file in Python

18 Answered Questions

[SOLVED] Copy a table from one database to another in Postgres

31 Answered Questions

[SOLVED] Copying files from one directory to another in Java

7 Answered Questions

[SOLVED] Copy files from one directory into an existing directory

2 Answered Questions

[SOLVED] Git: copy all files in a directory from another branch

  • 2010-04-19 15:55:02
  • alexenko
  • 82036 View
  • 177 Score
  • 2 Answer
  • Tags:   git file copy branch

9 Answered Questions

[SOLVED] Copy tables from one database to another in SQL Server

3 Answered Questions

0 Answered Questions

WMI 0x80041013 "Provider load failure"

1 Answered Questions

WMI Get Object Access Denied

1 Answered Questions

[SOLVED] Search and get file information from remote workstation on a Windows domain

  • 2012-04-29 18:12:37
  • Ravi Shankar
  • 754 View
  • 0 Score
  • 1 Answer
  • Tags:   c# wmi

Sponsored Content