Accessing GPS Data From a .Net Winform Application - c#

Does anyone out there have any experience programatically retreiving the lat/long from a GPS attached to a mobile PC? A team I'm on is currently looking at hardware options--as the programmer who will eventually have to live with whatever is selected I was wondering if anyone out there has had experience writing .Net programs that interface with a GPS? Any recomendations for hardware and/or programming would be greatly appreciated.
As I envision it, my application will need to ask the GPS for the current lat/long perhaps once every 10 to 20 seconds.

I've written such an application before.
As Henk said, you listen on a COM port. Build a component that reads the com stream in, in say a 1024 buffer. that'll be plenty to contain at least 1 complete NMEA sentence. From there, read the input until you find the start of a sentence and parse it. If for some reason you don't have the full sentence, read in another buffer, append and continue/try again.

If you're willing to be dependent on Windows 7, there's a Location API that handles the NMEA decoding for you.

If the Gps is integrated within your windows CE PC or windows mobile phone, you can simply use the GPS Intermediate Driver to pool for information.
Since you are in a .net environment, you could create a .Net wrapper to this native API.
public class GpsHardware
{
private const string gpsLibraryName = "gpsapi.dll";
private const string coreLibraryName = "coredll.dll";
[DllImport(GpsHardware.coreLibraryName, SetLastError = false)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EventModify(IntPtr hEvent, uint function);
[DllImport(GpsHardware.gpsLibraryName, SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr GPSOpenDevice(IntPtr hNewLocationData, IntPtr hDeviceStateChange, string szDeviceName, uint dwFlags);
[DllImport(GpsHardware.gpsLibraryName, SetLastError = true)]
private static extern uint GPSCloseDevice(IntPtr hGPSDevice);
[DllImport(GpsHardware.gpsLibraryName, SetLastError = true)]
private static extern uint GPSGetPosition(IntPtr hGPSDevice, IntPtr pGPSPosition, uint dwMaximumAge, uint dwFlags);
[DllImport(GpsHardware.gpsLibraryName, SetLastError = true)]
private static extern uint GPSGetDeviceState(IntPtr pGPSDevice);
...
}
Of course you will have to deal with marshaling and all the great interop things :)

Related

IoT Raspberry Pi 2 - Forcing load onto it

My project contains of measuring temperature at different "loads" put onto the raspberry pi's capability to see whether making the raspberry work "harder" or not will affect the temperature sensor input. I am using windows 10 on my raspberry pi 2 model B and am having trouble finding enough sources about this, hence asking here.
Is it possible to somehow place a load upon the raspberry programmatically from Visual Studio as a universal application for the raspberry, in terms of perhaps forcing it to increase usage of the available RAM or perhaps limiting it? If so, what would be the best solution for this?
Is there any way to check, programmatically how much RAM it is using in total, by already implemented functions in a universal application project?
Is there any other way to "place loads" on the raspberry and being able to measure how much load you are forcing it to work?
Any type of help is very appreciated, thank you in advanced for the effort placed to answer these questions!
Is there any way to check, programmatically how much RAM it is using
in total, by already implemented functions in a universal application
project?
There is no direct API of getting total RAM in use but you can get available RAM will be used, in C#, do it like this:
[StructLayout(LayoutKind.Sequential)]
private class MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
public MEMORYSTATUSEX()
{
this.dwLength = (uint)Marshal.SizeOf(typeof(MEMORYSTATUSEX));
}
}
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GlobalMemoryStatusEx([In, Out] MEMORYSTATUSEX lpBuffer);
// Alternate Version Using "ref," And Works With Alternate Code Below.
// Also See Alternate Version Of [MEMORYSTATUSEX] Defined As A Structure.
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", EntryPoint = "GlobalMemoryStatusEx", SetLastError = true)]
static extern bool _GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
void GetProcessUsage()
{
MEMORYSTATUSEX data = new MEMORYSTATUSEX();
GlobalMemoryStatusEx(data);
System.Diagnostics.Debug.WriteLine(data.ullTotalPageFile + "\t\t" + data.ullAvailPageFile);
}
Is there any other way to "place loads" on the raspberry and being
able to measure how much load you are forcing it to work?
You may try this:
List<byte[]> list = new List<byte[]>();
while (true)
{
var buf = new byte[1024 * 1024 * 50];
list.Add(buf);
System.Diagnostics.Debug.WriteLine("Allocating memory");
await Task.Delay(1000);
}
Memory can be used for app is 390MB of Raspberry Pi 3 with 1GB RAM. For 512 MB models seems to be 185MB. You can use Windows.System.MemoryManager.AppMemoryUsageLimit to confirm your device.

How to set MinWorkingSet and MaxWorkingSet in a 64-bit .NET process?

How do I set MinWorkingSet and MaxWorking set for a 64-bit .NET process?
p.s. I can set the MinWorkingSet and MaxWorking set for a 32-bit process, as follows:
[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
[DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr MyGetCurrentProcess();
// In main():
SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, int.MaxValue, int.MaxValue);
Don't pinvoke this, just use the Process.CurrentProcess.MinWorkingSet property directly.
Very high odds that this won't make any difference. Soft paging faults are entirely normal and resolved very quickly if the machine has enough RAM. Takes ~0.7 microseconds on my laptop. You can't avoid them, it is the behavior of a demand_paged virtual memory operating system like Windows. Very cheap, as long as there is a free page readily available.
But if it "blips" you program performance then you need to consider the likelihood that it isn't readily available and triggered a hard page fault in another process. The paging fault does get expensive if the RAM page must be stolen from another process, its content has to be stored in the paging file and has to be reset back to zero first. That can add up quickly, hundreds of microseconds isn't unusual.
The basic law of "there is no free lunch", you need to run less processes or buy more RAM. With the latter option the sane choice, 8 gigabytes sets you back about 75 bucks today. Complete steal.
All you have to do is change your declaration like so:
[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize",
SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess,
long dwMinimumWorkingSetSize, long dwMaximumWorkingSetSize);
The reason is because of the definition of the SetProcessWorkingSetSize function:
BOOL WINAPI SetProcessWorkingSetSize(
_In_ HANDLE hProcess,
_In_ SIZE_T dwMinimumWorkingSetSize,
_In_ SIZE_T dwMaximumWorkingSetSize
);
Note that it doesn't use a DWORD (as 32-bit integer) but a SIZE_T, which is defined as:
The maximum number of bytes to which a pointer can point. Use for a
count that must span the full range of a pointer. This type is
declared in BaseTsd.h as follows:
typedef ULONG_PTR SIZE_T;
This means that it's a 64-bit value, hence the ability to change to a long and have the function work on 64-bit systems. Also, from the section of MSDN titled "Common Visual C++ 64-bit Migration Issues":
size_t, time_t, and ptrdiff_t are 64-bit values on 64-bit Windows operating systems.
However, this presents a bit of a dilemma, in that you don't want to have to compile platform-specific assemblies (that would be a PITA). You can get around this by taking advantage of the EntryPoint field on the DllImportAttribute class (which you're already doing) to have two method declarations:
[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize",
SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize32(IntPtr pProcess,
int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize",
SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize64(IntPtr pProcess,
long dwMinimumWorkingSetSize, long dwMaximumWorkingSetSize);
Now you have two separate signatures. However, knowing which signature to call is still an issue. You don't want to place conditional checks everywhere. To that end, I'd recommend creating a method that performs the check for you and call that.
You'll want to use the Is64BitProcess property on the Environment class to make this determination. Don't use the Is64BitOperatingSystem property. You want the former because 32-bit processes can be run on 64-bit operating systems, and you want to make sure that your code is resilient to that; just checking to see if the operating system is 64 bit doesn't give you the entire picture.

How to scrape datagrid from a Windows Application

I am attempting to scrape data from a datagrid inside a windows application.
I have successfully scraped the data from textboxes in the application using the User32.dll and its methods such as GetWindow to find the handles and then using SendMessage to read the content.
[DllImport("user32.dll", EntryPoint = "GetWindow", SetLastError = true)]
internal static extern IntPtr GetWindow(IntPtr lpWindHandle, uint lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
My problem is that these methods don't seem to return any values for a DataGrid or table.
Does anyone have any advice on how I might be able to achieve this?
This is possible by using UI Automation API. I hope these links help you find the needed solution: Discussion of similar problem,UI Automation Support for the DataGrid Control Type. Although specific solution depends on many implementation details of the datagrid.

Programmatically change cursor speed in windows

Since getting a satisfactory answer on SuperUser is very difficult, I want to rephrase this question and ask:
Is there any way to programmatically detect a mouse was plugged in the usb port, and change the cursor speed in windows (perhaps through an API)?
I'd like to use C#, but I'm open to any language that can run on a windows 7 machine.
I don't know about the detection but you can use P/Invoke to the SystemParametersInfo api using
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, String pvParam, SPIF fWinIni);
with the uiAction as (SPI_SETMOUSESPEED) = 0x0071

How to wake up from Hibernation at a given day/time?

I need to wake up a hibernated laptop at a given time every day.
Should I use pinvoke? If yes? which one? How?
You can wake the computer up from sleep, I'm not sure about hibernate. This example shows you how to do it. In short you use these two imports:
[DllImport("kernel32.dll")]
public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume);
I've only tested it on Windows Vista and 7, these may not be available on XP.
I know it's VB and not C#, but take a look at this example, it does require that your motherboard meets certain requirements.

Categories

Resources