Get hotspot script on login?

Hello,
if I want to get the script that run on-login I do this: (and it’s working)

               
                Console.WriteLine("Hotspot login script");
                mikrotik.Send("/ip/hotspot/user/profile/print");
                mikrotik.Send("?name=default");
                mikrotik.Send("=.proplist=on-login", true);
                foreach (string h in mikrotik.Read())
                {
                       if (h == "!done")
                     break;
                                    
                    else
                    Console.WriteLine(h).Substring(13));
                }

my problem is that if there is not a script there - it get stuck ,
I see the reason is that when there is no script I don’t get in the proplist the option for “on-login”

how can I overcame this ?

Thanks ,

See… protocol quirks like this one are why one shouldn’t use a protocol level API client.

If a property is not set at all, it won’t be part of the response (makes sense IMO). Therefore, you need to inspect the whole sentence to check if it has this property in it or not. But to do that, you have to be far more creative than listing the individual API words. By the time you’re finished writing all the code, you’ll have essentially written a whole new better API client.

But one already exists so do yourself a favor and use that. With it, it’s as simple as

using tik4net;
// ...
ITikConnection mikrotik = ConnectionFactory.OpenConnection(TikConnectionType.Api, HOST, USER, PASS);
ITikCommand cmd = mikrotik.CreateCommand("/ip/hotspot/user/profile/print");
foreach (ITikReSentence h in cmd.ExecuteList()) {
    if (h.Words.Keys.Contains<string>("on-login")) {
        Console.WriteLine(h.GetResponseField("on-login"));
    }
}

Ok
I guess it time to move to tik4net :slight_smile:

I will start do it and see how it goes

just a simple (and stupid ) question
how do I use it?
I mean what do i need to copy and to where ?
in the mikrotik API for C# it was simple - just to copy the code and start
what do I need to do now ?
again sorry for the dumb quesion…
I’m using microsoft visual studio 2015

Thanks ,

Once you’ve opened your project, go to “Tools > NuGet Package Manager > Package Manager Console”, and in the newly opened window, type “Install-Package tik4net”. That will get all precompiled assemblies, and reference the correct one, making it ready to use within the project.

sorry for the question again

I open a new console project
call it tik4net.examples
install the packet you told me

but I get this error :

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS0103	The name 'ConfigurationManager' does not exist in the current context	tik4net.examples	c:\users\computer\documents\visual studio 2015\Projects\tik4net.examples\tik4net.examples\Program.cs	24	Active

What I miss?

this is what I have at start-

using System;
using System.Collections.Generic;
using System.Linq;
using tik4net.Objects;
using tik4net.Objects.Ip;
using tik4net.Objects.Ip.Dns;
using tik4net.Objects.Ip.Firewall;
using tik4net.Objects.Queue;
using tik4net.Objects.System;
using System.Configuration;

I think?

(Unless you have your own class called ConfigurationManager; tik4net doesn’t have one)

If you’re trying to run the example project, run it as a whole - don’t just copy the file into your own project. The “configuration” values are supposed to be edited from the App.config file.

No I don’t have one…
and I have download and copy the all code

any other idea?

Wait,

using System.Configuration;

did not work?

I mean, that one is part of the example code, and it is used at the very line your error message is.

no
this is all the code :

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using tik4net.Objects;
using tik4net.Objects.Ip;
using tik4net.Objects.Ip.Dns;
using tik4net.Objects.Ip.Firewall;
using tik4net.Objects.Queue;
using tik4net.Objects.System;

namespace tik4net.examples
{
    class ProgramExamples
    {
        static void Main(string[] args)
        {
            using (ITikConnection connection = ConnectionFactory.CreateConnection(TikConnectionType.Api))
            {
                connection.OnReadRow += Connection_OnReadRow;   // logging commands to cosole
                connection.OnWriteRow += Connection_OnWriteRow; // logging commands to cosole
                connection.Open(ConfigurationManager.AppSettings["host"], ConfigurationManager.AppSettings["user"], ConfigurationManager.AppSettings["pass"]);

                //------------------------------------------------
                //  LOW LEVEL API (hint: uncomment any example call and debug)
                Identity(connection);

                Torch(connection);

                Log(connection);

                //-------------------------------------------------
                // HIGHLEVEL API (hint: uncomment any example call and debug)

                PrintAddressList(connection);
                CreateOrUpdateAddressList(connection);
                PrintAddressList(connection);
                CreateOrUpdateAddressList(connection);
                PrintAddressList(connection);
                DeleteAddressList(connection);
                PrintAddressList(connection);

                PrintAddressList(connection);
                CreateOrUpdateAddressListMulti(connection);
                PrintAddressList(connection);
                CreateOrUpdateAddressListMulti(connection);
                PrintAddressList(connection);
                DeleteAddressListMulti(connection);
                PrintAddressList(connection);

                PrintIpAddresses(connection);

                PrintSystemResource(connection);

                ModifyIpAccounting(connection);

                AddFirewalFilter(connection);

                DhcpClientRelease(connection);

                DnsCachePrint(connection);

                //---------------------------------------------------------
                // Advanced merge support (hint: uncomment any example call and debug)
                QueueTreeMerge(connection);
                FirewallMangleMerge(connection);

                Console.WriteLine("Finito - press ENTER");
                Console.ReadLine();
            }
        }

