Feedback

C# - MAC-Adresse auslesen und spoolen

Veröffentlicht von am 6/28/2014
(0 Bewertungen)
Eine C#-Klasse zum: auslesen, ändern, zufälligen generieren, prüfen und konvertieren einer MAC-Adresse.

Version Nr. 2
using Microsoft.Win32;
using System;

namespace MAC_Change
{
    class MAC
    {
        public object GetMac(string name)
        {
            RegistryKey rkey;
            ComboBoxItem c_item = new ComboBoxItem();

            rkey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"+name, true);

            if (rkey.GetValue("DriverDesc") != null)
            {
                c_item.Text = rkey.GetValue("DriverDesc").ToString();
            }
            else
            {
                c_item.Text = "";
            }
            
            if (rkey.GetValue("NetworkAddress") != null)
            {
                c_item.Value = rkey.GetValue("NetworkAddress").ToString();
            }
            else
            {
                c_item.Value = "";
            }

            c_item.Name = name;

            return c_item;
        }

        public string CreateMac()
        {
            Random rand = new Random();
            int zufall = 0;
            string macadresseclear = "";

            for (int i = 0; i < 12; i++)
            {
                zufall = rand.Next(0, 15);
                switch (zufall)
                {
                    case 10: macadresseclear += "A"; break;
                    case 11: macadresseclear += "B"; break;
                    case 12: macadresseclear += "C"; break;
                    case 13: macadresseclear += "D"; break;
                    case 14: macadresseclear += "E"; break;
                    case 15: macadresseclear += "F"; break;
                    default: macadresseclear += zufall.ToString(); break;
                }
            }

            return ConvertMac(macadresseclear);
        }

        public string ConvertMac(string macadresseclear)
        {
            string macadresse = "";
            int k = 1;

            for (int i = 0; i < macadresseclear.Length; i++)
            {
                macadresse += macadresseclear[i];
                if (k == 2)
                {
                    k = 0;
                    macadresse += ":";
                }
                k++;
            }
            return macadresse.Substring(0, 17);
        }

        private string convert_mac_for_system(string macadresse)
        {
            string macadresseclear = "";

            for (int i = 0; i < macadresse.Length; i++)
            {
                if (macadresse[i].ToString() != ":")
                {
                    macadresseclear += macadresse[i];
                }
            }
            return macadresseclear;
        }

        public string ChangeMac(string macadresse, string name)
        {
            macadresse = convert_mac_for_system(macadresse);
            RegistryKey rkey;

            rkey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\" + name, true);
            rkey.SetValue("NetworkAddress", macadresse);

            return ConvertMac(macadresse);
        }

        public string SetOriginalMac(string name)
        {
            RegistryKey rkey;
            string macadresseclear;

            rkey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"+name, true);

            if (rkey.GetValue("NetworkAddressOriginal") != null)
            {
                macadresseclear = rkey.GetValue("NetworkAddressOriginal").ToString();
            }
            else
            {
                macadresseclear = convert_mac_for_system(CreateMac());
            }

            return ConvertMac(macadresseclear);
        }

        public bool CheckMac(string macadresse)
        {
            bool macOkay = false;

            if(macadresse.Length == 17)
            {
                for (int i = 0; i < macadresse.Length; i++ )
                {
                    switch(macadresse[i])
                    {
                        case '0': macOkay = true; break;
                        case '1': macOkay = true; break;
                        case '2': macOkay = true; break;
                        case '3': macOkay = true; break;
                        case '4': macOkay = true; break;
                        case '5': macOkay = true; break;
                        case '6': macOkay = true; break;
                        case '7': macOkay = true; break;
                        case '8': macOkay = true; break;
                        case '9': macOkay = true; break;
                        case 'A': macOkay = true; break;
                        case 'B': macOkay = true; break;
                        case 'C': macOkay = true; break;
                        case 'D': macOkay = true; break;
                        case 'E': macOkay = true; break;
                        case 'F': macOkay = true; break;
                        case ':': macOkay = true; break;
                        default: macOkay = false; break;
                    }

                    if(i % 3 == 2)
                    {
                        if(macadresse[i] != ':')
                        {
                            macOkay = false;
                        }
                    }

                    if(!macOkay)
                    {
                        return macOkay;
                    }
                }
            }

            return macOkay;
        }
    }
}

