diff --git a/WOLHelper.sln b/WOLHelper.sln new file mode 100644 index 0000000..c3ba49a --- /dev/null +++ b/WOLHelper.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32126.317 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WOLHelper", "WOLHelper\WOLHelper.csproj", "{385E5B21-B758-46BC-BE41-0ADEBF9BD97B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {385E5B21-B758-46BC-BE41-0ADEBF9BD97B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {385E5B21-B758-46BC-BE41-0ADEBF9BD97B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {385E5B21-B758-46BC-BE41-0ADEBF9BD97B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {385E5B21-B758-46BC-BE41-0ADEBF9BD97B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1EE2A704-678F-4E80-A189-1466153695E2} + EndGlobalSection +EndGlobal diff --git a/WOLHelper/Properties/AssemblyInfo.cs b/WOLHelper/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..cc0a648 --- /dev/null +++ b/WOLHelper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("WOLHelper")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Stadt Dortmund")] +[assembly: AssemblyProduct("WOLHelper")] +[assembly: AssemblyCopyright("Copyright © Stadt Dortmund 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird +[assembly: Guid("385e5b21-b758-46bc-be41-0adebf9bd97b")] + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// indem Sie "*" wie unten gezeigt eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/WOLHelper/WOLHelper.cs b/WOLHelper/WOLHelper.cs new file mode 100644 index 0000000..8fff26d --- /dev/null +++ b/WOLHelper/WOLHelper.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace WOLWin +{ + public static class WOLHelper + { + /// + /// Liest MAC-Adresse des Host aus Liste + /// + /// RQ-Nummer des Zielrechners + /// Dateipfad zur MAC-Liste + /// + public static async Task> GetMacAsync(string host, string pathToMacs) + { + List macs = new List(); + + using (StreamReader sr = new StreamReader(pathToMacs)) + { + await sr.ReadLineAsync(); + string line; + + while ((line = await sr.ReadLineAsync()) != null) + { + string[] splitted = line.Split(';'); + + if (splitted[0] == host) + { + if (splitted[2] != "") + { + macs.Add(splitted[1] + ";" + splitted[2]); + } + else + { + macs.Add(splitted[1]); + } + break; + } + } + } + return macs; + } + + /// + /// Weckt entfernten Rechner aus dem Energiesparmodus auf + /// + /// MAC-Adresse des Zielrechners + /// + public static async Task WakeOnLan(string mac) + { + int result = 0; + byte[] magicPacket = CreateMagicPacket(mac); + foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback && n.OperationalStatus == OperationalStatus.Up)) + { + IPInterfaceProperties ipProps = networkInterface.GetIPProperties(); + foreach (MulticastIPAddressInformation info in ipProps.MulticastAddresses) + { + IPAddress multiCastAdr = info.Address; + + //IPv6 + if (multiCastAdr.ToString().StartsWith("ff02::1%", StringComparison.OrdinalIgnoreCase)) + { + UnicastIPAddressInformation uniInfo = ipProps.UnicastAddresses.Where(u => u.Address.AddressFamily == AddressFamily.InterNetworkV6 && !u.Address.IsIPv6LinkLocal).FirstOrDefault(); + if (uniInfo != null) + { + result = await SendUdpAsync(uniInfo.Address, multiCastAdr, magicPacket); + } + } + //IPv4 + else if (multiCastAdr.ToString().Equals("224.0.0.1")) + { + UnicastIPAddressInformation unicastIPAddressInformation = ipProps.UnicastAddresses.Where(u => u.Address.AddressFamily == AddressFamily.InterNetwork && !ipProps.GetIPv4Properties().IsAutomaticPrivateAddressingActive).FirstOrDefault(); + if (unicastIPAddressInformation != null) + { + result = await SendUdpAsync(unicastIPAddressInformation.Address, multiCastAdr, magicPacket); + break; + } + } + } + } + return result; + } + + /// + /// Erstellt Magic Packet anhand MAC-Adresse des Zielrechners + /// + /// MAC-Adresse des Zielrechners + /// + private static byte[] CreateMagicPacket(string macAdress) + { + var macAdressNorm = Regex.Replace(macAdress, "[: -]", ""); + byte[] macBytes = new byte[6]; + for (int i = 0; i < 6; i++) + { + //i to hex to byte + macBytes[i] = Convert.ToByte(macAdressNorm.Substring(i * 2, 2), 16); + } + + using (MemoryStream memStream = new MemoryStream()) + { + using (BinaryWriter binWriter = new BinaryWriter(memStream)) + { + //Beginne Paket mit 6x 255 + for (int i = 0; i < 6; i++) + { + binWriter.Write((byte)0xff); + + } + //Füge Paket 16x MAC des Zielrechners hinzu + for (int i = 0; i < 16; i++) + { + binWriter.Write(macBytes); + } + } + return memStream.ToArray(); + } + } + + /// + /// Sendet Magic Packet in UDP-Paket aus + /// + /// Lokale IP + /// Multicast IP + /// Magic Packet enthält MAC des Ziels + /// + private static async Task SendUdpAsync(IPAddress adr, IPAddress multicastIp, byte[] magicPacket) + { + int count; + + //Sendet UDP an Port 0 + using (UdpClient client = new UdpClient(new IPEndPoint(adr, 0))) + { + count = await client.SendAsync(magicPacket, magicPacket.Length, multicastIp.ToString(), 9); + } + return count; + } + + /// + /// Prüft, ob Rechner erfolgreich aufgeweckt wurde + /// + /// RQ-Nummer des Zielrechners + /// + public static bool PingHost(string host) + { + bool pinged = false; + + try + { + Ping p = new Ping(); + PingReply reply = p.Send(host, 1000); + if (reply != null && reply.Status == IPStatus.Success) + { + pinged = true; + } + } + catch + { + pinged = false; + } + + return pinged; + } + } +} diff --git a/WOLHelper/WOLHelper.csproj b/WOLHelper/WOLHelper.csproj new file mode 100644 index 0000000..2026171 --- /dev/null +++ b/WOLHelper/WOLHelper.csproj @@ -0,0 +1,48 @@ + + + + + Debug + AnyCPU + {385E5B21-B758-46BC-BE41-0ADEBF9BD97B} + Library + Properties + WOLHelper + WOLHelper + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + none + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + \ No newline at end of file