How to check for line break in a string? - vbscript

I am trying to check if a line break exists in a string. I have intentionally included a line break in the string to check if it returns an error. However, it does not return an error despite having a line break in the string.
A sample of the string:
<Project_Title> Proposed
Envelope Control </Project_Title>
The code for find the line breaks:
if instr(1,trim(strProjDetails),"</Project_Title>",vbtextcompare) then
if instr(1,trim(strProjDetails), vbCrLf) > 0 Then
Response.write "sam"
call logClass.setLogs(userid, menu, action, "Error! Line break exists in XML File.", f)
Response.Write("Please remove the line break from the XML file.")
Response.end
End if
End if

There are 3 options for line break:
Constant Value Description
----------------------------------------------------------------
vbCr Chr(13) Carriage return
vbCrLf Chr(13) & Chr(10) Carriage return–linefeed combination
vbLf Chr(10) Line feed
See here:
Differences Between vbLf, vbCrLf & vbCr Constants
So if you not sure which one of them is in use in your text I would suggest to search for every one of them as following:
if instr(1,trim(strProjDetails),"</Project_Title>",vbtextcompare) then
if instr(1,trim(strProjDetails), Chr(10)) > 0 or instr(1,trim(strProjDetails), Chr(13)) > 0 or instr(1,trim(strProjDetails), Chr(13) & Chr(10)) > 0 Then
Response.write "sam"
call logClass.setLogs(userid, menu, action, "Error! Line break exists in XML File.", f)
Response.Write("Please remove the line break from the XML file.")
Response.end
End if
End if

