2011-11-04 4 views
1

나는 정말로 문제에 매달렸고 그래서 나는 두 번째 의견 (들)을 얻을 것이라고 생각했다.VbScript, 사용자 입력없이 원격으로 exe를 설치 하시겠습니까?

클라이언트 컴퓨터에 .exe 및 .msi를 원격으로 설치하려고합니다. 파일을 다운로드하고 파일을 실행하는 vb 스크립트가 있지만 몇 가지 문제점이 있습니다. 첫째, 로컬 관리자 계정으로 실행하는 데 문제가 있습니다. 테스트 목적으로 나는 관리자로서 그것을 실행하고 잘 작동하지만 클라이언트 컴퓨터에 설치하면 로컬 관리자에게 액세스해야합니다.

둘째, 중요한 것은 exe 파일을 설치하기 전에 사용자 입력이 어느 정도 필요합니다. 나는 침묵하는 msi 설치가 가능하다는 것을 알고 있지만, 침묵하는 exe는 불가능하다고 생각합니까?

해결책으로 PsExec을 살펴 보았지만 여기에 뭔가 빠져있는 것처럼 느껴집니다. 코멘트에 제안으로

Dim TApp 
Dim IEObj 
Dim tArea 
Dim tButton 

Const HIDDEN_WINDOW = 12 
Const SHOW_WINDOW=1 

'Array of Patch files to install. 
Dim InstallFiles() 

'maximum of 100 workstations to install patches to. 
Dim wsNames(100) 
Dim numComputers 
Dim retVal 
Dim PatchFolder 
'Create explorer window 
Set IEObj=CreateObject("InternetExplorer.Application") 
IEObj.Navigate "about:blank" 
IEObj.Height=400 
IEObj.Width=500 
IEObj.MenuBar=False 
IEObj.StatusBar=False 
IEObj.ToolBar=0 
set outputWin=IEObj.Document 
outputWin.Writeln "<title>RemotePatchInstall version 1.0</title>" 
outputWin.writeln "<HTA:APPLICATION ID='objPatchomatic' APPLICATIONNAME='Patchomatic' SCROLL='no' SINGLEINSTANCE='yes' WINDOWSTATE='normal'>" 

outputWin.writeln "<BODY bgcolor=ButtonFace ScrollBar='No'>" 
outputWin.writeln "<TABLE cellSpacing=1 cellPadding=1 width='75pt' border=1>" 
outputWin.writeln "<TBODY>" 

outputWin.writeln "<TR>" 
outputWin.writeln "<TD>" 
outputWin.writeln "<P align=center><TEXTAREA name=Information rows=6 cols=57 style='WIDTH: 412px; HEIGHT: 284px'></TEXTAREA></P></TD></TR>" 
outputWin.writeln "<TR>" 
' outputWin.writeln "<TD><P align=center><INPUT id=button1 style='WIDTH: 112px; HEIGHT: 24px' type=button size=38 value='Install Patches' name=button1></P></TD>" 
outputWin.writeln "</TR>" 
outputWin.writeln "<TR>" 
outputWin.writeln "<TD></TD></TR></TBODY></TABLE>" 
outputWin.writeln "</BODY>" 

IEObj.Visible=True 
'Get the Information textarea object from the window 
set tempObj=outputWin.getElementsByName("Information") 
objFound=false 
'loop through its object to find what we need 
For each objN in tempObj 
if objN.name="Information" then 
objFound=true 
set tArea=objN 
end if 
next 
'if we didnt find the object theres a problem 
if ObjFound=False then 
'so show an error and bail 
MsgBox "Unable to access the TextBox on IE Window",32,"Error" 
WScript.Quit 
end if 



'************************* 
'ADMINS: The below is all you should really have to change. 
'************************* 

'Change this to the location of the patches that will be installed. 
'they should be limited to the amout you try to install at one time. 
'ALSO the order they are installed is how explorer would list them by alphabetically. 
'So given file names: 
'patch1.exe 
'patch2.exe 
'patch11.exe 
'installation order would be patch1.exe,patch11.exe, patch2.exe 

