VbScript to trim trailing pipes off file at 35 pipes - windows

So I was initially writing this in batch, but the number of tokens usable with ASCII were too small, i guess it only allows 26, and I need 35 pipes to remain in my output file.
I am new to VBScript, but basically I want it to read in the original file, do some magic to select the first character in the file to the last 35 pipes (and everything between, even in the space between the two pipes is blank). Then output that file to another file, while retaining the integrity of original.
Here is my code so far:
' **************
' ** Anthony B.
' **************
' ** PipeDropper
' **************
Dim WshShell, oExec
Set wshShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objInputFile = objFSO.OpenTextFile("C:\Users\aborgetti\Desktop\Pipe Delimiter Project\oauthrn.cms",1)
Set objOutputFile = objFSO.OpenTextFile("C:\Users\aborgetti\Desktop\Pipe Delimiter Project\output.txt",8,True)
Do until objInputFile.AtEndofStream
strcomputer = objInputFile.ReadLine
strCommand = "dsquery computer -name " & strComputer
Set oExec = WShShell.Exec(strCommand)
If (oExec.Status = 0) Then
If (oExec.stdOut.ReadAll = "") Then
objOutputFile.WriteLine(strComputer)
End If
End If
Loop
objInputFile.Close
objOutputFile.Close
Issues
This line Set oExec = WShShell.Exec(strCommand)
says it can't find the file that's specified...so I'm not sure why that's bad.
And then where do I go from here?
Thanks in advance!
UPDATE
Here is a line that would be in the file, usually anywhere from 10-100 times...
RE|922124607|1 |KimV|HOS99999|Y|N|2014-04-02 15:49:14|2014-04-02 15:49:58|Y|2014-04-02 00:00:00|R9815|01|1 |2014-04-02 00:00:00|493.90||||2016-04-02|N||HOS99999|||06|PROV99999|2014-04-02 15:48:20|2014-04-02||R9815|2014-04-02 00:00:00|2016-04-02 00:00:00||||||98960|06 |08|6|6|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||02|||||||Z4|2014-04-02 15:49:58|04|001|01|***|PMER|***|***|2013-08-01||||||||||||||||||||||||||||||||||||||||
Everything after the last 01 needs to go...so:
|***|PMER|***|***|2013-08-01||||||||||||||||||||||||||||||||||||||||
Should be:
Start of line ... |***|PMER|***|***|2013-08-01

I doubt that your problem
has anything to do with pipes
the code you published is the code that caused the error
There are two ways to get an error 424 "Object required" for a statement like
Set a = b.c(d)
The first (and obvious): b isn't an object. The second: the return value of b.c(d) isn't an object.
Your code condensed:
Set wshShell = CreateObject("WScript.Shell")
strCommand = "hostname"
Set oExec = WShShell.Exec(strCommand)
WScript.Echo oExec.Stdout.Readline()
runs without a problem. A slight change:
Set wshShell = CreateObject("WScript.Shell")
strCommand = "hostname"
Set oExec = WShShel1.Exec(strCommand)
WScript.Echo oExec.Stdout.Readline()
fails with "Object required". Do you spot the typo? Why not let "Option Explicit" help you:
Option Explicit
Dim wshShell : Set wshShell = CreateObject("WScript.Shell")
Dim strCommand : strCommand = "hostname"
Dim oExec : Set oExec = WShShel1.Exec(strCommand)
WScript.Echo oExec.Stdout.Readline()
output:
...\22871772.vbs(4, 18) Microsoft VBScript runtime error: Variable is undefined: 'WShShel1'
If you made sure that no typo caused the problem, you'll have to check whether the variable is changed/assigned to between initialization and use:
Option Explicit
Dim wshShell : Set wshShell = CreateObject("WScript.Shell")
Dim strCommand : strCommand = "hostname"
'...
wShSheLL = "oops"
'...
Dim oExec : Set oExec = WShShell.Exec(strCommand)
WScript.Echo oExec.Stdout.Readline()
again fails with error 424.
Update wrt the pipes:
I'd choose Split() (with count set to #pipes you want + 1) to deal with the trailing pipes:
>> n = 8 + 1
>> s = "|abc123|1*|004|**gobbligook|001|%|2014-01-01|||||||||||||"
>> a = Split(s, "|", n) ' <-- 9th elm get all the junk
>> WScript.Echo UBound(a)
>> a(n - 1) = "" ' <-- zap the junk
>> WScript.Echo Join(a, "|")
>>
8
|abc123|1*|004|**gobbligook|001|%|2014-01-01|
To delete a tail of |'s, a RegExp seems more appropriate:
>> set r = New RegExp
>> r.Pattern = "\|+$"
>> WScript.Echo r.Replace(s, "")
>>
|abc123|1*|004|**gobbligook|001|%|2014-01-01

