VBS Script to adapt in another language - windows

I have a script that works perfectly fine on english-based computers but does not once in another language.
The script gets the Recovery Key for Bitlocker of a Machine and then backs it up into Active Directory.
I've identified that I need to update the "Numerical Password" into the value in my corresponding language but this does not change the output of a blank variable NumericalKeyID in the end...
Option Explicit
Dim strNumericalKeyID
Dim strManageBDE,strManageBDE2
Dim oShell
Dim StrPath
Dim StdOut, strCommand
Dim Result, TPM, strLine
Dim Flag, NumericalKeyID
Set oShell = CreateObject("WSCript.Shell")
'====================================================================================
'This section looks for the Bitlocker Key Numerical ID
strManageBDE = "Manage-BDE.exe -protectors -get c:" 'Bitlocker command to gather the ID
Flag = False
Set Result = oShell.Exec(strManageBDE)'sees the results and places it in Result
Set TPM = Result.StdOut 'Sets the variable TPM to the output if the strManageBDe command
While Not TPM.AtEndOfStream
strLine = TPM.ReadLine 'Sets strLine
If InStr(strLine, "Numerical Password:") Then ' This section looks for the Numerical Password
Flag = True
End If
If Flag = True Then
If InStr(strLine, "ID:") Then 'This section looks for the ID
NumericalKeyID = Trim(strLine)' This section trims the empty spaces from the ID {} line
NumericalKeyID = Right(NumericalKeyID, Len(NumericalKeyID)-4)
Flag = False 'Stops the other lines from being collected
End If
End If
Wend
strManageBDE2 = "Manage-BDE.exe -protectors -adbackup C: -ID " & NumericalKeyID
oShell.Run strManageBDE2, 0, True 'Runs the Manage-bde command to move the numerical ID to AD.
I'm sure this is pretty dumb but my script knowledge is quite new.
Thank you a lot ! :)
In English the output of manage-bde:

Much as I hate to suggest a solution using regular expressions (Obligatory XKCD link)
I think it might be your best option here
Something like this should do the trick
.*ID:.*{(.*)}.*
To break it down for you
.* - Match any character
ID: - Match ID:
.* - Match any character
{ - match {
( - remember anything between this and the next )
} - match }
.* - Match any character
If you're not familiar with VBScript's support for regular expressions this link is pretty good Regular Expression - VBScript
Dim myRegExp, myMatches id
Set myRegExp = New RegExp
myRegExp.Global = True
myRegExp.Pattern = ".*ID:.*{(.*)}.*"
Set myMatches = myRegExp.Execute(subjectString)
id = myMatches(0).SubMatches(0)
A caveat with this solution
You might need to tweak the regular expression if the output varies a lot from machine to machine (do you ever have more than one protector?)
If you're new to Regex Expresso is a useful tool for testing/learning

Thank you David.
I only have one protector to backup, and also one drive.
The thing is, as I said, everything works perfectly when the language of the computer is in english but as soons as I have a language that replace the "Numerical Password" with some words with special characters like "é" "ñ" it will not be recognized and the variable will get a blank value.
Maybe it is because vbscript this way does not handle unicode.
To illustrate my sayings, here is a screenshot of the same screen than in my first post, but in french:

Related

How can I specify that the value of a variable in VBscript be case insensitive?