Abgelegt unter MAC-Adresse, MAC, MAC-Address, spooling, ändern.

6 Kommentare zum Snippet

SteeW schrieb am 9/1/2014:
Kurze Alternative zu public bool get_mac

public static bool check_mac(string macadresse)
{
long converted;
bool macOkay = true;
if (long.TryParse(macadresse.Replace(":", string.Empty), NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat,
out converted) && macadresse.Length == 17)
{
if (macadresse.Split(':').Any(macpart => macpart.Length != 2))
{
macOkay = false;
}
}
else
{
macOkay = false;
}
return macOkay;
}
Koopakiller schrieb am 9/1/2014:
@SteeW Deine Variante funktioniert wahrscheinlich (nicht getestet), braucht aber deutlich mehr Leistung als die Variante von Tera3yte. Wenn dir die originale Methode trotzdem zu lang ist, es geht auch anders:
public static bool check_mac(string macadresse)
{
if (macadresse.Length != 17)
return false;
for (int i = 0; i < macadresse.Length; ++i)
{
if (i % 3 == 2)
{
if (macadresse[i] != ':')
return false;
}
else
if ((macadresse[i] >= '0' && macadresse[i] <= '9') || (macadresse[i] >= 'a' && macadresse[i] <= 'f') || (macadresse[i] >= 'A' && macadresse[i] <= 'F'))
return false;
}
return true;
}
SteeW schrieb am 9/1/2014:
@Koopakiller Deine Variante ist gemessen die schnellste. Gefällt mir sehr gut.
Eine ganz kurze (Code) aber ebenfalls leistungshungrige Variante wäre noch:

public static bool check_mac(string macadresse)
{

if (Regex.IsMatch(macadresse, @"^(?:([\da-f]{2})\:){5}[\da-f]{2}$", RegexOptions.IgnoreCase))
return true;

return false;
}

mcjoin schrieb am 9/3/2014:
@SteeW: Die Schnellste wäre bis dato deine letzte Version
ticks: [original: 1190 | deine 1. Version: 1954 | Koopakiller: 1282 | deine 2. Version (Regex): 561]

Wenn der Regex Ausdruck ausgelagert wird:

private static Regex MacCheckRegex = new Regex(@"^(?:[0-9A-F]{2}[:-]){5}(?:[0-9A-F]{2})$", RegexOptions.IgnoreCase);
public bool check_mac(string macadresse)
{
return MacCheckRegex.IsMatch(macadresse);
}

