VbScript,无需用户输入即可远程安装exe?
我真的陷入了一个问题,所以我想我会得到第二个意见。
我正在尝试将 .exe 和 .msi 远程安装到客户端计算机。我有一个 vb 脚本来下载该文件并运行该文件,但存在一些问题。首先,我无法在本地管理员帐户上运行它。出于测试目的,我以管理员身份运行它并且工作正常,但如果放在客户端计算机上,则需要访问本地管理员。
其次,更重要的是,微软在安装 exe 文件之前需要一定量的用户输入。我知道静默 msi 安装是可能的,但我认为静默 exe 是不可能的?
作为一个解决方案,我正在研究 PsExec,但我觉得我在这里遗漏了一些东西。
作为参考,这是我的 vb 脚本:
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
I'm really stuck on a problem so I figured I would get a second opinion(s).
I'm trying to remotely install .exe and .msi to client computers. I have a vb script that downloads the file and runs the file, but there's a few problems. First, I'm having trouble getting it to the run on the local admin account. For testing purposes I'm running it as an Admin and it works fine, but if put on a client computer it would need access to the local Admin.
Secondly, and more importantly, microsoft requires some amount of user input before installing an exe file. I know silent msi install is possible, but I assume silent exe is impossible?
As a solution I'm looking into PsExec, but I feel like I'm missing something here.
For reference, here is my vb script:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
正如评论中所建议的, psexec 将是这种情况下的最佳解决方案。只是不要忘记在其语法中使用 /accepteula 以确保它在等待某人接受其 EULA 时不会有效地“挂起”。 :) 如果您对安装中的 psexec 有疑问或问题,请在此处发表评论。
As suggested in the comments, psexec will be your best solution for this scenario. Just don't forget to use /accepteula in its syntax to ensure it doesn't effectively "hang" while waiting for someone to accept its EULA. :) If you have questions or issues with psexec in your installs, comment back here.