C# Get MAC Address from the Access Point I am connected to - c#

here goes my first post in here.
I am writing a program in C# .NET Framework 4.6.1. I need to somehow get the BSSID (MAC-Address) from the Access Point a device is connected to, to put it in a string variable.
I have been searching for hours over the internet. But all I have found gives me a list of all access points.
A couple of solutions try to parse from the CMD command "netsh wlan show interfaces", but doesn´t seem to work properly. Besides I don´t like the parsing approach, it´s ugly and not performance friendly at all.
Would be golden if someone has a solution for this an could share it.
Best Regards
Enrique
Tryed the code below from another User from here, but it doesn´t seem to give anything back. The returns are empty and for example the function GetAccessPoint isn´t even triggered. (Is the only solution I found with parsing which seemed to be plausible), but as I said, I would like to stay away from parsing.
class AccessPoint
{
public string SSID { get; set; }
public string BSSID { get; set; }
public byte Signal { get; set; }
}
class Program
{
private static async Task Main(string[] args)
{
var apList = await GetSignalOfNetworks();
foreach (var ap in apList)
{
WriteLine($"{ap.BSSID} - {ap.Signal} - {ap.SSID}");
}
Console.ReadKey();
}
private static async Task<AccessPoint[]> GetSignalOfNetworks()
{
string result = await ExecuteProcessAsync(#"C:\Windows\System32\netsh.exe", "wlan show networks mode=bssid");
return Regex.Split(result, #"[^B]SSID \d+").Skip(1).SelectMany(network => GetAccessPointFromNetwork(network)).ToArray();
}
private static AccessPoint[] GetAccessPointFromNetwork(string network)
{
string withoutLineBreaks = Regex.Replace(network, #"[\r\n]+", " ").Trim();
string ssid = Regex.Replace(withoutLineBreaks, #"^:\s+(\S+).*$", "$1").Trim();
return Regex.Split(withoutLineBreaks, #"\s{4}BSSID \d+").Skip(1).Select(ap => GetAccessPoint(ssid, ap)).ToArray();
}
private static AccessPoint GetAccessPoint(string ssid, string ap)
{
string withoutLineBreaks = Regex.Replace(ap, #"[\r\n]+", " ").Trim();
string bssid = Regex.Replace(withoutLineBreaks, #"^:\s+([a-f0-9]{2}(:[a-f0-9]{2}){5}).*$", "$1").Trim();
byte signal = byte.Parse(Regex.Replace(withoutLineBreaks, #"^.*(Signal|Sinal)\s+:\s+(\d+)%.*$", "$2").Trim());
return new AccessPoint
{
SSID = ssid,
BSSID = bssid,
Signal = signal,
};
}
private static async Task<string> ExecuteProcessAsync(string cmd, string args = null)
{
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = cmd,
Arguments = args,
RedirectStandardInput = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8,
}
};
process.Start();
string result = await process.StandardOutput.ReadToEndAsync();
process.WaitForExit();
return result;
}
private static async Task<string> GetFakeData()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "ConsoleApp2.FakeData.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
return await reader.ReadToEndAsync();
}
}
private static void WriteLine(string str)
{
Console.WriteLine(str);
}
}
}

After trial and error I found a simple solution =D
class Program
{
static void Main(string[] args)
{
var wlanClient = new WlanClient();
foreach (WlanClient.WlanInterface wlanInterface in wlanClient.Interfaces)
{
var test = wlanInterface.CurrentConnection.wlanAssociationAttributes.Dot11Bssid;
Console.WriteLine(test);
}
Console.ReadKey();
}
}

Related

SevenZipSharp doesn't extract archive

I'm trying to use SevenZipSharp from https://github.com/squid-box/SevenZipSharp to extract a zip archive. The dll setup is as follows:
public class Paths
{
private static readonly string SynthEBDexeDirPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
public static readonly string ResourcesFolderPath = Path.Combine(SynthEBDexeDirPath, "Resources");
// Toggle between the x86 and x64 bit dll
public readonly string SevenZipPath = Path.Combine(ResourcesFolderPath, "7Zip", Environment.Is64BitProcess ? "x64" : "x86", "7z.dll");
The dll files are copied into my Resources folder from the latest version of 7-Zip. The calling code looks as follows:
using System.IO;
using System.Windows.Controls;
using SevenZip;
namespace SynthEBD;
public class VM_ZipArchiveHandler : VM
{
public VM_ZipArchiveHandler(Window_SevenZipArchiveHandler window)
{
if (File.Exists(PatcherSettings.Paths.SevenZipPath))
{
SevenZipBase.SetLibraryPath(PatcherSettings.Paths.SevenZipPath);
Initialized = true;
}
else
{
CustomMessageBox.DisplayNotificationOK("Initialization Error", "Could not initialize Seven Zip from " + PatcherSettings.Paths.SevenZipPath);
}
Window = window;
}
public string DispString { get; set; } = string.Empty;
public ProgressBar Prog = new ProgressBar();
public Window_SevenZipArchiveHandler Window { get; set; }
private bool Initialized { get; set; } = false;
public void Unzip(string archivePath, string destinationFolder)
{
if (!Initialized)
{
return;
}
Prog.Minimum = 0;
Prog.Maximum = 100;
Prog.Value = 0;
Window.Show();
var progressHandler = new Progress<byte>(
percentDone => Prog.Value = percentDone);
var progress = progressHandler as IProgress<byte>;
var file = new SevenZipExtractor(archivePath);
file.Extracting += (sender, args) =>
{
progress.Report(args.PercentDone);
};
file.ExtractionFinished += (sender, args) =>
{
// Do stuff when done
};
Task.Run(() =>
{
//Extract the stuff
file.ExtractArchive(destinationFolder);
});
Window.Close();
}
public static void UnzipArchive(string archivePath, string destinationDir)
{
Window_SevenZipArchiveHandler window = new Window_SevenZipArchiveHandler();
VM_ZipArchiveHandler handler = new(window);
window.DataContext = handler;
handler.Unzip(archivePath, destinationDir);
}
}
I call UnzipArchive():
string tempFolderPath = Path.Combine(PatcherSettings.ModManagerIntegration.TempExtractionFolder, DateTime.Now.ToString("yyyy-MM-dd-HH-mm", System.Globalization.CultureInfo.InvariantCulture));
try
{
Directory.CreateDirectory(tempFolderPath);
}
catch (Exception ex)
{
Logger.LogError("Could not create or access the temp folder at " + tempFolderPath + ". Details: " + ex.Message);
return installedConfigs;
}
try
{
VM_ZipArchiveHandler.UnzipArchive(path, tempFolderPath);
}
In the end I get an empty directory; the .7z contents are never extracted to it. I've tried using both a .zip and .7z file as inputs, each containing two json files and nothing else. When I set a breakpoint at file.ExtractArchive(destinationFolder), it seems semi-correctly initialized: https://imgur.com/qjYpDur
It looks like it's correctly recognized as a SevenZip archive, but fields like _filesCount are null.
Am I doing something wrong with my setup?
I believe the issue is that your ExtractArchive is wrapped inside a Task and the calling thread returns before the extraction completes and isn't awaited. Not 100% on the details but as an experiment I found what works and what leaves the destination directory empty:
public static void Main(string[] args)
{
SevenZipBase.SetLibraryPath(
Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"7z.dll"));
string archivePath = "D:\\Downloads\\imgs.7z";
var file = new SevenZipExtractor(archivePath);
// works
file.ExtractArchive("D:\\Downloads\\unzipped");
// doesnt work
Task.Run(() =>
{
file.ExtractArchive("D:\\Downloads\\unzipped");
});
// works
Task.Run(() =>
{
file.ExtractArchive("D:\\Downloads\\unzipped");
}).Wait();
}

OptionSet Incorrect number or types of arguments (Parameter 'arguments'

I need to use OptionSet to get args in the console. However I am quite struggling to understand the documentation and the examples I found. LIke this when I am debuging and set the debug to init of OptionSet I see an exception " Incorrect number or types of arguments (Parameter 'arguments') "Could you please advise how to pass the parameters?
http://www.ndesk.org/doc/ndesk-options/NDesk.Options/OptionSet.html
static async Task Main(string[] args)
{
var dessert = new string[] {PhoneNum = 123456,"Cake","Candy"};
await Test(dessert);
}
private static CommandLineOptions GetOptions(string[] args)
{
CommandLineOptions options = new CommandLineOptions();
var os = new OptionSet
{
{ "PhoneNum=", PhoneNum => options.PhoneNumn = PhoneNum },
};
os.Parse(args);
return options;
}
static async Task Test(string[] args)
{
var test = GetOptions(args);
Console.WriteLine(test.PhoneNum);
}
public class CommandLineOptions
{
public string PhoneNum { get;set; }
}
First, you need to add a List<string> property in CommandLineOptions to store the rest of the command line arguments (Candy and Cake), which will be returned by os.Parse.
public class CommandLineOptions
{
public string PhoneNum { get; set; }
public List<string> Rest { get; set; }
}
Then, set Rest when you parse the args:
private static CommandLineOptions GetOptions(string[] args)
{
CommandLineOptions options = new CommandLineOptions();
var os = new OptionSet
{
{ "PhoneNum=", PhoneNum => options.PhoneNum = PhoneNum },
};
options.Rest = os.Parse(args); // Here!
return options;
}
To pass the PhoneNum option, you need to prefix with a hyphen (that's how command line arguments work):
var dessert = new string[] { "-PhoneNum=123456", "Cake", "Candy" };
Then in Test, you can get the Rest of the arguments:
static void Test(string[] args)
{
var test = GetOptions(args);
Console.WriteLine(test.PhoneNum);
foreach (var arg in test.Rest) {
Console.WriteLine(arg);
}
}
I have no idea why you made Test and Main async.

Failing to send protobuf stream over a named pipe and getting result back

I have having troubles sending objects back and forth (duplex communication) using named pipes. The code:
Dto:
[ProtoContract]
public class ServerResponse
{
[ProtoMember(1)]
public string FirstName { get; set; }
[ProtoMember(2)]
public string LastName { get; set; }
}
[ProtoContract]
public class ServerRequest
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public int Age { get; set; }
}
Server:
static void Main(string[] args)
{
Console.WriteLine("Starting Server");
StartServer();
Console.WriteLine("Press any key to stop server..");
Console.ReadKey();
}
static void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("MyPipes");
server.WaitForConnection();
Console.WriteLine("Connected");
//StreamReader reader = new StreamReader(server);
//StreamWriter writer = new StreamWriter(server);
while (true)
{
//string line = reader.ReadLine();
//Console.WriteLine(line);
//writer.WriteLine(line.ToUpper());
//writer.Flush();
var request = Serializer.Deserialize<ServerRequest>(server);
Console.WriteLine($"Name: {request.Name}, Age: {request.Age}");
var response = new ServerResponse() { FirstName = request.Name, LastName = "Always this name!" };
Serializer.Serialize(server, response);
server.Flush();
}
});
}
Client:
static void Main(string[] args)
{
Console.WriteLine("Client");
var client = new NamedPipeClientStream("MyPipes");
client.Connect();
//StreamReader reader = new StreamReader(client);
//StreamWriter writer = new StreamWriter(client);
while (true)
{
//string input = Console.ReadLine();
//if (String.IsNullOrEmpty(input)) break;
//writer.WriteLine(input);
//writer.Flush();
//Console.WriteLine(reader.ReadLine());
string firstName = Console.ReadLine();
var request = new ServerRequest() { Name = firstName, Age = firstName.Length };
Serializer.Serialize(client, request);
client.Flush();
var response = Serializer.Deserialize<ServerResponse>(client);
Console.WriteLine($"Name: {response.FirstName}, Age: {response.LastName}");
}
Console.WriteLine("Done");
Console.ReadKey();
}
It works just fine, when sending a single line of string, but the protobuf fails on me.
For some reason, Deserialize method seems to never stop reading data from stream, therefore I am never able to decode the incoding server request. But if the client is forcefully stopped, then the request gets received.
I also tried using SteamWriter and StreamReader to no avail.. Is it possible to transmit protobuf objects in duplex communication? I would appreciate if somebody would point out what I am doing wrong..
protobuf is not a self-terminating data format; you need to use some kind of framing. Fortunately, the library includes a few basic implementations for your convenience, so : if you use SerializeWithLengthPrefix and DeserializeWithLengthPrefix (making sure to use the same configuration on both sides): it should work.
Without framing: the nature of protobuf is "read until the end of the stream", i.e. exactly what you're seeing. The reason for this is that protobuf is desiged to be concatenatable (is that a word?) even for single messages.

ldap principalsearcher very slow

I want to get information from only 1 user out of 20,000 users. The response time of the method I used below is 40 seconds. What is the solution to this problem?
public AuthenticatedUserProperties Info(string Username)
{
try
{
var context = new PrincipalContext(ContextType.Domain, Settings.LDAPDomain, Settings.LDAPContainer, Settings.LDAPUsername, Settings.LDAPPassword);
UserPrincipal user = new UserPrincipal(context);
user.SamAccountName = Username;
var searcher = new PrincipalSearcher(user);
var searchResults = searcher.FindOne();
DirectoryEntry de = searchResults.GetUnderlyingObject() as DirectoryEntry;
ActiveDirectoryUserProperties prop = ConvertLdapUserPropertyToArray(de);
return new AuthenticatedUserProperties
{
Status = true,
Properties = prop
};
}
catch (Exception e)
{
return new AuthenticatedUserProperties
{
Status = false,
Properties = null
};
}
}
I use the System.DirectoryServices.Protocols library instead. It is always blazing fast. I can never get System.DirectoryServices.AccountManagement to have reliable performance and it is often agonizingly slow (10+ seconds) to get just one user. TBH - I think our Network setup is likely to blame causing the bind to be dysfunctional - but the Protocols library yields good results without much effort regardless of our network dysfunction.
You have to do slightly more work - but nothing particularly difficult. I'm not an expert with this library - but this sample code works reliably for me.
using System.DirectoryServices.Protocols;
public class UserInfo
{
public string SAMAccountName;
public string DomainHostName;
public string ADSDirectory;
public Dictionary<string, string> UserAttributes;
// Some attributes not really strings and require extra handling - but simplied for example
// This is really just for illustrative purposes
public UserInfo(string a_SAMAccountName, string a_DomainHostName = "ldap.mydomain:3268", string a_ADSDirectory = "ours.net")
{
UserAttributes = new Dictionary<string, string>();
SAMAccountName = a_SAMAccountName;
DomainHostName = a_DomainHostName;
ADSDirectory = a_ADSDirectory;
}
}
public static class GetUserAttributes
{
public static List<string> WantedAttributes;
static GetUserAttributes()
{
WantedAttributes = new List<string>();
WantedAttributes.Add("mail");
//... Add Properties Wanted
}
public static void GetUserAttributes(UserInfo a_user)
{
using (HostingEnvironment.Impersonate())
{
LdapDirectoryIdentifier z_entry = new LdapDirectoryIdentifier(a_user.DomainHostName, true, false);
using (LdapConnection z_remote = new LdapConnection(z_entry))
{
z_remote.SessionOptions.VerifyServerCertificate = delegate (LdapConnection l, X509Certificate c) { return true; };
z_remote.SessionOptions.ReferralChasing = ReferralChasingOptions.None;
z_remote.SessionOptions.ProtocolVersion = 3;
z_remote.Bind();
SearchRequest z_search = new SearchRequest();
z_search.Scope = System.DirectoryServices.Protocols.SearchScope.Subtree;
z_search.Filter = "(SAMAccountName=" + a_user.SAMAccountName + ")";
z_search.DistinguishedName = a_user.ADSdirectory;
foreach (List<string> z_item in WantedAttributes)
{
z_search.Attributes.Add(z_item);
}
SearchResponse z_response = (SearchResponse)z_remote.SendRequest(z_search);
if (z_response != null)
{
foreach (SearchResultEntry z_result in z_response.Entries)
{
foreach (string z_property in z_result.Attributes.AttributeNames)
{
if (WantedAttributes.ContainsKey(z_property))
{
DirectoryAttribute z_details = a_result.Attributes[z_property];
if (z_details.Count == 1)
{
// Special handling required for Attributes that aren't strings objectSid, objectGUID, etc
string z_value = z_details[0].ToString().Trim();
if (!string.IsNullOrWhiteSpace(z_value))
{
a_user.UserAttributes.Add(z_property, z_value);
}
}
}
}
}
}
}
}
}
}

Parse .net SDK Get Object

I have been trying to return the string of the result but it doesn't return anything. When I do Console.WriteLine it shows the link.
But the line:
s = nzk.Get<string>("link");
doesn't do anything, and I don't know why.
Here's my code:
public string getlink(String ID)
{
ParseClient.Initialize(new ParseClient.Configuration
{
ApplicationId = "xxxxxxxxxxxxxx5335c1fxxx0f19efxxxx06787e",
Server = "http://api.assintates.net/parse/"
});
string s = "";
ParseQuery<ParseObject> query = ParseObject.GetQuery("test");
query.GetAsync(ID).ContinueWith(t =>
{
ParseObject nzk = t.Result;
Console.WriteLine(nzk.Get<string>("link")); // this works
s = nzk.Get<string>("link");// this doesn't work
});
return s;
}
class Program
{
static void Main(string[] args)
{
g_get x = new g_get();
Console.WriteLine(x.getlink("iLQLJKPoJA")); // shows nothing since i initialized the s with ""
Console.ReadLine();
}
}
Here is a little example to demonstrate your problem:
static void Main(string[] args)
{
Console.WriteLine(GetString());
Console.ReadLine();
}
private static async Task TimeConsumingTask()
{
await Task.Run(() => System.Threading.Thread.Sleep(100));
}
private static string GetString()
{
string s = "I am empty";
TimeConsumingTask().ContinueWith(t =>
{
s = "GetString was called";
});
return s;
}
Your output will be the following:
I am empty
Why? The thing to deal with is the ContinueWith()-function (see msdn).
ContinueWith returns you the Task-object. You have to await this task and in your code you didn't await it.
So simple solution call wait on your Task-object.
string s = "";
ParseQuery<ParseObject> query = ParseObject.GetQuery("test");
query.GetAsync(ID).ContinueWith(t =>
{
ParseObject nzk = t.Result;
Console.WriteLine(nzk.Get<string>("link")); // this works
s = nzk.Get<string>("link");// this doesn't work
}).Wait();
return s;
Here some more information about asynchronous programming in C#.
Edit: Some more information
You will see the console output because your task will be run anyway. But it will be run after you returned your string.

Categories