C# .NET Custom ConfigurationSection, ConfigurationElementCollection, and ConfigurationElement

The built in configuration classes for .NET are powerful and incredibly useful but can be quite confusing due to their flexibility. This is a simple example of a custom ConfigurationSection with custom element names and nested ConfigurationElementCollection objects.

FIRST: Add a reference to System.Configuration in your project and make sure to add “using System.Configuration;” to the top of your class files.

This is the App.Config file the example with comments to explain each important line.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!-- 
  configSections must be immediately after <configuration>
  type = the full namespace to your custom configuration section then a comma then the file name of the assembly it is in without the extension (no .exe or .dll)
  The default namespace for this example is 'ConfigTesting' and the assembly name is 'ConfigTesting.exe' or "DefaultNamespace.ClassName, AssemblyName"
  which gives ConfigTesting.MyConfigSection, ConfigTesting
  -->
  <configSections>
    <section name="MyConfig" type="ConfigTesting.MyPetsConfigSection, ConfigTesting"/>
  </configSections>
  
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>

  <!-- The name of the section is whatever is in the 'name' attribute in the above section definition -->
  <MyConfig>
    <!-- The word Pet replaces the standard 'add' keyword to add an element to the collection -->
    <Pet name="FirstElement" personality="FirstPersonality">
      <!-- 
      The 'Pet' element contains a default collection in the same way as the configuration section. 
      The Toy collection is the one accessed without any extra tags around it.
      Here the 'Toy' word replaces the standard 'add' keyword
      -->
      <Toy name="Toy1" description="desc1" />
      <!-- 
      This is an additional collection that must have extra tags around it to show .NET that it is a collection.
      In this case the collection is called 'Food'
      -->
      <Food>
        <!-- The word 'Product' replaces the standard 'add' keyword -->
        <Product name="Collards Dry Food" source="Kennelgate" />
      </Food>
    </Pet>
    
    <!-- Second 'Pet' element without the per-line comments -->
    <Pet name="SecondElement" personality="SecondPersonality">
      <Toy name="Toy2" description="desc2" />
      <Toy name="Toy3" description="desc3" />
      <Food>
        <Product name="Lamb Liver" source="Butchers" />
        <Product name="Carrots" source="Garden" />
        <Product name="Cashews" source="Tesco" />
      </Food>
    </Pet>
    
  </MyConfig>
</configuration>

Defining the section itself is relatively easy.

using System.Configuration;

namespace ConfigTesting
{
    public class MyPetsConfigSection : ConfigurationSection
    {
        //This makes the collection the default one that is accessed.
        //Look at the App.config and see that the collection's elements are immediately within the section instead of 
        //being enclosed by another layer of tags
        [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
        public MyPetConfigCollection Pets
        {
            get { return base[""] as MyPetConfigCollection; }
            set { base[""] = value; }
        }
    }
}

This is the class referenced in the configSection tag in App.Config. You can see that it has one property which is of type MyPetConfigCollection.

using System.Configuration;

namespace ConfigTesting
{
    public class MyPetConfigCollection : ConfigurationElementCollection
    {
        public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMap;
        protected override string ElementName => "Pet";

        protected override ConfigurationElement CreateNewElement()
        {
            return new MyPetConfigElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((MyPetConfigElement)element).Name;
        }
    }
}

The MyPetConfigCollection is a simple class that is mostly generated for you. The CreateNewElement and GetElementKey methods are compulsory and Visual Studio offers to generate them for you but you have to fill in the content. CreateNewElement should simply return a new object of whatever type the collection holds while GetElementKey should return the key of the given object (it’s like a primary key, if you’re familiar with databases) which is defined in the element class.

NOTE: Overriding ElementName is how you replace the default ‘add’ keyword with your own string but you must also override CollectionType.

 

using System.Configuration;

namespace ConfigTesting
{
    public class MyPetConfigElement : ConfigurationElement
    {
        //This is the key for the element, it's how to find this particular one in the
        //collection
        [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get { return base["name"] as string; }
            set { base["name"] = value; }
        }

        [ConfigurationProperty("personality", IsRequired = true)]
        public string Personality
        {
            get { return base["personality"] as string; }
            set { base["personality"] = value; }
        }

