VBScript - Output command to file - linux

I am using secureCRT to connect to a Linux server. SecureCRT reads VBScript, and I am new to this language so my problem might sound easy for you.
When I connect to the server from secureCRT, I a script containing a command let's say "date" ,the output of the command must come out on a text file on my local host ( windows ) and not on the server.
This is the script that I am using:
# $language = "VBScript"
# $interface = "1.0"
' This script demonstrates how to capture line by line output
' from a command sent to a server. It then saves each line of output
' to a file. This script shows how the 'WaitForStrings' command can be
' used to wait for multiple possible outputs.
' Constants used by OpenTextFile()
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Sub Main
crt.Screen.Synchronous = True
' Create an instance of the scripting filesystem runtime so we can
' manipulate files.
'
Dim fso, file
Set fso = CreateObject("Scripting.FileSystemObject")
' Open a file for writing. The last True parameter causes the file
' to be created if it doesn't exist.
'
Set file = fso.OpenTextFile("C:\Users\elieme\Desktop\TTX1.txt", ForWriting, True)
' Send the initial command then throw out the first linefeed that we
' see by waiting for it.
'
crt.Screen.Send "gsh list_imsins" & Chr(10)
crt.Screen.WaitForString Chr(10)
' Create an array of strings to wait for.
'
Dim waitStrs
waitStrs = Array( Chr(10), "linux$" )
Dim row, screenrow, readline, items
row = 1
Do
While True
' Wait for the linefeed at the end of each line, or the shell prompt
' that indicates we're done.
'
result = crt.Screen.WaitForStrings( waitStrs )
' If we saw the prompt, we're done.
If result = 2 Then
Exit Do
End If
' The result was 1 (we got a linefeed, indicating that we received
' another line of of output). Fetch current row number of the
' cursor and read the first 20 characters from the screen on that row.
'
' This shows how the 'Get' function can be used to read line-oriented
' output from a command, Subtract 1 from the currentRow to since the
' linefeed moved currentRow down by one.
'
screenrow = crt.screen.CurrentRow - 1
readline = crt.Screen.Get(screenrow, 1, screenrow, 45 )
' NOTE: We read 20 characters from the screen 'readline' may contain
' trailing whitespace if the data was less than 20 characters wide.
' Write the line out with an appended '\r\n'
file.Write readline & vbCrLf
Wend
Loop
crt.screen.synchronous = false
End Sub
I read the script several time to understand it, and tried to manipulate it for hours, and asking for help was my last resort.
In the script I have crt.Screen.Send "date" & Chr(10) which will send my command and execute it. Then when I go in the loop, I don't understand what does this mean.
'If we saw the prompt, we're done.
If result = 2 Then
Exit Do
End If
What do they mean by if we saw the prompt? Is it something that i have to input for it to exit ? Because i tried several keys and I'm always stuck in this while loop.
I tried to manipulate the script but every time I was either getting an empty file as output, or wrong data in the file.
Is there anyway to make this script execute only the command that I sent ("date"), and output what this command will do on the text file ?
If not, is there any shortcut to stop the script without having to go in the menu and selecting cancel script?
Thank you
EDIT:
I fixed it guys, very easy.
The rt.Screen.WaitForStrings takes as a second parameter a timeout number, so that fixed everything.
Thanks

Fixed
The rt.Screen.WaitForStrings takes as a second parameter a timeout number, so that fixed everything.

Related

Search txt and csv files for string using Excel VBA without opening files

