Programmatically detect if Mouse and Keyboard are plugged in - vb.net

I was wanting to know what is the best way to detect if a mouse or keyboard is plugged in to the computer? I have an application that is mostly used in a touchscreen standalone but I want to know if there is a keyboard plugged in don't fire off pulling up the windows keyboard or a form that contains a numeric keypad. Then change some behavior if the mouse is plugged in against if it isn't.

Using VB.Net, I would use System.Management (don't forget to add this reference in the Project [Menu] -> Add Reference) ManagementObjectSearcher combined with System.Linq to find the solution like this,
Imports System
Imports System.Management
Imports System.Linq
Public Module Module1
Public Sub Main()
Console.WriteLine(HasDevice("PointingDevice"))
Console.WriteLine(HasDevice("Keyboard"))
Console.ReadKey()
End Sub
Public Function HasDevice(strtype As String)
Dim searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_" + strtype)
Dim result = From mobj In searcher.Get()
Select mobj Where mobj("Status").ToString() = 0
Return Not IsNothing(result)
End Function
End Module
Result
You could also hard-coded it to avoid input mistake like TRiNE suggested (though using C#)
Public Function HasPointingDevice()
Dim searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_PointingDevice")
Dim result = From mobj In searcher.Get()
Select mobj Where mobj("Status").ToString() = 0
Return Not IsNothing(result)
End Function
Public Function HasKeyboard()
Dim searcher As New ManagementObjectSearcher("root\CIMV2", "SELECT * FROM Win32_Keyboard")
Dim result = From mobj In searcher.Get()
Select mobj Where mobj("Status").ToString() = 0
Return Not IsNothing(result)
End Function
And call them like this
Public Sub Main()
Console.WriteLine(HasPointingDevice())
Console.WriteLine(HasKeyboard())
Console.ReadKey()
End Sub
They will produce the same result

You can use C# System.Management and ManagementObjectSearcher
Here is a sample code. Modify as it matches your need.
public bool isPointingDeviceAttached()
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PointingDevice");
int devCount = 0;
foreach (ManagementObject obj in searcher.Get()) {
if(obj["Status"].ToString().Contains("OK")) // if device is ready
devCount++;
}
return devCount>0;
}
public bool isKeyboardAttached()
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_Keyboard");
int devCount = 0;
foreach (ManagementObject obj in searcher.Get()) {
if (obj["Status"].ToString().Contains("OK")) // if device is ready
devCount++;
}
return devCount>0;
}
Make sure to add using System.Management; line and to add System.Management in references.
You can use more ManagementObject attributes as match your need. Here is a list of attributes and some other external references.
Pointing device class ref. & attribute list
C#, C++ similar example

