|
-
Jul 9th, 2009, 02:23 PM
#1
Thread Starter
Hyperactive Member
Logical Help Please
I have the following Method:
Code:
Public Sub checkPlugins()
'get the dll files
Dim dllFiles As String() = Directory.GetFiles(Directory.GetCurrentDirectory() & "\Plugins")
'read the table
Dim dsRead As New DataSet()
dsRead.ReadXml(Directory.GetCurrentDirectory() & "\Plugins.xml")
Dim dtWrite As New DataTable()
dtWrite.TableName = "Plugin"
dtWrite.Columns.Add("Name")
dtWrite.Columns.Add("Enabled")
'loop through and add them to the writer
For Each dllFile As String In dllFiles
For Each dr As DataRow In dsRead.Tables(0).Rows
If dllFile.ToString() = "test" Then
dtWrite.Rows.Add(dllFile.ToString(), dr(1).ToString())
Else
dtWrite.Rows.Add(dllFile.ToString(), "True")
End If
Next
Next
'write the data
dtWrite.WriteXml(Directory.GetCurrentDirectory() & "\Plugins.xml")
End Sub
Everything is working fine except for one part. The part where the second foreach loop runs. If I only have one plugin installed it puts 2 entries in the list. The reason is because it has 2 rows and it is adding it twice. I know what the issue is I just am drawing a blank right now. Any help is appreciated.
If I helped you please rate me.
-
Jul 9th, 2009, 02:31 PM
#2
Re: Logical Help Please
This is not a direct answer, but it might give you an idea. The following is taken from one of my current projects:
Code:
Using fs As New System.IO.FileStream(flnm, IO.FileMode.OpenOrCreate, IO.FileAccess.Write, IO.FileShare.Write)
Using zStrm As New System.IO.Compression.GZipStream(fs, IO.Compression.CompressionMode.Compress)
ds.WriteXml(zStrm, XmlWriteMode.WriteSchema)
End Using
End Using
This writes a dataset into a file using compression. If you chop out that inner using, you get the dataset without compression. The same WriteXML method exists for datatables, so you can swap the ds for your datatable and use this to write out the XML without any loops.
Here is the code for reading the same file:
Code:
Using inFile As New System.IO.FileStream(flnm, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.Read)
Using zStrm As New System.IO.Compression.GZipStream(inFile, IO.Compression.CompressionMode.Decompress)
ds.ReadXml(zStrm, XmlReadMode.Auto)
End Using
End Using
I'd say that is a fair bit easier than filling the table manually, as you are doing. Once again, I used compression to write out the table, so I use compression to read it back in. Far easier to do that without the compression (though it actually takes out only two lines in each).
My usual boring signature: Nothing
 
