falahati / WindowsFirewallHelper

A class library to manage the Windows Firewall as well as adding your program to the Windows Firewall Exception list.
MIT License
274 stars 72 forks source link

FirewallRule objects fail to serialize #33

Closed gfs closed 5 years ago

gfs commented 5 years ago

It is caused by an underlying failure of the IAddress [] to properly serialize.

Here's a minimum viable demo of the broken behavior:

using System;
using System.Linq;
using Newtonsoft.Json;
using WindowsFirewallHelper;

namespace FirewallHelperTest
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (IFirewallRule rule in FirewallManager.Instance.Rules.ToArray())
            {
                Console.WriteLine(JsonConvert.SerializeObject(rule));
            }
        }
    }
}

Which results in:

Newtonsoft.Json.JsonSerializationException
  HResult=0x80131500
  Message=Error getting value from 'ScopeId' on 'WindowsFirewallHelper.Addresses.SingleIP'.
  Source=Newtonsoft.Json
  StackTrace:
   at Newtonsoft.Json.Serialization.ExpressionValueProvider.GetValue(Object target)

Inner Exception 1:
SocketException: The attempted operation is not supported for the type of object referenced

You don't need to serialize the whole Rule for this behavior. I isolated each field to determine it was the addresses. For example, this also will not work: JsonConvert.SerializeObject(rule.LocalAddresses)

falahati commented 5 years ago

Hey @gfs, None of the classes in this library is serializable. Therefore this is expected. A lot of properties might throw NotSupportedException or InvalidOperationException.

Also, there is a 1-1 relationship for IRule classes and the underlying COM objects (in fact every property value requested from the COM object and then translated when used in realtime) and even if you serialize them it is not possible to deserialize that exact instance. I can make it more serialize friendly but the extent of these facts won't allow for full compatibility.

I suggest you use another class to hold the information you need and then try to serialize that one. For deserialization, the best way is to go through all rules and find the one most similar to the information you already saved or serialize and hope that nobody modified it in the meanwhile.

For your specific problem with the SingleIP class, however, since it is a child of the System.Net.IPAddress class you might be interested in the following SO question: https://stackoverflow.com/questions/18668617/json-net-error-getting-value-from-scopeid-on-system-net-ipaddress

gfs commented 5 years ago

Thanks for the response! Makes sense to me.