I spent a couple of days tackling this and found nothing that says a keyboard is detached. Only what is attached currently. That gave me an idea though! With my keyboard attached I checked and three keyboard devices were listed. I removed the keyboard and one disappeared. Now I just look for obj.tostring.contains("USB") and if it doesn't I know there is no keyboard attached to my tablet.
The other two were HID and ACPI which I guess are the touchscreen and mousepad.
Of course other tablets may be different so it isn't a robust
Edit: TO be clear, using the previous answer's code foreach (ManagementObject obj in searcher.Get()) { if (obj["Status"].ToString().Contains("OK")) // if device is ready devCount++;
I use obj.tostring.contains("USB") instead of (obj["Status"]xxxx If the tablet is plugged in I will get three keyboards listed and all the "Status" variables report OK. If I unplug the keyboard there are only two entries both of which have a status of OK while the USB keyboard status simply isn't there. So I just look for the USB string in the object and if it isn't there then I know it isn't plugged in.

Related

Compilation error: object library invalid or contains references to object definitions that could not be found

I want to import some data from an Oracle Database, but I don't want to leave the Password on the macro, as it is very easy to access. Then I found this code to hide myconnection string, which works pretty well, at least on my PC. I created a .dll of the next code so that the database data is not available for users.
using ADODB;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace HiddenConnectionString
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("2FCEF713-CD2E-4ACB-A9CE-E57E7F51E72E")]
public interface IMyServer
{
Connection GetConnection();
void Shutdown();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("57BBEC44-C6E6-4E14-989A-B6DB7CF6FBEB")]
public class MyServer : IMyServer
{
private Connection cn;
private string cnStr = "Provider=MSDAORA.1;Password=YourPass;User ID=YourID;Data Source=IP:Port";
public MyServer)(
{
}
public Connection GetConnection()
{
cn = new Connection();
cn.ConnectionString = cnStr;
cn.Open();
return cn;
}
public void Shutdown()
{
cn.Close();
}
}
}
The next code is the one that I am trying to run:
Option Explicit
Sub Main()
Dim myCn As MyServer
Set myCn = New MyServer
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
'Consumos
rs.Open "select * from tablename, myCn.GetConnection
Sheets.Add After:=ActiveSheet
Range("A2").CopyFromRecordset rs
rs.Close
myCn.Shutdown
Set rs = Nothing
Set myCn = Nothing
End Sub
I've been trying to make it work on other computers but when I run the testing code on them i get this error:
Compilation error: object library invalid or contains references to object definitions that could not be found
So it seems like the library hasn't been imported, but when I check on the reference list, my "hiddenconnectionString.dll" is activated, so I don't know what it going on.
Can someone give me some advice on how to make it work? Any help is welcome. Thanks :D
Sounds like the dll is only installed on your machine. Items in the reference list are not imported and/or stored in the VBA. They need to be present on each host machine.
I'm not sure that hidden connection strings are a good idea. Security by obscurity is generally discouraged, as often it can be bypassed by anyone willing to invest enough time.
This design also uses a shared UID and PWD. With each user sharing an account you lose the ability to audit who did what.
Where possible, I'd always recommend providing each user with their own account.

What are DShellFolderViewEvents and DShellFolderViewEvents_Event?

The names make it sound like some sort of event handler.
Both were identified as an interface from Shell32 using the code below:
I can't find either of these in the MSDN libraries. Google returned some pages with code where they appeared, but I didn't see anything that really described the interface.
Public Sub ListTypes()
Dim NS As String = "Shell32"
For Each t As Type In Assembly.GetExecutingAssembly().GetTypes()
If (t.IsClass Or t.IsInterface) And t.Namespace = NS Then
Debug.Print(t.Name)
End If
Next
End Sub
Based on the definition in ShlDisp.h it appears to simply be a thin wrapper around IDispatch with a different GUID.
MIDL_INTERFACE("62112AA2-EBE4-11cf-A5FB-0020AFE7292D")
DShellFolderViewEvents : public IDispatch
{
};
It seems to be used in obtaining event notification from the shell - Raymond Chen's blog has some example code.

Best method for initializling the Okuma API if I want a program that works for both lathe and mills?

