InitiateSystemShutdown call on local computer - c#

When using
InitiateSystemShutdown(null, null, 0, true, false);
some weird things happen. It all works well when I just call the function, also works fine build in my shut-down timer application but the thing is that it does not shut down pc when it's idle for 30+ min and my monitors turn off.
I used other functions to try and shut down the system but I come across the same problem whatever I use. The system does not go to sleep or hibernate or anything like that, it just turns off the displays.
is there a need to "wake" system up somehow prior to calling the function or anything like that.
Method declared as:
static extern bool InitiateSystemShutdown(
[MarshalAs(UnmanagedType.LPStr)] string lpMachinename,
[MarshalAs(UnmanagedType.LPStr)] string lpMessage,
Int32 dwTimeout,
bool bForceAppsClosed,
bool bRebootAfterShutdown);

Related

Force windows to wake up from standby mode [duplicate]

What's the best way to programmatically cause a Windows XP (or above) machine to wake up at a specific time. (Ideally a lot like how Media Center can start up automatically to record a particular TV program)
I've got a Windows service (written in C#) and I'd like this service to be able to cause the machine it is hosted on to start up at predetermined times.
Are there any BIOS settings or prerequisites (eg. ACPI) that need to be configured for this to work correctly?
This machine would be using dialup or 3G wireless modem, so unfortunately it can't rely on Wake on LAN.
You can use waitable timers to wake from a suspend or hibernate state. From what I can find, it is not possible to programmatically wake from normal shut down mode (soft off/S5), in that case, you need to specify a WakeOnRTC alarm in BIOS. To use waitable timers from C#, you need pInvoke. The import declarations are:
public delegate void TimerCompleteDelegate();
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetWaitableTimer(IntPtr hTimer, [In] ref long pDueTime, int lPeriod, TimerCompleteDelegate pfnCompletionRoutine, IntPtr pArgToCompletionRoutine, bool fResume);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CancelWaitableTimer(IntPtr hTimer);
You can use those functions in the following way:
public static IntPtr SetWakeAt(DateTime dt)
{
TimerCompleteDelegate timerComplete = null;
// read the manual for SetWaitableTimer to understand how this number is interpreted.
long interval = dt.ToFileTimeUtc();
IntPtr handle = CreateWaitableTimer(IntPtr.Zero, true, "WaitableTimer");
SetWaitableTimer(handle, ref interval, 0, timerComplete, IntPtr.Zero, true);
return handle;
}
You can then cancel the waitable timer with CancelWaitableTimer, using the returned handle as an argument.
Your program can hibernate and sleep using pInvoke:
[DllImport("powrprof.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
public static bool Hibernate()
{
return SetSuspendState(true, false, false);
}
public static bool Sleep()
{
return SetSuspendState(false, false, false);
}
Your system may not allow programs to let the computer enter hibernation. You can call the following method to allow hibernation:
public static bool EnableHibernate()
{
Process p = new Process();
p.StartInfo.FileName = "powercfg.exe";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.Arguments = "/hibernate on"; // this might be different in other locales
return p.Start();
}
The task scheduler program in Win7, taskschd.msc (and I beleive XP as well) can be set to wake the system on different triggers. Those triggers can be schedule, time, event, etc.
In at least Win7, you need to set "Allow Wake Timers" to 'Enabled' for this to work. This setting is found under...
--> Control Panel\Hardware and Sound\Power Options
click - "Edit Plan Settings"
click - "Change advanced power setting"
expand - "Sleep"
Expand - "Allow Wake timers"
Your best bet is using Wake on LAN capability. This will require another machine to send a packet of a special kind to wake your machine up.
This will not be helpful if your machine is not connected to the network or you for some reason don't wasnt to move this logic onto another machine. But it's useful for some configurations where you have multiple machines and want to wake them up programmatically.
Some machines have a BIOS alarm clock that can be set to wake up the computer at a certain hour. It should be possible to program this clock, but I don't know the specific details.
Edit: I found this program that should let you set the time. It's in C, under Linux, but maybe it can give you some hints.
A warning though: before trying anything that changes the BIOS settings directly be sure to write down every setting from BIOS screens, because in case of an error the BIOS might revert to factory default and you might need to set it up again as it was.

Alternative to GetWindowModuleFileName to get other processes ApplicationFileName?

In order to get the application name of the foreground Window (or the name of application file) I want to use GetActiveWindow with GetWindowModuleFileName.
I found a similar question relating to GetWindowText here
That implementation of GetWindowText works fine, but GetWindowModuleFileName only returns a value for visual studio (when I click inside the devenv) for all other applications it stays blank.
Any hint how I can find out what goes wrong? Might this have to do with permission/security of my application querying the applicationfilename of another process?
EDIT: http://support.microsoft.com/?id=228469 looks like this doesn't work under Win >=XP
Any alternatives how to get the application file name?
In order to get the application name of the foreground Window (or the name of application file) I want to use GetActiveWindow with GetWindowModuleFileName.
... querying the applicationfilename of another process ...
In my opinion your problem with use of GetActiveWindow() function. It is used for gathering information from the calling thread/process only. If calling thread is inactive GetActiveWindow return 0;
From MSDN:
GetActiveWindow Retrieves the window handle to the active window attached to the calling thread's message queue.
Try to use GetForegroundWindow() function instead of GetActiveWindow()
By chance do you have UAC turned off?
Starting with Vista, if your code touches an HWND in another process, your process needs to be run at the same privilege level.
In other words, if the window is hosted in a process running as administrator, your app must also run as administrator.
I found a workaround using this:
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
IntPtr handle = IntPtr.Zero;
handle = GetForegroundWindow();
uint processId;
if (GetWindowThreadProcessId(handle, out processId) > 0)
{
Console.WriteLine(Process.GetProcessById((int)processId).MainModule.FileName);
}

Detecting that the user is away from the PC with .NET

I have a desktop application in which I would like to know two things:
Is the user currently on the PC (more specifically, is he giving any input to the PC), so I can change his state to "away" if needed; and
Is the screensaver running right now, so I can perform more CPU intensive work during that time.
I'm using C#/.NET. How would you suggest to tackle these two tasks?
NOTE: WIN32 invocation will be just as good, as well as any unmanaged code solution.
http://dataerror.blogspot.com/2005/02/detect-windows-idle-time.html
^ Detect Windows Idle Time. :)
The enabler for this feature is the GetLastInputInfo() Win32 API and the LASTINPUTINFO Win32 structure.
Here is the code to detect if a screen saver is running. See this for more details
const int SPI_GETSCREENSAVERRUNNING = 114;
[DllImport( "user32.dll", CharSet = CharSet.Auto )]
private static extern bool SystemParametersInfo(
int uAction, int uParam, ref bool lpvParam,
int flags );
// Returns TRUE if the screen saver is actually running
public static bool GetScreenSaverRunning( )
{
bool isRunning = false;
SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0,
ref isRunning, 0 );
return isRunning;
}
Rather than figuring out when to run more intensive work... Consider doing your "intensive work" as early as you can, but at a lower thread priority.
I don't think your questions have an answer in pure C#, unless you poll the mouse position and observe movements... Or something like that.
You could use a global keyboard/mouse hook and just reset your "counter" to 0 when you receive an event from either. When your counter reaches the idle time that you're looking for, perform your background actions.
There is some code here that allows you to easily do the hooking in .NET: http://www.codeproject.com/KB/cs/globalhook.aspx

