Deserializing Macros from XML

SyntaxEditor for Windows Forms Forum

Posted 13 years ago by Marianne
Avatar
I have read (and copied) some code from posts on here that reference deserializing macros from xml but I'm unable to get the macro to actually run. Here is my code
            MacroCommand macro = new MacroCommand();
            MemoryStream memoryStream = new MemoryStream();

            //StringReader sr = new StringReader(xmlData);            
            //XmlTextReader xmlTextReader = new XmlTextReader(sr);
            StreamWriter w = new StreamWriter(memoryStream, System.Text.Encoding.Default);


            w.Write(xmlData); // xmlData is a valid variable that contains the xml macro data
            w.Flush();
            memoryStream.Position = 0;
            XmlTextReader xmlTextReader = new XmlTextReader(memoryStream);
            macro.ReadFromXml(xmlTextReader);
            //macro.Execute(new EditCommandContext(f.ActiveSyntaxEditor.SelectedView.Selection, false));
            f.ActiveSyntaxEditor.SelectedView.RaiseEditCommand(macro);
            
            w.Close();
            xmlTextReader.Close();
            memoryStream = null;
I've tried both the macro.Execute and the RaiseEditCommand functions but the macro is never run. What am I missing? Thanks.

------------------------------- Marianne

Comments (13)

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Marianne,

This code works fine for me:
MacroCommand macro = editor.MacroRecording.LastMacroCommand;
MemoryStream memoryStream = new MemoryStream();
System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(memoryStream, System.Text.Encoding.Unicode);
macro.WriteToXml(writer);
writer.Flush();
memoryStream.Position = 0;

System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(memoryStream);
macro = new MacroCommand();
macro.ReadFromXml(reader);
writer.Close();
reader.Close();

macro.Execute(new EditCommandContext(editor.SelectedView.Selection, false));


Actipro Software Support

Posted 13 years ago by Marianne
Avatar
I am persisting the macros in a window where you can call them up later by name/description. To achieve this, the Actipro xml data is actually a sub-node so I can't pass the entire xml at once. In other words, I am retrieving the actual data that was provided by the WriteToXml function (as a string) and passing it to ReadFromXml but I get the following error:

Data at the root level is invalid. Line 1, position 1.

Here is the modified code I'm using:
        public void PlayMacro(string _Macro)
        {
            MacroCommand macro = new MacroCommand();
            MemoryStream memoryStream = new MemoryStream();

            XmlTextWriter w = new XmlTextWriter(memoryStream, System.Text.Encoding.Unicode);
            w.WriteString(_Macro);
            w.Flush();
            memoryStream.Position = 0;

            XmlTextReader r = new XmlTextReader(memoryStream);
            macro.ReadFromXml(r);

            w.Close();
            r.Close();

            macro.Execute(new EditCommandContext(f.ActiveSyntaxEditor.SelectedView.Selection, false));            
            
        }
_Macro is the xml string data that was originally created with the call to WriteToXml. In my sample, I have a macro that hits backspace twice and looks like:
    <MacroCommand>
      <EditCommand AssemblyName="ActiproSoftware.SyntaxEditor" TypeName="ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand" />
      <EditCommand AssemblyName="ActiproSoftware.SyntaxEditor" TypeName="ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand" />
    </MacroCommand>
However, the above error always occurs on the ReadFromXml method.

------------------------------- Marianne

Posted 13 years ago by Marianne
Avatar
Just to clarify, the _Macro string literal is:
"<MacroCommand><EditCommand AssemblyName=\"ActiproSoftware.SyntaxEditor\" TypeName=\"ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand\" /><EditCommand AssemblyName=\"ActiproSoftware.SyntaxEditor\" TypeName=\"ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand\" /></MacroCommand>"
This is the string that causes the exception. The odd thing is that this is the same data that is passed with the first call to WriteToXml. You should be able to reproduce this by using the 'PlayMacro' function provided and passing the literal string. The only change you'd have to make is passing a valid SyntaxEditor instance in the Execute method.

------------------------------- Marianne

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Oh strange, I had replied earlier to your previous post but it's not showing up. I wonder if I forgot to hit the save post button.

Anyhow, I found that it works fine if you use a StreamWriter instead of an XmlTextWriter. The XmlTextWriter must be inserting some other stuff whereas the StreamWriter will insert the raw XML.