        private static void Connection_OnWriteRow(object sender, TikConnectionCommCallbackEventArgs args)
        {
            Console.BackgroundColor = ConsoleColor.Magenta;
            Console.WriteLine(">" + args.Word);
            Console.BackgroundColor = ConsoleColor.Black;
        }

        private static void Connection_OnReadRow(object sender, TikConnectionCommCallbackEventArgs args)
        {
            Console.BackgroundColor = ConsoleColor.Green;
            Console.WriteLine("<" + args.Word);
            Console.BackgroundColor = ConsoleColor.Black;

        }

        private static void Identity(ITikConnection connection)
        {
            ITikCommand cmd = connection.CreateCommand("/system/identity/print");
            var identity = cmd.ExecuteScalar(); //cmd.ExecuteSIngleRow()
            Console.WriteLine("Identity: " + /*identity.GetResponseField("name")*/ identity);

            Console.WriteLine("Press ENTER");
            Console.ReadLine();
        }

        private static void Torch(ITikConnection connection)
        {
            ITikCommand torchCmd = connection.CreateCommand("/tool/torch",
                connection.CreateParameter("interface", "ether1"),
                connection.CreateParameter("port", "any"),
                connection.CreateParameter("src-address", "0.0.0.0/0"),
                connection.CreateParameter("dst-address", "0.0.0.0/0")
                );
            torchCmd.ExecuteAsync(response =>
            {
                Console.WriteLine("Row: " + response.GetResponseField("tx"));
            });
            Console.WriteLine("Press ENTER");
            Console.ReadLine();
            torchCmd.CancelAndJoin();
        }

        private static void Log(ITikConnection connection)
        {
            var logs = connection.LoadList<Log>();
            foreach (Log log in logs)
            {
                Console.WriteLine("{0}[{1}]: {2}", log.Time, log.Topics, log.Message);
            }
        }


        const string listName = "TEST_LIST";
        const string ipAddress = "192.168.1.1";
        const string ipAddress2 = "192.168.1.2";
        private static void PrintAddressList(ITikConnection connection)
        {
            var addressLists = connection.LoadList<FirewallAddressList>(
                connection.CreateParameter("list", listName));
            foreach (FirewallAddressList addressList in addressLists)
            {
                Console.WriteLine("{0}{1}: {2} {3} ({4})", addressList.Disabled ? "X" : " ", addressList.Dynamic ? "D" : " ", addressList.Address, addressList.List, addressList.Comment);
            }
        }

        private static void CreateOrUpdateAddressList(ITikConnection connection)
        {
            var existingAddressList = connection.LoadList<FirewallAddressList>(
                connection.CreateParameter("list", listName),
                connection.CreateParameter("address", ipAddress)).SingleOrDefault();
            if (existingAddressList == null)
            {
                //Create
                var newAddressList = new FirewallAddressList()
                {
                    Address = ipAddress,
                    List = listName,
                };
                connection.Save(newAddressList);
            }
            else
            {
                //Update
                existingAddressList.Comment = "Comment update: " + DateTime.Now.ToShortTimeString();

                connection.Save(existingAddressList);
            }
        }

        private static void DeleteAddressList(ITikConnection connection)
        {
            var existingAddressList = connection.LoadList<FirewallAddressList>(
                connection.CreateParameter("list", listName),
                connection.CreateParameter("address", ipAddress)).SingleOrDefault();

            if (existingAddressList != null)
                connection.Delete(existingAddressList);
        }

        private static void CreateOrUpdateAddressListMulti(ITikConnection connection)
        {
            var existingAddressList = connection.LoadList<FirewallAddressList>(
                connection.CreateParameter("list", listName)).ToList();
            var listClonedBackup = existingAddressList.CloneEntityList(); //creates clone of all entities in list

            if (existingAddressList.Count() <= 0)
            {
                //Create (just in memory)
                existingAddressList.Add(
                    new FirewallAddressList()
                    {
                        Address = ipAddress,
                        List = listName,
                    });
                existingAddressList.Add(
                    new FirewallAddressList()
                    {
                        Address = ipAddress2,
                        List = listName,
                    });
            }
            else
            {
                //Update (just in memory)
                foreach (var addressList in existingAddressList)
                {
                    addressList.Comment = "Comment update: " + DateTime.Now.ToShortTimeString();
                }
            }

            //save differences into mikrotik  (existingAddressList=modified, listClonedBackup=unmodified)
            connection.SaveListDifferences(existingAddressList, listClonedBackup);
        }

