12

I am having some trouble with the XMLWriter not closing. I can successfully write the XML file once but if I try to write it again (overwrite) I get the exception:

"The process cannot access the file 'somefile.xml' because it is being used by another process."

    Dim settings = New XmlWriterSettings()
    settings.Indent = True
    settings.IndentChars = " "
    settings.NewLineOnAttributes = True

    Try
    Dim writer As XmlWriter = XmlWriter.Create(System.IO.File.Create("somefile.xml"))
        writer.WriteStartDocument(True)
        writer.WriteStartElement("root")
        For rowCounter As Integer = ds.Tables(0).Rows.Count - 1 To 0 Step -1
            writer.WriteStartElement("someelement")
            writer.WriteElementString("col0", ds.Tables(0).Rows(rowCounter)(0).ToString)
            writer.WriteElementString("col1", ds.Tables(0).Rows(rowCounter)(1).ToString)
            writer.WriteElementString("col2", ds.Tables(0).Rows(rowCounter)(2).ToString)
            writer.WriteElementString("col3", ds.Tables(0).Rows(rowCounter)(3).ToString)
            writer.WriteElementString("col4", ds.Tables(0).Rows(rowCounter)(4).ToString)
            writer.WriteElementString("col5", ds.Tables(0).Rows(rowCounter)(5).ToString)
            writer.WriteElementString("col6", ds.Tables(0).Rows(rowCounter)(6).ToString)
            writer.WriteElementString("col7", ds.Tables(0).Rows(rowCounter)(7).ToString)
            writer.WriteEndElement()
        Next
        writer.WriteEndElement()
        writer.WriteEndDocument()
    Catch ex As System.IO.IOException
        MessageBox.Show(ex.Message)
    Finally
        writer.Flush()
        writer.Close()
    End Try
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Error1f1f
  • 529
  • 2
  • 9
  • 20

2 Answers2

17

What you are missing, is XmlWriterSettings. You declare it, but you don't use it, and when you don't set CloseOutput by hand, the default is false, which means that the output is not closed (in this case your filestream).

To have it behave the way you want it, change your code like this:

Dim settings = New XmlWriterSettings()
settings.Indent = True
settings.IndentChars = " "
settings.NewLineOnAttributes = True
settings.CloseOutput = True             ' <<<< the change '

Using writer As XmlWriter = XmlWriter.Create(System.IO.File.Create("somefile.xml"), settings)
    '.... etc'
End Using

In case you're wondering about how this really works internally, here's the Close method of XmlEncodedRawTextWriterIndent, the internal XmlWriter used in your scenario.

// courtesy of Red Gate's Reflector
public override void Close()
{
    this.FlushBuffer();
    this.FlushEncoder();
    this.writeToNull = true;
    if (this.stream != null)
    {
        this.stream.Flush();
        if (this.closeOutput)      //this flag is set to settings.CloseOutput
        {
            this.stream.Close();
        }
        this.stream = null;
    }
    else if (this.writer != null)
    {
        this.writer.Flush();
        if (this.closeOutput)
        {
            this.writer.Close();
        }
        this.writer = null;
    }
}
Abel
  • 56,041
  • 24
  • 146
  • 247
  • Ah thank you sir, you were right i was forgetting to use the settings after declaring them. – Error1f1f Mar 05 '11 at 19:50
  • 1
    On Windows Phone, Isolated Storage (IsolatedStorage) doesn't detail this error, so this is good to know. I noticed a StreamWriter with a .txt didn't break my program, but a XMLWriter did. – Léon Pelletier Feb 15 '13 at 23:19
3

I would expect this to be the file rather than the writer; if this were C#, I would use something like:

using(var file = File.Create("somefile.xml"))
using(var writer = XmlWriter.Create(file))
{
    // write to the writer
}

using (and I believe VB has the same thing, probably Using) saves a lot of pain here...

Abel
  • 56,041
  • 24
  • 146
  • 247
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900