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.
Related
In my C# console application, I am using SendMessage() to minimize all windows, effectively showing the Windows 8 Legacy Desktop. This works great, but I have to use a Thread.Sleep(1000) in order to wait for the Legacy Desktop to actually show before before I try to do anything else.
IntPtr lHwnd = FindWindow("Shell_TrayWnd", null);
SendMessage(lHwnd, WM_COMMAND, (IntPtr)MIN_ALL, IntPtr.Zero);
Thread.Sleep(1000);
I really want to replace the Thread.Sleep() with a more efficient way to detect that the Legacy Desktop is showing before continuing on.
Any ideas?
Edit:
Here are the Interop wrappers and constants. just in case it helps..
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
static extern IntPtr SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, IntPtr lParam);
const int WM_COMMAND = 0x111;
const int MIN_ALL = 419;
const int MIN_ALL_UNDO = 416;
I'm not sure if this will work any better for you, but perhaps it's worth a try...
(1) Add to your project a reference to "Shell32" (via Add Reference -> COM -> Microsoft Shell Controls and Automation).
(2) Set the reference's "Embed Interop Types" to false.
(3) Use the following code to minimise all the windows:
dynamic shell = new Shell32.ShellClass();
shell.MinimizeAll();
However, I suspect that this is just an alternative way of doing the SendMessage().
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.
I want to close window with some name (any application, for example, calculator and etc.). How to do it in C#? Import WinAPI functions?
Yes, you should import the Windows API functions: FindWindow(), SendMessage(); and WM_CLOSE constant.
Native definitions of the Windows API functions:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// Find window by Caption only. Note you must pass IntPtr.Zero as the first parameter.
/// </summary>
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
const UInt32 WM_CLOSE = 0x0010;
Client code:
IntPtr windowPtr = FindWindowByCaption(IntPtr.Zero, "Untitled - Notepad");
if (windowPtr == IntPtr.Zero)
{
Console.WriteLine("Window not found");
return;
}
SendMessage(windowPtr, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
You're trying to close windows belonging to other processes. That isn't something you can assume will go reliably. For one thing, YOU don't own those windows so YOU don't really have any automatic entitlement to go and mess with the other processes' windows.
As the other answer suggests, you can try sending a WM_CLOSE to the window but it comes with the caveat that the other process isn't really entitled to honour it. The response to WM_CLOSE can be anything to acceptance and a clean shutdown to outright rejection. In the latter case, you've really got no option. It's not your process. In between, as you've seen, there could be any sort of intermediate windows, dialog boxes, etc, that you'd have to contend with.
So what are you trying to achieve here? Why are you trying to close windows belonging to other processes? It might help to clarify what the aim is.
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
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 :)