        private static void DeleteAddressListMulti(ITikConnection connection)
        {
            var existingAddressList = connection.LoadList<FirewallAddressList>(
                connection.CreateParameter("list", listName)).ToList();
            var listClonedBackup = existingAddressList.CloneEntityList(); //creates clone of all entities in list

            existingAddressList.Clear();

            //save differences into mikrotik  (existingAddressList=modified, listClonedBackup=unmodified)
            connection.SaveListDifferences(existingAddressList, listClonedBackup);
        }

        private static void PrintIpAddresses(ITikConnection connection)
        {
            var ipAddresses = connection.LoadList<IpAddress>();
            foreach (var addr in ipAddresses)
            {
                Console.WriteLine(addr.EntityToString());
            }
        }

        private static void PrintSystemResource(ITikConnection connection)
        {
            var sysRes = connection.LoadSingle<SystemResource>();
            Console.WriteLine(sysRes.EntityToString());
        }

        private static void QueueTreeMerge(ITikConnection connection)
        {
            var original = connection.LoadAll<QueueTree>().Where(q => q.Name == "Q1" || q.Name == "Q2" || q.Name.StartsWith("Q3"));

            string unique = Guid.NewGuid().ToString();
            List<QueueTree> expected = new List<QueueTree>()
            {
                new QueueTree() { Name = "Q1", Parent = "global", PacketMark = "PM1" },
                new QueueTree() { Name = "Q2", Parent = "global", PacketMark = "PM2", Comment = unique }, //always update
                new QueueTree() { Name = "Q3 " + unique, Parent = "global", PacketMark = "PM3" }, // always insert + delete from previous run
            };

            //Merge with Name as key - can not save via SaveListDifferences because all items in 'expected' are new (.id=null) => insert will be done, not CUD
            connection.CreateMerge(expected, original)
                .WithKey(queue => queue.Name)
                .Field(q => q.Parent)
                .Field(q => q.PacketMark)
                .Field(q => q.Comment)
                .Save();
        }

        private static void FirewallMangleMerge(ITikConnection connection)
        {
            //manage just subset before rules marked with comment =START= and =END=

            //Create subset boundaries if not present
            const string startComment = "=START=";
            const string endComment = "=END=";
            var startMangle = connection.LoadSingleOrDefault<FirewallMangle>(connection.CreateParameter("comment", startComment));
            if (startMangle == null)
            {
                startMangle = new FirewallMangle()
                {
                    Chain = "forward",
                    Action = FirewallMangle.ActionType.Passthrough,
                    Comment = startComment,
                    Disabled = true,
                };
                connection.Save(startMangle);
            };
            var endMangle = connection.LoadSingleOrDefault<FirewallMangle>(connection.CreateParameter("comment", endComment));
            if (endMangle == null)
            {
                endMangle = new FirewallMangle()
                {
                    Chain = "forward",
                    Action = FirewallMangle.ActionType.Passthrough,
                    Comment = endComment,
                    Disabled = true,
                };
                connection.Save(endMangle);
            };

            //Merge subset between boundaries
            string unique = Guid.NewGuid().ToString();
            List<FirewallMangle> original = connection.LoadAll<FirewallMangle>().SkipWhile(m => m.Comment != startComment).TakeWhile(m => m.Comment != endComment)
                .Concat(new List<FirewallMangle> { endMangle })
                .ToList(); //just subset between =START= and =END= (not very elegant but functional and short ;-) )
            List<FirewallMangle> expected = new List<FirewallMangle>();
            expected.Add(startMangle);
            expected.Add(new FirewallMangle()
            {
                Chain = "forward",
                SrcAddress = "192.168.1.1",
                Action = FirewallMangle.ActionType.MarkPacket,
                NewPacketMark = "mark-001",
                Passthrough = false,
            });
            expected.Add(new FirewallMangle()
            {
                Chain = "forward",
                SrcAddress = "192.168.1.2",
                Action = FirewallMangle.ActionType.MarkPacket,
                NewPacketMark = "mark-002" + "-" + unique,
                Passthrough = false,
            });
            expected.Add(new FirewallMangle()
            {
                Chain = "forward",
                SrcAddress = "192.168.1.3",
                Action = FirewallMangle.ActionType.MarkPacket,
                NewPacketMark = "mark-003",
                Passthrough = false,
                Comment = unique,
            });
            expected.Add(endMangle);

            connection.CreateMerge(expected, original)
                .WithKey(mangle => mangle.SrcAddress + ":" + mangle.Comment) //Use src-address as key
                .Field(q => q.Chain)
                .Field(q => q.SrcAddress) //Do not forget include also key fields !!!
                .Field(q => q.Action)
                .Field(q => q.NewPacketMark)
                .Field(q => q.Passthrough)
                .Field(q => q.Comment)
                .Save();
        }
        private static void ModifyIpAccounting(ITikConnection connection)
        {
            var accounting = connection.LoadSingle<IpAccounting>();
            accounting.Threshold = 257;
            connection.Save(accounting);
        }

