Results 1 to 12 of 12

Thread: Logical Help Please

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2009
    Posts
    448

    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.

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    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

  3. #3
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    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 -

  4. #4

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2009
    Posts
    448

    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.

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    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

  6. #6
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    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 -

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2009
    Posts
    448

    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.

  8. #8
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    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

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Jan 2009
    Posts
    448

    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.

  10. #10
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    Re: Logical Help Please

    Quote Originally Posted by ngreenwood6 View Post
    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 -

  11. #11
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    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

  12. #12
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    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
  •  



Click Here to Expand Forum to Full Width