.NET Minimize to Tray AND Minimize required resources

I have a WinForms application (I'm using VB) that can be minimized to the system tray. I used the "hackish" methods described in multiple posts utilizing a NotifyIcon and playing with the Form_Resize event.
This all works fine aesthetically, but the resources and memory used are unaffected. I want to be able to minimize resources when minimizing to system tray, just like Visual Studio does. If you are coding in Visual Studio, the memory usage can creep up (depending on project size) to above 500 MB, but when minimizing Visual Studio to the taskbar, the memory drastically decreases to (what I'm assuming) is the minimal amount.
Does anyone have any clue as to how to accomplish this?
Here's a short description of the application, if anyone finds it relevant: I have a windows form with a ListView that contains Work Orders for my IT department. The application has a "listener" that notifies when a new Work order is submitted. So, when the application is running in the system tray, all I really do is compare the count of items in the ListView to a count of rows in a SQL table every couple of minutes.
EDIT: To be more specific, a windows form intrinsically has threads and resources being used by means of the controls, when the form is invisible (in the system tray) these resources are still being used. What can I do to minimize these resources, short of killing all the controls and redrawing them when the form is restored.
Calling MiniMizeMemory() will do a garbage collection, trim the process working size, then compact the process' heap.
public static void MinimizeMemory()
{
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
SetProcessWorkingSetSize(
Process.GetCurrentProcess().Handle,
(UIntPtr)0xFFFFFFFF,
(UIntPtr)0xFFFFFFFF);
IntPtr heap = GetProcessHeap();
if (HeapLock(heap))
{
try
{
if (HeapCompact(heap, 0) == 0)
{
// error condition ignored
}
}
finally
{
HeapUnlock(heap);
}
}
}
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SetProcessWorkingSetSize(
IntPtr process,
UIntPtr minimumWorkingSetSize,
UIntPtr maximumWorkingSetSize);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcessHeap();
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool HeapLock(IntPtr heap);
[DllImport("kernel32.dll")]
internal static extern uint HeapCompact(IntPtr heap, uint flags);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool HeapUnlock(IntPtr heap);
You're probably looking for this function call: SetProcessWorkingSetSize
If you execute the API call SetProcessWorkingSetSize with -1 as an argument, then Windows will trim the working set immediately.
However, if most of the memory is still being held by resources you haven't released minimizing the working set will do nothing. This combined with the suggestion of forcing Garbage Collection might be your best bet.
From your application description, you might want to also verify how much memory the ListView is consuming as well as the database access objects. I'm also not clear on how you're making those monitoring database calls. You might want to isolate that into a separate object and avoid touching any of the forms while minimized, otherwise the program will be forced to keep the controls loaded and accessible. You could start a separate thread for monitoring, and pass the ListView.Count as a parameter.
Some sources:
.NET Applications and the Working Set
How much memory does my .Net Application use?
To clean up unused memory, use GC.Collect()... though you should read up on why to do it and why its usually a bad idea to use it often.
If you mean other resources, you will need to be more specific.
While this is in C#, look at the source code, it will solve any issues you have:
http://www.codeproject.com/KB/cs/NotifyIconExample.aspx

Prevent Pocket PC device from Shutting down application on power off

How can I prevent the pocket PC device from shutting down from my application when the power button pressed? I am using C#.
You could use the Microsoft.WindowsCE.Form.MessageWindows class to intercept the Power Button event. This solution will not be portable, as the hardware key will be different in different machines.
I recommend however that you don't disable power down completely. Have a look at my answer in another question here. You could also use openetcf to easily create power down events handlers and register wake up events. You should implement the application logic based on what you are trying to achieve, for instance wake up every one minute to run a process.
You can try changing the power requirements for the device "BLK1:", which is the blacklight device. Be aware that the behavior may not be the same on all devices and version of the OS or Vendor specific Extensions.
To do this, you can write something like :
[DllImport("coredll")]
private extern static IntPtr SetPowerRequirement(string pvDevice, int deviceState,
int deviceFlags, IntPtr pvSystemState, int stateFlags);
[DllImport("coredll")]
private extern static int ReleasePowerRequirement(IntPtr handle);
and call it this way :
IntPtr handle = SetPowerRequirement("BLK1:", 0 /* D0, Full On */, 1, IntPtr.Zero, 0);
// Do something that requires the device to stay on ...
ReleasePowerRequirement(handle);
But this is generally not a good practice, leaving a device with the backlight on for extended periods might reduce dramatically its autonomy.

Categories