4

私はVBScriptが初めてです。VBS で WMI を使用して、ある XP ホストから別の XP ホストにファイルをコピーする方法が見つかりません。ファイルをコピーする通常の方法 (RPC - リモート プロシージャ コール、SMB、UNC) はいくつかのホストでは使用できませんが、WMI はすべてのホストで使用でき、管理ホストからターゲットの Windows ホストにファイルをコピーする必要があります。サンプルコードがいくつかあると思っていましたが、それに関する情報は見つかりませんでした。それができないと言っているものも見つかりませんでした。

ソース ファイルは、実行可能ファイルであり、管理コンピューターの「F:\TEMP」フォルダーにある「test1.txt」です。ファイルをリモート ホスト HOST1 の「C:\TEMP」フォルダに配置したいと考えています。私は両方のホストで完全な管理者権限を持っています。これまでのところ、1つのファイルだけです(テストを簡単にするため):

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シャープのFrank Whiteのコードで、その後に彼の例が続きます: https://stackoverflow.com/a/8913231/1569434

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

次のすべてのスクリプトレットを使用するには、次の 4 つのものが必要です。これらのスクリプトレットは相互に構築され、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 がすべてのコンピューターでリモートで使用できる場合、それは少なくとも 1 つのポートが開いていることを意味します。その場合、開いている他のポートはありますか? その場合、管理ホストのポート X に FTP サーバーをセットアップし、デフォルトの XP FTP クライアントを自動化して、他のホストにファイルを送信させることができます。

于 2012-08-02T13:56:40.700 に答える
-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 に答える