C# - Logging Available Wifi Connections (While I'm in the car) - c#

For a couple of days, I have puzzled about how to do this in the best way possible. I created a form application like so:
I gave the name "WiFi Hacker" for giggles. But my question is, why does Visual Studio give me this error after a couple minutes using the program?
Additional information: Type 'NativeWifi.Wlan+WlanReasonCode' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.
I am using NativeWifi for my program, and the code for logging networks is as follows:
WlanClient client = new WlanClient();
private void wifilister()
{
foreach (WlanClient.WlanInterface wI in client.Interfaces)
{
foreach (Wlan.WlanAvailableNetwork network in wI.GetAvailableNetworkList(0))
{
Wlan.Dot11Ssid ssid = network.dot11Ssid;
string networkName = Encoding.ASCII.GetString(ssid.SSID, 0, (int)ssid.SSIDLength);
if (wifis.Contains(networkName) == false)
{
//Name
ListViewItem item = new ListViewItem(networkName);
wifis.Add(networkName);
listBox1.Items.Add(networkName);
//Encryption Type
item.SubItems.Add(network.dot11DefaultCipherAlgorithm.ToString());
wifis.Add(network.dot11DefaultCipherAlgorithm.ToString());
//Signal
item.SubItems.Add(network.wlanSignalQuality + "%");
wifis.Add(network.wlanSignalQuality + "%");
//Logged Time
item.SubItems.Add(DateTime.Now.ToString("T"));
wifis.Add(DateTime.Now.ToString("T"));
listView1.Items.Add(item);
label2.Text = "Networks: " + (wifis.Count / 4).ToString();
}
if (checkBox2.Checked)
{
label1.Text = track;
if (Encoding.ASCII.GetString(ssid.SSID, 0, (int)ssid.SSIDLength) == track)
{
label1.Text += " " + network.wlanSignalQuality + "%";
}
}
}
}
I got most of this off a tutorial from YouTube, but after it logs more than about 40 different networks in the List, it seems to give that weird error about
'NativeWifi.Wlan+WlanReasonCode'.
This annoyed me, is there a way around it?

Related

C# Listview is not drawing the ListView SubItems on linux but works on windows

I am creating a C# .NET Mono application to read logs in from a text file and display them in a listview. The logs are stored in JSON format so they can be parsed easily and be displayed as subitems in the listview.
Picture of the working ListView run on Windows
My application is working correctly when I run the application on windows, however when I run it on the raspbian OS using mono none of the items in the listview are shown. I know that the logs are being read correctly from the text file on both Windows & Linux, as I have logged them to the console for debugging purposes. I have also confirmed that the logs have been copied into the ListViewItem "eachRow" correctly by logging it to the console as well.
I am hoping to find the problem that is causing the ListView Items to not be displayed when run on Raspbian. Due to the fact that I have the data stored correctly all the way up until it is added to the listview, I believe my problem is with the redrawing of the screen/listview.
This is the code I am using to Add each JSON item to the listview.
private void AddLogsToScreen()
{
//Create a copy of the current logList Stack
LogMutex.WaitOne();
Stack<string[]> logListCopy = new Stack<string[]>(new Stack<string[]>(LogList));
Console.WriteLine("LLC: " + string.Join(" , ", logListCopy.Peek()));
LogMutex.ReleaseMutex();
if (HUBsLogsListView.InvokeRequired)
{
HUBsLogsListView.Invoke(new MethodInvoker(delegate
{
MessageBox.Show("Invoke Begin Update");
HUBsLogsListView.BeginUpdate();
}));
}
else
{
MessageBox.Show("Begin Update");
HUBsLogsListView.BeginUpdate();
}
var allItemsToAdd = new List<ListViewItem>();
int totalLogs = logListCopy.Count;
for (int logNum = 0; logNum < totalLogs; logNum++)
{
string[] log = logListCopy.Pop();
string[] deepLogCopy = new string[8];
// Copy to avoid messing up original
log.CopyTo(deepLogCopy, 0);
deepLogCopy[2] = DateTime.Parse(log[2]).ToString("dd-MM-yyyy, hh:mm:ss tt");
ListViewItem eachRow = new ListViewItem(deepLogCopy);
Console.WriteLine("ListViewItem eachRow: " + eachRow.SubItems[0] + " , " + eachRow.SubItems[1] + " , " + eachRow.SubItems[2] + " , " + eachRow.SubItems[3] + " , " + eachRow.SubItems[4] + " , " + eachRow.SubItems[5] + " , " + eachRow.SubItems[6] + " , " + eachRow.SubItems[7]);
if (deepLogCopy[4] == "3") //Warning
{
eachRow.BackColor = Color.Yellow;
}
else if (deepLogCopy[4] == "4") //Error
{
eachRow.BackColor = Color.Red;
}
allItemsToAdd.Add(eachRow);
}
if (HUBsLogsListView.InvokeRequired)
{
HUBsLogsListView.Invoke(new MethodInvoker(delegate
{
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(HUBsLogsListView);
lvic.AddRange(allItemsToAdd.ToArray());
HUBsLogsListView.EndUpdate();
}));
}
else
{
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(HUBsLogsListView);
lvic.AddRange(allItemsToAdd.ToArray());
HUBsLogsListView.EndUpdate();
}
}
I can't come up with a reason why this function is acting differently, with the same files, on Windows compared to running on Linux using mono. I am not as experienced writing .NET programs using mono, so any and all help is appreciated.
Does anyone have any idea what could be the problem? Thanks!

C# console local chat group

I'm working on a C# console application that includes a chat group. I thought I had figured it out but it doesn't seems to work... I'm a total beginner, so the way I did it was to create a folder the program fills with .txt files with the message infos (no internet included). That worked to support the user/password/options part of the program but the chat is reacting weirdly. When you enter a message, it react and shows it on screen but when someone else post it you don't see it unless you restart the app. Here's the code:
chat_group:
temp1I = Directory.GetFiles((message_folder + "\\1-Groupe"), "*", SearchOption.AllDirectories).Length;
temp1S = temp1I.ToString();
System.IO.StreamReader ChatFile = new System.IO.StreamReader(message_folder + "\\1-Groupe\\" + temp1S + ".txt");
counter = 0;
while ((temp2S = ChatFile.ReadLine()) != null)
{
switch (counter)
{
case 0:
text = (temp2S + ": ");
WRITE_R();
break;
case 1:
text = (temp2S);
WRITE();
break;
}
counter++;
}
ChatFile.Close();
Console.WriteLine("");
test:
if (File.Exists((message_folder + "\\1-Groupe\\" + (temp1S + 1) + ".txt")))
{
goto chat_group;
}
if ((temp3S = Console.ReadLine()) != null)
{
temp1S = (temp1I + 1).ToString();
string[] ChatLines2 = { username, temp3S };
System.IO.File.WriteAllLines(message_folder + "\\1-Groupe\\" + temp1S + ".txt", ChatLines2);
}
goto test;
Note: As it is a big application, I've not copy the variables but I ensure they are correct as they work on all the other parts of the app.

Multiple AxWindowsMediaPlayer controls exception: System.Runtime.InteropServices.COMException' in AxInterop.WMPLib.dll

Developing a winforms C# 4.5 on Win10 that creates multiple AxWindowsMediaPlayer control objects dynamically on Form1 (the only form). Relative code segments look like this:
axWMPn[zi] = new AxWindowsMediaPlayer();
((ISupportInitialize)(axWMPn[zi])).BeginInit();
axWMPn[zi].Name = "Zone " + zi; //Zone name + index
axWMPn[zi].Tag = "Z" + zi; // "Z" + Zone index
axWMPn[zi].Location = loc;
axWMPn[zi].Size = sz;
Controls.Add(axWMPn[zi]);
((ISupportInitialize)(axWMPn[zi])).EndInit();
axWMPn[zi].uiMode = "none";
axWmpDisplayZones.Add(axWMPn[zi].Tag.ToString(), axWMPn[zi]);
axWMPn[zi].StatusChange += axWMPx_StatusChange;
axWMPn[zi].PlayStateChange += axWMPx_PlayStateChange;
I create 6 zones - 3 are assigned static JPEG images and the other 3 are used for video (*.avi and *.mov). The video files are assigned like this:
private void playVideo(string file)
{
int tc6 = 0;
axWMPn[0].URL = file;
axWMPn[4].URL = file;
axWMPn[5].URL = file;
axWMPn[6].URL = "C:/test/AmexDonut.mov";
}
This all works - playVideo is called from another process and the first time all videos run without errors; however when I call playVideo a second time I intermittently get a COMException error:
Exception thrown: 'System.Runtime.InteropServices.COMException' in AxInterop.WMPLib.dll -- Message: The message filter indicated that the application is busy. (Exception from HRESULT: 0x8001010A (RPC_E_SERVERCALL_RETRYLATER)).
Notes:
1. If I just do 2 axWMPn[x].URL=file it always works no COMException; if I had a third axWMPn[x].URL=file it mostly works with a COMException once every few dozen calls to playVideo. Adding the 4th awWMPn[x].URL=file almost always causes the COMException but not every single time.
So I did following to see more about what was going on:
private void playVideo(string file)
{
int tc6 = 0;
try
{
axWMPn[0].URL = file;
}
catch (System.Runtime.InteropServices.COMException comEx)
{
Console.WriteLine("playVideo COMException 0: " + comEx.Source + " -- " + comEx.Message);
}
try
{
axWMPn[4].URL = file;
}
catch (System.Runtime.InteropServices.COMException comEx)
{
Console.WriteLine("playVideo COMException 4: " + comEx.Source + " -- " + comEx.Message);
}
try
{
axWMPn[5].URL = file;
}
catch (System.Runtime.InteropServices.COMException comEx)
{
Console.WriteLine("playVideo COMException 5: " + comEx.Source + " -- " + comEx.Message);
}
Again:
try
{
axWMPn[6].URL = "C:/test/AmexDonut.mov";
}
catch (System.Runtime.InteropServices.COMException comEx)
{
tc6++;
Console.WriteLine("playVideo COMException 6: try again count = " + tc6 + " - " + comEx.Source + " -- " + comEx.Message);
goto Again;
}
The COMException "busy" when it occurs always occurs in axWMPn[6].URL=file and putting the goto Again in works - tc6 will always just be 1. So merely trying one more time to assign axWMPn[6].URL=file always works. It never takes more than 1 additional try (tc6 never goes beyond 1).
I could leave it this way - I have run it dozens of times and it works just fine; but it sure seems like a bad hack. Does anybody have any thoughts or ideas?
Thanks for any input

How to identify what device was plugged into the USB slot?

I want to detect when the user plugs in or removes a USB sound card. I've managed to actually catch the event when this happens, but I can't tell what just got plugged in.
I tried an approach based on this question:
string query =
"SELECT * FROM __InstanceCreationEvent " +
"WITHIN 2 "
+ "WHERE TargetInstance ISA 'Win32_PnPEntity'";
var watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
While I get the notifications via the EventArrived event, I have no idea how to determine the actual name of the device that just got plugged in. I've gone through every property and couldn't make heads or tails out of it.
I also tried a different query:
var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent where EventType = 1 or EventType = 2");
var watcher = new ManagementEventWatcher(query);
watcher.EventArrived += watcher_EventArrived;
watcher.Stopped += watcher_Stopped;
watcher.Query = query;
watcher.Start();
but also to no avail. Is there a way to find the name of the device that got plugged in or removed.
The bottom line is that I'd like to know when a USB sound card is plugged in or removed from the system. It should work on Windows 7 and Vista (though I will settle for Win7 only).
EDIT: Based on the suggestions by the winning submitter, I've created a full solution that wraps all the functionality.
If I use your first code, I can define my event like this:
// define USB class guid (from devguid.h)
static readonly Guid GUID_DEVCLASS_USB = new Guid("{36fc9e60-c465-11cf-8056-444553540000}");
static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject )e.NewEvent["TargetInstance"];
if (new Guid((string)instance["ClassGuid"]) == GUID_DEVCLASS_USB)
{
// we're only interested by USB devices, dump all props
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
}
}
And this will dump something like this:
Availability =
Caption = USB Mass Storage Device
ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}
CompatibleID = System.String[]
ConfigManagerErrorCode = 0
ConfigManagerUserConfig = False
CreationClassName = Win32_PnPEntity
Description = USB Mass Storage Device
DeviceID = USB\VID_18A5&PID_0243\07072BE66DD78609
ErrorCleared =
ErrorDescription =
HardwareID = System.String[]
InstallDate =
LastErrorCode =
Manufacturer = Compatible USB storage device
Name = USB Mass Storage Device
PNPDeviceID = USB\VID_18A5&PID_0243\07072BE66DD78609
PowerManagementCapabilities =
PowerManagementSupported =
Service = USBSTOR
Status = OK
StatusInfo =
SystemCreationClassName = Win32_ComputerSystem
SystemName = KILROY_WAS_HERE
This should contain everything you need, including the device ID that you can get with something like instance["DeviceID"].
EDIT 1: Oh is see that it is not a USB storage device but only a USB device. I will look for another solution.
Two links that describe the same problem:
http://hintdesk.com/c-catch-usb-plug-and-unplug-event/
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/37123526-83fa-4e96-a767-715fe225bf28/
if (e.NewEvent.ClassPath.ClassName == "__InstanceCreationEvent")
{
Console.WriteLine("USB was plugged in");
//Get disk letter
foreach (ManagementObject partition in new ManagementObjectSearcher(
"ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + mbo.Properties["DeviceID"].Value
+ "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get())
{
foreach (ManagementObject disk in new ManagementObjectSearcher(
"ASSOCIATORS OF {Win32_DiskPartition.DeviceID='"
+ partition["DeviceID"]
+ "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get())
{
Console.WriteLine("Disk=" + disk["Name"]);
}
}
}
When I tried #AngryHacker solution, I noticed that the DeviceChangedEventArgs class did not ever get called, though. I removed it and just added Console.WriteLines() in the watcher_eventArrived methods.
Besides the deletion of the DeviceChangedEventArgs, here are my changes:
(at line 46 in EstablishedWatchEvents)
// setup the query to monitor removal
const string qryRemoval = "SELECT *" + "FROM __InstanceDeletionEvent "
+ "WITHIN 2 " + "WHERE TargetInstance ISA 'Win32_PnPEntity' ";
#region Events
private void insertWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
var mbo = (ManagementBaseObject) e.NewEvent["TargetInstance"];
if (new Guid((string) mbo["ClassGuid"]) == GUID_DEVCLASS_USB)
{
var deviceName = (string) mbo["Name"];
Console.WriteLine(deviceName + " was inserted");
}
}
private void removeWatcher_EventArrived(object sender, EventArrivedEventArgs e)
{
var mbo = (ManagementBaseObject)e.NewEvent["TargetInstance"];
if (new Guid((string)mbo["ClassGuid"]) == GUID_DEVCLASS_USB)
{
var deviceName = (string)mbo["Name"];
Console.WriteLine(deviceName + " was removed");
}
}
#endregion

ImapX IndexOutOfRangeException on Message.Process()

I've just started using your ImapX library to retrieve and read mails from gmail.
Now, everything is working fine and it's a great library.
However, when i'm trying to mark a mail read using the Message.Process() option, it returns the IndexOutOfRangeException.
private void Start()
{
int amountRead = 0;
failedMessages.Clear();
foreach(string origin Properties.Settings.Default.MailOrigins)
{
IMailOriginAdapter adapter = MailOriginFactory.CreateMailOriginContainer(origin);
foreach (ImapX.Message message in adapter.Messages())
{
if (SendWebRequest(url))
{
message.Process();
amountRead++;
Dispatcher.BeginInvoke(new MethodInvoker(delegate
{
this.btnStart.Content = "Read [" + amountRead + "/" + GmailUser.Instance.Messages.Count + "]";
}));
}
else
{
failedMessages.Add(message);
}
}
System.Windows.MessageBox.Show(adapter.GmailFromEmail() + " reading completed.");
}
}
Hopefully someone's capable of helping me with this problem which i've had now for over then a month..
Thanks in advance.
Yours Sincerely,
Larssy1

Categories