        //This is the default collection for this object and can be accessed without looking for extra tags
        [ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
        public PetToyCollection Toys
        {
            get { return base[""] as PetToyCollection; }
            set { base[""] = value; }
        }

        //This is another collection and must be accessed by using its enclosing tag. In this case <Food>
        [ConfigurationProperty("Food", IsRequired = false)]
        public PetFoodCollection Food
        {
            get { return base["Food"] as PetFoodCollection; }
            set { base["Food"] = value; }
        }
    }
}

This element contains two collections, one is the default collection and the other is specifically named Food. It’s important to note that the in-code name of the property does not need to match the tags/attributes in App.Config. The code names are used in code, the ConfigurationProperty names are used in App.Config.

using System.Configuration;

namespace ConfigTesting
{
    public class PetToyCollection : ConfigurationElementCollection
    {

        public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMap;
        protected override string ElementName => "Toy";

        protected override ConfigurationElement CreateNewElement()
        {
            return new ToyElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ToyElement)element).Name;
        }
    }
}

This is the toys collection, which is the default collection (you don’t have to have a default).

using System.Configuration;

namespace ConfigTesting
{
    public class ToyElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get { return base["name"] as string; }
            set { base["name"] = value; }
        }

        [ConfigurationProperty("description", IsRequired = true)]
        public string Description
        {
            get { return base["description"] as string; }
            set { base["description"] = value; }
        }
    }
}

The ToyElement does not contain any collections but it could if you wanted to add some here.

 

The below two blocks are the Food collection and elements.

using System.Configuration;

namespace ConfigTesting
{
    public class PetFoodCollection : ConfigurationElementCollection
    {

        public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.BasicMap;
        protected override string ElementName => "Product";

        protected override ConfigurationElement CreateNewElement()
        {
            return new PetFoodElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((PetFoodElement)element).Name;
        }
    }
}

 

using System.Configuration;

namespace ConfigTesting
{
    public class PetFoodElement : ConfigurationElement
    {
        //Name of pet food product
        [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
        public string Name
        {
            get { return base["name"] as string; }
            set { base["name"] = value; }
        }

        //Shop to buy the pet food from
        [ConfigurationProperty("source", IsRequired = true)]
        public string Source
        {
            get { return base["source"] as string; }
            set { base["source"] = value; }
        }
    }
}

Finally, here is the test I used in a Windows Forms application to make sure each element was usable. This iterates over each element and I had a breakpoint to pause so I could hover over it to read the contents.

private void button1_Click(object sender, EventArgs e)
        {
            MyPetsConfigSection section = ConfigurationManager.GetSection("MyConfig") as MyPetsConfigSection;

            var c = section.Pets.Count;
            foreach (MyPetConfigElement i in section.Pets)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine($"{i.Name} has {i.Toys.Count} toy(s)");
                if (i.Food != null)
                    sb.AppendLine($"Foods: {i.Food.Count}");

                MessageBox.Show(sb.ToString(), i.Personality);
            }
        }

 

HOW TO: Completely Remove Asterisk

This was tested against a Ubuntu 16.04 virtual machine with Asterisk 13.22.0 and all commands were run from ~

sudo service asterisk stop
sudo rm /etc/init.d/asterisk
sudo rm /etc/init.d/asterisk.org
sudo rm -rf /etc/asterisk/
sudo rm -rf /var/log/asterisk/
sudo rm -rf /var/lib/asterisk/
sudo rm -rf /var/spool/asterisk/
sudo rm -rf /usr/lib/asterisk/

All of the Asterisk program and configuration files will now be deleted and you should have seen a notice about needing to run systemctl daemon-reload because the service files have been removed (they’re the ones from /etc/init.d/).

If you then whereis asterisk you may still see some leftovers in a few other places which you can also delete. Here is where I found remaining files:

  • /usr/sbin/asterisk
  • /usr/include/asterisk/
  • /usr/include/asterisk.h
  • /usr/share/man/man8/asterisk.8

tmux Script

I use tmux a lot and like to have a good layout that’s relevant to the work I’m doing. Mainly, this is very simple things like DNS queries, nmap scans, telnet/ssh checking which leaves most screen space free for displays such as watching failed hack attempts or showing system usage. Here are my scripts.

linkstart

This is the script that launches tmux and sets up the panes or rejoins an existing session.