I am writing a program that will run on both lathe and machining centers. How best can I initialize the API without doing during loading. Should I call a class for each machine type or can I call each (and close them) within the same class?
Added example of current method for just Lathe...
using Okuma.CLDATAPI.DataAPI;
using Okuma.CLDATAPI.Enumerations;
using Okuma.CLDATAPI.Structures;
using Okuma.CLDATAPI.DataAPI.MacMan;
public class LatheDutyOnline
{
private CMachine Objl;
private CVariables Objlv;
private CIO IO;
private CATC ObjAtc;
private CAxis objaxis;
private CBallScrew objBS;
private CProgram objProgram;
private CSpec objSpec;
private CSpindle objSpindle;
private void Form1_Load(System.Object sender, System.EventArgs e)
{
Objl = new CMachine();
Objl.Init();
Objlv = new CVariables();
IO = new CIO();
ObjAtc = new CATC();
objaxis = new CAxis();
objBS = new CBallScrew();
objProgram = new CProgram();
objSpec = new CSpec();
objSpindle = new CSpindle();
}
You need a routine to check the current machine type. Something like this:
Private Sub CheckMachineType()
If System.IO.File.Exists("C:\OSP-P\SHAREDDLL\LDATAPI.DLL") And System.IO.File.Exists("C:\OSP-P\VOLANTE\CRAD\LCMDAPI.EXE") Then
MachineType = Lathe
ElseIf System.IO.File.Exists("C:\OSP-P\SHAREDDLL\MDATAPI.DLL") And System.IO.File.Exists("C:\OSP-P\VOLANTE\CRAD\MCMDAPI.EXE") Then
MachineType = MachiningCenter
Else
MachineType = NonOSP
End If
End Sub
Then you can initialize the correct API type based on the value of MachineType.
UPDATE
We now have a standard machine agnostic library that is perfect for this.
Please have a look at the sample program for SCOUT.
https://github.com/OkumaAmerica/Open-API-SDK/tree/master/Scout
Take a look at c# intro to Interfaces and this video using .Net interfaces for machine neutral applications. Using interfaces allows you to program against the interface instead of directly against the API.

FakeItEasy VB.NET issues with parameters

Ok, I am trying to teach myself testing using a mock framework and I work in VB.NET, I am new to lambda expressions and all my previous applications were written in version 2005 or earlier. I now have 2010.
So I have tried Rhino.Mocks but found it difficult to get my head around it mostly because of the older syntax. Since, no-one seems to be bloggin in VB.NET these days, I have been looking at C# examples and trying to figure out what is going on.
So I have a situation where I pass an interface to the constructor of a class and hold a refrence to that interface. When an method is called on the object and event is raise that should be handled by the class that implements the inteface.
I was having trouble, so I tried to create a simple version in C# and repeat the steps in vb.net.
So my interface:
public interface IBroadcastClient
{
void MessageReceivedHandler(string msg);
}
The class that raises the events:
public class Broadcaster
{
public Broadcaster(IBroadcastClient c)
{
_client= c;
this.SendMessage += new MessageReceived(_client.MessageReceivedHandler);
}
private IBroadcastClient _client;
public event MessageReceived SendMessage;
public void SendMessageNow()
{
string _Message;
if (SendMessage != null)
{
_Message = #"Yay!";
SendMessage(_Message);
}
}
}
The test:
[TestMethod]
public void TestSendMessageWithIgnoreParameter()
{
//string msg = #"Yay!";
var client = A.Fake<IBroadcastClient>();
Broadcaster b = new Broadcaster(client);
b.SendMessageNow();
A.CallTo(() => client.MessageReceivedHandler(A<string>.Ignored)).MustHaveHappened();
}
This passes, no problems so far.
Now to try the same this in vb.net;
The same interface and broadcaster class, just in vb.net rather than C# with initially hte following unit test.
<TestMethod()>
Public Sub TestMethod1()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).MustHaveHappened()
client.MessageReceivedHandler(A(Of String).Ignored)
End Sub
This fails with the following error message;
" Assertion failed for the following call:
TestFakeItEasyVB.IBroadcastClient.MessageReceivedHandler(msg: )
Expected to find it at least once but found it #0 times among the calls:
1: TestFakeItEasyVB.IBroadcastClient.MessageReceivedHandler(msg: "Yay!")"
Funnily enough writing it this way;
<TestMethod()>
Public Sub TestMethod3()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
A.CallTo(Sub() client.MessageReceivedHandler(A(Of String).Ignored)).MustNotHaveHappened()
End Sub
Will also fail with the same error message, however, this version of the test passes.
<TestMethod()>
Public Sub TestMethod2()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).MustHaveHappened()
client.MessageReceivedHandler("Yay!")
End Sub
This variation also passes in C#, my quandry is what am I doing wrong to get the test to ignore the argument passed to the faked event handler?
The NextCall-syntax is there for legacy reasons, it's better to use the expression syntax:
A.CallTo(Sub() client.MessageReceivedHandler(A(Of String).Ignored)).MustNotHaveHappened()
In your tests above all others has MustHaveHappened, but this specific one has MustNotHaveHappened, I guess that's why your test is failing. I've compiled your code and run it and once it's changed to MustHaveHappened the test passes.
Currently you can not use argument constraints in the VB-specific "NextCall"-syntax. However you can use the method "WhenArgumentsMatch" to rewrite your first test like this:
<TestMethod()>
Public Sub TestMethod1()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).WhenArgumentsMatch(Function(a) a.Get(Of String)(0) = "Yay!").MustHaveHappened()
client.MessageReceivedHandler(Nothing)
End Sub
Or you could use the extension "WithAnyArguments" to ignore all arguments:
<TestMethod()>
Public Sub TestMethod1()
Dim client = A.Fake(Of IBroadcastClient)()
Dim b As New Broadcaster(client)
b.SendMessageNow()
NextCall.To(client).WithAnyArguments().MustHaveHappened()
client.MessageReceivedHandler(Nothing)
End Sub