Related

Trying to create a grads script and getting error " Expected end of statement " how can I solve it?

This is a screenshot of what I'm getting the error:
The file name of the script it's coming with the grads program.
gradsgui.vbs
The content of the file the script:
' Lightweight script to call actual executables down bellow. Eventually it
' could include the same functionality of the Perl version. Now it seats in
' the very top, above Contents/
Dim objFileSystem, objFILE
' Find out where we actually are
' ------------------------------
ScriptPath = Left(WScript.ScriptFullName, _
Len(WScript.ScriptFullName) - Len(WScript.ScriptName))
' Get the current version from file
' ---------------------------------
Set objFileSystem = CreateObject("Scripting.fileSystemObject")
Set objFILE = objFileSystem.OpenTextFile(ScriptPath & "Contents\Cygwin\Versions\Current#", 1)
Versions = Split(objFILE.ReadAll, vbCrLf)
Version = Left(Versions(0),Len(Versions(0))-1)
objFile.Close
Set objFileSystem = Nothing
' Actual executable path
' ----------------------
ActualPath = ScriptPath & "Contents\Cygwin\Versions\" & Version & "\i686\"
ExecutableName = Left(WScript.ScriptName,Len(WScript.ScriptName)-4) & ".exe"
ExecutableFullName = ActualPath & ExecutableName
' WScript.echo "Running <" & ExecutableFullName & ">"
' Command line arguments
' ----------------------
Set ArgObj = WScript.Arguments
sArgCount = ArgObj.Count
args = " "
For x = 0 To sArgCount - 1
args = args & " " & ArgObj(x)
Next
Set ArgObj = Nothing
Set xsize = 650 500
'Start actual application down below
'-----------------------------------
Set objShell = CreateObject("WScript.Shell")
'objShell.Run "%COMSPEC% /k" & ExecutableFullName & args
objShell.Run ExecutableFullName & args
Set objShell = Nothing
The line that I added that give the error is:
set xsize = 650 500
If I type this command in the console window when running the grads.exe it will work fine. But using the script it's giving me this error.
What i did is adding to the end of the file script two lines:
'Start actual application down below
'-----------------------------------
Set objShell = CreateObject("WScript.Shell")
Set env = objShell.Environment("PROCESS")
env("xsize") = "650 500"
' objShell.Run "%COMSPEC% /k" & ExecutableFullName & args
objShell.Run ExecutableFullName & args
Set objShell = Nothing
The lines i added are:
Set env = objShell.Environment("PROCESS")
env("xsize") = "650 500"
But they are not doing anything. It's not opening the new window in this size.
Looks like you're mixing VBScript and CMD commands here. You probably mean to set xsize=650 500 as an environment variable, but in VBScript the Set keyword is used for assigning objects to variables, not for defining variables in general like in CMD.
Try defining the variable in the process environment, so that it's inherited by the child process you're starting:
Set objShell = CreateObject("WScript.Shell")
Set env = objShell.Environment("PROCESS")
env("xsize") = "650 500"
objShell.Run ExecutableFullName & args

How to run windows executable and delete files from sub folders