I have a text file that is automatically generated from a machine. The machine writes the txt file in "chunks" (sorry I don't know the exact terminology). I need to pull data from this txt file, but I need the txt file to be finished before pulling data from it. I found a solution to verify that the machine has finished writing to the file... It is not as elegant as i had hoped, but seems to do the trick. Excel VBA opens a command prompt, the command prompt uses a Find command to find the string "End of Report"... This is basically one of the last lines of the txt file and pretty safe to assume the txt file is finished after this is found. This code runs in a loop 1000 times, every 10 seconds, until it finds this string or reaches 1000 tries...
The issue is that "result" returns some other characters besides just "End of Report" this is further complicated by the fact that I am attempting to run this on some csv files too... and "result" returns some additional characters also, but different from the ones returned from the txt files. For example, if I check the length of "result"... The length comes back as 43 on one file and 48 on another file... I think it is counting the file path + "End of Report" + a few more characters?
Anyways, I don't really need the "result"... I really only need a "true" / "false" if "Find" found "End of Report" or not... How can I accomplish this? Is there a different better way to do this? I am not familiar with command prompt programming.
Note: It is important that I search these files without opening them.
Sub test()
Dim SearchStr As String
Dim cmdLine As Object
Dim result As String
Dim FilePath As String
FilePath = "D:\test2.txt"
SearchStr = """End of Report"""
Set cmdLine = CreateObject("WScript.Shell")
result = cmdLine.Exec("%comspec% /C Find " & SearchStr & " " & Chr(34) & FilePath & Chr(34)).STDOut.ReadAll
Debug.Print (result)
End Sub
I am not really an expert in command line, but what I would do is export the result of the FIND command to a file, like here
Then I would check in your VBA code how many rows are in the file (either clean the file before, or check the number of rows before the export is done).
If the number of rows meets the criteria (probably 2 or more rows instead of 1), then you can set the flag to True.

How to check file lock on .txt file before opening

Long story short... I am using a pc to open a .txt file located on a server... but sometimes the .txt file is not finished (there is still data stored in a buffer of the source computer).
FilePath = "D:\test.txt"
Workbooks.Open(Filename:=FilePath, ReadOnly:=True, IgnoreReadOnlyRecommended:=True)
Someone smarter than I am has identified that the .txt file is "locked" by the operating system until it is finished but I am still able to open it. I would like to wait for the .txt file to be "not locked" before opening it. How do I do this?
Note: The "smarter" person than me explained... the .txt file can be opened by a "dumb" program like "notepad" but if you try to use "Microsoft Word" to open it... you get a message telling you that it is locked...
import time
is_open = False
while not(is_open):
try:
f = open('test.txt','w')
is_open=True
except:
time.sleep(1)
I don't know how well the code below will work for your scenario.
You could change the constants into parameters (if you think their values need to change/be determined dynamically).
You could also change the GetFileOrWait's implementation such that it allows an infinite loop (I chose to avoid this, but maybe you want this).
All in all, the below is basically a function which tries to return the workbook in 120 seconds (or times out with an error) -- which you can hopefully use in a parent subroutine/procedure.
You may be able to specify finer frequencies (seconds may be too coarse) by using Timer instead or other lower level APIs.
Option Explicit
Private Function GetFileOrNothing() As Workbook
Const FILE_PATH As String = "D:\test.txt" ' Could pass this in as argument (if needed).
On Error Resume Next
Set GetFileOrNothing = Workbooks.Open(Filename:=FILE_PATH, ReadOnly:=True, IgnoreReadOnlyRecommended:=True)
On Error GoTo 0
End Function
Private Function GetFileOrWait() As Workbook
' Attempts to open a file. If access fails, waits n seconds before trying again.
' This function raises an error (times out to prevent infinite loop) after N seconds.
Const MAXIMUM_WAIT_IN_SECONDS As Long = 10
Const INTERVAL_WAIT_IN_SECONDS As Long = 1
Dim timeToStopAt As Date
timeToStopAt = DateAdd("s", MAXIMUM_WAIT_IN_SECONDS, Now)
Do While Now < timeToStopAt
Dim outputWorkbook As Workbook
Set outputWorkbook = GetFileOrNothing()
If Not (outputWorkbook Is Nothing) Then Exit Do
Application.Wait DateAdd("s", INTERVAL_WAIT_IN_SECONDS, Now)
DoEvents
Loop
If outputWorkbook Is Nothing Then
Err.Raise vbObjectError + 5, , "Failed to access file within the specified time frame."
End If
Set GetFileOrWait = outputWorkbook
End Function

VBscript and Excel: Opening and closing Excel objects - Arraylist preventing closing of object

I've got a problem with a vbscript which creates Excel objects and reads from an Excel file.
The vbscript is executed from an Excel macro, and then creates and opens the Excel file and reads from it. The problem is that the Excel object isn't allways closed, even though I'm trying to to it.
Here's the code from the vbscript:
Set ExcelObject = createobject("Excel.Application")
ExcelObject.workbooks.open testWorkBookPath
Set testActionArray = CreateObject( "System.Collections.ArrayList" )
Function getTestsCaseActions (testsPath, esheet, row, col)
Set my_sheet = ExcelObject.sheets.item(esheet)
tempArray = array(my_sheet.cells(row, col-2), "")
testActionArray.Add tempArray
Do While my_sheet.cells(row, col).Value <> ""
tempArray = array(my_sheet.cells(row, col), my_sheet.cells(row+1, col))
testActionArray.Add tempArray
col = col+1
Loop
End Function
getTestsCaseActions testWorkBookPath, testCaseSheet, 3, 4
ExcelObject.Quit
Now, if I run the above code and watch the process explorer, a new Excel process is spawned when the script is started, and then closes, as expected.
However, if I insert this code after running the function, before the ExcelObject.Quit line:
For Each ArrayItem in testActionArray
IF ArrayItem(1) = "" Then
Wscript.Echo ArrayItem(0)
Else
Wscript.Echo ArrayItem(0) & " -> " & ArrayItem(1)
End If
Next
ExcelObject.Quit (STILL HERE)
then the spawned process does NOT quit, and the process list grows until Excel goes completely bananas.
I don't understand this; All the last bit of code does is loop through the ArrayList and print the contents. Why's not the process quitting?
EDIT: At seems that at least some of the Excel objects eventually disappear from the Process Explorer, but this takes about 20-30 minutes. And it's just a few of them - most are still there. At least my list at the moment has shrinked some, but there are still about 15 Excel processes running.
Also, suddenly this message appears:
File Now Available
'filename.xlsm ' is now available for editing. Choose Read-Write to open it for editing.
This line seems to help. It doesn't completely remove all extra processes, but the number grows to five, then goes back to two, and so on. So it works pretty well.
dim book: for each book in ExcelObject.Workbooks: book.saved = true: next

Reading each line of a text file into VB

I'm looking to automate some work that I currently have to carry out.
I currently receive a number of machine names that I have to query in unix from config files, but I have to amend the list I receive each day to produce the command. I'm looking for a way to automate this, so I can store the names in a text file and run a script in vb that will automatically produce the command I need to run in unix.
e.g the text file (machines.text) may contain the following:
ABCDE1234
ADEFR1234
BCDFREWE1
each line will be the machine name, but i require this to be changed to lower case and get the following commands output:
grep -i abcdef1234 */*.cfg
grep -i adefr1234 */*.cfg
grep -i bcdfrewe1 */*.cfg
I sometimes get hundreds a day, so looking to shorten the processes as I can just use the original file i receive and not have to manually go through it.
Any suggestions will be much appreciated, even if anyone has any alternatives to VB and excel.
Thanks
you could open the list in Excel, so that all the data to be manipulated goes into Column A, then use formulas as below to create your UNIX commands in Columns B, C, D:
FIRST Command:
="grep -i " &LOWER(LEFT(A:A,FIND(" ",A:A))) & " */*.cfg"
SECOND Command:
="grep -i "&LOWER(LEFT(TRIM(MID(A:A,FIND(" ",A:A),LEN(A:A))),FIND(" ",TRIM(MID(A:A,FIND(" ",A:A),LEN(A:A))))))&" */*.cfg"
THIRD Command:
="grep -i "&LOWER(MID(RIGHT(A:A,LEN(A:A)-FIND(" ",A:A)),FIND(" ",RIGHT(A:A,LEN(A:A)-FIND(" ",A:A))),LEN(RIGHT(A:A,LEN(A:A)-FIND(" ",A:A)))))&" */*.cfg"
Once you have got all your texdt to be manipulated in Column A, copy down the formulas in columns B,C,D
then you could run the below code (may need tweaking) to create your output:
Sub getCommands()
Dim oFso As New Scripting.FileSystemObject
Dim oWriteFile As TextStream
Dim oRange As Range
Set oWriteFile = oFso.CreateTextFile("C:\Commands.txt", True)
Set oRange = Range("B2")
Do Until oRange.Text = ""
With oWriteFile
.WriteLine oRange.Text
.WriteLine oRange.Offset(0, 1).Text ' second command
.WriteLine oRange.Offset(0, 2).Text ' third command
End With
Set oRange = oRange.Offset(1, 0)
Loop
oWriteFile.Close
End Sub

access command line data in Excel VBA fails

I need to access the command line parameters in an Excel VBA macro, and found many variations but only one that worked with Excel-2010, seems that the API has changed over time. I tried this code I found "out there":
Dim pCmdLine As Long ' Pointer to the Comand-line string
Dim strCmdLine As String ' Command line string
Dim CmdLine As String ' Command line string
' Get the pointer to the command line string
pCmdLine = GetCommandLineA
' Fill the string with zeros
' (300 characters for command line seems to be enough)
strCmdLine = String$(300, vbNullChar)
' Copy from the pointer to VBA-style string
lstrcpynA strCmdLine, pCmdLine, Len(strCmdLine)
' At this point we got the string,
' now skip the rest of it filled with 0 characters.
CmdLine = Left(strCmdLine, InStr(1, strCmdLine, vbNullChar) - 1)
MsgBox "Length of the command line = " & Len(CmdLine) '' Debug
MsgBox "Command Line:: " & CmdLine '' Debug
Which I put into the Auto_open macro of a spreadsheet. If I try this call:
start excel TestMacro.xlsm /e/abcd/xyz
It seems to generally work and the macro reports:
Command line = " C:/.../excel.exe TestMacro.xlsm"
So I get the invocation part, but the parameters are lost.
Partial Solution:
I find that if I change the invocation to:
start excel /e/abcd/xyz TestMacro.xlsm
It works, except the parsing code has to be changed to ignore the file name which is not at the end, and also this form doesn't seem to allow any blanks in any parameter, even if quoted. The system seems to interpret them as file names for a target excel file and give an error. For example:
start excel /e/abc/"my sheet"/ TestMacro.xlsm
gives the error:
file 'sheet"/.xlsx' not found
Although after the spurious startup error, the intended sheet does open and get teh entire line to work with.

Resources