XMLDocument.Save() = 0 length files, half written files etc.

I'm having something most unusual happen with .NET 2.0 on a very few computers (like 2 or 3 out of thousands). We store our information in a custom config file, which we write out from an xml document. Well 99.9% of the time it works just fine to do XMLDocument.Save() and the file is writen correctly.

But every once and a while on these specific machines, the file doesn't get saved correctly. Sometimes the file is completely blank (i.e. the file length = 0) and sometimes the file is half written and doesn't have any of the closing tags to complete the file.

There are NO ERRORS or exceptions thrown when this happens, it just marily goes on it's way. It only throws errors when it tries to open the file again.

The users all have permissions to write to the directory and it works probably 98% of the time for these users. We have noticed that it happens far more often on computers with Macafee or Norton Antivirus installed, but we have one user that used to have Norton and it was removed and it's still doing it.

To me this is a bug in the .NET framework, because it should at least throw an error... although I think that this might be evil antivirus programs screwing with file writes... anyone have any ideas on how to get around this It's a real PITA.



Answer this question

XMLDocument.Save() = 0 length files, half written files etc.

  • subhanet

    Hi,

    Can you post your Code and machine.config data.



  • AlfonsAberg

    The problem with Form_Closing is that another event might get hooked up for which we won't know the order that they're fired and it may cancel the close and then the save will have happened when it shouldn't have. the Form_Closed is the natural location and ensures that no cancelation happens.

    Why is windows killing the app instead of allowing it to close properly This is a BUG as far as I'm concerned. You can see this behaviour in other applications (Windows Media Player, and Trillian come to mind) where setings aren't saved unless you close the app and then windows. This is silly and should be fixed.


  • Dan Lukinykh

    Thanks for giving bigger picture.

    I agree this is insane and should never happen.

    I have never seen such behavior before and is quite lost.

    As I wrote before, lets try several more things:

    1. Close the writer explicitly:

    using (XmlWriter xw = new XmlWriter(FileName)) {

    xDoc.Save(xw);

    xw.Close();

    }

    2. Would you be able to repro the problem if you do form save without exiting the form

    3. Would the problem be reproducible in simple repro Console app that Loads the file, makes a change and saves document.



  • HSBF Lewe

    Sorry, I run out of ideas.

    The steps we didn't try yet are:

    1. Call save outside of form close code. You can call save explicitly.

    2. Step 1 in extreme form would be simplified repro, that doesn't have any forms.

    Do you use multithreading in your application Can this be the case

    Is this ASP.NET app or window app

    In any case it is unlikely that problem is related to XmlWriter or XmlDocument.

    I move this thread to CLR forum. If you want to contact me directly you can use: sdub.xslt2@mailnull.com address.



  • Supersonic

    Why would my machine.config file matter

    This is a Windows application running on default installations of .NET 2.0 that haven't had their machine.config files changed.

    The stream writer solution doesn't solve the issue, it still happens. It's something with the XMLDocument class that is causing it.


  • Karenros

    You need to to override the FormClosing Event

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)

    {

    if (e.CloseReason == CloseReason.WindowsShutDown)

    {

    }

    }

    When you hook the FormClosed Event windows will not wait until you did finish the closed handler. Any must do cleanup activities should go into the FormClosing Handler. There you can even prevent a shutdown when you do not want to close your application right now.

    Yours,

    Alois Kraus


  • mikecuth

    I tried the explict close and it still does it.

    All of our saves have always been on form close.

    The problem on reproing it is that I don't ever get it on my computer. Only a few customers get it and it's random. 9 times out of 10 it works, the other one I'm never around to see it... I just get the aftermath of having to rebuild their config file :<


  • Intuit Recruiter

    Hi,

    I'm not sure what is happening at your case but if you would like to be sure that the file is written and if you are using the following:

    XmlDocument doc = new XmlDocument();
    //do something with doc...
    doc.Save(@"c:\doc.xml");

    Change it to:

    using (StreamWriter sw = new StreamWriter(@"c:\doc.xml"))
    {
    doc.Save(sw);
    }

    With this you shouldn't have any issues.

    Thanks,

    Sinan



  • Polity4h

    It's bad.

    Can you post code snippet where you create and close to XmlWriter

    If you create Stream or TextWriter outside of XmlWriter, please provide the code where it is created/closed as well.

    Simplified repro may help (us as well as you) diagnose the problem. (I realize that chances for me to actually repro the problem are low.)

    One more notes. For valid, but questionable reasons XmlWriter.Dispose() catches all exceptions. If you need more details about XmlWriter look it in Rotor sources: http://www.microsoft.com/downloads/details.aspx FamilyId=8C09FD61-3F26-4555-AE17-3121B4F51D4D&displaylang=en

    So can you try explicitly call XmlWriter.Close() before exiting using() {} block In the light of previous note, I'd recommend doing this any way.

    This is just "in case". You mentioned before that resulting file may be empty and throwing exception in Dispose() would not give such results.  

    Please update us on your progress.



  • OldDrongo

    Sounds mystically.

    XmlTextWriter automatically closes unclosed tags in the Close() method. Dispose() would do this. So use of using() {} helps to close it promptly.

    If you don't close it GS destructor would call Close() it may try to close unclosed tags. In the .NET destructors can be called in arbitrary order (indeterministic) and underline stream may be already closed.

    The same may happen with any layer that does caching. TextWriter for example.

    The way to deal with this -- close all resources yourself and don't relly on GS for this.

    If this is not the case I don't know what else can help. XmlWriter would die or finish the work (with exception probably). The only explanation I have is that Close() happens in the finalizer and underline stream is closed already. Exception would not be thrown from finalizer.

    XmlTextWriter follows Dispose() pattern: http://www.gotdotnet.com/team/libraries/whitepapers/resourcemanagement/resourcemanagement.aspx#_Toc522530587



  • Dave Massy

    I found a case that repros every time:

    If you save an xml file on Form_closed and then user pushes the power button on his computer which causes windows to shut down (properly using ACPI) then the file will always be corrupt and no error will be thrown.

    It should save the file and then shut down the computer...


  • Izzy545

    The Form_Closing event is not the last event but surely the last one a user can interact with. You said that you safe user settings when shutting down. The user will not be able to make any changes in the time frame when shutting your application down (disable the UI if you really need to prevent such a sitation).

    I do not think that this will be changed because this is by design. OnClosing does allow you to control the shtudown process. OnClosed is not guaranteed to be called when shutting down windows because you did allow the shutdown to proceed when leaving the OnClosing handler without cancelling the shutdown process. This behaviour is by design and has nothing to do with a faulty XmlDocument implementation. To make the shutdown clean is not easy but if you put your code into the OnClosing handler is by far the easiest solution to get a reliable shutdown behaviour.

    Another PInvoke solution would be to listen for the WM_ENDSESSION, WM_QUERYENDSESSION but you will not get around the fact that the OS is killing your App the hard way sooner or later when shutting down.

    Yours,

    Alois Kraus


  • ConfigSSIS

    I use a using(){} on all streams. It doesn't seem to matter, it still doesn't close the file or even finish writting the file, it just creates a corrupted file without throwing an error.

    I've worked around it by writting the file to the temp directory, testing if I can open it as an XML Document, if I can then I do a copy with overwrite, if not, I try again until it works. This results in the file not being corrupted, but does take time. Fortunately I don't save this file often...


  • Jkumar

    using (XmlWriter xw = new XmlWriter(FileName)) {

    xDoc.Save(xw);

    }

    This is called in the FormClose() event of our main form.

    There are no other streams or writters that are used. XDoc is loaded directly from the file, we work on it and make changes continually in code without saving as the user has preference changes. Then when the logoff our software or close the software entirely, it will save the changes. When it does this, it gets this error.

    We used to save after every change to their profiles, but were getting these issues so often it was insane.

    I now write the file to the temp directory, then read it into an xmldocument again, if it errors on read I retry (up to 3 times) until I get a valid file, and then do a System.IO.File.Copy(temp, filename, true) if the file actually was valid. If not, I give up and don't save the settings.

    While this works in this case, it's obviously ugly code, and not a solution where the xml file MUST be written succesfully because it has real data.


  • XMLDocument.Save() = 0 length files, half written files etc.