Try that and let me know if it helps.


Actipro Software Support

Posted 13 years ago by Marianne
Avatar
This is odd...

After changing to StreamWriter, it reverts to the original behavior. The macro does not execute but there is no error either. It seems to run but doesn't do anything. When checking the value of Macro.Count, it always shows 0, so I'm assuming that the macro command is not actually getting populated correctly with the call to macro.ReadFromXml().

And by the way, I'm using version 3.1.0202.

Can you verify this?

[Modified at 02/07/2006 08:10 PM]

------------------------------- Marianne

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
I took your exact PlayMacro code and changed XmlTextWriter to StreamWriter. Then changed the next line to w.Write(_Macro). Then I called it with the C# string you posted. It works fine for me and I see the two backspaces execute. The macro also has 2 items.


Actipro Software Support

Posted 13 years ago by Marianne
Avatar
Then how can I go about troubleshooting the ReadFromXml method which, for me, does not populate the Macro object?

------------------------------- Marianne

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
I'm not sure what to tell you because it works fine for me if you make the changes I indicated and I'm pretty sure that stuff hasn't changed in the various .NET framework versions. If you email us, I can send you the ReadFromXml code we use so that you can debug with that. Maybe that will help.


Actipro Software Support

Posted 13 years ago by Marianne
Avatar
I am using .NET 2.0 exclusively. I will send you an email. Thanks.

------------------------------- Marianne

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
I just tested it in a 2.0 version of our sample project and it works fine there too. Here's the exact code I used. I just replaced the Help/About menu item to call your macro and made the other changes I mentioned above.

private void helpAboutMenuItem_Click(object sender, System.EventArgs e) {
    // editor.ShowAboutForm();
    this.PlayMacro("<MacroCommand><EditCommand AssemblyName=\"ActiproSoftware.SyntaxEditor\" TypeName=\"ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand\" /><EditCommand AssemblyName=\"ActiproSoftware.SyntaxEditor\" TypeName=\"ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand\" /></MacroCommand>");
}

public void PlayMacro(string _Macro) {
    MacroCommand macro = new MacroCommand();
    MemoryStream memoryStream = new MemoryStream();

    StreamWriter w = new StreamWriter(memoryStream, System.Text.Encoding.Unicode);
    w.Write(_Macro);
    w.Flush();
    memoryStream.Position = 0;

    XmlTextReader r = new XmlTextReader(memoryStream);
    macro.ReadFromXml(r);

    w.Close();
    r.Close();

    macro.Execute(new EditCommandContext(editor.SelectedView.Selection, false));            
}


Actipro Software Support

Posted 13 years ago by Marianne
Avatar
Still doesn't work for me. Here is the exact code I'm using:
        public void PlayMacro()
        {
            MacroCommand macro = new MacroCommand();
            MemoryStream memoryStream = new MemoryStream();

            StreamWriter w = new StreamWriter(memoryStream, System.Text.Encoding.Unicode);
            w.Write("<MacroCommand><EditCommand AssemblyName=\"ActiproSoftware.SyntaxEditor.Net20\" TypeName=\"ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand\" /><EditCommand AssemblyName=\"ActiproSoftware.SyntaxEditor.Net20\" TypeName=\"ActiproSoftware.SyntaxEditor.Commands.BackspaceCommand\" /></MacroCommand>");
            w.Flush();
            memoryStream.Position = 0;

            XmlTextReader r = new XmlTextReader(memoryStream);
            macro.ReadFromXml(r);

            w.Close();
            r.Close();

            macro.Execute(new EditCommandContext(editor.SelectedView.Selection, false)); 

        }
When debugging, I can parse through the XmlTextReader so I know it's got valid data from the memory stream, but after the call to ReadFromXml, the macro object has a count of 0 for the number of commands in the macro. There is a problem with the ReadFromXml() method but obviously I can't get into the code to debug it. I also get the same results when adding this code into the sample app.

------------------------------- Marianne

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
In .NET 2.0 Microsoft seems to have changed how Type.GetType works and code that used to work
no longer seems to. I've just made a change that should help work around this problem
wherever we were using a call to that method. It will be in the next maint release.


Actipro Software Support

Posted 13 years ago by Marianne
Avatar
Great! Thanks.

------------------------------- Marianne

The latest build of this product (v2018.1 build 0341) was released 7 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.