I need a quick script do two parts.
Run a windows executable
Delete files within a folder and subfolders (*.jpg, *.img).
The first part of the below script works (running the executable) but I am getting stuck on part 2. I get
Cannot use parentheses when calling a sub
The error is on the line with the RecursiveDelete call. I actually cut and pasted that code from another SO question. I have googled the error but still don't understand.
Can anybody know how to get this script working?
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\Users\acer\Desktop\CT\process.exe" & Chr(34), 0
Set WshShell = Nothing
Dim PicArray(2)
Dim p
PicArray(1) = "*.jpg"
PicArray(2) = "*.img"
For p = 1 To 2
RecursiveDelete ("D:\pictures", PicArray(p))
Next p
Private Sub RecursiveDelete(ByVal Path As String, ByVal Filter As String)
Dim s
For Each s In System.IO.Directory.GetDirectories(Path)
try
RecursiveDelete(s, Filter)
catch dirEx as exception
debug.writeline("Cannot Access " & s & " : " & dirEx.message
end try
Next
For Each s In System.IO.Directory.GetFiles(Path, Filter)
try
System.IO.File.Delete(s)
catch ex as exception
debug.writeline("Cannot delete " & s & " : " & ex.message)
end try
Next
End Sub
Update: Revised answer from Hackoo that works great.
Option Explicit
Dim fso,RootFolder, wshShell
set fso = CreateObject("Scripting.FileSystemObject")
RootFolder = "D:\pictures"
Set RootFolder = fso.GetFolder(RootFolder)
Call RecursiveDelete(RootFolder)
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\process.exe" & Chr(34), 0
Set WshShell = Nothing
'*****************************************************************************
Function RecursiveDelete(Folder)
Dim File,MyFile,Ext,i,SubFolder
Set Folder = fso.GetFolder(Folder)
For each File in Folder.Files
Set MyFile = fso.GetFile(File)
Ext = Array("iMG","JPG")
For i = LBound(Ext) To UBound(Ext)
If LCase(fso.GetExtensionName(File.name)) = LCase(Ext(i)) Then
MyFile.Delete()
Exit For
end if
Next
Next
For each SubFolder in Folder.SubFolders
Call RecursiveDelete(SubFolder)
Next
End Function
'*****************************************************************************
Try like this way :
Option Explicit
Dim fso,RootFolder
set fso = CreateObject("Scripting.FileSystemObject")
RootFolder = "D:\pictures"
Set RootFolder = fso.GetFolder(RootFolder)
Call RecursiveDelete(RootFolder)
Msgbox "Pictures Cleaned !",vbInformation,"Pictures Cleaned !"
'*****************************************************************************
Function RecursiveDelete(Folder)
Dim File,MyFile,Ext,i,SubFolder
Set Folder = fso.GetFolder(Folder)
For each File in Folder.Files
Set MyFile = fso.GetFile(File)
Ext = Array("jpg","img")
For i = LBound(Ext) To UBound(Ext)
If LCase(fso.GetExtensionName(File.name)) = LCase(Ext(i)) Then
MyFile.Delete()
Exit For
end if
Next
Next
For each SubFolder in Folder.SubFolders
Call RecursiveDelete(SubFolder)
Next
End Function
'*****************************************************************************
Instead of passing the array item into RecursiveDelete, obtain the contents of the array item into a variable within the loop, and pass that variable instead.
Code would be similar to this- did not have a chance to test syntax.
For p = 1 To 2
Dim PicItem
PicItem = PicArray(p)
RecursiveDelete ("D:\pictures", PicItem )
Next p

VBS Run cmd.exe output to a variable; not text file

This is what I have so far. It works; outputing the folder path to temp to a text file.
What I really want, is to output the data to a variable. Every example I see online, show how to do this using something like:
set objScriptExec = wshShell.Exec (strCommand)
followed by
strresult = LCase(objScriptExec.StdOut.ReadAll. // code
I want this to run with Run, not Exec, because I want the command prompt windows to be hidden as I will performing many commands with the code below. How can I capture that output to a variable?
Set wsShell = CreateObject("WScript.Shell")
strCommand = "cmd /c echo %temp% > %temp%\test.txt"
wsShell.Run strcommand,0,True
This may be done with the Windows Script Host Exec command. StdOut, StdIn, and StdErr may all be accessed, and ERRORLEVEL is available when the command completes.
Dim strMessage, strScript, strStdErr, strStdOut
Dim oExec, oWshShell, intErrorLevel
Dim ComSpec
Set oWshShell = CreateObject("WScript.Shell")
ComSpec = oWshShell.ExpandEnvironmentStrings("%comspec%")
intErrorLevel = 0
strScript = ComSpec & " /C echo %temp%"
On Error Resume Next
Set oExec = oWshShell.Exec (strScript)
If (Err.Number <> 0) Then
strMessage = "Error: " & Err.Message
intErrorLevel = 1
Else
Do While oExec.Status = 0
Do While Not oExec.StdOut.AtEndOfStream
strStdOut = strStdOut & oExec.StdOut.ReadLine & vbCrLf
Loop
Do While Not oExec.StdErr.AtEndOfStream
strStdErr = strStdErr & oExec.StdErr.ReadLine & vbCrLf
Loop
WScript.Sleep 0
Loop
intErrorLevel = oExec.ExitCode
strMessage = strStdOut & strStdErr & CStr(intErrorLevel)
End If
WScript.Echo (strMessage)
NOTE: Replacing "ReadLine" above with "Read(1)" accomplishes the same thing, but adds an ability to process characters rather than whole lines.
Of course Wscript.Shell would be a lot easier, but, since you want more fine grain control of your session, consider using Win32_Process. Usually, one uses this to control the placement of a new window, but, in your case, you want it hidden, so I set startupInfo.ShowWindow = 0 which means SW_HIDE. The following declares a VBScript function called RunCmd and which will run a command in an invisible window saving the output to a text file and then return the contents of the text file to the caller. As an example, I invoke RunCmd with the HOSTNAME command:
Function RunCmd(strCmd)
Dim wmiService
Set wmiService = GetObject("winmgmts:\\.\root\cimv2")
Dim startupInfo
Set startupInfo = wmiService.Get("Win32_ProcessStartup")
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim cwd
cwd = fso.GetAbsolutePathname(".")
startupInfo.SpawnInstance_
startupInfo.ShowWindow = 0
' startupInfo.X = 50
' startupInfo.y = 50
' startupInfo.XSize = 150
' startupInfo.YSize = 50
' startupInfo.Title = "Hello"
' startupInfo.XCountChars = 36
' startupInfo.YCountChars = 1
Dim objNewProcess
Set objNewProcess = wmiService.Get("Win32_Process")
Dim intPID
Dim errRtn
errRtn = objNewProcess.Create("cmd.exe /c """ & strCmd & """ > out.txt", cwd, startupInfo, intPID)
Dim f
Set f = fso.OpenTextFile("out.txt", 1)
RunCmd = f.ReadAll
f.Close
End Function
MsgBox RunCmd("HOSTNAME")
References:
Create method of the Win32_Process class
Win32_ProcessStartup class

I am trying to find specific links on users desktops and create a file logging the results

I have used similar before and I have local admin rights on every computer in our network. The following code generates an error on line 16 char 1.
line 16 For Each objsubfolder In objFSO.GetFolder("\" & strComputer & "%HOMEPATH%").subfolders
If the file exists it should write a line in the text file to indicate so for each user with a profile. If the file doesn't exist is should write a line in the same text file.
The error I get is Path not found 800A004C.
The computers.txt file contains a list of all the computers I want to check.
InputFile = "computers.txt"
Const DeleteReadOnly = True
Const ForAppending = 8
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim gsLog : gsLog = ".\logdemo.log"
WScript.Echo gsLog, "exists:", CStr(goFS.FileExists(gsLog))
' .OpenTextFile(filename[, iomode[, create[, format]]])
Dim goLog : Set goLog = goFS.OpenTextFile(gsLog, ForAppending, True)
goLog.WriteLine Now & " start"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(InputFile)
Do While Not (objFile.AtEndOfStream)
strComputer = objFile.ReadLine
For Each objsubfolder In objFSO.GetFolder("\\" & strComputer & "%HOMEPATH%").subfolders
If objFSO.FileExists(objsubfolder.Path & "\desktop\program1.LNK") Then
golog.WriteLine Join(Array(Now, strComputer, objsubfolder, "This Computer has Program 1"))
Else
golog.WriteLine Join(Array(Now, strComputer, objsubfolder, "None"))
End If
Next
Loop
golog.WriteLine Now & " End"
golog.WriteLine "-----------------------------------------------------------"
golog.Close
MsgBox "Done"
To prove that the FSO does not expand environment strings automagically:
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oWS : Set oWS = CreateObject("WScript.Shell")
Dim sPath
sPath = "%windir%\addins"
WScript.Echo qq(sPath), CStr(oFS.FolderExists(sPath))
sPath = oWS.ExpandEnvironmentStrings("%windir%\addins")
WScript.Echo qq(sPath), CStr(oFS.FolderExists(sPath))
output:
"%windir%\addins" False
"C:\WINDOWS\addins" True
So put some work into feeding a valid path to .GetFolder().

how to add a log to my vbscript

i have this script that reads a list of computers and check to see if the computers have the right software version install. the script echo to me the computers with the wrong version, but i want to make a log instead
Dim strComputer, objFSO, ObjShell, strDisplayName, objList, strObject
Dim objReg, arrSubKeys, strProduct, strVersion, strReqVersion
Const For_Writing = 2
Const ForReading = 1
const ForAppending = 3
Const HKLM = &H80000002
Const strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
strReqVersion = "8.2.1 MP2"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objList = objFSO.OpenTextFile("c:\test\test.txt",ForReading)
Do While Not objList.AtEndOfStream
strComputer = objList.ReadLine
If HostOnline(strComputer) = True Then
Inventory(strComputer)
End If
Loop
Function Inventory(strComputer)
Set objTextFile = objFSO.OpenTextFile("c:\test\inventory.txt",2,true)
'creating a dictionary object
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
' Enumerate the subkeys of the Uninstall key
objReg.EnumKey HKLM, strKeyPath, arrSubKeys
For Each strProduct In arrSubKeys
' Get the product's display name
objReg.GetStringValue HKLM, strKeyPath & "\" & strProduct, "DisplayName", strDisplayName
' Process only products whose name contain 'symantec'
If InStr(1, strDisplayName, "Symantec", vbTextCompare) > 0 Then
' Get the product's display version
objReg.GetStringValue HKLM, strKeyPath & "\" & strProduct, "DisplayVersion", strVersion
If strReqVersion <> strVersion Then
WScript.Echo strObject
objDictionary.Add strComputer, strVersion
For Each strObject In objDictionary
WScript.Echo strObject
objTextFile.WriteLine(strObject)
Next
objTextFile.Close
End If
End If
Next
End Function
Function HostOnline(strComputername)
'---------- Test to see if host or url alive through ping -----------------
' Returns True if Host responds to ping
'
' strComputername is a hostname or IP
Const OpenAsASCII = 0
Const FailIfNotExist = 0
Const ForReading = 1
Dim objShell, objFSO, sTempFile, fFile
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
sTempFile = objFSO.GetSpecialFolder(2).ShortPath & "\" & objFSO.GetTempName
objShell.Run "cmd /c ping -n 2 -l 8 " & strComputername & ">" & sTempFile, 0 , True
Set fFile = objFSO.OpenTextFile(sTempFile, ForReading, FailIfNotExist, OpenAsASCII)
Select Case InStr(fFile.ReadAll, "TTL=")
Case 0
HostOnline = False
Case Else
HostOnline = True
End Select
ffile.close
objFSO.DeleteFile(sTempFile)
Set objFSO = Nothing
Set objShell = Nothing
End Function
can some one help me please thanks
There are several ways to do this. The simplest way, without any modification to your script, would be to call the script with cscript.exe (in a command prompt) and redirect the output to a file:
cscript your.vbs > output.log
However, if you want a log to be created even when users double-click your script you'll have to change your script so that it writes to a file instead of echoing the output. Open the log file at the beginning of the script:
Set myLog = objFSO.OpenTextFile("C:\my.log", For_Writing, True)
replace WScript.Echo ... with myLog.WriteLine ..., and close the file before you exit from the script:
myLog.Close
A somewhat more sophisticated approach would be to create a set of logging functions, which will allow you create log lines depending on certain conditions, e.g. LogInfo() for informational log messages and LogError() for errors.
Shameless plug: Some time ago I got fed up with writing the same boilerplate logging functions over and over again, so I wrote a logger class that encapsulates the usual logging facilities (interactive console, files, eventlog) and provides logging methods for 4 log levels (Error, Warning, Information, Debug). The class can be used for logging to a file like this:
Set myLog = New CLogger
myLog.LogToConsole = False
myLog.LogFile = "C:\my.log"
myLog.LogInfo "info message"
...
myLog.LogError "an error occurred"
The log file is automatically closed when the object is released.
Why not use the system's event log? I described how in this answer
It means most of the work is done for you and you don't need to worry about where to put your log file

Resources