locked
Native method call error - ContactCollection.Add() RRS feed

  • Question

  • I'm writing an application to backup and restore contacts and other information on Windows Mobile 6 and .NETCF 2.0.

    The code below is to save contacts. I intend to write the contacts in to an XML file then deserialize it to restore.

    private void saveContacts()<br/>
        {<br/>
          string location = System.IO.Path.Combine(path, "Backup.xml");<br/>
          XmlWriterSettings setting = new XmlWriterSettings();<br/>
          setting.Encoding = Encoding.UTF8;<br/>
          setting.Indent = true;<br/>
          setting.IndentChars = " ";<br/>
          setting.NewLineOnAttributes = false;<br/>
          if (File.Exists(location))<br/>
          {<br/>
            setting.OmitXmlDeclaration = true;<br/>
          }<br/>
          FileStream fs = new FileStream(location, FileMode.Append, FileAccess.Write, FileShare.Write);<br/>
          ContactCollection conts = sess.Contacts.Items;<br/>
          XmlWriter writer = XmlWriter.Create(fs, setting);<br/>
          MessageBox.Show("Saving Contacts ...");<br/>
          if (conts.Count != 0)<br/>
          {<br/>
            writer.WriteStartDocument();<br/>
            writer.WriteStartElement("contacts");<br/>
            XmlSerializer serializer = new XmlSerializer(typeof(ContactCollection));<br/>
            serializer.Serialize(writer, conts);<br/>
            writer.WriteEndElement();<br/>
            writer.WriteWhitespace("\r\n");<br/>
            writer.WriteEndDocument();<br/>
            writer.Flush();<br/>
          }<br/>
          fs.Close();<br/>
        }
    

    To backup

    private void restoreContact()<br/>
        {<br/>
          XmlSerializer serializer = new XmlSerializer(typeof(Contact));<br/>
          FileStream fs = new FileStream(path, FileMode.Open);<br/>
          XmlReaderSettings sett = new XmlReaderSettings();<br/>
          sett.ConformanceLevel = ConformanceLevel.Fragment;<br/>
          XmlReader reader = XmlReader.Create(fs,sett);<br/>
          Contact cont = null;<br/>
          ContactCollection contactcollect = sess.Contacts.Items;<br/>
          while (true)<br/>
          {<br/>
            if (reader.NodeType == XmlNodeType.Element && reader.Name<br/>
            == "Contact")<br/>
            {<br/>
              cont = (Contact)serializer.Deserialize(reader,null);<br/>
              contactcollect.Add(cont);<br/>
            }<br/>
            else<br/>
            {<br/>
              if (!reader.ReadToFollowing("Contact")) break;<br/>
            }<br/>
          }<br/>
          fs.Close();<br/>
        }
    

    Here's the exception raised.

    System.ComponentModel.Win32Exception was unhandled
      Message="Native method call failed."
      ErrorCode=-2147467259
      NativeErrorCode=87
      StackTrace:
        at Microsoft.WindowsMobile.PocketOutlook.Utilities.CheckHRESULT()
        at Microsoft.WindowsMobile.PocketOutlook.Utilities.CheckHRESULT()
        at Microsoft.WindowsMobile.PocketOutlook.PimItemCollection.Add()
        at Microsoft.WindowsMobile.PocketOutlook.ContactCollection.Add()
        at Abc.RestoreForm.restoreContact()
        at Abc.RestoreForm.OkButton_Click()
        at System.Windows.Forms.Control.OnClick()
        at System.Windows.Forms.Button.OnClick()
        at System.Windows.Forms.ButtonBase.WnProc()
        at System.Windows.Forms.Control._InternalWnProc()
        at Microsoft.AGL.Forms.EVL.EnterModalDialog()
        at System.Windows.Forms.Form.ShowDialog()
        at Abc.MainForm.ResButt_Click()
        at System.Windows.Forms.Control.OnClick()
        at System.Windows.Forms.Button.OnClick()
        at System.Windows.Forms.ButtonBase.WnProc()
        at System.Windows.Forms.Control._InternalWnProc()
        at Microsoft.AGL.Forms.EVL.EnterMainLoop()
        at System.Windows.Forms.Application.Run()
        at Abc.Program.Main()
      InnerException:
    It's strange that I was able to save and restore the contacts without error. Then, I edited some code than it wouldn't work anymore.

    Any suggestion would be appreciated. Thanks for your help.

     

    Thursday, July 15, 2010 9:00 AM

Answers

  • I have figured out this problem. The problem comes from default values when you serialize a contact. If the anniversary or birthday is null, these fields will have their default values. When you deserialize it, these default values are not accepted. After deserializing, Microsoft.WindowsMobile.PocketOutlook.Utilities.CheckHRESULT() will check if the values are correct or not. If not, it will throw an exception.

    The only way to fixed it is controlling the serialize process. However, as I said above, writing my own Contact class would be painful.

    • Marked as answer by Vic4ever Friday, July 23, 2010 4:10 AM
    Friday, July 23, 2010 4:10 AM

All replies

  • The cause may not be so obvious to tell. Here are some suggestions:

    1. Run the saveContacts method multiple times; check out the content of the XML file you've saved. I noticed that you used the File.Append option. Is that what you intended to do? When saving the contact multiple times, there will be duplicate entries in the XML file, or even worse the XML file may no longer be well formatted.

    2. The stack trace suggests that the exception was thrown from "contactcollect.Add(cont);". The error code 87 means ERROR_INVALID_PARAMETER (See System Error Codes ). Try to find the invalid arguments.

    Just like the issue when you saved the contacts, your code could also create duplicate contacts (as you did not delete old ones). Instead of calling the ContactCollection.Add, a better approach would be updating existing contacts with the properties you get from the saved XML file. In this way you don't have to delete old contacts, and thus reduce the risk of corrupting them.

    3. You'd better not use the default serialization; Define the serialization yourself so that you have the exact control of the process. The following article can show you some tips: http://www.zorched.net/2007/02/28/custom-xml-serialization-for-the-net-compact-framework/ 

    4. Alway add unit tests and test your code thoroughly.


    Please mark the post that helps you, and unmark that does not. This benefits our community.
    • Marked as answer by warrentang Wednesday, July 21, 2010 2:15 AM
    • Unmarked as answer by Vic4ever Thursday, July 22, 2010 7:59 AM
    Monday, July 19, 2010 8:15 AM
  • 1) Because I have to backup not only contacts but also task... I need to save all of them in one file. That's why I used File.Append.

    2)Sorry but I don't know how to find the invalid arguments. It seems like this bug happens in native code.

    Is there an elegant way to update contacts ? Because I only think of searching through the contact collection to find for old ones and then update them.

    3)The Contact class is so big with many fields and properties. Writing my own Contact class would be painful.

    However, I haven't fixed this bug yet. :(

    Thursday, July 22, 2010 8:03 AM
  • I have figured out this problem. The problem comes from default values when you serialize a contact. If the anniversary or birthday is null, these fields will have their default values. When you deserialize it, these default values are not accepted. After deserializing, Microsoft.WindowsMobile.PocketOutlook.Utilities.CheckHRESULT() will check if the values are correct or not. If not, it will throw an exception.

    The only way to fixed it is controlling the serialize process. However, as I said above, writing my own Contact class would be painful.

    • Marked as answer by Vic4ever Friday, July 23, 2010 4:10 AM
    Friday, July 23, 2010 4:10 AM