-
Jul 9th, 2009, 02:35 PM
#3
Re: Logical Help Please
It would help if you tell us what's the job of checkPlugins method is.
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
Jul 9th, 2009, 02:42 PM
#4
Thread Starter
Hyperactive Member
Re: Logical Help Please
@ShaggyHiker I am confused by what your code is doing. Care to explain it?
@stanav I thought it was pretty self explanatory but I will explain what it is doing. First it gets a list of all the files in the "Plugins" directory. Then it reads in the xml file currently there. Then it creates a new datatable that is going to have the same columns (just recreating it so that I can save it again with modifications). Then it loops through the files but while its looping through the files it also loops through the current xml file to see if the file is already in the datatable. If the file is already there it should just add what was already there and if not then it should add it as a new entry. Then it just saves the xml file to what it was before with the new data.
Like I said though because the second loop has 2 datarows it is adding each one twice instead of just once. The point of this method is to get a list of the files in the "Plugins" folder. Then if it is already in the xml file do nothing but if it is a new file then it needs to add it to the xml file. The point of that is for a plugin system. When the program starts if there are any new plugins it will add them and if not it will just keep all the old ones.
If I helped you please rate me.
-
Jul 9th, 2009, 03:15 PM
#5
Re: Logical Help Please
Uhhh...no, I think I shouldn't explain.
I made an assumption as to what you were doing based on a brief glance at your code, and my memory of a related thread from a day or two back, and leapt to the wrong conclusion. I thought you were going to set up a datatable to store the plugin, and whether or not it was in use, so I saw you manually loading the table, and mistook it for something else.
To get after the ACTUAL question: I would suggest that you already have the datatable, so why bother creating a new one? What you are doing might actually be easier, but consider this:
1) You have a datatable, and each datatable has a DefaultView property, which returns a DataView.
Code:
Dim dt As Datatable = dsRead.Tables(0)
Dim dv As DataView = dt.DefaultView 'For convenience
For Each dllFile As String In dllFiles
dv.RowFilter = "Name = '" & dllFile & "'" 'Note, this is ", ', ".
If dv.Count > 0
'It is already in the table
Else
'It is not already in the table.
End If
Next
That cuts out one of the loops, which may solve your problem. The other thing this does is removes the need for the second datatable. You have the one table, you update it, then you save it (using the exact design that I was headed towards in the first post, but that's water under the wrong bridge now). One problem with this design is that if you are removing plugins, then this code won't handle that. In that situation, your double loop is probably better than the alternatives for this case.
The problem you were having with your double loop (and you've only seen the tip of that iceberg) is that in every case, the inner loop ALWAYS adds a new row to the new table. This means that if there are two items in the old table, and two items in the XML file, then each time through the XML, the inner loop will add one row per record in the old table. Therefore, the number of rows in the final table will always be (#XML rows) * (# old DT rows).
My usual boring signature: Nothing
 
-
Jul 9th, 2009, 03:23 PM
#6
Re: Logical Help Please
So you don't need the 2nd datatable. Just use the one that you read from the xml file and edit that (adding/removing/changing...) and then save it back to xml file.
Try this:
Code:
Public Sub checkPlugins()
'get the dll files
Dim dllFiles As String() = Directory.GetFiles(Directory.GetCurrentDirectory() & "\Plugins", "*.dll")
'read the table
Dim xmlFilePath As String = Directory.GetCurrentDirectory() & "\PluginInventory.xml"
Dim dtPlugins As New DataTable("Plugins")
If File.Exists(xmlFilePath) Then
dtPlugins.ReadXml(xmlFilePath)
Else
'The file does not exists because this is the 1st time the program runs.
'We need to create it
With dtPlugins.Columns
.Add("PluginName", GetType(String))
.Add("Enabled", GetType(Boolean))
End With
End If
'Now start checking the dlls
For Each dll As String In dllFiles
If dtPlugins.Select("PluginName = '" & dll & "'").Length = 0 Then
'This plugin is not yet added in the datatable
'So just add it
dtPlugins.Rows.Add(dll, True)
End If
Next
'write the data
dtPlugins.WriteXml(xmlFilePath)
End Sub
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
Jul 9th, 2009, 03:55 PM
#7
Thread Starter
Hyperactive Member
Re: Logical Help Please
Thanks to both of you. Stanav I love the code. I didnt know you could do that. It works fine when I dont have the xml file there(let the program create it) but when it is there it gives me this error:
DataTable does not support schema inference from Xml.
I think when you use a datatable to read an xml file you have to read a schema too. Any Ideas?
Oh yeah just thought about something. What if I remove a plugin from that directory? How would I go about know that is was removed?
Last edited by ngreenwood6; Jul 9th, 2009 at 04:07 PM.
If I helped you please rate me.
-
Jul 9th, 2009, 05:30 PM
#8
Re: Logical Help Please
Well, there IS something useful out of my post #2, as I was writing the Schema, and reading it back in. It's a second argument to WriteXML.
Deleting is going to be a bit of a pain. What Stanav posted will cover the situation where new plugins are added to the datatable. After that has run, the number of strings in dllFiles will be the same as the number of rows in the datatable...unless some of the plugins were deleted. Therefore, first check:
dllFiles.Count = dtPlugins.Rows.Count
If that is true, then all is well. If not, you will need to loop backwards through the rows:
Code:
For x as Integer = dtPlugins.Rows.Count-1 To 0 Step -1
if not dllfiles.Contains( dtPlugins.Rows(x).Item("PluginName").ToString) Then
dtPlugins.Rows.RemoveAt(x)
End If
Next
Something like that should work.
My usual boring signature: Nothing
 
-
Jul 9th, 2009, 08:17 PM
#9
Thread Starter
Hyperactive Member
Re: Logical Help Please
Thanks for the help Shaggy. I appreciated both of your posts by the way. Now I noticed what you were talking about with the "XmlReadMode.Auto" and the "XmlWriteMode.WriteSchema". However when I do the read one it says:
No overload for method 'ReadXml' takes '2' arguments
If I helped you please rate me.
-
Jul 10th, 2009, 07:16 AM
#10
Re: Logical Help Please
 Originally Posted by ngreenwood6
Thanks to both of you. Stanav I love the code. I didnt know you could do that. It works fine when I dont have the xml file there(let the program create it) but when it is there it gives me this error:
I think when you use a datatable to read an xml file you have to read a schema too. Any Ideas?
Oh yeah just thought about something. What if I remove a plugin from that directory? How would I go about know that is was removed?
Oh, sorry... I wrote that code without actually test it. But the error is very simple to fix. Try this again:
Code:
Public Sub checkPlugins()
'get the dll files
Dim dllFiles As String() = Directory.GetFiles(Directory.GetCurrentDirectory() & "\Plugins", "*.dll")
'read the table
Dim xmlFilePath As String = Directory.GetCurrentDirectory() & "\PluginInventory.xml"
'Create a datatable with correct schema to store plugin data
Dim dtPlugins As New DataTable("Plugins")
With dtPlugins.Columns
.Add("PluginName", GetType(String))
.Add("Enabled", GetType(Boolean))
End With
'Check and load the xml file if exists
If File.Exists(xmlFilePath) Then
dtPlugins.ReadXml(xmlFilePath)
End If
'Now start checking the dlls
For Each dll As String In dllFiles
If dtPlugins.Select("PluginName = '" & dll & "'").Length = 0 Then
'This plugin is not yet added in the datatable
'So just add it
dtPlugins.Rows.Add(dll, True)
End If
Next
'write the data
dtPlugins.WriteXml(xmlFilePath)
End Sub
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
Jul 10th, 2009, 08:50 AM
#11
Re: Logical Help Please
I didn't realize that. The Dataset.ReadXML can read the schema and the table. The Datatable.ReadXML can only read the table. There is a separate Datatable.ReadXMLSchema method, though. Why they did that is beyond me.
It appears that you have two options:
1) Put the datatable into a dataset and use that form of ReadXML/WriteXML.
2) Call Datatable.ReadXMLSchema prior to the call to ReadXML.
My usual boring signature: Nothing
 
-
Jul 10th, 2009, 09:16 AM
#12
Re: Logical Help Please
@Shaggy: normally, when using a datatable and write it to xml, one would first save the schema by calling the WriteXmlSchema and then save the xml by WriteXml. To read back the xml file, one will do ReadXmlSchema first and then ReadXml. However, we can skip the writexmlschema and readxmlschema if we create the table schema manually (as I did in the last post).
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|