        private static void AddFirewalFilter(ITikConnection connection)
        {
            var firewallFilter = new FirewallFilter()
            {
                Chain = FirewallFilter.ChainType.Forward,
                Action = FirewallFilter.ActionType.Accept,
            };

            connection.Save(firewallFilter);

            var loaded = connection.LoadAll<FirewallFilter>().First();
            loaded.Comment = "TEST";
            connection.Save(loaded);
        }

        private static void DhcpClientRelease(ITikConnection connection)
        {
            connection.LoadAll<IpDhcpClient>().First().Release(connection);
        }

        private static void DnsCachePrint(ITikConnection connection)
        {
            var cache = connection.LoadAll<DnsCache>();
            foreach (var c in cache)
            {
                Console.WriteLine(c.EntityToString());
            }
        }
    }
}

and this is the error I get :

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS0103	The name 'ConfigurationManager' does not exist in the current context	tik4net.examples	C:\Users\Computer\Documents\Visual Studio 2015\Projects\tik4net.examples\tik4net.examples\Program.cs	22	Active

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS0103	The name 'ConfigurationManager' does not exist in the current context	tik4net.examples	C:\Users\Computer\Documents\Visual Studio 2015\Projects\tik4net.examples\tik4net.examples\Program.cs	22	Active

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS0103	The name 'ConfigurationManager' does not exist in the current context	tik4net.examples	C:\Users\Computer\Documents\Visual Studio 2015\Projects\tik4net.examples\tik4net.examples\Program.cs	22	Active

Ah… I see… If you’ve simply copied the code into your own project, that’s not enough, as “System.Configuration” is also a separate assembly.

You need to right click on “References”, select “Add references…” and add a check mark to “System.Configuration” before clicking “OK”.

(The example project solution does include it…)

I must say, Visual Studio’s error messages have gotten worse since I was actively using it… Back in VS2012, the error message did say “Are you missing a reference maybe?” which would immediately prompt you to check that very thing.

I’m very new at virtual studio–sorry ,

when I press right click and referance this is what I get :
mikrotik1.PNG

On the right, where it says “References”… Right click on that.

(And after looking at the menus some more… “Project > Add Reference…” leads to the same dialog; I’ve just never used that particular way…)

now its running
but he say I have a problem in this line

connection.Open(ConfigurationManager.AppSettings["host"], ConfigurationManager.AppSettings["user"], ConfigurationManager.AppSettings["pass"]);

value can’t by null

but even if I change it to “10.0.0.1” “admin” “123456”
I get the same error

You mean

connection.Open("10.0.0.1", "admin", "123456");

Errors saying null is not allowed?

Or are you modifying App.config to that and still getting the same error? If the latter, you can go to “Project > Properties”, click “Settings” from there, and adjust the values from there instead.

this is what I did :

connection.Open(ConfigurationManager.AppSettings["10.0.0.1"], ConfigurationManager.AppSettings["admin"], ConfigurationManager.AppSettings["123456"]);

I didn;t change nothing in App.config

That’s not how the configuration manager works…

The values in the brackets are the names of configuration options specified in App.config. You don’t specify the values you want - you specify the name where the value you want is at.

And you don’t have settings with such names… In other words, the original code

connection.Open(ConfigurationManager.AppSettings["host"], ConfigurationManager.AppSettings["user"], ConfigurationManager.AppSettings["pass"]);

corresponds to th original App.config file, where the settings “host”, “user” and “pass” exist.

The above line with the original App.config is equivalent to having hardcoded the line

connection.Open("192.168.4.236", "admin", "")

You only need to modify the App.config file so that instead of “192.168.4.236”, it ihas the IP you actually want to, and so on for the rest of the settings.

So to fix all this, change that line back to the above, and have your App.config file be

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="host" value="10.0.0.1"/>
    <add key="user" value="admin"/>
    <add key="pass" value="123456"/>
  </appSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/></startup></configuration>

yes now it’s woring
Thanks ,

I will start “play” with this and see how it goes

Thanks again!