How can one obtain the details of a windows file using VB.net?
The type of details I mean are those found when I right click on a file, say an MS word doc, then click "Properties" and select the "Details" tab.
I know some can be obtained via FileInfo, but not all, such as "Tags" for example.
Thanks
For that stuff you need to use Shell32. From the COM tab, find and add Microsoft Shell Controls and Automation. Here is code to create a list of property-values for a given file:
' class to hold the goodies
Friend Class ShellInfo
Public Property Name As String
Public Property Value As String
Public Sub New(n As String, v As String)
Name = n
Value = v
End Sub
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Then a function to fill it up
Private Function GetXtdShellInfo(filepath As String) As List(Of ShellInfo)
' ToDo: add error checking, maybe Try/Catch and
' surely check if the file exists before trying
Dim xtd As New List(Of ShellInfo)
Dim shell As New Shell32.Shell
Dim shFolder As Shell32.Folder
shFolder = shell.NameSpace(Path.GetDirectoryName(filepath))
' its com so iterate to find what we want -
' or modify to return a dictionary of lists for all the items
Dim key As String
For Each s In shFolder.Items
' look for the one we are after
If shfolder.GetDetailsOf(s, 0).ToLowerInvariant = Path.GetFileName(file).ToLowerInvariant Then
Dim ndx As Int32 = 0
key = shfolder.GetDetailsOf(shfolder.Items, ndx)
' there are a varying number of entries depending on the OS
' 34 min, W7=290, W8=309 with some blanks
' this should get up to 310 non blank elements
Do Until String.IsNullOrEmpty(key) AndAlso ndx > 310
If String.IsNullOrEmpty(key) = False Then
xtd.Add(New ShellInfo(key,
shfolder.GetDetailsOf(s, ndx)))
End If
ndx += 1
key = shfolder.GetDetailsOf(shfolder.Items, ndx)
Loop
' we got what we came for
Exit For
End If
Next
Return xtd
End Function
Using it is simple:
Dim xtd As List(Of ShellInfo) = GetXtdShellInfo("C:\Temp\Capri.jpg")
For Each s As ShellInfo In xtd
Console.WriteLine("{0}: {1}", s.Name, s.Value)
Next
The return should be a list of ShellInfo items where the Name is the property name such as Name, BitRate, Album and the associated Value will be that returned by Shell32. e.g
Name: Capri.jpg
Size: 15.2 KB
Item type: Image File
Date modified: 7/20/2014 12:19 PM
Date created: 7/20/2014 12:17 PM
Date accessed: 7/20/2014 12:17 PM
(etc)
The actual number returned will vary depending on the OS ver
As noted in the comment Microsoft Shell Controls and Automation is renamed as Microsoft Shell Folder View Router (in Windows 8.1).
Also, the first 35 properties are fairly well known and more common, but with Win7 there are about 291. Under Windows 8, the max is 309 with some blank spots and deep into the list some property indices are changed.
See this answer related question How to read the bit rate information from a .mov video file header
Dim shellAppType = Type.GetTypeFromProgID("Shell.Application")
Dim shellApp = Activator.CreateInstance(shellAppType)
Dim folder = shellApp.NameSpace("c:\users\frank")
Dim folderitem = folder.parsename("yourfile.jpg")
Dim value = folder.GetDetailsOf(folderitem, 24) 'eg. 24 retrieves File Comments.
Just use something like :
Dim MyFileInfos as System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(PathToYourFile)
Then get infos using MyFileInfo.* (whatever you need, use IntelliSense).
Have a nice day
Related
I want to know if there is a way to read a text file that lets say has content like so:
Store - 001P
Owner - Greg
Price - 45000
Employees - 30
Store - 002
Owner- Jen
Price - 34400
Now lets say I only want to work with the store information in the block where the store number contains a P. Is there a way to read the text file to check for the P after the delimiter, and then skip to the next instance of "store" in the text file? I tried to find which function is best as in different languages you can GoTo function, but I cannot find anything on this.
This is a snippet of my current code:
Dim columnV As New Dictionary(Of String, Integer)
Dim descriptionV As String
Dim quantityV As Integer
For Each totalLine As String In MyData
descriptionV = Split(totalLine, "-")(0)
quantityV = Split(totalLine, "-")(1)
If columnV.ContainsKey(descriptionV) Then
columnV(descriptionV) = colSums(descriptionV) + quantityV
Else
columnV.Add(descriptionV, quantityV)
End If
'Next
Ok, if I read this correct, you only want to worry about and process stores that end in a "P". Did I get that right?
and your data is like this then:
Store - 001P \n Owner - Greg \n Price - 45000 \n Employees - 30 \n
Store - 002\n Owner- Jen \n Price - 34400 \n
So in code we could go:
dim store as string
dim Owner as string
dim Price as decimal
dim employees as integer
' your code to read the data
now we have the process loop
For Each totalLine As String In MyData
store = trim(split(split(totalLine,"\n)(0),"-")(1))
Owner = trim(split(split(totalLine,"\n)(1),"-")(1))
Price = trim(split(split(totalLine,"\n")(3),"-")(1))
Employees = trim(split(split(totalLine,"\n")(4),"-")(1))
if strings.right(store,1) = "P" then
' our process code
If columnV.ContainsKey(store) Then
end if
Next
So you can use Strings.Right(some text,1) to get the right most character. You simply then have a if/then block around that code, and thus you skip anything that does not have a store with "P" as the last letter. The above is air code, but the simple concept here is to first:
Split out the line into the correct parts.
Check if store ends in "P" with the above if/then, and thus only stores ending in P will be processed.
However, your sample code and the variable names used really does not make a lot of sense.
It appears as if a record can be represented across multiple lines, but not a defined number of multiple lines (e.g. 001P is over 4 lines but 002 is over 3 lines).
It also appears as if the line represents the data in a {property} - {value} format.
The first thing that I would do is create a class to represent your record.
The second thing would be to get every line from your text file and iterate over them.
The third thing would be take the incoming information and convert it to your custom class which would be added to a List.
The last thing would be to then filter the List where Stores do not contain the letter "P".
Here is the code, in action:
Imports System
Imports System.Collections.Generic
Imports System.Linq
Public Module Module1
Public Sub Main()
IO.File.WriteAllLines("test.txt", {
"Store - 001P",
"Owner - Greg",
"Price - 45000",
"Employees - 30",
"Store - 002",
"Owner - Jen",
"Price - 34400"
})
Dim lines() As String = IO.File.ReadAllLines("test.txt")
Dim stores As List(Of Store) = ConvertLinesToStores(lines)
Dim storesWithP() As Store = stores.Where(Function(s) s.StoreId.Contains("P")).ToArray()
Console.WriteLine("Stores with P: ")
Console.WriteLine(String.Join(Environment.NewLine, storesWithP.Select(Function(s) s.StoreId).ToArray()))
End Sub
Private Function ConvertLinesToStores(ByVal lines() As String) As List(Of Store)
Dim stores As New List(Of Store)
Dim item As Store
For Each line As String In lines
Dim parts() As String = line.Split(" - ")
If (lines.Length < 3) Then
Continue For
End If
Dim propertyName As String = parts(0)
Dim propertyValue As String = parts(2)
Dim employeeCount As Integer
If (propertyName = "Store") Then
If (item IsNot Nothing) Then
stores.Add(item)
End If
item = New Store() With {.StoreId = propertyValue}
ElseIf (propertyName = "Owner") Then
item.Owner = propertyValue
ElseIf (propertyName = "Price") Then
item.Price = propertyValue
ElseIf (propertyName = "Employees" AndAlso Integer.TryParse(propertyValue, employeeCount)) Then
item.EmployeeCount = employeeCount
End If
Next
If (item IsNot Nothing) Then
stores.Add(item)
End If
Return stores
End Function
End Module
Public Class Store
Public Property StoreId As String
Public Property Owner As String
Public Property Price As Integer
Public Property EmployeeCount As Integer
End Class
Fiddle: Live Demo
Assuming your text file has a consistent pattern the following will give you a list of your stores with all the properties.
My Stores.txt looks like this...
Store - 001P
Owner - Greg
Price - 45000
Employees - 30
Store - 002
Owner- Jen
Price - 34400
Employees - 20
Store - 03P
Owner - Mary
Price - 50000
Employees - 22
Store - 04P
Owner - Bill
Price - 42000
Employees - 90
I created a simple class to hold the store data.
Public Class Store
Public Property ID As String
Public Property Owner As String
Public Property Price As Decimal
Public Property Employees As Integer
End Class
First I read the file getting an array of lines. I loop through the lines of the file skipping ahead by 5 on each iteration (Step 5).This should hit the Store line (Store appears every 5 lines).
If it contains a P then I create a new Store and set it properties by moving down one line (the i + 1 etc.). After the properties are set, I add the Store to the list.
Now you have a List(Of Store) containing only the stores who's Id contains a P. You can access the items by index or in a For Each loop and have all the properties available.
Private StoreList As New List(Of Store)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lines = File.ReadAllLines("C:\Users\maryo\Desktop\Stores.txt")
For i = 0 To lines.Length - 4 Step 5
Dim ID = lines(i).Split("-"c)(1).Trim
If ID.Contains("P") Then
Dim st As New Store
st.ID = ID
st.Owner = lines(i + 1).Split("-"c)(1).Trim
st.Price = CDec(lines(i + 2).Split("-"c)(1).Trim)
st.Employees = CInt(lines(i + 3).Split("-"c)(1).Trim)
StoreList.Add(st)
End If
Next
'Just to check if my list contains what I expected.
DataGridView1.DataSource = StoreList
End Sub
I'm writing a program that is using a validation of graphic card.
I tried using multiple ways; the closest one i found was using:
lblGrapics.Text = infotypes.VideocardName.GetName()
but the automatic return is equals 1.
how can i get the card name and other specifations?
This will allow you to poll any WMI class and get the desired values for the properties. In your case, you would select from the Win32_VideoController class. Other WMI class can be found here.
Imports System.Management
Public Class WMI
Public Shared Function GetWMISettingsDictionary(ByVal wmiClass As String,
ShoppingList() As String) As Dictionary(Of String, String)
Dim wmiInfo As New Dictionary(Of String, String)
Dim searcher As New System.Management.ManagementObjectSearcher("select * from " & wmiClass)
For Each item As System.Management.ManagementObject In searcher.Get
For Each PC As System.Management.PropertyData In item.Properties
' perform case insensitive search
For Each s As String in ShoppingList
If s.ToLowerInvariant = PC.Name.ToLowerInvariant Then
If PC.Value IsNot Nothing Then
wmiInfo.Add(PC.Name, PC.Value.ToString)
' halt search-by-name
Exit For
End If
End If
Next
Next
' Note: this is to prevent a crash when there is more than one item
' WMI reports on such as 2 display adapters; just get the first one.
Exit For
Next
Return wmiInfo
End Function
' helpful tool to see how WMI props are organized, discover the names etc
Public Shared Sub DebugWMIPropValues(wmiClass As String)
Using searcher As New Management.ManagementObjectSearcher("Select * from " & wmiClass)
Dim moReturn As Management.ManagementObjectCollection = searcher.Get
For Each mo As Management.ManagementObject In moReturn
Console.WriteLine("====")
DebugProperties(mo)
Next
End Using
End Sub
' debug tool to poll a management object to get the properties and values
Private Shared Sub DebugProperties(mo As Management.ManagementObject)
For Each pd As PropertyData In mo.Properties
If pd.Value IsNot Nothing Then
If pd.Value.GetType Is GetType(String()) Then
Dim n As Integer = 0
For Each s As String In CType(pd.Value, Array)
Console.WriteLine("{0}({1}): {2}", pd.Name, n.ToString,
If(pd.Value IsNot Nothing,
s,
"Nothing"))
n += 1
Next
Else
Console.WriteLine("{0}: {1}", pd.Name,
If(pd.Value IsNot Nothing,
pd.Value.ToString,
"Nothing"))
End If
End If
Next
End Sub
End Class
To use it you just create a "shopping list" of the properties you want and pass the WMI Class:
Dim shopList() As String = {"VideoProcessor", "Name", "AdapterRAM"}
' the return is a Dictionary to keep the Name and Value together
Dim wmiItems As Dictionary(Of String, String)
wmiItems = WMI.GetWMISettingsDictionary("Win32_VideoController", shopList)
' print them to the console window:
For Each kvp As KeyValuePair(Of String, String) In wmiItems
Console.WriteLine("Item: {0} value: {1}", kvp.Key, kvp.Value)
Next
The class includes a way to dump the property names and values for a class. To use it:
WMI.DebugWMIPropValues("Win32_VideoController")
Just look in the Output window for the results (Debug menu -> Windows -> Ouput)
Sample output for the shopping list:
Item: AdapterRAM value: 1073741824
Item: Name value: AMD Radeon HD 6450
Item: VideoProcessor value: ATI display adapter (0x6779)
Works on My SystemTM
Notes, Update: GetWMISettingsDictionary is intended for harvesting the properties for a single item. As is, it will get the settings for most things, but only the first video card, the first display etc.
There are several ways to change this depending on what you need. It could be modified to return a separate Dictionary in a List for each item. Or you could append a WHERE clause to the WMI class name to get the properties for a specific device and call it as often as needed:
wmiClass = "Win32_VideoController WHERE Name = 'FizzBar Deluxe'"
' or
wmiClass = "Win32_VideoController WHERE DeviceID = 'VideoController1'"
wmiItems = WMI.GetWMISettingsDictionary(wmiClass , shopList)
The name search is now case-insensitive.
Finally, note that with low-end video adapters, AdapterRAM will report total System RAM. This is because adapters without any on-board RAM simply use system RAM, so it is reporting correctly.
It is possible to get graphics card info using WMI. You need to reference the System.Management and import it.
WMI is a great library which contains the details about various components required for the system to operate. Hard Disk Drive related information, processor information, Network components and the list goes on. It is really easy to query the data if you know a little about the data how it is organized.
You have to use the ManagementObjectSearcher class.
Example:
Imports System.Management
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles Button1.Click
MsgBox(GetGraphicsCardName())
End Sub
Private Function GetGraphicsCardName() As String
Dim GraphicsCardName = String.Empty
Try
Dim WmiSelect As New ManagementObjectSearcher _("rootCIMV2", "SELECT * FROM Win32_VideoController")
For Each WmiResults As ManagementObject In WmiSelect.Get()
GraphicsCardName = WmiResults.GetPropertyValue("Name").ToString
If (Not String.IsNullOrEmpty(GraphicsCardName)) Then
Exit For
End If
Next
Catch err As ManagementException
MessageBox.Show(err.Message)
End Try
Return GraphicsCardName
End Function
End Class
Source
"invalid namespace" is not about System.Management, it is because the first parameter of
Dim WmiSelect As New ManagementObjectSearcher _("rootCIMV2", "SELECT * FROM
is not accepted.
Try to use another constructor without first parameter:
Dim WmiSelect As New ManagementObjectSearcher _("SELECT * FROM Win32_VideoController")
I'm trying to add "file type" and "last modified" to my Listview when adding items in It same as in Explorer, but I don't find what property should be assigned to SubItem. Here is my code:
For Each MyFile As IO.FileInfo In ItemDirectory.GetFiles
Dim lvi As New ListViewItem
lvi.Tag = mFile.FullName
lvi.Text = mFile.Name
lvi.ImageKey = CacheShellIcon(mFile.FullName)
Listview1.Items.Add(lvi)
lvi.SubItems.Add("File type ??")
lvi.SubItems.Add(mFile.LastAccessTime.ToShortDateString & " " & mFile.LastAccessTime.ToShortTimeString) 'This isn't same as last modified ?
Next
If somebody knows how to do It please let me know, I want to have this in my Details view.
The linked answer provides an all-purpose way to get all the extended properties. With 300+ elements in newer Windows versions it is clearly overkill to fetch them all if you are only interested in one or two. This returns just the file type. A better approach might be to pass a "shopping list" of desired property names.
As before, you need to add a reference to Microsoft Shell Controls and Automation or Microsoft Shell Folder View Router based on your OS version.
Imports Shell32
Imports SHDocVw
Partial Friend Class Shell32Methods
Friend Shared Function GetShellFileProperty(filepath As String, index As Int32) As String
Dim shell As New Shell32.Shell
Dim shFolder As Shell32.Folder
shFolder = shell.NameSpace(Path.GetDirectoryName(filepath))
' get shell data for this file, cast to folder item
Dim shFolderItem = DirectCast(shFolder.Items().Item(Path.GetFileName(filepath)),
Shell32.ShellFolderItem)
If shFolderItem IsNot Nothing Then
Return shFolder.GetDetailsOf(shFolderItem, index)
Else
Return String.Empty
End If
End Function
...
End Class
Usage:
Dim lvi As ListViewItem
Dim fileType As String
For Each f As String In Directory.EnumerateFiles("C:\Temp\ShellTest")
fileType = Shell32Methods.GetShellFileProperty(f, 9)
lvi = New ListViewItem
lvi.Text = Path.GetFileName(f)
lvi.SubItems.Add(fileType)
lvFiles.Items.Add(lvi)
Next
Ideally, you'd want to create an Enum for the properties so the code could avoid magic numbers:
fileType = Shell32Methods.GetShellFileProperty(f, Shell32FileProps.FileType)
As noted elsewhere, the index of the ones >260 or so can change depending on the OS version. That could be easily modified to accept an Enum/Int array and return a list of values so as to prevent iterating all 300+ propertied to get one or three.
For filetype you can use lvi.SubItems.Add(MyFile.Extension)
and for the "last modified" date, of course the last modified! :D
lvi.SubItems.Add(MyFile.LastWriteTime.ToShortDateString)
Last write and last access are not the same ;)
I figured out another solution, I think this one is easier, at least for me :
Public Function ExProperty(filepath As String, PropertyItem As Integer)
Dim arrHeaders As New List(Of String)()
Dim shell As New Shell
Dim rFolder As Folder = shell.[NameSpace](Path.GetDirectoryName(filepath))
Dim rFiles As FolderItem = rFolder.ParseName(Path.GetFileName(filepath))
'I needed only File type so I looped to 2 only (2 is the file type in my case - Windows 10 -
' to see all available properties do a loop
' 0 To Short.MaxValue - 1" and then extract whatever property you like)
For i As Integer = 0 To 2
Dim value As String = rFolder.GetDetailsOf(rFiles, i).Trim()
arrHeaders.Add(value)
Next
Dim DesiredProperty As String
DesiredProperty = arrHeaders.Item(PropertyItem)
Return DesiredProperty
End Function
Usage with Listview just simply (this adds File type subitem):
Listview1_Item.SubItems.Add(ExProperty(filepath, 2))
As in all solutions, a reference to Microsoft Shell Controls and Automation must be set.
I've seen a couple of posts asking a similar question but I have not been able to duplicate the answers in my code successfully.
The following code adds items and their value member to a list box.
Public Shared Sub ListFiles(hTab As Hashtable)
Debug.Print("create file and key" & Now)
Dim Enumerator As IDictionaryEnumerator
Enumerator = hTab.GetEnumerator()
Dim MyKeys As ICollection
Dim Key As Object
MyKeys = hTab.Keys()
If (hTab.Count > 0) Then
For Each Key In MyKeys
Dim sfileName As String = hTab(Key)
Dim first As Integer = sfileName.IndexOf("_")
Dim last As Integer = sfileName.LastIndexOfAny("_")
Dim first2 = (first + 1)
Dim splitFile = sfileName.Substring(first2)
frmViewFiles.ListBox1.Items.Add(splitFile)
frmViewFiles.ListBox1.ValueMember = Key
frmViewFiles.ListBox1.SelectedValue = Key
Next
End If
End Sub
When I run my code to get the selected items value member
Dim file = ListBox1.ValueMember.ToString()
I can acess the first item I choose but subsequent selections dont change the value member to that of the selected item.
Please direct me.
Thank you for your answers. this is my new code:
Public Shared Sub runListFiles(CustomerId As String)
Dim cfp As New CloudFilesProvider(cloudId)
Dim containerObjectList As IEnumerable(Of ContainerObject) = cfp.ListObjects(container:="EstherTest", identity:=cloudId, prefix:=CustomerId & "_")
For Each file As ContainerObject In containerObjectList
Dim sFullFileName As String = file.Name
Dim first As Integer = sFullFileName.IndexOf("_")
Dim first2 = (first + 1)
Dim splitFile = sFullFileName.Substring(first2)
'frmViewFiles.ListBox1.Items.Add(splitFile)
'frmViewFiles.ListBox1.ValueMember = sFullFileName
Dim fb = New myFile
fb.FileName = splitFile
fb.FullPath = sFullFileName
frmViewFiles.ListBox1.Items.Add(fb)
frmViewFiles.ListBox1.DisplayMember = fb.FileName
frmViewFiles.ListBox1.ValueMember = fb.FullPath
This is my class:
Public Class myFile
Public Property FileName As String
Public Property FullPath As String
Public Sub New(f As String, b As String)
FileName = f
FullPath = b
End Sub
End Class
Please see my comment below and assist
ValueMember is supposed to indicate the property name of an object added to the Items collection: the property to use as the actual value for the items in the ListControl.
You are not adding objects to the control, so Key from the hashtable is meaningless as the ValueMember. Your post references a file variable in passing, so I will assume this revolves around showing the filename while wanting to get the full pathname when selected/clicked. WebForms/Winforms/WPF was not indicated, I am assuming WinForms:
Public Class myFile
Public Property FileName As String
Public Property FullPath As String
Public Property FileSize As Int64 ' just so there is something else
Public Sub New(f as String, p as String, s as Int64)
FileName = f
FullPath = b
FileSize = s
End Sub
End Class
Lets say we want to add some of these to a ListBox, for each item added we want FileName to display as the text, but want to get them back by FullPath:
Dim f As myFile
' assume these come from a fileinfo
For Each fi as FileInfo in DirectoryInfo.GetFiles(searchFor)
f = New myFile
f.FileName = fi.Name
f.FullPath = fi.FullPath
f.FileSize = fi.Length
' myFile accepts all the prop values in the constructor
' so creating a new one could also be written as:
' f = New myFile(fi.Name, fi.FullPath, fi.Length)
myListBox.Items.Add(f)
Next n
If the myFile objects were stored to a List(of myFile) rather than adding them to the control, we can bind the List as the DataSource and not have to iterate or copy:
mylistBox.DataSource = myFileList
Either way, Display- and ValueMember refer to the property names we wish to use:
myListBox.DisplayMember = "FileName" ' indicate property name of obj to SHOW
myListBox.ValueMember = "FullPath" ' prop name of object to return
When you select a listbox item, myListBox.SelectedValue would refer to the FullPath of the myFile object clicked on. The SelectedIndex would still refer to the index of the item in the list.
tl;dr
ValueMember and DisplayMember refers to the Property Names of Objects represented in the list.
Note:
I know this is many years later, but still relevant information.
It took me a while to parse what was said above, until I grokked it fully, so I thought it might help if I restated it slightly.
When you select a listbox item,
myListBox.SelectedValue is the contents of the field, myListBox.ValueMember. ValueMember contains the Field Name, SelectedValue contains the contents of the field.
myListBox.SelectedItem is the contents of the field myListBox.DisplayMember. DisplayMember contains the field name and SelectedItem contains the value of the field.
The SelectedIndex refers to the index of the item in the list. To see which item is selected, reference myListBox.SelectedIndex. You can, for example, change the selection to the last item in the list by using myListBox.SelectedIndex = myListBox.Items.Count - 1
If you want to display the values, then
Console.WriteLine("The value of {0} is {1}",myListBoxDisplayMember,myListBox.SelectedItem)
Console.WriteLine("The Value of {0} is {1}",myListBox.ValueMember,myListBox.SelectedValue)
I am having trouble turning a set of data from a .txt file into arrays, basically, what i have in the text file is:
Eddy vbtab 20
Andy vbtab 30
James vbtab 20
etc..
I want to set up the names as a Names array, and numbers as number array.
Now what I have done is
strFilename = "CustomerPrices.txt"
If File.Exists(strFilename) Then
Dim srReader As New StreamReader(strFilename)
intRecords = srReader.ReadLine()
intRows = intRecords
For i = 0 To intRows - 1
intLastBlank = strInput.IndexOf(vbTab)
strName(intPrices) = strInput.Substring(0, intLastBlank)
dblPrices(intPrices) = Double.Parse(strInput.Substring(intLastBlank + 1))
But when I debug I get a problem "Object Reference not set to an instance of an object"
Can anyone give me some advise?
Thanks
Separate arrays are probably a bad idea here. They group your data by fields, when it's almost always better to group your data by records. What you want instead is a single collection filled with classes of a particular type. Go for something like this:
Public Class CustomerPrice
Public Property Name As String
Public Property Price As Decimal
End Class
Public Function ReadCustomerPrices(ByVal fileName As String) As List(Of CustomerPrice)
Dim result As New List(Of CustomerPrice)()
Using srReader As New StreamReader(fileName)
Dim line As String
While (line = srReader.ReadLine()) <> Nothing
Dim data() As String = line.Split(vbTab)
result.Add(new CustomerPrice() From {Name = data(0), Price = Decimal.Parse(data(1))})
End While
End Using
Return result
End Function
Some other things worth noting in this code:
The Using block will guarantee the file is closed, even if an exception is thrown
It's almost never appropriate to check File.Exists(). It's wasteful code, because you still have to be able to handle the file io exceptions.
When working with money, you pretty much always want to use the Decimal type rather than Double
This code requires Visual Studio 2010 / .Net 4, and was typed directly into the reply window and so likely contains a bug, or even base syntax error.