If I have a text file that contains the below information, what is the best way to search for the version, for example on system1 only? (in vb6 code, can I use InStr?)
[system1]
version=xx
date=xx
[system2]
version=xx
date=xx
The sample file looks like a standard INI file. You can read these using the GetPrivateProfileString() and related functions. You can also enumerate the sections and values using GetPrivateProfileSectionNames() and GetPrivateProfileSection().
Supposing there is a space after the version and before date (str would be your text):
Dim version As String
version = Mid(str, InStr(str, "version") + 8)
version = Mid(version, 1, InStr(version, " "))
But there are a bunch of functions to parse .ini files out there.
I created a text file "C:\MYFILE.TXT" and this is the content of the file:
[system1]
version=aa
date=bb
[system2]
version=yy
date=zz
[system3]
date=4
[system4]
[system5]
As you can see, I made all possible situation, ie. a system with version info, a system with no version info, etc. Then I wrote this code:
Here is one way to look for a value under a categorized list:
Dim mySystem As String
Dim myVersion As String
mySystem = "[system2]" 'Replace this with the system you are looking for
Dim strTmp As String
Dim SystemFound As Boolean
Dim VersionFound As Boolean
Open "c:\myfilename.txt" For Input As #1
Do While Not EOF(1)
Line Input #1, strTmp
If InStr(UCase(strTmp), UCase(mySystem)) > 0 Then
SystemFound = True
strTmp = ""
Do While Not EOF(1) And InStr(strTmp, "[") = 0
Line Input #1, strTmp
If InStr(UCase(strTmp), "VERSION") > 0 Then
VersionFound = True
myVersion = Mid(strTmp, InStr(strTmp, "=") + 1, Len(strTmp))
End If
Loop
Exit Do
End If
Loop
Close #1
If SystemFound And VersionFound Then
MsgBox "The Version of " & mySystem & " is " & myVersion
ElseIf SystemFound And Not VersionFound Then
MsgBox "The system " & mySystem & " has no version definition"
ElseIf SystemFound = False Then
MsgBox "The system " & mySystem & " is not found in file"
End If
Related
Ok, so we need to create a GPO that allows our users to only use specific programs.
GPO Location:
User Configuration
Policies
Administrative Templates [...]
System
Run only specified Windows applications
Then setting the GPO to enabled and clicking on List of allowed applications --> Show...
I have created an excel spreadsheet containing the names of all the programs and their associated executable files with other pertinent information so that we can easily organize, add, delete, etc. the executable files that we need to allow our users access to.
This spreadsheet then dumps all the executable files into a text file.
Here is an example of what the text file looks like:
Acrobat.exe
chrome.exe
calc.exe
.
.
.
There are a lot of entries and these are likely subject to change. What I am trying to do is create a script that will take that text file and populate the GPO automatically. I don't care if we have to open the window and then run it, it does not need to run from the task scheduler (although that would be amazing if someone has that code ready). We just need it to populate this ridiculous amount of executable filenames into the fields.
Here is code I found (VBScript) that when run, should populate the fields automatically, however I cannot get it to run in the Group Policy Management Editor (it runs in the windows explorer window instead and ends up searching for some of the files)
' Open the text file, located in the same path as the script
Set objFSO = CreateObject("Scripting.FileSystemObject")
strPath = Mid(Wscript.ScriptFullName, 1, InStrRev(Wscript.ScriptFullName, wscript.ScriptName) -1)
Set objFile = objFSO.OpenTextFile(strPath & "appList.txt")
' Activate the "Show Contents" window with the "List of allowed applications".
' Note the window must be opened already and we should have selected where in
' the list we want to enter the data before running the script
set WshShell = WScript.CreateObject("WScript.Shell")
WScript.Sleep 1000
WshShell.AppActivate "Show Contents"
' Read the file line by line
Do While objFile.AtEndOfStream <> True
' Each line contains one EXE name
exeName = objFile.ReadLine
' Escape forbidden chars { } [ ] ( ) + ^ % ~
exeName = Replace(exeName, "[", "{[}")
exeName = Replace(exeName, "]", "{]}")
exeName = Replace(exeName, "(", "{(}")
exeName = Replace(exeName, ")", "{)}")
exeName = Replace(exeName, "+", "{+}")
exeName = Replace(exeName, "^", "{^}")
exeName = Replace(exeName, "%", "{%}")
exeName = Replace(exeName, "~", "{~}")
' Send the EXE name to the window
WScript.Sleep 100
WshShell.SendKeys exeName
' Move to the next one
WshShell.SendKeys "{TAB}"
Loop
objFile.Close
from: http://blogs.msdn.com/b/alejacma/archive/2011/03/24/how-to-update-quot-run-only-specified-windows-applications-quot-gpo-programmatically-vbscript.aspx
"C:\Windows\System32\GroupPolicy\User\Registry.pol"
Is where my policies are stored. It's a semi text file. Try writing to that file.
Ok, so I tried it many different ways. If anyone is looking for an answer to do this, this is the way I've figured it out and the way I've decided to proceed. I will post all relevant code below.
In Excel, the format of my table is as follows:
(With obviously WAY more entries)
Here is the VBA code I used to turn the data from this file into the proper format for the registry key:
VBA - In Excel
Public Sub ExportToTextFile(FName As String, _
Sep As String, SelectionOnly As Boolean, _
AppendData As Boolean)
Dim WholeLine As String
Dim FNum As Integer
Dim RowNdx As Long
Dim ColNdx As Integer
Dim StartRow As Long
Dim EndRow As Long
Dim StartCol As Integer
Dim EndCol As Integer
Dim CellValue As String
Application.ScreenUpdating = False
On Error GoTo EndMacro:
FNum = FreeFile
StartRow = 2
If SelectionOnly = True Then
With Selection
StartCol = .Cells(2).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(2).Column
End With
Else
With ActiveSheet.UsedRange
StartCol = .Cells(2).Column
EndRow = .Cells(.Cells.Count).Row
EndCol = .Cells(2).Column
End With
End If
If AppendData = True Then
Open FName For Append Access Write As #FNum
Else
Open FName For Output Access Write As #FNum
End If
For RowNdx = StartRow To EndRow
WholeLine = ""
For ColNdx = StartCol To EndCol
If Cells(RowNdx, ColNdx).Value = "" Then
CellValue = ""
Else
CellValue = Cells(RowNdx, ColNdx).Value
End If
WholeLine = WholeLine & Chr(34) & CellValue & ".exe" & Chr(34) & "=" & Chr(34) & CellValue & ".exe" & Chr(34) & Sep
Next ColNdx
WholeLine = Left(WholeLine, Len(WholeLine) - Len(Sep))
Print #FNum, WholeLine; ""
Next RowNdx
EndMacro:
On Error GoTo 0
Application.ScreenUpdating = True
Close #FNum
End Sub
Sub PipeExport()
Dim FileName As Variant
Dim Sep As String
FileName = Application.GetSaveAsFilename(InitialFileName:="appList", filefilter:="Text (*.txt),*.txt")
If FileName = False Then
''''''''''''''''''''''''''
' user cancelled, get out
''''''''''''''''''''''''''
Exit Sub
End If
Sep = "|"
If Sep = vbNullString Then
''''''''''''''''''''''''''
' user cancelled, get out
''''''''''''''''''''''''''
Exit Sub
End If
Debug.Print "FileName: " & FileName, "Extension: " & Sep
ExportToTextFile FName:=CStr(FileName), Sep:=CStr(Sep), _
SelectionOnly:=False, AppendData:=False
End Sub
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
PipeExport
End Sub
The file that is created is appList.txt and its format is the same format as the registry key:
"Acrobat.exe"="Acrobat.exe"
"AcroRd32.exe"="AcroRd32.exe"
Now in your GPO, add a unique program name to the allowed applications list (say test1234.exe) and in your registry editor, go to Edit > Find test1234.exe.
Export that registry key under File > Export. Remove the test1234.exe line and paste in your text file. Then reimport that file and you're done!
I am trying to compare some Md5's of some files to see if they are the same after I have copied them to another drive, and if they are the same then to delete the original files. I am lost on the syntax because I have never done something like this before.
I am using a free utility vmd5.exe (command line) to get the md5's. I am just not sure how to tell vbscript that if the outputs are the same then to go ahead and delete the files. This is just a snippet of the part where I am trying to compare the two md5's but this is what I have so far:
Dim md5Command, md5Command2
md5Command = "C:\Program Files\vmd5.exe " vmd5 & " " & C:\Testscripts\
md5Command2 = "C:\Program Files\vmd5.exe " vmd5 & " " & E:\CopyTestFolder\
If md5Command = md5Command2 then
objFSO.DeleteFolder("C:\ScriptOutput") 'Can either delete entire archived folder, or just .zip files in folder
objFSO.DeleteFile("C:\Testscripts\Archive*.evtx") 'This will be path where archived logs are located once finished
Else
End If
This syntax is wrong for sure. But from what I know about IF then's I need it to look something like this. I am just not sure if I need to be telling the script to run the commands in the "set" part or how I can tell the script to grab the md5 output from the command line and compare it to another.
After the Else statement I would like it to either end the script or just output a text file with the different md5's but I am not to that point yet and haven't really decided on anything.
If there is a better way to do something like this I would also be up to do that, this is about all I was coming up with this morning though.
EDIT: I thought of something that might be possible. If I tell the command line to output the contents of the output to a text file then I could compare two different text files and if the contents match then it could proceed with the rest of the script. I don't know how to get this to work but the logic seems to make sense.
Here is what the output of the text file that it creates looks like:
Vallen VMD5 R2009.1215
Filename MD5 sum
------------------------------------------------------------
[C:\ScriptOutput\]
Testzip.zip d5db2ff8c372a12c145170fb7340e682
To tackle your task, you have to solve some sub problems:
String concatenation in VBScript: "... exe " vmd5 & " " - to splice in the content of the variable vmd5, you need the concatenation operator on both sides - but is that what you want to do? " " & C:\Testscripts\ - to append the literal 'C:\Testscripts\', you need to (double) quote the literal - but then you could combine all the components into one string literal.
In VBScript " are used as string literal delimiters; they don't work like backticks in more powerful scripting languages. md5Command must hold the command you want to execute; to get the result of that command is a different kettle of fish.
To shell out/execute a command, you'll have to use the .Exec or the .Run method of the WScript.Shell object and collect the output.
Depending on the (output of) the tool you use, you won't be able to compare the results via the = operator - e.g. the pathes or the order of the files/cheksums may differ. So you'll need a strategy for parsing the captured output.
Which sub problem do you want to deal with first?
As your comments prove, getting the syntax right should be the starting point. This:
Dim aDirs : aDirs = Array("..\data\one", "..\data\two")
' Join an array of the components (no more problems
' with (forgetting (to concat)) separators)
' Use qq() function to lessen the noise
Dim sCmdT : sCmdT = Join(Array( _
"fciv" _
, "-add" _
, qq("§DIR§") _
), " ")
Dim nDir, sDir, sCmd
For nDir = 0 To UBound(aDirs)
sDir = aDirs(nDir)
' Use replace on a template to avoid repetition
sCmd = Replace(sCmdT, "§DIR§", sDir)
WScript.Echo "sCmd: |" & sCmd & "|"
Next
output:
sCmd: |fciv -add "..\data\one"|
sCmd: |fciv -add "..\data\two"|
illustrates 3 methods to make it easier/less errorprone to 'build' (shell) commands or SQL statements. (Implementation of the qq() function is left as exercise).
As I don't have the vmd5 utility, I'll use fciv in the further examples.
The next (version of the) script:
Dim aDirs : aDirs = Array("..\data\one", "..\data\two")
Dim sCmdT : sCmdT = Join(Array( _
"fciv" _
, "-add" _
, qq("§DIR§") _
), " ")
Dim oWSH : Set oWSH = CreateObject("WScript.Shell")
Dim nDir, sDir, sCmd, oExec, sRes
For nDir = 0 To UBound(aDirs)
sDir = aDirs(nDir)
sCmd = Replace(sCmdT, "§DIR§", sDir)
Set oExec = oWSH.Exec(sCmd)
sRes = oExec.Stdout.ReadAll()
WScript.Echo sRes
Next
output:
CmpMd500 - compare md5 checksums
==============================================================
//
// File Checksum Integrity Verifier version 2.05.
//
09fea378b96141413f5f09444573f0f3 ..\data\one\version.txt
4945c1ffd9ceb14c83e003091c6e8455 ..\data\one\README.md
4c4c34f7b6f0863056615d2cbcdf6912 ..\data\one\History.txt
//
// File Checksum Integrity Verifier version 2.05.
//
09fea378b96141413f5f09444573f0f3 ..\data\two\version.txt
4945c1ffd9ceb14c83e003091c6e8455 ..\data\two\README.md
4c4c34f7b6f0863056615d2cbcdf6912 ..\data\two\History.txt
==============================================================
demonstrates the absolute minimum of code to execute a command and capture the output - a production version must add a lot of code for error handling. At the same time, it shows sample output to discuss how to parse/compare the checksums. Can you post sample output of your vmd5 utility?
Whether you get the output of the md5 utility directly (my above sample) or from a file, you'll need a Regular Expression to parse the string into data that can be processed further. A simple script to work with files like you published in your question:
Dim reMd5File : Set reMd5File = New RegExp
reMd5File.Global = True
reMd5File.Multiline = True
reMd5File.Pattern = "^(\S+)\s+(\w{32})"
Dim sDir : sDir = "..\data\three"
Dim oFile
For Each oFile In goFS.GetFolder(sDir).Files
Dim sAll : sAll = oFile.OpenAsTextStream(ForReading).ReadAll()
WScript.Echo sAll
Dim oMTS : Set oMTS = reMd5File.Execute(sAll)
Dim oMT
For Each oMT In oMTS
WScript.Echo "** parsed:", qq(oMT.Submatches(1)), qq(oMT.Submatches(0))
Next
Next
output:
CmpMd501 - compare md5 checksums
==================================================================
Vallen VMD5 R2009.1215
Filename MD5 sum
------------------------------------------------------------
[C:\ScriptOutput\]
Testzip.zip d5db2ff8c372a12c145170fb7340e682
version.txt 09fea378b96141413f5f09444573f0f3
README.md 4945c1ffd9ceb14c83e003091c6e8455
History.txt 4c4c34f7b6f0863056615d2cbcdf6912
** parsed: "d5db2ff8c372a12c145170fb7340e682" "Testzip.zip"
** parsed: "09fea378b96141413f5f09444573f0f3" "version.txt"
** parsed: "4945c1ffd9ceb14c83e003091c6e8455" "README.md"
** parsed: "4c4c34f7b6f0863056615d2cbcdf6912" "History.txt"
********************
Vallen VMD5 R2009.1215
Filename MD5 sum
------------------------------------------------------------
[C:\ScriptOutput\]
Testzip.zip d5db2ff8c372a12c145170fb7340e682
** parsed: "d5db2ff8c372a12c145170fb7340e682" "Testzip.zip"
********************
==================================================================
xpl.vbs: Erfolgreich beendet. (0) [0.14844 secs]
After working thru that code, you'll have no problem with this script, that adds
'storing of the results in dictionaries' to my 'read .Exec output' version:
Dim aDirs : aDirs = Array("..\data\one", "..\data\two")
Dim sCmdT : sCmdT = Join(Array( _
"fciv" _
, "-add" _
, qq("§DIR§") _
), " ")
Dim oWSH : Set oWSH = CreateObject("WScript.Shell")
ReDim aRes(UBound(aDirs))
Dim reMd5File : Set reMd5File = New RegExp
reMd5File.Global = True
reMd5File.Multiline = True
reMd5File.Pattern = "^(\w{32})\s(.+?)\s+$"
Dim nDir, sDir, sCmd, oExec, sRes, oMTS, oMT
For nDir = 0 To UBound(aDirs)
sDir = aDirs(nDir)
sCmd = Replace(sCmdT, "§DIR§", sDir)
Set oExec = oWSH.Exec(sCmd)
sRes = oExec.Stdout.ReadAll()
Set aRes(nDir) = CreateObject("Scripting.Dictionary")
Set oMTS = reMd5File.Execute(sRes)
For Each oMT in oMTS
aRes(nDir)(goFS.GetBaseName(oMT.SubMatches(1))) = oMT.SubMatches(0)
Next
Next
Dim sFile
For nDir = 0 To UBound(aDirs)
For Each sFile In aRes(nDir).Keys
WScript.Echo aRes(nDir)(sFile), sFile
Next
WScript.Echo
Next
output:
===========================================
09fea378b96141413f5f09444573f0f3 version
4945c1ffd9ceb14c83e003091c6e8455 README
0252535193507019a0eb97328d28dd80 robic
4c4c34f7b6f0863056615d2cbcdf6912 History
09fea378b96141413f5f09444573f0f3 version
4945c1ffd9ceb14c83e003091c6e8455 README
4c4c34f7b6f0863056615d2cbcdf6912 History
c46264f8101b6c1609c77b4c674bd327 Rakefile
===========================================
The next - and last, I hope - step would be to do the comparisons (Are files missing from one folder?, Do the checksums for the 'same' file differ?). Any ideas from your side?
how o write vb code which can except parameter at runtime
ex. My exe is "readfile.exe" and if i want to give file name rom command line the command to be executed will be
readfile.exe filename
it should take the file name parameter and perform the action
Look at the Command function, that should give you all the parameters that were passed in.
I can't find the VB6 docs for it online, but MSDN have the docs for the VBA version, and that's usually the same so I'd suggest looking here for more info. And it even has a full sample here.
You can do something like this:
Sub Main()
Dim a_strArgs() As String
Dim blnDebug As Boolean
Dim strFilename As String
Dim i As Integer
a_strArgs = Split(Command$, " ")
For i = LBound(a_strArgs) To UBound(a_strArgs)
Select Case LCase(a_strArgs(i))
Case "-d", "/d"
' debug mode
blnDebug = True
Case "-f", "/f"
' filename specified
If i = UBound(a_strArgs) Then
MsgBox "Filename not specified."
Else
i = i + 1
End If
If Left(a_strArgs(i), 1) = "-" Or Left(a_strArgs(i), 1) = "/" Then
MsgBox "Invalid filename."
Else
strFilename = a_strArgs(i)
End If
Case Else
MsgBox "Invalid argument: " & a_strArgs(i)
End Select
Next i
MsgBox "Debug mode: " & blnDebug
MsgBox "Filename: " & strFilename
End Sub
I want to store some addresses in a text file and then read specific portions of the file, based on group membership. I've done all of the group membership stuff so I don't need any help for that.
But I'm not sure if I should use a plain text file or an INI file?
The thing is, the post addresses are in two or three lines and I need line break.
I tried using a plain text file, but I couldn't manage to get a line break correctly.
So INI files would be preferable?
The INI file could look like this:
[London]
Address 1
Postbox 3245
58348 London
[Copenhagen]
Address 2
Postbox 2455
5478347 Copenhagen
I'm not quite sure if this is possible in an INI file though, perhaps I need to name each line as well. OR, I could possibly use a plain text file and search for the word [london] and then read each line until there's a line break. Then store all of those lines in a variable that I'll pass along?
How would you guys solve this?
I have written a small VBScript Class that handles "real' ini files written with such format:
[section_name]
key1 = value1
key2 = value2
The code for the class is:
Class IniFileObject
Private m_Data
Private Sub Class_Initialize
Set m_Data = Server.CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate
Dim key
If IsObject(m_Data) Then
For Each key In m_Data
m_Data(key).RemoveAll
Set m_Data(key) = Nothing
Next
m_Data.RemoveAll
Set m_Data = Nothing
End If
End Sub
Public Function Init(sFilePath)
Dim arrLines, sLine, x
Dim sCurSection, oSectionDict
Set Init = Me
arrLines = GetFileLines(sFilePath)
If Not(IsArray(arrLines)) Then Exit Function
sCurSection = ""
For x = 0 To UBound(arrLines)
sLine = Trim(arrLines(x))
If Len(sLine)>0 Then
If Left(sLine, 1)="[" Then
If Not(HandleSectionLine(sLine, sCurSection)) Then Exit Function
Else
If Len(sCurSection)=0 Then
Err.Raise 1005, "IniFileObject init", "Found value outside any section (" & Server.HTMLEncode(sLine) & ")"
Exit Function
End If
Set oSectionDict = m_Data(sCurSection)
If Not(ParseOneLine(sLine, oSectionDict)) Then Exit Function
Set m_Data(sCurSection) = oSectionDict
End If
End If
Next
End Function
Public Property Get ReadValue(section, key)
Dim oSectionDict
ReadValue = ""
If m_Data.Exists(section) Then
Set oSectionDict = m_Data(section)
If oSectionDict.Exists(key) Then ReadValue = oSectionDict(key)
End If
End Property
Private Function ParseOneLine(ByVal sLine, ByRef oSectionDict)
Dim arrTemp, sErrorMsg, sKey
sErrorMsg = ""
ParseOneLine = True
If Left(sLine, 2)="//" Or Left(sLine, 1)="'" Or Left(sLine, 1)="{" Then Exit Function
arrTemp = Split(sLine, "=")
If UBound(arrTemp)=1 Then
sKey = Trim(arrTemp(0))
If (Len(sKey)>0) And (Len(arrTemp(1))>0) Then
If Not(oSectionDict.Exists(sKey)) Then
oSectionDict.Add sKey, Trim(arrTemp(1))
Else
sErrorMsg = "Key already exists"
End If
Else
sErrorMsg = "Empty key or value"
End If
Else
sErrorMsg = "Missing or too much '=' characters"
End If
Erase arrTemp
If Len(sErrorMsg)>0 Then
ParseOneLine = False
Err.Raise 1006, "IniFileObject Init", "Failed to parse single line (" & Server.HTMLEncode(sLine) & "): " & sErrorMsg
End If
End Function
Private Function HandleSectionLine(ByVal sLine, ByRef sCurSection)
HandleSectionLine = False
If (Len(sLine)<3) Or (Right(sLine, 1)<>"]") Then
Err.Raise 1002, "IniFileObject init", "Invalid line found: " & Server.HTMLEncode(sLine)
Exit Function
End If
sCurSection = Mid(sLine, 2, Len(sLine) - 2)
If m_Data.Exists(sCurSection) Then
Err.Raise 1003, "IniFileObject init", "Section exists more than once: " & Server.HTMLEncode(sCurSection)
Exit Function
End If
m_Data.Add sCurSection, Server.CreateObject("Scripting.Dictionary")
HandleSectionLine = True
End Function
Private Function GetFileLines(sFilePath)
Dim objFSO, oFile
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
If Not(objFSO.FileExists(sFilePath)) Then
Set objFSO = Nothing
Err.Raise 1001, "IniFileObject init", "file path '" & Server.HTMLEncode(sFilePath) & "' does not exist, check permissions"
Exit Function
End If
Set oFile = objFSO.OpenTextFile(sFilePath)
GetFileLines = Split(oFile.ReadAll, VBCrLf)
oFile.Close
Set oFile = Nothing
Set objFSO = Nothing
End Function
End Class
Usage example:
Dim filePath, ini
filePath = Server.MapPath("config.ini")
Set ini = New IniFileObject.Init(filePath)
Response.Write("Value for 'Key001': " & ini.ReadValue("MySection", "Key001") & "<br />")
Set ini = Nothing
The code throw various errors when the file does not exist or contains invalid lines, the errors are pretty much clear. It's possible to "suppress" the errors and not display error page by using such code when consuming:
On Error Resume Next
Set ini = New IniFileObject.Init(filePath)
If Err.Number<>0 Then
Response.Write("Error reading ini file")
End If
On Error Goto 0
If IsObject(ini) Then
Response.Write("Value for 'IP001': " & ini.ReadValue("IPaddress", "IP001") & "<br />")
Set ini = Nothing
End If
I would probably use CSV file instead where each row will represent a country.
Country,Address1,Address2,Address3,Address4
London,Address 1,Postbox 3245,58348 London
Copenhagen,Address 2,Postbox 2455,5478347,Copenhagen
If you can easily identify your data then you could probably have more descriptive column names (i.e. Street1, Street2, Town, Postcode, etc.).
This file format is also easy to read since you only read one line of the input file at a time and split it using something like
aAddress = split(sLine, ",")
To make it even easier to work with you could use dictionary object and use country as a key and array as a value
'sLine should be read from input file'
sLine = "Copenhagen,Address 2,Postbox 2455,5478347,Copenhagen"
'Create dictionary for addresses'
Set dic = CreateObject("Scripting.Dictionary")
'Split line into array'
aAddressParts = Split(sLine, ",")
'Remove the first element of the array'
sValues = Mid(sLine, InStr(sLine, ",")+1)
aValues = Split(sValues, ",")
'Add new entry into dictionary'
dic.Add aAddressParts(0), aValues
'Usage'
MsgBox "Address for Copenhagen: " & vbNewLine & _
Join(dic("Copenhagen"), "," & vbNewLine)
Thanks,
Maciej
You could store the addresses in one line and use a special character, for example an underscore, to indicate a line break. When you read the address, you just need to replace the special character with a line break.
[London]
Address = "Postbox 3245_58348
London"
[Copenhagen]
Address = "Postbox
2455_5478347 Copenhagen"
That allows you to store addresses with more lines or without a postbox line, as well. In my experience, information like "our addresses always have exactly two lines and the first one is always a postbox" is very often incorrect...
I use a small executable that launches native api for that: GetPrivateProfileString and WritePrivateProfileString.
The executable is called like that:
Set sh = CreateObject("WScript.Shell")
Set exec = sh.Exec("ini.exe get %APPDATA%\sth\file.ini ""Section name"" key")
sFirma1 = exec.StdOut.ReadLine
Call sh.Run("ini.exe set %APPDATA%\sth\file.ini ""Section name"" key set_value", 0)
See also Running command line silently with VbScript and getting output?.
This is the code of the executable:
#include <stdio.h>
#include <windows.h>
void usage()
{
puts("ini <get>/<set> <file> <section> <key> <value>");
exit(1);
}
int main(int cArg, char **aszArg)
{
int iFile = 2;
int iSection = 3;
int iKey = 4;
int iValue = 5;
if (cArg < 5) usage();
if (strcmp(aszArg[1], "get") != 0 && strcmp(aszArg[1], "set") != 0) usage();
if (strcmp(aszArg[1], "set") == 0 && cArg < iValue + 1) usage();
if (strcmp(aszArg[1], "set") == 0) {
if (!WritePrivateProfileString(aszArg[iSection], aszArg[iKey],
aszArg[iValue], aszArg[iFile]))
puts("Failure in WriteProfileString.");
} else {
char buf[1000];
buf[0] = 0;
GetPrivateProfileString(
aszArg[iSection], aszArg[iKey], "", buf, 999, aszArg[iFile]);
puts(buf);
}
return 0;
}
You need to compile it using a c compiler for Windows. I did it with gcc, but a free compiler from ms should also work. If this page with a 32-bit executable is still available, you may give it a try, but on your own responsibility. Hackers already visited my site once.
When I look at a directory in Windows Explorer, I can see a ProductName and ProductVersion property for the DLL's in that directory.
I need to export this DLL list with ProductName and ProductVersion into a text file.
If I do c:\>dir *.dll > test.log, the test.log does not have the ProductName and ProductVersion.
Could someone help me to get these properties exported to a file along with the filename?
Even if it is a freeware tool or some other dir switch, that will be useful.
PowerShell is your friend here - and it's freely (as in beer) available from Microsoft.
The following is a one liner to spit out the product name, product version and file name of all the dlls in the windows directory into test.log:
dir c:\windows\*.dll | % {[System.Diagnostics.FileVersionInfo]::GetVersionInfo($_)} | % { $_.ProductName + ", " + $_.ProductVersion + ", " + $_.FileName} > test.log
OK, so it's a long line - but it is still just one line at the command prompt.
PowerShell afficionados will probably be able to condense the above still further. Note that PowerShell allows us to use the .Net base class library (or even your own assemblies) such as System.Diagnostics.FileVersionInfo from the command line!
If you haven't played with PowerShell yet, you have a treat in store - particularly if you are a .Net developer :)
Using VBScript you could do the following:
Set objShell = CreateObject ("Shell.Application")
Set objFolder = objShell.Namespace ("C:\Scripts")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim arrHeaders(40)
For i = 0 to 40
arrHeaders(i) = objFolder.GetDetailsOf (objFolder.Items, i)
Next
For Each strFileName in objFolder.Items
For i = 0 to 40
Wscript.echo arrHeaders(i) & ": " & objFolder.GetDetailsOf (strFileName, i)
Next
Wscript.Echo
Next
You can do this fairly easily with a .NET application.
using System;
using System.Diagnostics;
static class MainClass
{
static void Main(string[] args)
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo("c:\\test.txt");
// Display version information.
Console.WriteLine("Checking File: " + info.FileName);
Console.WriteLine("Product Name: " + info.ProductName);
Console.WriteLine("Product Version: " + info.ProductVersion);
Console.WriteLine("Company Name: " + info.CompanyName);
}
}
Obviously, you'd have to add a function that retrieved all the files in a specified directory.
Adding a VB.Net version to the list:
Sub CreateLog(ByVal Logfile As String, ByVal PathToLog As String, Optional ByVal SearchPattern As String = "*.*")
Dim FileInfo As FileVersionInfo
Dim ret As String = ""
For Each File As String In IO.Directory.GetFiles(PathToLog, SearchPattern)
FileInfo = FileVersionInfo.GetVersionInfo(File)
If FileInfo.ProductName & FileInfo.ProductVersion <> "" Then
ret &= FileInfo.ProductName & ", " & FileInfo.ProductVersion & vbCrLf
End If
Next
IO.File.WriteAllText(Logfile, ret)
End Sub
Call it by: CreateLog("c:\log.txt", "c:\windows", "*.dll")
Edit:Added searchpattern.
I cannot speak to this software at all, but this appears to do what you're looking for:
http://www.softpedia.com/get/Programming/Other-Programming-Files/STRFINFO.shtml
SYNTAX
~~~~~~
StrFInfo[.EXE] ExeDllOcxFileName [Property1 [Property2 ...]]
COMMON PROPERTIES
~~~~~~~~~~~~~~~~~
FileDescription FileVersion InternalName
OriginalFileName ProductName ProductVersion
CompanyName LegalCopyRight $Translation
Interesting, I didn't know this GetDetailsOf function.
I wondered about the arbitrary size...
I am not sure what is the limit, which seem to vary between folders or at least user settings or something, so I made something more flexible:
Set shell = CreateObject("Shell.Application")
Set folder = shell.Namespace("D:\Documents")
Set fso = CreateObject("Scripting.FileSystemObject")
For Each fileName in folder.Items
i = 0
emptyNb = 0
Do
detail = folder.GetDetailsOf(folder.Items, i)
If detail = "" Then
emptyNb = emptyNb + 1
Else
detailValue = folder.GetDetailsOf(fileName, i)
If detailValue <> "" Then
Wscript.Echo i & " " & detail & ": " & detailValue
End If
emptyNb = 0
End If
i = i + 1
Loop While emptyNb < 3 ' Arbirary, adjust as you see fit
detailValue = folder.GetDetailsOf(fileName, -1)
If detailValue <> "" Then
Wscript.Echo "Tooltip:" & vbCrLf & detailValue
End If
Wscript.Echo
Next
To answer the question, you can check when detail is equal to the info you are looking for and only display these values.