PatchFolder="C:\IUware Online\Install\" 

'Change this to location where the patches will be copied to on remote cp. This directory must exist on remote computer. 
'I have it hidden on all workstations. 
RemotePatchFolder="C:\Users\jorblume\Backup\" 

'Workstation names to refer to as array 
wsNames(1)="129.79.205.153" 
'wsNames(2)="192.168.0.11" 

'number of remote computers 
numComputers=1 
'********************** 
'ADMINS: The above is all you should really have to change. 
'********************** 

'Copy files to remote computers. 

'Get a list of the executable file in the folder and put them into the InstallFiles array 
'on return, retVal will be number of files found. 
retVal=GetPatchFileList (PatchFolder,InstallFiles) 

'for each file copy to remote computers 
For cc=1 to numComputers 'for each computer 
For i = 1 to retVal 'for each file 
Dim copySuccess 
Dim SharedDriveFolder 
'do a replacement on the : to $, this means you must have admin priv 
'this is because i want to copy to "\\remotecpname\c$\PathName" 
SharedDriveFolder=replace(RemotePatchFolder,":","$") 
'copy it from the PatchFolder to the path on destination computer 
'USE: RemoteCopyFile (SourceFilePath,DestinationFilePath, RemoteComputerName) 
CurrentCP=cc 
copySuccess=RemoteCopyFile(PatchFolder & "\" & InstallFiles(i),SharedDriveFolder,wsNames(CurrentCP)) 
if copySuccess=true then 
tArea.Value=tArea.Value & PatchFolder & "\" & InstallFiles(i) & " copy - OK" & vbcrlf 
else 
tArea.Value=tArea.Value & PatchFolder & "\" & InstallFiles(i) & " copy - FAILED" & vbcrlf 
end if 
Next 
Next 


'Install the files on remote computer 

'go through each filename and start that process on remote PC. 
'for each file install them on the computers. 
For cc=1 to numComputers 

'if theres more than one patch 
if retVal>1 then 
For i=1 to retVal-1 
CurrentCp=cc 

'Now create a process on remote computer 
'USE: CreateProcessandwait(ComputerName, ExecutablePathonRemoteComputer 
'Create a process on the remote computer and waits. Now this can return a program terminated which is ok, 
'if it returns cancelled it means the process was stopped, this could happen if the update required a 
'computer restart. 

CreateProcessandWait wsNames(CurrentCP), RemotePatchFolder & InstallFiles(i) & " /quiet /norestart", tArea 

next 
end if 

'do the last patch with a forcereboot 
CreateProcessandWait wsNames(CurrentCP), RemotePatchFolder & InstallFiles(retVal) & " /quiet" & " /forcereboot" , tArea 

next 

tArea.value=tArea.Value & "Script Complete!" & vbcrlf 


'**************************** FUNCTIONS 

'Get list of files in Folder. 

Function GetPatchFileList(FileFolder, FileStringArray()) 

'create file system object 
Set objFS=CreateObject("Scripting.FileSystemObject") 
'set the a variable to point to our folder with the patches in it. 
Set objFolder=objFS.GetFolder(FileFolder) 
'set the initial file count to 0 
numPatches=0 

for each objFile in objFolder.Files 
if UCase(Right(objFile.Name,4))=".EXE" then 
numPatches=numPatches+1 

redim preserve FileStringArray(numPatches) 
FileStringArray(numPatches)=objFile.Name 
end if 

next 
GetPatchFileList=numPatches 
End Function 

'Copy files to remote computer. 

Function RemoteCopyFile(SrcFileName,DstFileName,DestinationComputer) 
Dim lRetVal 
'create file system object 
Set objFS=CreateObject("Scripting.FileSystemObject") 

lRetVal=objFS.CopyFile (SrcFileName, "\\" & DestinationComputer & "\" & DstFileName) 
if lRetVal=0 then 
RemoteCopyFile=True 
else 
RemoteCopyFile=False 
end if 
End Function 


'Create process on remote computer and wait for it to complete. 

Function CreateProcessAndWait(DestinationComputer,ExecutableFullPath,OutPutText) 
Dim lretVal 

strComputer= DestinationComputer 
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2:Win32_Process") 
Set objWMIServiceStart= GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2:Win32_ProcessStartup") 

Set objConfig = objWMIServiceStart.SpawnInstance_ 

objConfig.ShowWindow = 1 'show window or use HIDDEN_WINDOW 



lretVal= objWMIService.Create(ExecutableFullPath, null, objConfig, intProcessID) 
if lretVal=0 then 
OutPutText.Value = OutPutText.Value & "Process created with ID of " & intProcessID & " on " & DestinationComputer & vbcrlf 
OutPutText.Value = OutPutText.Value & " Waiting for process " & intProcessID & " to complete." & vbcrlf 

WaitForPID strComputer, intProcessID,OutPutText 
OutPutText.Value = OutPutText.Value & "Process complete." & vbcrlf 
else 
OutPutText.Value = OutPutText.Value & "Unable to start process " & ExecutableFullPath & " on " & DestinationComputer & vbcrlf 
end if 
End Function 


'Wait for PRocess to complete 

Function WaitForPID(ComputerName,PIDNUMBER,OutPutText) 
Dim ProcessNumber 

Set objWMIServiceQ = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & ComputerName & "\root\cimv2") 
Set colItems = objWMIServiceQ.ExecQuery("Select * from Win32_Process",,48) 
For Each objItem in colItems 
'check if this process is the one we are waiting for 
if objItem.ProcessID=PIDNUMBER then 
OutPutText.Value = OutPutText.Value & "Process Info:" & vbcrlf 
OutPutText.Value = OutPutText.Value & " Description: " & objItem.Description & vbcrlf 
OutPutText.Value = OutPutText.Value & " ExecutablePath: " & objItem.ExecutablePath & vbcrlf 
OutPutText.Value = OutPutText.Value & " Name: " & objItem.Name & vbcrlf 
OutPutText.Value = OutPutText.Value & " Status: " & objItem.Status & vbcrlf 
OutPutText.Value = OutPutText.Value & " ThreadCount: " & objItem.ThreadCount & vbcrlf 
ProcessNumber=objItem.ProcessID 
end if 

Next 

PidWaitSQL="SELECT TargetInstance.ProcessID " & " FROM __InstanceDeletionEvent WITHIN 4 " _ 
& "WHERE TargetInstance ISA 'Win32_Process' AND " _ 
& "TargetInstance.ProcessID= '" & ProcessNumber & "'" 

Set Events = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & ComputerName & "\root\cimv2").ExecNotificationQuery (PidWaitSQL) 



