Run cmd from vbscript silently - windows

I created the following runas.vbs script:
**************
Option explicit
Dim oShell, k
Const PASSWORD = "Pass123~"
set oShell= Wscript.CreateObject("WScript.Shell")
WScript.Sleep 500
oShell.run("RunAs /noprofile /user:%computername%\postgres " & Chr(34) & "cmd /c\" &
Chr(34) & WScript.Arguments(0) & "\" & Chr(34) & Chr(34))
WScript.Sleep 1000
For k=1 To Len(PASSWORD)
WScript.Sleep 200
oShell.SendKeys Mid(PASSWORD,k,1)
Next
Wscript.Quit
**************
I use this vbscript in a Batch file to run initdb.exe (Postgresql).
Used as:
cscript //Nologo //B runasNSPostgres.vbs ""%LG_PATH%\initdb.exe" --locale=C --encoding=UTF-8 -U %DBADMIN% -D "%DBDATA%""
When this command is executed, another command prompt screen opens up which starts the initdb processing. I do not want the new cmd prompt screen to show up. I want the initdb.exe to run in the background.

If you hide the command prompt window, you won't be able to use SendKeys to send it your password keystrokes.
You can use another method, though. Try using the ECHO command and pipe its output to RunAs.
oShell.Run "echo " & PASSWORD & " | runas /noprofile ...", 0
Use a 0 as the 2nd parameter to prevent the window from appearing.

Related

VBScript not running from windows service

I have a Windows service which calls a bat file. That bat file calls a PowerShell script, and inside that PowerShell script a VBScript is called.
Windows Service > bat file > powershell file > vbscript
When I manually run the bat file, the VBscript is successfully executed, but if I execute the same bat file from the Windows service, then all scripts are called, but the VBScript skips to run.
Executing a bat file manually successfully executes the VBScript, but not via Windows service
I tried to call The VBScript inside PowerShell in different ways:
& c:\windows\system32\cscript.exe NameOfFile.vbs
start-process
invoke-expression
C:\Windows\System32\cscript.exe NameOfFiles.vbs //B //Nologo $IP_SU $RemoteSessions_Output $user
My VBScript is:
dim ip
dim sessions_dir
dim temp
dim username
dim password
set temp = Wscript.Arguments
ip = temp(0)
sessions_dir = temp(1)
username = temp(2)
password = temp(3)
Sub WaitEnter()
WshShell.AppActivate("telnet " & ip )
WScript.Sleep 2000
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys "{Enter}"
WshShell.AppActivate("telnet " & ip)
WScript.Sleep 2000
End Sub
set WshShell = WScript.CreateObject("WScript.Shell")
Wscript.Sleep 1000
WshShell.AppActivate("telnet " & ip )
WshShell.Run "telnet " & ip & " -f " & sessions_dir & "\" & ip & "_SU_Status_Output.txt",2
WshShell.AppActivate("telnet " & ip)
WScript.Sleep 1000
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys username
WaitEnter
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys password
WaitEnter
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys "SU_INrOmk=` pl | awk '{{}print {$}3{}}' | head -3 | cut -d '=' -f2`; SU_type=` pl | grep $SU_INrOmk | tail -1 | awk '{{}print {$}12{}}'`"
WaitEnter
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys "echo $SU_type"
WaitEnter
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys "exit"
WshShell.AppActivate("telnet " & ip)
WshShell.SendKeys "{Enter}"
and PowerShell script from where it is called is like:
if(Test-Path C:\Windows\System32\cscript.exe){
echo "Cscript found"
$command = "& C:\Windows\System32\cscript.exe NameOfFile.vbs $IP_SU $RemoteSessions_Output $user $DecPwd | out-null"
Invoke-Expression -Command $Command
start-Sleep 10
if($?){
start-sleep 10
$SU_Output_File = $IP_SU + "_SU_Status_Output.txt"
$SU_Remote_FilePath = $RemoteSessions_Output + "\" + $SU_Output_File
}
}
i expect that VBScript is called when Windows service calls the bat file.
I see several things that could be causing issues for you here.
I'm no master of VBS, but my guess here is that you are using Wscript which requires interactivity I think, but you should be using Cscript variant calls instead. My guess is that your script may be bombing due to this. Services can not run in an interactive context since Vista/Windows Server 2008.
You are calling this with Invoke-Expression, which (almost) always returns successful even if the cmdlet failed. In other words, Invoke-Expression will (almost) always set $? to $True even if the command failed. However, you can slip in an evaluation of ; $? at the end of your expression which will end up setting $? as you would expect, which breaks the notion of "always sets $? to $True".
However, you are also using $? incorrectly as well. $? only evaluates the success of cmdlets, not commands. cscript.exe is an executable, and must have its success evaluated with the $LASTEXITCODE automatic variable instead. This will be typically be 0 for success and any other value for non-success. You will have to check the success of this $LASTEXITCODE yourself, as even when the ErrorActionPreference is set to Stop, it won't automatically treat non-zero exit codes as terminating errors.
Outside of the scope of this answer, but worth a mention, I would recommend replacing Invoke-Expression with a straight call to the executable and splat your parameters instead.

How to launch System File Checker tool with vbs

In batch or cmd, sfc.exe run with a simple command:
%windir%\system32\SFC.exe /SCANNOW
How to run this command with .vbs script (x86 x64)??
Thanks
You can do something like this, just give a try !
Option Explicit
' Run as Admin
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
, WScript.ScriptFullName & " /elevate", "", "runas", 1
WScript.Quit
End If
Dim ws,MyCommand,Execution
Set ws = createobject("wscript.shell")
MyCommand = "SFC /SCANNOW"
Execution = ws.run(MyCommand,1,False)

capture command line output in vbscript

Got a simple script that executes a command to a server - briefly:
//Create shell
set WshShell=CreateObject("WScript.Shell")
WshShell.run "cmd.exe"
//send commands
WshShell.SendKeys "telnet IP_ADDRESS"
WshShell.Sendkeys "dir"
Server offers feedback which I want to capture. I just need to capture the first line into a variable, and then just print that variable out to confirm.
Can you help? Thanks.
Do not use the Windows telnet client for automation purposes. The telnet client that ships with Windows was made for interactive use only.
I'd use plink (from the PuTTY suite) in batch mode for this:
plink.exe -telnet -batch IP_ADDRESS dir
The tool doesn't require installation, so you can simply deploy it alongside your script.
Run it either in a batch file using head/tail, or in a VBScript using the Exec method, so you can read from StdOut:
addr = "62.39.x.x"
port = 24
timeout = 300 'seconds
timedOut = False
cmdline = "echo ""mute near get"" | plink.exe -telnet -batch " & addr & " -P " & port
Set sh = CreateObject("WScript.Shell")
'change working directory to directory containing script and plink executable
Set fso = CreateObject("Scripting.FileSystemObject")
sh.CurrentDirectory = fso.GetParentFolderName(WScript.ScriptFullName)
'wait until command completes or timeout expires
expiration = DateAdd("s", timeout, Now)
Set cmd = sh.Exec("%COMSPEC% /c " & cmdline)
Do While cmd.Status = 0 And Now < expiration
WScript.Sleep 100
Loop
If cmd.Status = 0 Then
cmd.Terminate
timedOut = True
End If
WScript.Echo cmd.StdOut.ReadAll
If cmd.ExitCode <> 0 Then
WScript.Echo "Command terminated with exit code " & cmd.ExitCode & "."
WScript.Echo cmd.StdErr.ReadAll
WScript.Quit 1
ElseIf timedOut Then
WScript.Echo "Command timed out."
WScript.Echo cmd.StdErr.ReadAll
WScript.Quit 2
End If
It might not be the best method, but worked for me:
Windows telnet command can save the output in client side using -f arguments. Therefore, you could use:
WshShell.SendKeys "telnet -f D:\output\telnet.out IP_ADDRESS"
and at the end of your script, simply process the content of telnet.out

VBscript and CMD writing into a text file

I am writing a script that executes and write everything to the file
here is example,
I stored the complete command in the variable 'Command' ,
Command = "ftp ftp.xyz.com 21 " & vbCRLF
and then executing it in command prompt,
shell.Run "%comspec% /c FTP " & Command & " > " & E:/abc.txt, 0, TRUE
but when this program execute it won't write anything to the text file because this is an incomplete command, this command on execution prompt user to input username and password of FTP,
how can i do this , that my programm automatically input username and password when prompt and then write everything to file ?
You need to run FTP using an unattended script. (Try ftp /? and look at the -s switch.)
It looks like this:
Const HOSTNAME = "ftp.myserver.com"
Const USERNAME = "Login"
Const PASSWORD = "password"
Set WshShell = CreateObject("WScript.Shell")
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFile = objFso.CreateTextFile("session.txt")
With objFile
.WriteLine "USER username"
.WriteLine "password"
.WriteLine "cd /public_html/" ' continue adding commands like this
.Close
End With
strOutput = "C:\somefilepath\output.txt"
strCommand = "%systemroot%\System32\ftp.exe -s:session.txt > " & strOutput
strCommand = WshShell.ExpandEnvironmentStrings(strCommand)
WshShell.Run strCommand, 0, vbTrue
objFso.DeleteFile "session.txt", vbTrue
You can read more in my article Using FTP in WSH on ASP Free. I also answered a related question here.

Psexec not outputting to log file in VB script

I have a VB script which needs to run psexec to launch an app called md5 on a remote server. Md5 generates a hash key of a file and takes one parameter - the file path\name. I need to retrieve the has key that is generated to store in a variable. Below is the code I am using:
Set objShell = CreateObject("Wscript.Shell")
strcomputer = "remotecomputer"
tempDest = "C:\somedir"
filename = "somefile"
strCommand = "psexec -accepteula \\" & strcomputer & " -c md5.exe " & tempDest & "\" & filename & " > log.txt"
Set objExecObject = objShell.Exec("%comspec% /c " & strCommand)
Do While objExecObject.Status <> 1 'loop until previous process has finished
WScript.Sleep 100
Loop
The MD5 command is run however nothing is written to the log file. When I copy and paste strCommand (substituting all the variables for the actual data) into a cmd prompt and run it, it successfully writes the output of Md5 to the log file.
At the end of the day I just need the output of Md5, if anyone knows a better way than writing it to a log file please let me know. I have already tried using objExecObject.StdOut.Readall() to try and catch the output which resulted in random failures - sometimes it would catch the output, sometimes it wouldn't, without changing anything in the script.
Just a guess: Are you sure about what the current directory is when the script is running? Try giving an absolute path to the log file and see if it helps.
I found a solution for this. Instead of using the following code:
strCommand = "psexec -accepteula \\" & strcomputer & " -c md5.exe " & tempDest & "\" & filename & " > log.txt"
Set objExecObject = objShell.Exec("%comspec% /c " & strCommand)
Do While objExecObject.Status <> 1 'loop until previous process has finished
WScript.Sleep 100
Loop
I used this instead:
strCommand = "psexec -accepteula \\" & strcomputer & " -c md5.exe " & tempDest & "\" & filename & " > log.txt"
objShell.Run "%comspec% /c " & strCommand, 0, true
The script is now redirecting to log.txt properly.

Resources