If this code doesn't work for your strings
testString = "<Project_Title> Proposed "&VbCrLf&" Envelope Control </Project_Title>"
if instr(testString,vbCrLf)>0 or instr(testString,vbCr)>0 or instr(testString,vbLf)>0 then
Response.Write "Line break"
else
Response.Write "No line break"
end if
Then there's something else going on, and your string doesn't have a line break in it (Adirmola's code checks the same thing, his code should work fine too)
Try getting the Char/Chr codes of the breaks in your string here: http://asciivalue.com/ just to check what the actual thing you're trying to find is!
In this example it's 13 followed by 10 - a VbCrLf
Then you can substitute vbCrLf for chr(whatever).
Best of luck.

Related

Understanding VBS multi-line notation

I am trying to understand something about about the way VBS splits single lines of code across multiple lines.
In the below function the _ character is used in two places to split execution across two lines, ok all fine.
For Each objItem in colItems
if i=0 then
header = ""
For Each param in objItem.Properties_
header = header & param.Name & vbTab
Next
WScript.Echo header
i=1
end if
serviceData = ""
For Each param in objItem.Properties_
serviceData = serviceData & param.Value & vbTab
Next
WScript.Echo serviceData
Next
What I do not understand then is how this is supposed to look on a single line. When I modify either of the lines with any of the below I get an error.
For Each param in objItem.Propertiesheader = header & param.Name & vbTab
For Each param in objItem.Properties.header = header & param.Name & vbTab
For Each param in objItem.Properties header = header & param.Name & vbTab
Errors to the effect of:
C:\Program Files (x86)\ManageEngine\AppManager12\working\conf\application\scripts\wmiget.vbs(86,2) Microsoft VBScript runtime error: Object doesn't support this property or method: 'objItem.PropertiesserviceData'
How would the above be correctly represented on a single line?
The issue here is you are using the Line Continuation Character _ to continue a line when it isn't required.
You only use it if you need a single line of code to span multiple lines, using your example something like;
For Each _
param _
in _
objItem.Properties
serviceData = serviceData & param.Value & vbTab
Next
will work (be it a bit pointless) because the single line
For Each param in objItem.Properties
is being spanned across multiple lines.
So, because the line;
For Each param in objItem.Properties
is a single line of code no continuation is required as the next line of code is expected. However, when you provide it, it causes VBScript to error with;
Microsoft VBScript compilation error: Expected end of statement
Which is VBScript's way of telling you that the line isn't finished and still expects the end of the code statement.
If you do want to span multiple code statements across a single line use colon (:) which acts as a statement seperator, i.e;
For Each param in objItem.Properties : serviceData = serviceData & param.Value & vbTab : Next
Useful Links
Line Continuation Character (_) also known as a Statement Break.
Breaking a String Across Multiple Lines (Focuses on strings but talks about the Line Continuation Character).
VBScript, purpose of colon?

Vbscript type mismatch error apparently not justifiable

I'm trying to figure out why I would get this error for the code below. I've searched on the web for possible causes but I couldn't find. Please have a look:
Dim descr, code
If WScript.Arguments.Count = 0 Then
Set objShell = CreateObject("Shell.Application")
objShell.ShellExecute "wscript.exe", Chr(34) & Script.ScriptFullName Chr(34) & " Run", , "runas", 1
Else
descr = InputBox("restore point description","Crepo")
If (descr) Then
code = GetObject("winmgmts:\\.root default:Systemrestore").CreateRestorePoint (descr, 0, 100)
If (code) Then
Msgbox "System Restore Point not created (" & code & ") !", 48, "Crepo"
Else
Msgbox "System Restore Point successfully created", 64, "Crepo"
End If
End If
End If
At runtime, if I input anything, i.e. qwerty I get this error:
Line: 8
Char: 2
Error: Type mismatch: '[string: "qwerty"]'
Code: 800A000D
From my researches, return type of InputBox is string and CreateRestorePoint first argument is also string. In fact, it works if I call InputBox directly as the argument.
The If clause needs a boolean (not a string):
>> descr = "qwerty"
>> If (descr) Then WScript.Echo "nonsense"
>>
Error Number: 13
Error Description: Type mismatch
InputBox returns a string or an empty value (see here), but never Null.
Instead of If (descr) Then try If (Not IsNull(descr)) Then.
You may also want to check for empty strings too: If (Not IsNull(descr) and descr <> "") Then. In fact, as pointed out in the other answer, since the VBScript InputBox function docs note that If the user clicks Cancel, the function returns a zero-length string ("") you definitely need to check for an empty/zero-length string.

Delete registry folder and sub folder using VBS

I want to delete registry folder and sub-folder under it using vb script.
In reg file we can script like below:
[-HKEY_LOCAL_MACHINE\SOFTWARE\abc\prr]
Above script will delete sub-folder under prr
How to achieve same using VB script?
I tried using .RegDelete but I think it work only for key and not for registry folder.
Thanks.
[path] RegDelete [Key] | [Value]
Path Path to RegDelete (so Windows can find it). See the tip on the Windows 98 Tips and Hacks page to make Windows always find it.
Nothing Starts RegDelete with a User Interface. Do not enclose keys or values in inverted commas when typing the key or value to delete.
Key The key to delete. Keys always end in a backslash. If the key contains a space it must be enclosed in inverted commas. Keys and sub-keys will be deleted.
Value The value to delete. Values do not have a trailing backslash. If the key contains a space it must be enclosed in inverted commas.
Copy the following lines into a new text document and save as RegDelete.vbs.
'RegDelete.vbs
'Deletes keys or values from the registry.
'
'
On Error Resume Next
vbPara=vbCRLF & vbCRLF
strExplain="RegDelete deletes keys and values from the registry." & vbPara & "Keys must end with a backspace and values must not." & vbPara & "Start without parameters to type in a key or value to delete, or place the key or value on the command line (use inverted commas to surround the key or value if it contains spaces)." & vbPara & "Continue"
strTitle="Reg Delete"
Key=""
Dim silent
Silent=""
Dim Sh
Set Sh = WScript.CreateObject("WScript.Shell")
ReportErrors "Creating Shell"
Key=GetKey()
If Key<>"" then
B=Sh.RegRead (Key)
If Err.Number=0 Then
Sh.RegDelete Key
If Err.Number =0 Then
If silent<>"yes" Then MsgBox Key & " deleted", vbOKOnly + vbInformation, strTitle
Else
ReportErrors "DeletingKey"
End If
Else
If Err.Number=-2147024893 then
Err.Clear
MsgBox Key & " didn't exist", vbOKOnly + vbCritical, strTitle
Else
ReportErrors "Reading before Deleting Key"
End If
End If
End If
ReportErrors "Main"
Function GetKey()
Dim Ag
Set Ag=Wscript.Arguments
ReportErrors "Creating Aguments"
If Ag.Count=1 then GetKey=Ag(0)
Silent="yes"
If Ag.Count >1 then sgBox "Too many parameters on command line. Try enclosing the key in a space",vbOKOnly + vbCritical, strTitle
If Ag.Count=0 then
If MsgBox (strExplain, vbYesNo + vbInformation, strTitle)=6 Then
GetKey=InputBox ("Enter the value or key to delete." & vbPara & "Keys must end in a backspace.", strTitle, strNamet1)
End If
End If
End Function
Sub ReportErrors(strModuleName)
If err.number<>0 then Msgbox "Error occured in " & strModuleName & " module of " & err.number& " - " & err.description & " type" , vbCritical + vbOKOnly, "Something unexpected"
Err.clear
End Sub

Editing Text File In vb6

I Have Displayed text file in richtextbox.
and onclick on command button value of textbox1 is being replaced in text file.
but How to keep both data . previous one and another which is entered new in textbox
I HAVE USE THIS CODE BUT IT REPLACES ALL THE TEXT :
Open "D:\chat.txt" For Output As #1
a = Text1.Text
Print #1, a
Close #1
Change For Output to For Append, and it will add the new text to the end of the file instead of overwriting it.
Additional note
Since I'm not able to add a comment to Boann's answer (the one marked as accepted).
The Append access mode used with the Print statement automatically appends a new line at the end of the file. This is fine in almost all cases, but for anyone reading this that wants to avoid this behavior, just add a semicolon at the end of the Print statement (this is the only instance I've seen the semicolon used in VB6).
a = Text1.Text
intHandle = FreeFile
Open "D:\chat.txt" For Append As intHandle
Print #intHandle, a; ' Notice the semicolon; prevents a new line after this output.
Close #intHandle
I'm sure the code you posted originally was just for the sake of getting an answer and is not what your code actually looks like. Otherwise:
To you or any future readers, here's a simple AppendToFile() function which will make repeated calls easier, ensures the file gets closed even if a run-time error is encountered, and shows useful debug information upon failure (i.e. with an invalid filename):
How your original code would be written when putting my below function in your code:
AppendToFile "D:\chat.txt", Text1.Text
And here's the function:
Private Function AppendToFile( _
ByRef FilePath As String, _
ByRef Text As String, _
Optional ByVal AppendNewLine As Boolean = True _
) As Boolean
On Error GoTo ErrorHandler
Dim intHandle As Integer
' Get an available file handle to use.
intHandle = FreeFile
Open FilePath For Append As intHandle
' Only use semicolon at end if we do NOT want to append a new line.
If AppendNewLine Then
Print intHandle, Text
Else
Print intHandle, Text;
End If
Close intHandle
intHandle = 0
AppendToFile = True
Exit Function
ErrorHandler:
' Ensure that file is indeed closed.
If intHandle <> 0 Then
Close intHandle
End If
' Show error in debug window (CTRL+G)
Debug.Print _
"Error (#" & CStr(Err.Number) & ") in " & _
"TextToFile( _" & vbCrLf & _
"`" & FilePath & "`, _" & vbCrLf & _
"`" & Text & "`, _" & vbCrLf & _
IIf(AppendNewLine, "`True`", "`False`") & vbCrLf & _
"): " & Err.Description & IIf("." = Right$(Err.Description, 1), "", ".") & vbCrLf
Exit Function
End Function

How to extract context informationm the equivalent of __LINE__, __FILE__,etc., in VBSCRIPT

I'd like to know how to get the line number of a line in vbscript programmaticly either at the point of the code like __LINE__ or more ideally a way to get the line number of where the current function was called like python's stack module so I can write a reusable debugging function(and the file the code is located in) and no I don't want to know how to turn on line numbers in my editor.
Also I'd like to now any similar useful information that can be extracted such as calling function, variable type as string, etc.
Unfortunatly that doesn't work the way like in Ruby and Python. The next best thing i worked out is putting a call to a errorhandling function everywhere where things could go wrong. The numbers in the parameter of this function are adapted each time i execute a macro in my editor (i use textpad, the \i is autonumbering in a Regular Expression). If your editor doesn't support this you could write a script that does this. So when an error occurs, it is logged with the number the errorhandling function was called and you can easily find it back in the source by looking for #number#.
This is usable for both asp and vbs but for vbs there is an easier way.
Some editors like textpad or sublimle text let you execute a vbs script, show the output in a tab and if an error is produced let you double click the line with the errormessage which opens the script at that line. This is also done by a regular expression. Let me know if you need the one for textpad.
on error resume next
'initialize constants DEBUGLEVEL and LOGFILE
'initialize strHostName
'some code
oConn.execute(sql)
if not LogError("#1#") then
'do the things if successfull, otherwise log error with number
end if
'again some code
if not LogError("#2#") then
'do the things if successfull, otherwise log error with number
end if
'the debug and log functions
function LogError(errornumber)
'LogError\(\"#[0-9]+#\"\) replace by LogError("#\i#")
if err.number <> 0 then
call debug("<name of script>/Logerror","","","Errornumber:" _
& errornumber & " " & err.number & " " & err.description & " " _
& err.source)
LogError = True
err.clear
errors = errors+1
else
LogError = False
end if
end function
function Debug (pagina, lijn, varnaam, varinhoud)
if DEBUGLEVEL > 0 then
const forReading = 1, forWriting = 2, forAppending = 8, CreateFile = True
dim fs,f, var, strHostName
set fs=CreateObject("Scripting.FileSystemObject")
strHostName = fs.GetFileName(WScript.FullName)
if fs.FileExists(LOGFILE) then
set f=fs.OpenTextFile(LOGFILE, forAppending)
else
set f=fs.OpenTextFile(LOGFILE, forWriting,true)
end if
var = now & " " & pagina & ":" & lijn & ":" & varnaam & ":" & varinhoud
f.WriteLine var
if LCase(strHostName) = "cscript.exe" then 'debugging
if DEBUGLEVEL > 1 then
wscript.echo var
end if
end if
f.Close
set f=Nothing
set fs=Nothing
end if
debug = true
end function
VBScript doesn't expose that information, so you can't access it programmatically from within the script (edge cases notwithstanding). You're going to need a debugger for extracting this kind of information. Or you could have another script interpret the first one and keep track of line numbers (like this). I wouldn't recommend the latter for any kind of production environment, though.
As long as it's happening outside of a function, the following works.
Automatic error-handling is turned off at the start of the script by On Error Resume Next, so that the script doesn't just exit before you can do anything. BUT, you can then turn error-handling back on using On Error GoTo 0 and Raise an exception yourself. That will output the line number in addition to any of your debugging messages.
For example:
On Error Resume Next
server = WScript.Arguments(0)
If Err.Number <> 0 Then
WScript.Echo("Need to pass in an argument!")
On Error GoTo 0
Err.Raise(1)
End if
If you run this without any arguments, you get the following output:
Need to pass in an argument!
C:\script.vbs(6, 5) Microsoft VBScript runtime error: Unknown runtime error
The "6" refers to the line number where the exception was raised.
This way you can print custom output, and also you'll know what line the error happened at.
Yes!
There is a way to get the exact error line number, but it's HUGLY, as we are talking about an ancient programming tool....
And yes, it is worth it, especially if your code is going to run in front of many users. That way you can get past isolating and reproducing the bug, right to solving it.
Take a close look at the last variable "Erl" in the line of code below. It is an undocumented global variable the VB script processor holds.
Dim sErrorMsg as String
sErrorMsg = Err.Description & "(" & Err.Number & ")" & vbNewLine & "Source: " & Err.Source & vbNewLine & "At line number: " & Erl
In order to get anything from that global "Erl" variable you need to (manually)** set its value at the beginning of each line of code as shown below. Beware, you set the line number, if you forget to set the number for a specific line, Erl will report the last set value. See the division by zero error line, it reports the line number set above because I did not set a line number value at the beginning of the line that caused the error.
I have not figured out the inbuilt call stack, though I know there is one. Please let me know if you figure that one out, for now I use a module level variable to build the stack.
More tips at the very end, below this code sample
Sub WhatEverSub ()
2 Const iColIdxPageNbr As Integer = 2
3 Const iColIdxDefinition As Integer = 3
5 Dim oDoc_Source As Document
6 Dim oDoc_Target As Document
10 Dim oTable As Table
11 Dim oRange As Range
12 Dim n As Long
13 Dim strAllFound As String
14 Dim Title As String
15 Dim Msg As String
On Error GoTo PrepErrorHandler
Dim xyz As Long
xyz = Rnd(3) / 0
16
17 Title = "Evil Finder - This program is about doing something important for the world"
18
19 'Show msg - stop if user does not click Yes
20 Msg = "This macro finds all evil things consisting of 2 or more " & _
"uppercase letters and extracts the hex representation to a table " & _
"in a new document." & vbNewLine & vbNewLine & _
"Do you want to continue?"
21 If MsgBox(Msg, vbYesNo + vbQuestion, Title) <> vbYes Then
22 Exit Sub
23 End If
(... whatever code ...)
820 Application.ScreenUpdating = True
830 If n = 1 Then
840 Msg = "No evil things were found. Need to find better detection tool"
850 oDoc_Target.Close savechanges:=wdDoNotSaveChanges
860 Else
870 Msg = "Finished extracting " & n - 1 & " evil thing(s) to a new document."
880 End If
PrepErrorResumeLine:
890 MsgBox Msg, vbOKOnly, Title
'Clean up
1000 Set oRange = Nothing
1010 Set oDoc_Source = Nothing
1020 Set oDoc_Target = Nothing
1030 Set oTable = Nothing
Exit Sub
PrepErrorHandler:
Msg = Err.Description & "(" & Err.Number & ")" & vbNewLine & "Source: " & Err.Source & vbNewLine & "At line number: " & Erl
Resume PrepErrorResumeLine
End Sub
**Some more tips:
1)
As for setting the error line number values manually, I wrote a utility (more than a decade ago) to automate the addition or removal or renumbering of all lines in a module by working directly on the VB project files (or standalone .vbs files), but the below will take care of the basic, with a few manual adjustsments remaining...
Set up VB code line #s using MS Excel
a) paste code in column C
b) set column A's first cell value to 10, and second to 20 and drag copy down to auto increment until you reach the last line/row of code in column B
c) in column B paste in the following formula and drag copy down =A1 & REPT(" ", 8 - LEN(A1))
d) copy columns B and C back into the VB code pane et voila!
Strip out the line numbers to do major edits using Word
Paste the code in,
Hit CTRL + H and make sure wildcards is checked (click the "more" button)
Fill in the following settings
FIND
[^13][0-9 ]{4}
REPLACE
^p
Done!
2)
number each line in increments of 10 at least so you can wedge in a few lines at the last minute without having to renumber each line below your change
3) On Error Resume Next is evil and will cost you a lot of debugging hours!
At least 90% of the time, one should use a specific handler, or nothing. If you do not already know how to recover from an error, do not use RESUME NEXT to silence it, instead, log all the details (using Erl) and learn from the run time logs and use GoTo 0 'Zero, not the letter O to let the rest of the errors bubble up the call stack.
On Error GoTo MyErrorHandlerSection
(... write your risky code here ...)
On Error GoTo 0
'the line immediately above disables all error handling in the current function, if any error happens, it will be passed to the calling function
Nothing prevents you from adding another handling section in the same function if you have another chunk of risky code using
On Error GoTo MySecondErrorHandlerSection

Resources