Set TerminationEvent = Events.nextevent 
OutPutText.Value = OutPutText.Value & "Program " & TerminationEvent.TargetInstance.ProcessID & _ 
" terminated. " & vbcrlf 
set TerminationEvent=Nothing 
exit function 

End Function 
+0

나는 이것을 위해 psexec을 사용할 필요가 있다고 생각한다. – HK1

+2

많은 exe 기반 설치 프로그램이 자동으로 실행될 수 있지만 올바른 명령 줄 매개 변수를 알아야합니다. 예를 들어 대부분의 MS 소프트웨어 업데이트는/passive/norestart를 지정하여 자동으로 설치할 수 있습니다. –

+0

디자인 목표에 따라 psexec을 사용하는 대신 코드를 시작 스크립트 또는 시스템 서비스로 실행하는 것이 좋습니다. –

답변

2

, psexec에이 시나리오에 대한 최선의 해결책이 될 것입니다 :

는 참고로, 여기 내 비주얼 베이직 스크립트입니다. 다른 사람이 EULA를 수락하기를 기다리는 동안 효과적으로 "응답하지"않도록 구문에서/accepteula를 사용하는 것을 잊지 마십시오. :) 설치시 psexec에 대한 질문이나 문제가 있으면 여기에 의견을 남기십시오.

관련 문제