verkürzt sich die Zeit auf ca. 360 ticks
Koopakiller schrieb am 9/3/2014:
@mcjoin Du solltest die Messung lieber mit einer Schleife wiederhohlen. Nur eine einzige Ausführung sagt wenig über die Ergebnisse aus.
Ich habe den Test nochmal mit folgendem Code wiederhohlt:
class Program
{
static void Main(string[] args)
{
var macs = new List<string>();
Random rnd = new Random();
for (int i = 0; i < 10000000; ++i)
{
var bytes = new byte[6];
rnd.NextBytes(bytes);
macs.Add(string.Format("{0:X}:{1:X}:{2:X}:{3:X}:{4:X}:{5:X}", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5]));
}
Stopwatch sw = new Stopwatch();

sw.Start();
foreach (var mac in macs)
check_mac1(mac);
sw.Stop();
Console.WriteLine("Original: " + sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
foreach (var mac in macs)
check_mac2(mac);
sw.Stop();
Console.WriteLine("als long: " + sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
foreach (var mac in macs)
check_mac3(mac);
sw.Stop();
Console.WriteLine("Koopakiller: " + sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
foreach (var mac in macs)
check_mac4(mac);
sw.Stop();
Console.WriteLine("Regex: " + sw.ElapsedMilliseconds);
sw.Reset();

sw.Start();
foreach (var mac in macs)
check_mac5(mac);
sw.Stop();
Console.WriteLine("static Regex: " + sw.ElapsedMilliseconds);
sw.Reset();

Console.ReadKey();
}

public static bool check_mac1(string macadresse)
{
bool macOkay = false;

if (macadresse.Length == 17)
{
for (int i = 0; i < macadresse.Length; i++)
{
switch (macadresse[i])
{
case '0': macOkay = true; break;
case '1': macOkay = true; break;
case '2': macOkay = true; break;
case '3': macOkay = true; break;
case '4': macOkay = true; break;
case '5': macOkay = true; break;
case '6': macOkay = true; break;
case '7': macOkay = true; break;
case '8': macOkay = true; break;
case '9': macOkay = true; break;
case 'A': macOkay = true; break;
case 'B': macOkay = true; break;
case 'C': macOkay = true; break;
case 'D': macOkay = true; break;
case 'E': macOkay = true; break;
case 'F': macOkay = true; break;
case ':': macOkay = true; break;
default: macOkay = false; break;
}

if (i % 3 == 2)
{
if (macadresse[i] != ':')
{
macOkay = false;
}
}

if (!macOkay)
{
return macOkay;
}
}
}

return macOkay;
}

public static bool check_mac2(string macadresse)
{
long converted;
bool macOkay = true;
if (long.TryParse(macadresse.Replace(":", string.Empty), NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat,
out converted) && macadresse.Length == 17)
{
if (macadresse.Split(':').Any(macpart => macpart.Length != 2))
{
macOkay = false;
}
}
else
{
macOkay = false;
}
return macOkay;
}

public static bool check_mac3(string macadresse)
{
if (macadresse.Length != 17)
return false;
for (int i = 0; i < macadresse.Length; ++i)
{
if (i % 3 == 2)
{
if (macadresse[i] != ':')
return false;
}
else
if ((macadresse[i] >= '0' && macadresse[i] <= '9') || (macadresse[i] >= 'a' && macadresse[i] <= 'f') || (macadresse[i] >= 'A' && macadresse[i] <= 'F'))
return false;
}
return true;
}

public static bool check_mac4(string macadresse)
{

if (Regex.IsMatch(macadresse, @"^(?:([\da-f]{2})\:){5}[\da-f]{2}$", RegexOptions.IgnoreCase))
return true;

return false;
}

private static Regex MacCheckRegex = new Regex(@"^(?:[0-9A-F]{2}[:-]){5}(?:[0-9A-F]{2})$", RegexOptions.IgnoreCase);
public static bool check_mac5(string macadresse)
{
return MacCheckRegex.IsMatch(macadresse);
}
}


Ich erhielt folgende Ergebnisse:
Original:     2744
als long: 7584
Meine Lsg.: 301
Regex: 17743
static Regex: 9995


Meine Lösung ist als mit Abstand die schnellste. Das ist ganz einfach der Programmierung geshculdet. Ich überprüfe jedes Zeichen nur einmal und Fertig. Ein Regex muss noch initialisiert werden und auch die Abfrage kann der Leistungsaufwendig werden. Das merkt man auch bei den Messungen, Regex ist in beiden Varianten das Langsamste.

Letzten Endes macht es trotzdem kaum einen Unterschied, da die Methode wohl keine 10 Millionen mal aufgerufen wird. Muss man die Methode jedoch oft aufrufen, sollte man über eine Effektivierung nachdenken.

PS: Weil die Hexadezimalzahlen in den Adressen nicht immer Zweistellig sind werden auch ungültige Zeichenfolgen erzeugt. So wird auch eine gewisse Fehlerrate eingeschlossen. Auch wenn diese nicht sehr groß ist.
Tera3yte schrieb am 10/27/2014:
Danke für die Kommentare, ich werde es bei Gelegenheit entsprechend verbessern.
 

Logge dich ein, um hier zu kommentieren!