#!/bin/bash
# TMUX Startup script
# C-m means enter key
#Inspired by https://github.com/seyrenhe/linux-autoconfig/blob/master/tmux.sh

tmux start-server

if ! $(tmux has-session -t 'linkstart'); then
tmux new-session -d -s 'linkstart' -n 'linkstart' # -d *
tmux select-window -t 'linkstart'
tmux split-window -h -p 40
tmux select-pane -t 1
tmux split-window -v -p 15
tmux split-window -v -l 1
tmux send-keys -t 1 './watchfail' C-m
tmux send-keys -t 2 './watchauth' C-m
tmux send-keys -t 3 './watchusage' C-m
tmux new-window -n 'general'

tmux select-window -t 'linkstart'
tmux select-pane -t 0
fi

tmux attach-session -d -t 'linkstart'

watchfail

Sometimes it’s interesting to see the brute force attempts and get a feel for what usernames are popular with malicious actors.

#!/bin/bash

watch -t -n 30 "tail -n 400 /var/log/auth.log \
| grep 'for invalid' \
| awk '{print \$1, \$2, \$3 \"\t\" \$13 \"\t\" \$11 }'"

watchauth

This is so I can easily see where any successful connections have come from as I know the IPs I usually connect from.

#!/bin/bash

watch -t -n 300 "tail -n 2000 /var/log/auth.log | grep 'Accepted' | awk '{print \$1, \$2, \$3 \"\t\" \$9 \"\t\" \$11 }'"

watchusage

It’s a very, very, low-usage VM so this is really a “just because” pane.

#!/bin/bash

watch -t -n 20  "echo "CPU `LC_ALL=C top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}'`% RAM `free -m | awk '/Mem:/ { printf("%3.1f%%", $3/$2*100) }'` HDD `df -h / | awk '/\// {print $(NF-1)}'`""

 

Google Chrome Yellow Tint Version 68

If you’ve updated Google Chrome and now have a horrible yellow tint to everything that should be white you’ve been struck by the Overly Helpful Application Syndrome. This disease commonly affects Microsoft products but can also infect other applications and displays itself as a “helpful default” that is completely stupid.

The yellow tint in Google Chrome is easily fixed by going here and setting Force color profile to sRGB:

chrome://flags/#force-color-profile

You’ll have to copy that URL and paste it into the address bar of Chrome because the latest versions of the browser do not allow clicking chrome:// links.

Why does this happen? The Chrome developers have modified the way Google Chrome displays so that it tries to match the default colour profile of the monitor it is in. Unfortunately, it often fails to do this properly which leaves you with just Chrome looking like an old yellowed smoker’s desktop PC from the 90s.

Update Ubuntu 16.04 Login Message

The standard login message is called the MOTD and usually looks like this:

Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-116-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

29 packages can be updated.
11 updates are security updates.


Last login: Wed Jul 11 18:35:08 2018 from 555.555.555.555
[email protected]:~$

This text is generated by a series of executable files in /etc/update-motd.d that you can change or even add your to.

[email protected]:~$ ls -la /etc/update-motd.d
total 36
drwxr-xr-x  2 root root 4096 Jun  6 15:43 .
drwxr-xr-x 92 root root 4096 Jun 28 08:34 ..
-rwxr-xr-x  1 root root 1220 Oct 22  2015 00-header
-rwxr-xr-x  1 root root 1157 Jun 14  2016 10-help-text
-rwxr-xr-x  1 root root   97 May 24  2016 90-updates-available
-rwxr-xr-x  1 root root  299 Jul 22  2016 91-release-upgrade
-rwxr-xr-x  1 root root  111 Jan 11 05:42 97-overlayroot
-rwxr-xr-x  1 root root  142 May 24  2016 98-fsck-at-reboot
-rwxr-xr-x  1 root root  144 May 24  2016 98-reboot-required

I decided to modify mine to display the system’s IP addresses on login and disable 00-header, 10-help-text from running:

[email protected]:~$ ls -la /etc/update-motd.d
total 44
drwxr-xr-x  2 root root 4096 Jul 11 19:54 ./
drwxr-xr-x 91 root root 4096 Jul 11 16:59 ../
-r--r--r--  1 root root 1220 Oct 22  2015 00-header
-r--r--r--  1 root root 1157 Jun 14  2016 10-help-text
-rwxr-xr-x  1 root root  147 Jul 11 19:54 50-ip*
-rwxr-xr-x  1 root root   97 May 24  2016 90-updates-available*
-rwxr-xr-x  1 root root  299 Jul 22  2016 91-release-upgrade*
-rwxr-xr-x  1 root root  111 Jan 11 05:42 97-overlayroot*
-rwxr-xr-x  1 root root  142 May 24  2016 98-fsck-at-reboot*
-rwxr-xr-x  1 root root  144 May 24  2016 98-reboot-required*

As you can see, to disable a file you only need to remove the execute permissions. When you add a file it’s important to think about the order in which they’ll execute. These scripts are run alphabetically which is NOT the same as ‘numerical order’

 

Here’s the IP script I added.

#!/bin/bash
echo -e "\n\nSystem IP Addresses: "
ifconfig | grep "inet addr" | cut -d: -f2 | awk '/([0-9]{1,3}\.){3}[0-9]{1,3}/ { print "\t" $1; }'

Of course you’re could do anything in these scripts such as list the current load, free space, memory usage, logged on users, etc…

Illegal Phone Call Scams

These days the average user is far wiser against email spam than ever before and criminals are turning back towards direct threats in telephony-based shakedowns of vulnerable people. Thankfully the advent of websites like Who Called Me and Twitter mean you can easily discover if the number that called you is a known scam or not.

Once you know it’s a scam you can report it to the police directly through 101 if it’s not an emergency or 999 if you believe it’s something more serious than a simple scammer. Remember, you can also report crime anonymously through CrimeStoppers so make sure you say something if you get one of these calls!

Is it a scam?

  1. Do you recognise the number?
  2. Is the caller from a company you have a relationship with?
  3. Are they asking for your details?

It may sound obvious that a call from a company you don’t know from a number you don’t recognise asking for your bank information is suspicious but what would you do if you got a call from a stern police officer demanding to you know where you were on Tuesday? Or a pleasant individual calling to advise you’ve over paid on your water bill and are due a refund?

Whatever the purpose someone claims you need to be mindful of what information you’re giving out. Did the caller address you by your full name like a real company representative would or did they wait until you gave up that information first? Did they confirm your address to you or get you to let go of that as well?

If you’re ever in any way doubtful of the authenticity of a caller’s identity HANG UP and use the Internet to identify the number it came from. You could even simply call the company back on a known safe contact number from their website or your contract with them.

Elite Dangerous Useful Tips

Elite Dangerous is a massively multiplayer online role play game with a huge amount of space and wide-open gameplay with a few key areas for players to interact with. These are some links I have found to be particularly useful in the game.

The Road to Riches – Easy money from exploration of Earth Like Worlds, Water Worlds, and so on. By taking your ship out to these worlds and scanning them you will earn anything from 2 million to 6 million an hour.

Make sure not to explode, though, as you’ll only get your reward once getting back to a station and selling your data on the Stella Cartography section of Station Services.

https://www.edsm.net/ has several useful tools but I like this mainly because it shows an out of game log of what you’ve done, your credits, your ships, and a bunch of stats which can be shared with friends. You’ll need to use a tool to read your player logs and send them to the site, I use Elite Dangerous: Market Connector.

http://elitedangerous.hozbase.co.uk/ is useful for finding specific things like black holes to go sight-seeing.

Building your ship is the most expensive, and fun, thing you can do in the game made much easier with the excellent Coriolis tool. You can use this to see how much money you need to buy certain ships, use its links to find stations to buy the modules from, see how effective it’ll be at combat, and even plan out module engineering.

Travian – Worth Playing?

No! Not unless you can get in at the start of a game round. In the village-building and conquest game you control a ‘hero’ character who can go on adventures and build up local resource gathering so you can progress to better structures, defences, unites, and even grow your own guild.

You begin with newbie protection from other “players” (usually just scripted bots) so you cannot be attacked until you’re ready. However, you can never catch up to withstand any attacks by long-standing players and there’s nothing you can do to prevent the botting from whittling away your resources.

The game has many microtransactions and is extremely pay-to-win so if you like throwing money at something this game may be interesting for you. However, if you like to have fun and enjoy building things in games this is definitely something to avoid.

Proudly powered by WordPress | Theme: Baskerville 2 by Anders Noren.

Up ↑