Reflection - Iterate object's properties recursively within my own assemblies (Vb.Net/3.5)

I wonder if anyone can help me - I've not done much with reflection but understand the basic principles.
What I'm trying to do:
I'm in the process of developing a class that gathers a lot of information about the local system, network, etc... to be used for automated bug reporting. Instead of having to change my test harness every time I add a new property, I'd (ideally) like to be able to serialise the lot as an XML string and just display that in a textbox.
Unfortunately, the Framework won't use the default XML serializer on read-only properties (which almost all of mine are) as they wouldn't deserialize properly
[Not sure I agree with the assumption that anything serialized must be de-serializable - MS says this is a feature "by design" which I suppose I can understand - Perhaps a tag to indicate that it should be serialized anyway would be advantageous?]
The initial approach was to make properties gettable and settable (with a throw exception on the setter) but the amount of work tidying this up afterwards seems a little excessive and I would want the properties to be read-only in the final version.
What I need help with:
My current plan is to use reflection to recursively iterate through each (public) property of my topmost gathering class. The problem is, the samples I've seen don't handle things recursively. Additionally, I only want to inspect an object's properties if it's in one of my assemblies - Otherwise just call .ToString on it.
If I don't have the inspection limited to my assembly, I assume I'll get (say) a string which then contains a Length which in turn will have .Tostring method...
For the purposes of this project, I can almost guarantee no circular references within my code and as this will only be used as a development tool so I'm not too concerned about it running amok now and then.
I'd appreciate some examples/advice.
Many thanks in advance.
This will hopefully get you started. It prints a tree directly to the console so you'll need to adjust to output XML. Then change the IsMyOwnType method to filter out the assemblies you're interested in, right now it only cares about types in the same assembly as itself.
Shared Sub RecurseProperties(o As Object, level As Integer)
For Each pi As PropertyInfo In o.GetType().GetProperties()
If pi.GetIndexParameters().Length > 0 Then Continue For
Console.Write(New String(" "c, 2 * level))
Console.Write(pi.Name)
Console.Write(" = ")
Dim propValue As Object = pi.GetValue(o, Nothing)
If propValue Is Nothing Then
Console.WriteLine("<null>")
Else
If IsMyOwnType(pi.PropertyType) Then
Console.WriteLine("<object>")
RecurseProperties(propValue, level+1)
Else
Console.WriteLine(propValue.ToString())
End If
End If
Next
End Sub
Shared Function IsMyOwnType(t As Type) As Boolean
Return t.Assembly Is Assembly.GetExecutingAssembly()
End Function
you extension version on c# to use on any object
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Extensions
{
public static class ObjectExtension
{
public static string ToStringProperties(this object o)
{
return o.ToStringProperties(0);
}
public static string ToStringProperties(this object o, int level)
{
StringBuilder sb = new StringBuilder();
string spacer = new String(' ', 2 * level);
if (level == 0) sb.Append(o.ToString());
sb.Append(spacer);
sb.Append("{\r\n");
foreach (PropertyInfo pi in o.GetType().GetProperties())
{
if (pi.GetIndexParameters().Length == 0)
{
sb.Append(spacer);
sb.Append(" ");
sb.Append(pi.Name);
sb.Append(" = ");
object propValue = pi.GetValue(o, null);
if (propValue == null)
{
sb.Append(" <null>");
} else {
if (IsMyOwnType(pi.PropertyType))
{
sb.Append("\r\n");
sb.Append(((object)propValue).ToStringProperties(level + 1));
} else{
sb.Append(propValue.ToString());
}
}
sb.Append("\r\n");
}
}
sb.Append(spacer);
sb.Append("}\r\n");
return sb.ToString();
}
private static bool IsMyOwnType(Type t)
{
return (t.Assembly == Assembly.GetExecutingAssembly());
}
}
}