Part of a VBscript I'm writing inside of an HTA calls for the user to type a name into a text box which will generate a folder with that name. I am building checks into the script to make sure that no illegal characters or names are used. Where I am getting stuck at is trying to make sure that if a user enters COM1 or LPT1 they will be told that the name they tried to use is not allowed instead of getting a script error. The problem is I can't figure out how to do it without writing an If statement for every possible way the letters in COM1 through COM9 and LPT1 through LPT9 could be arranged in different cases (e.g. com1, Com1, cOm1, etc.). The code snippet below shows what I mean.
sFldrName = BasicTextbox.Value
sFldrBadMsg = "You've chosen an illegal folder name."
If sFldrname = "COM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "COM2" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "COM3" Then
Msgbox sFldrBadMsg
In the above example whatever the user enters into the text box is assigned to "sFldrname". Then the script checks whether the string assigned "sFldrname" is COM1 or COM2 or COM3. The problem is I can only check for those strings in the exact case specified. If the user enters COM1 they will get my warning message. But, if they enter com1 (all lower case) or CoM1 (mixed case) they will get a script error because it is still an illegal name regardless of case. In order to account for this with the method I used above I would have to do something like this:
sFldrName = BasicTextbox.Value
sFldrBadMsg = "You've chosen an illegal folder name."
If sFldrname = "COM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "Com1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "COm1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "cOm1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "coM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "cOM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "CoM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "com1" Then
Msgbox sFldrBadMsg
And I would have to do that for COM2 through COM9 and LPT1 through LPT9 as well. I really don't want to have to do that. So, when I am checking the value of "sFldrname" to see what string it is, is there a way to ignore the case of that string? Or, is there a better way altogether to go about doing what I am trying to do? Thanks.
The canonical way, as others have already mentioned, is to uppercase (or lowercase) the value of the variable you want to compare:
If LCase(sFldrname) = "com1" Then
Msgbox sFldrBadMsg
ElseIf LCase(sFldrname) = "com2" Then
Msgbox sFldrBadMsg
ElseIf LCase(sFldrname) = "com3" Then
Msgbox sFldrBadMsg
End If
Using the StrComp function would be another option:
If StrComp(sFldrname, "COM1", vbTextCompare) = 0 Then
Msgbox sFldrBadMsg
ElseIf StrComp(sFldrname, "COM2", vbTextCompare) = 0 Then
Msgbox sFldrBadMsg
ElseIf StrComp(sFldrname, "COM3", vbTextCompare) = 0 Then
Msgbox sFldrBadMsg
End If
However, since you're doing an n-way comparison of the same variable, your best choice would probably be a Select statement in combination with UCase or LCase:
Select Case UCase(sFldrname)
Case "COM1", "COM2", "COM3" : MsgBox sFldrBadMsg
Case Else : MsgBox "OK"
End Select
Well, you could do something like:
If UCase(sFldrname) = "COM1" Then
Msgbox sFldrBadMsg
end if
That will uppercase your string, and then you can just compare the results with all uppercase. You are better off probably just looking for COM, and a colon. Now, for the BEST possible security,. and assurance that a path is correct, you want to look into something a little more serious, like Regular Expressions. Regular Expression can take the users input and test it for a valid "Path like" string.
Something like:
Dim RegEx, bFound
Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "^(?:\b((?#drive)[a-z]):\\((?#folder)[^/:*?""<>|\r\n]*\\)?((?#file)[^\\/:*?""<>|\r\n]*))$"
bFound = RegEx.Test(Data)
Will match when the users have entered a VALID drive, folder, and filename. Or, you use other iterations of the RegEx to test the matches. Keep in mind, you do not have to check for "COM1:", "LPT1:", etc, because the RegEx will not allow colons in the path, except at the very start for the drive letter...
Dim RegEx
Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "\b((?#drive)[a-z]):\\((?#folder)[^/:*?""<>|\r\n]*\\)?((?#file)[^\\/:*?""<>|\r\n]*)"
If RegEx.Test(sFldrname ) Then
' Successful match
Else
' Match attempt failed
End If
Now, lets just say that you want to test for DOS Device names in the input from the user. You can use a RegEx like the following to test for all combinations of COMn:, LPTn:, CON:, and NIL:. This RegEx, of course, requires that the input START with COM, LPT, CON, etc, if the string does not start with it, lets, say, for example, they typed in a directory name of Welcome, or heck, when WelCOM3: the RegEx would NOT match, indicating a clean path. If you want it to be able to search the ENTIRE input string for the appearance of COM{n}:, then remove the \b out of the pattern...
Dim RegEx
Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "\b(COM[0-9]+|LPT[0-9]+|CON|NIL)\:"
If RegEx.Test(sFldrname ) Then
' We discovered a DOS Device name as a PATH, and it is therefore invalid.
End If
Now, to address your actual, QUESTION, you'll note the RegEx.IGNORECASE = true. THAT is your ace in the hole there...
In my first example, I only showed you that as a lesson in how to do a case insensitive string comparison, something you will use OFTEN in writing just about any code in any language. I'm showing you the OTHER examples as more of a "proper" way, or an "easier" way, or a more "assured" way to search for bad things in a path. I think it's important that you look into something more solid, and much less code on your part, for a much more stable codebase. Since you are dealing with PATHS, which, as you know, is a serious ability for someone to enter path names that can put them in the wrong folder, (for example, entering a folder name like ..\..\..\..\..\..\Windows\System32\ now, they end up with a folder created in Windows System32, and depending on what your app does, this can be a SERIOUS security risk. So, don't just use the Regular Expressions I demonstrated. You an employ tactics like FORCING the starting directory to be your programs home directory, and eating any periods,back-slashes, and any other "path" chars, and force the directory to be created under your home dir. Hope this helps, sorry for the flood of data, but we've all been where you are!
Convert the input to uppercase, then compare to your uppercase forbidden string:
If uCase(sFldrname) = "COM1" Then
...
To avoid mistakes with the forbidden strings, uppercase them too:
If uCase(sFldrname) = uCase("COM1") Then
...

Is there a way to make special characters work when using InStr in VBScript?

A VBScript is in use to shorten the system path by replacing entries with the 8.3 versions since it gets cluttered with how much software is installed on our builds. I'm currently adding the ability to remove duplicates, but it's not working correctly.
Here is the relevant portion of code:
original = "apple;orange;apple;lemon\banana;lemon\banana"
shortArray=Split(original, ";")
shortened = shortArray(1) & ";"
For n=2 to Ubound(shortArray)
'If the shortArray element is not in in the shortened string, add it
If NOT (InStr(1, shortened, shortArray(n), 1)) THEN
shortened = shortened & ";" & shortArray(n)
ELSE
'If it already exists in the string, ignore the element
shortened=shortened
End If
Next
(Normally "original" is the system path, I'm just using fruit names to test...)
The output should be something like
apple;orange;lemon\banana
The issue is entries with punctuation, such as lemon\banana, seem to be skipped(?). I've tested it with other punctuation marks, still skips over it. Which is an issue, seeing how the system path has punctuation in every entry.
I know the basic structure works, since there are only one of each entry without punctuation. However, the real output is something like
apple;orange;lemon\banana;lemon\banana
I thought maybe it was just a character escape issue. But no. It still will not do anything with entries containing punctuation.
Is there something I am doing wrong, or is this just a "feature" of VBScript?
Thanks in advance.
This code:
original = "apple;orange;apple;lemon\banana;lemon\banana"
shortArray = Split(original, ";")
shortened = shortArray(0) ' array indices start with 0; & ";" not here
For n=1 to Ubound(shortArray)
'If the shortArray element is not in in the shortened string, add it
'i.e. If InStr() returns *number* 0; Not applied to a number will negate bitwise
' If 0 = InStr(1, shortened, shortArray(n), 1) THEN
If Not CBool(InStr(1, shortened, shortArray(n), 1)) THEN ' if you insist on Not
WScript.Echo "A", shortArray(n), shortened, InStr(1, shortened, shortArray(n), vbTextCompare)
shortened = shortened & ";" & shortArray(n)
End If
Next
WScript.Echo 0, original
WScript.Echo 1, shortened
WScript.Echo 2, Join(unique(shortArray), ";")
Function unique(a)
Dim d : Set d = CreateObject("Scripting.Dictionary")
Dim e
For Each e In a
d(e) = Empty
Next
unique = d.Keys()
End Function
output:
0 apple;orange;apple;lemon\banana;lemon\banana
1 apple;orange;lemon\banana
2 apple;orange;lemon\banana
demonstrates/explains your errors (indices, Not) and shows how to use the proper tool for uniqueness (dictionary).

Extracting strings and writing to a new file

I was googling around but didn't find the right answer, perhaps people from here are willingly and able to help me.
I'm very new to VBS or WSH and I like to have a solution for this problem:
I'm searching for textstrings within a file without a line break (only one line). The textstrings I'm looking for start always with the same content "jpgline" and ends with the three letters "qbm". How can we extract each sentence (the strings are always 64 chars long) containg "jpgline....qbm" into a separate file.
I'm looking for a solution in Visual Basic Script as I use Windows 7.
Thanks in advance
M i k e
Use a regular expression:
Set re = New RegExp
re.Pattern = "^jpgline.*qbm$"
re.IgnoreCase = True
Set fso = CreateObject("Scripting.FileSystemObject")
Set inFile = fso.OpenTextFile("C:\path\to\input.txt")
Set outFile = fso.OpenTextFile("C:\path\to\output.txt", 2, True)
Do Until inFile.AtEndOfStream
line = inFile.ReadLine
If re.Test(line) Then outFile.WriteLine line
Loop
inFile.Close
outFile.Close
As your input file has no lines, use .ReadAll() to load its entire content into a string variable. Apply a RegExp to get all parts (Matches) defined by the pattern "jpgline.{N}qbm" where N is either 64 or 64 - the length of the pre/suffix. Ansgar has shown how to open and write to the output file.
Use the RegExp Docs to learn about .Execute and how to loop over the resulting match collection. The docs will tell you about .Test too.

Need to find character within apostrophe substring and replace it, any ideas?

Ok, let me preface this question with the fact that I am extremely new to vb script, but I need to make an addition to a script that another developer created and he is away.
Problem. :
I am getting data that is feed into a process. The script I already have handles some things that I won't go into. One thing I found out that it doesn't handle correctly is commas that occur in double quotes.
So I get some data like this. :
Joe, Bill, James, Alex, "Google, Inc", Rose, "Kickstarter, LLC"
What happens is that when this script kicks to the process application it blows up because of these commas in the double quotes. I need to be able to have this script go in and replace those commas in the Google and Kickstarter blocks with something a little more unique.
If you have the answer to this I would appreciate it, but I wouldn't mind some direction either of something that does something like this, etc.
Any answers are greatly appreciated. Again very new to vbascript just started reading syntax on it today.
You left out a few details about the format of the input data and the replacement text. However, the approach you need to take is to use the regular expression capability of VBScript to identify patterns in your input data, then use the "Replace" method to replace them. Here's a short MS article about regular expressions in VBScript.
Here's an example of what it might look like. This example is definitely NOT bullet proof and it makes some assumptions, but I think it will get you started:
Dim re, strstr, newstrstr
Dim inputstrarray(7)
Set re = new regexp
inputstrarray(0) = "Joe"
inputstrarray(1) = "Bill"
inputstrarray(2) = "James"
inputstrarray(3) = "Alex"
inputstrarray(4) = """" & "Google, Inc" & """"
inputstrarray(5) = "Rose"
inputstrarray(6) = """" & "Kickstarter, LLC" & """"
re.pattern = ",\s" 'pattern is a comma followed by a space
For Each strstr In inputstrarray 'loop through each string in the array
newstrstr = re.Replace(strstr, "_") 'replace the pattern with an underscore
If StrComp(strstr,newstrstr) Then
Wscript.Echo "Replace " & strstr & " with " & newstrstr
Else
Wscript.Echo "No Change"
End If
Next
Output looks like the following:
No Change
No Change
No Change
No Change
Replace "Google, Inc" with "Google_Inc"
No Change
Replace "Kickstarter, LLC" with "Kickstarter_LLC"
No Change

vbscript - Replace all spaces

I have 6400+ records which I am looping through. For each of these: I check that the address is valid by testing it against something similar to what the Post Office uses (find address). I need to double check that the postcode I have pulled back matches.
The only problem is that the postcode may have been inputted in a number of different formats for example:
OP6 6YH
OP66YH
OP6 6YH.
If Replace(strPostcode," ","") = Replace(xmlAddress.selectSingleNode("//postcode").text," ","") Then
I want to remove all spaces from the string. If I do the Replace above, it removes the space for the first example but leave one for the third.
I know that I can remove these using a loop statement, but believe this will make the script run really slow as it will have to loop through 6400+ records to remove the spaces.
Is there another way?
I didn't realise you had to add -1 to remove all spaces
Replace(strPostcode," ","",1,-1)
Personally I've just done a loop like this:
Dim sLast
Do
sLast = strPostcode
strPostcode = Replace(strPostcode, " ", "")
If sLast = strPostcode Then Exit Do
Loop
However you may want to use a regular expression replace instead:
Dim re : Set re = New RegExp
re.Global = True
re.Pattern = " +" ' Match one or more spaces
WScript.Echo re.Replace("OP6 6YH.", "")
WScript.Echo re.Replace("OP6 6YH.", "")
WScript.Echo re.Replace("O P 6 6 Y H.", "")
Set re = Nothing
The output of the latter is:
D:\Development>cscript replace.vbs
OP66YH.
OP66YH.
OP66YH.
D:\Development>
This is the syntax Replace(expression, find, replacewith[, start[, count[, compare]]])
it will default to -1 for count and 1 for start. May be some dll is corrupt changing the defaults of Replace function.
String.Join("", YourString.Split({" "}, StringSplitOptions.RemoveEmptyEntries))
Because you get all strings without spaces and you join them with separator "".

Resources