In Windows Server 2003 and Windows XP the function to start a Windows Service in Automatic(Delayed) mode isnĀ“t available, so I need make that simulation with code, but when I start the service this will show a message that I need wait cuz are a Timer in the code and this need finish to start. But now I get this error "Tghe PcRegister Service service on local Computer started and then stopped. Some Services stop automatically if they have no work to do, for example, the Performance Logs and Alerts service"... Please I need help to add the timer.
class WinService : System.ServiceProcess.ServiceBase`
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new WinService() };
ServiceBase.Run(ServicesToRun);
}
protected override void OnStart(string[] args)
{
InitializeComponent();
PcRegisterService();
}
protected override void OnStop()
{
}
public void InitializeComponent()
{
this.ServiceName = "WinService";
RestartService("WinService", 600000);
}
public static void RestartService(string serviceName, int timeoutMilliseconds)
{
ServiceController service = new ServiceController(serviceName);
try
{
int millisec1 = Environment.TickCount;
TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);
service.Stop();
service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
// count the rest of the timeout
int millisec2 = Environment.TickCount;
timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds - (millisec2 - millisec1));
service.Start();
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
}
catch
{
// ...
}
}
public static void PcRegisterService()
{
}
public static class PerformanceInfo
{
[DllImport("psapi.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetPerformanceInfo([Out] out PerformanceInformation PerformanceInformation, [In] int Size);
[StructLayout(LayoutKind.Sequential)]
public struct PerformanceInformation
{
public int Size;
public IntPtr CommitTotal;
public IntPtr CommitLimit;
public IntPtr CommitPeak;
public IntPtr PhysicalTotal;
public IntPtr PhysicalAvailable;
public IntPtr SystemCache;
public IntPtr KernelTotal;
public IntPtr KernelPaged;
public IntPtr KernelNonPaged;
public IntPtr PageSize;
public int HandlesCount;
public int ProcessCount;
public int ThreadCount;
}
public static Int64 GetTotalMemoryInMiB()
{
PerformanceInformation pi = new PerformanceInformation();
if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi)))
{
return Convert.ToInt64((pi.PhysicalTotal.ToInt64() * pi.PageSize.ToInt64() / 1048576));
}
else
{
return -1;
}
}
}
}
Because - I would say - something in your RestartServicve method you blow (with an exception). THe code makes no sense. As in none at all. THere is no need to restart a service at all. THis is now how services work. Back to reading the documentation.
Related
I'm trying to crash my Console application after a certain amount of time (this is due to me testing whether the application will start itself after crashing. Following this tutorial)
What I have for this is this piece of code:
static class WebSocket
{
static int Main(string[] args)
{
Recovery.RegisterForAutostart();
Recovery.RegisterForRestart();
Test.Run();
// some more code
}
}
public static class Recovery
{
[Flags]
public enum RestartRestrictions
{
None = 0,
NotOnCrash = 1,
NotOnHang = 2,
NotOnPatch = 4,
NotOnReboot = 8
}
public delegate int RecoveryDelegate(RecoveryData parameter);
public static class ArrImports
{
[DllImport("kernel32.dll")]
public static extern void ApplicationRecoveryFinished(
bool success);
[DllImport("kernel32.dll")]
public static extern int ApplicationRecoveryInProgress(
out bool canceled);
[DllImport("kernel32.dll")]
public static extern int GetApplicationRecoveryCallback(
IntPtr processHandle,
out RecoveryDelegate recoveryCallback,
out RecoveryData parameter,
out uint pingInterval,
out uint flags);
[DllImport("KERNEL32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetApplicationRestartSettings(
IntPtr process,
IntPtr commandLine,
ref uint size,
out uint flags);
[DllImport("kernel32.dll")]
public static extern int RegisterApplicationRecoveryCallback(
RecoveryDelegate recoveryCallback,
RecoveryData parameter,
uint pingInterval,
uint flags);
[DllImport("kernel32.dll")]
public static extern int RegisterApplicationRestart(
[MarshalAs(UnmanagedType.BStr)] string commandLineArgs,
int flags);
[DllImport("kernel32.dll")]
public static extern int UnregisterApplicationRecoveryCallback();
[DllImport("kernel32.dll")]
public static extern int UnregisterApplicationRestart();
}
public class RecoveryData
{
string currentUser;
public RecoveryData(string who)
{
currentUser = who;
}
public string CurrentUser
{
get { return currentUser; }
}
}
// Restart after crash
public static void RegisterForRestart()
{
// Register for automatic restart if the application was terminated for any reason.
ArrImports.RegisterApplicationRestart("/restart",
(int)RestartRestrictions.None);
}
// Start app when PC starts
public static void RegisterForAutostart()
{
#if (!DEBUG)
RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
key.SetValue("websocket", #"c:\websocket\run.bat");
#endif
}
public static class Test
{
public static void Run()
{
crash();
}
static void crash()
{
double crashAfter = 1.5 * 60; // seconds
int secondsPassed = 0;
int waitSeconds = 1;
Console.WriteLine("\nCrash test startet, crash will occour in " + crashAfter + " seconds");
Timer timer = new Timer(
delegate (object seconds) {
secondsPassed += int.Parse(seconds.ToString());
if (secondsPassed > crashAfter)
{
Console.WriteLine("Crashing");
Environment.FailFast("Test - intentional crash."); // Error happens here
}
else
{
double timeUntilCrash = (crashAfter - secondsPassed);
Console.WriteLine("Time until crash = " + timeUntilCrash + " seconds");
}
},
waitSeconds,
TimeSpan.FromSeconds(waitSeconds),
TimeSpan.FromSeconds(waitSeconds));
}
}
When it's time to crash I get this message:
Cannot evaluate expression because a thread is stopped at a point
where garbage collection is impossible, possibly because the code is
optimized.
The checkbox for code optimization is unchecked.
I surpose this is because it's not in the main thread, if this is the case how do I return to the main thread. And if not, what might be the cause?
I created an application based on your code & found that everything runs as expected when the application is run from the command-line - it is only in Visual Studio debugger the restart does not work.
Thanks to PaulF we found the problem. I was testing in Debug mode, running the application in release mode outside of Visual Studio fixed the problem. The following NullReferenceException was caused by missing command line arguments upon restart.
There are already many answers about this topic, but is there a single way to get the the total amount of memory on a windows system from XP and above including Windows Server 2003?
What I have found:
Win32_LogicalMemoryConfiguration (Deprecated)
Win32_ComputerSystem (Minimum supported client: Vista)
Microsoft.VisualBasic.Devices.ComputerInfo (no XP support according to platforms)
thx
Add reference to Microsoft.VisualBasic and
var info = new Microsoft.VisualBasic.Devices.ComputerInfo();
Debug.WriteLine(info.TotalPhysicalMemory);
Debug.WriteLine(info.AvailablePhysicalMemory);
Debug.WriteLine(info.TotalVirtualMemory);
Debug.WriteLine(info.AvailableVirtualMemory);
edit : How can I get the total physical memory in C#?
or
You can make use of GlobalMemoryStatusEx : Example Here
private void DisplayMemory()
{
// Consumer of the NativeMethods class shown below
long tm = System.GC.GetTotalMemory(true);
NativeMethods oMemoryInfo = new NativeMethods();
this.lblMemoryLoadNumber.Text = oMemoryInfo.MemoryLoad.ToString();
this.lblIsMemoryTight.Text = oMemoryInfo.isMemoryTight().ToString();
if (oMemoryInfo.isMemoryTight())
this.lblIsMemoryTight.Text.Font.Bold = true;
else
this.lblIsMemoryTight.Text.Font.Bold = false;
}
Native class wrapper.
[CLSCompliant(false)]
public class NativeMethods {
private MEMORYSTATUSEX msex;
private uint _MemoryLoad;
const int MEMORY_TIGHT_CONST = 80;
public bool isMemoryTight()
{
if (_MemoryLoad > MEMORY_TIGHT_CONST )
return true;
else
return false;
}
public uint MemoryLoad
{
get { return _MemoryLoad; }
internal set { _MemoryLoad = value; }
}
public NativeMethods() {
msex = new MEMORYSTATUSEX();
if (GlobalMemoryStatusEx(msex)) {
_MemoryLoad = msex.dwMemoryLoad;
//etc.. Repeat for other structure members
}
else
// Use a more appropriate Exception Type. 'Exception' should almost never be thrown
throw new Exception("Unable to initalize the GlobalMemoryStatusEx API");
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
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", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GlobalMemoryStatusEx( [In, Out] MEMORYSTATUSEX lpBuffer);
}
I'm referring back to a post i made a long time ago as i've only just got back to working with this WRG305API.dll.
With referral to: calling C++ functions containing callbacks in C#
Ive been trying to write an app that interfaces with this DLL and thanks to the guys that helped me back then. I've been able to get it working for a short period of time.
Ive been stopped by this annoying issue which is stated as:
A callback was made on a garbage collected delegate of type 'WinFFT!WinFFT.winradioIO.winRadioIOWrapper+CallbackFunc::Invoke'. This may cause application crashes ...
Here is the wrapper code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace WinFFT.winradioIO
{
class winRadioIOWrapper
{
private const string APIDLL_PATH = "WRG305API.dll";
public delegate void CallbackFunc(IntPtr p);
public CallbackFunc mycallback;
[StructLayout(LayoutKind.Sequential)]
public struct Features
{
public uint feature;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RadioInfo
{
public uint length;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string serialNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string productName;
public UInt64 minFrequency;
public UInt64 maxFrequency;
public Features feature;
}
[DllImport(APIDLL_PATH)]
public static extern int OpenRadioDevice(int deviceNumber);
[DllImport(APIDLL_PATH)]
public static extern bool CloseRadioDevice(int radioHandle);
[DllImport(APIDLL_PATH)]
public static extern int GetRadioList(ref RadioInfo info, int bufferSize, ref int infoSize);
[DllImport(APIDLL_PATH)]
public static extern bool IsDeviceConnected(int radioHandle);
[DllImport(APIDLL_PATH)]
public static extern bool GetInfo(int radioHandle, ref RadioInfo info);
[DllImport(APIDLL_PATH)]
public static extern int GetFrequency(int radioHandle);
[DllImport(APIDLL_PATH)]
public static extern bool SetFrequency(int radioHandle, int frequency);
[DllImport(APIDLL_PATH)]
private static extern bool CodecStart(int hRadio, CallbackFunc func, IntPtr CallbackTarget);
[DllImport(APIDLL_PATH)]
private static extern uint CodecRead(int hRadio, byte[] Buf, uint Size);
[DllImport(APIDLL_PATH)]
private static extern bool CodecStop(int hRadio);
public static bool startIFStream(int radioHandle)
{
bool bStarted = CodecStart(radioHandle, MyCallbackFunc, IntPtr.Zero);
return bStarted;
}
// Note: this method will be called from a different thread!
private static void MyCallbackFunc(IntPtr pData)
{
// Sophisticated work goes here...
}
public static void readIFStreamBlock(int radioHandle, byte[] streamDumpLocation, uint blockSize)
{
CodecRead(radioHandle, streamDumpLocation, blockSize);
}
public static bool stopIFStream(int radioHandle)
{
bool bStoped = CodecStop(radioHandle);
return bStoped;
}
}
}
Here is my Application interfacing class layer which provides the friendly methods to use the dll interface:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace WinFFT.winradioIO
{
class radioInterface
{
enum DeviceStatus { Disconnected, Connected, Unknown };
private static DeviceStatus deviceStatus = DeviceStatus.Unknown;
public static string radioName, serialNumber;
public static int minimumFreq, maximumFreq;
static int radioHandle;
static radioInterface()
{
InitializeDeviceConnection();
}
public static void duffMethod(IntPtr ptr)
{
}
private static void InitializeDeviceConnection()
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
deviceStatus = DeviceStatus.Disconnected;
// Get Radio Info
winRadioIOWrapper.RadioInfo radioInfo = new winRadioIOWrapper.RadioInfo();
int aStructSize = Marshal.SizeOf(radioInfo), anInfoSize = 0;
radioInfo.length = (uint)aStructSize;
if (winRadioIOWrapper.GetRadioList(ref radioInfo, aStructSize, ref anInfoSize) == 1)
{
radioName = radioInfo.productName;
serialNumber = radioInfo.serialNumber;
minimumFreq = (int)radioInfo.minFrequency;
maximumFreq = (int)radioInfo.maxFrequency;
}
// Open device
radioHandle = winRadioIOWrapper.OpenRadioDevice(0);
CheckDeviceConnection();
}
private static void CheckDeviceConnection()
{
bool anIsDeviceConnected = winRadioIOWrapper.IsDeviceConnected(radioHandle);
if (deviceStatus == DeviceStatus.Unknown ||
deviceStatus == DeviceStatus.Disconnected && anIsDeviceConnected ||
deviceStatus == DeviceStatus.Connected && !anIsDeviceConnected)
{
if (anIsDeviceConnected)
{
deviceStatus = DeviceStatus.Connected;
winRadioIOWrapper.startIFStream(radioHandle);
}
else
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
deviceStatus = DeviceStatus.Disconnected;
}
}
}
public static void ReadIFStream(ref byte[] bufferLocation)
{
winRadioIOWrapper.readIFStreamBlock(radioHandle, bufferLocation, (uint)bufferLocation.Length);
}
public static void SetFreq(int valueInHz)
{
winRadioIOWrapper.SetFrequency(radioHandle, valueInHz);
}
public static void ShutDownRadio()
{
winRadioIOWrapper.CloseRadioDevice(radioHandle);
}
}
}
I Understand why AVIDeveloper chose the path, its is brilliant for continuously streaming out the data from the WinRadio Reciever (which is what the DLL is for), but the function CodecRead in the DLL allows one to copy a specified number of bytes from the radio's buffer. This is the path I went as I want to control how regularly I take the data and hence why I left the delegate function alone. But with this as it is at the moment, I am loosing the delegate in the wrapper to the GC and I am really stumped on how to prevent this.
Thanks in Advance guys.
Store the delegate as a field.
private static CallbackFunc _callback = new CallbackFunc(MyCallbackFunc);
public static bool startIFStream(int radioHandle)
{
bool bStarted = CodecStart(radioHandle, _callback, IntPtr.Zero);
return bStarted;
}
I want to leverage machine learning to model a user's intent and potentially automate commonly performed tasks. To do this I would like to have access to a fire-hose of information about user actions and the machine state. To this end, it is my current thinking that getting access to the stream of windows messages is probably the way forward.
I would like to have as much information as is possible, filtering the information to that which is pertinent I would like to leave to the machine learning tool.
How would this be accomplished? (Preferably in C#).
Please assume that I know how to manage and use this large influx of data.
Any help would be gratefully appreciated.
You can use SetWindowsHookEx to set low level hooks to catch (specific) windows messages.
Specifically these hook-ids might be interesting for monitoring:
WH_CALLWNDPROC (4) Installs a hook procedure that monitors messages
before the system sends them to the destination window procedure. For
more information, see the CallWndProc hook procedure.
WH_CALLWNDPROCRET(12) Installs a hook procedure that monitors
messages after they have been processed by the destination window
procedure. For more information, see the CallWndRetProc hook
procedure.
It's been a while since I've implemented it, but as an example I've posted the base class I use to hook specific messages. (For example, I've used it in a global mousewheel trapper, that makes sure my winforms apps behave the same as internet explorer: scroll the control underneath the cursor, instead of the active control).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Subro.Win32;
namespace Subro
{
/// <summary>
/// Base class to relatively safely register global windows hooks
/// </summary>
public abstract class GlobalHookTrapper : FinalizerBase
{
[DllImport("user32", EntryPoint = "SetWindowsHookExA")]
static extern IntPtr SetWindowsHookEx(int idHook, Delegate lpfn, IntPtr hmod, IntPtr dwThreadId);
[DllImport("user32", EntryPoint = "UnhookWindowsHookEx")]
private static extern int UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32", EntryPoint = "CallNextHookEx")]
static extern int CallNextHook(IntPtr hHook, int ncode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThreadId();
IntPtr hook;
public readonly int HookId;
public readonly GlobalHookTypes HookType;
public GlobalHookTrapper(GlobalHookTypes Type):this(Type,false)
{
}
public GlobalHookTrapper(GlobalHookTypes Type, bool OnThread)
{
this.HookType = Type;
this.HookId = (int)Type;
del = ProcessMessage;
if (OnThread)
hook = SetWindowsHookEx(HookId, del, IntPtr.Zero, GetCurrentThreadId());
else
{
var hmod = IntPtr.Zero; // Marshal.GetHINSTANCE(GetType().Module);
hook = SetWindowsHookEx(HookId, del, hmod, IntPtr.Zero);
}
if (hook == IntPtr.Zero)
{
int err = Marshal.GetLastWin32Error();
if (err != 0)
OnHookFailed(err);
}
}
protected virtual void OnHookFailed(int Error)
{
throw Win32Functions.TranslateError(Error);
}
private const int HC_ACTION = 0;
[MarshalAs(UnmanagedType.FunctionPtr)]
private MessageDelegate del;
private delegate int MessageDelegate(int code, IntPtr wparam, IntPtr lparam);
private int ProcessMessage(int hookcode, IntPtr wparam, IntPtr lparam)
{
if (HC_ACTION == hookcode)
{
try
{
if (Handle(wparam, lparam)) return 1;
}
catch { }
}
return CallNextHook(hook, hookcode, wparam, lparam);
}
protected abstract bool Handle(IntPtr wparam, IntPtr lparam);
protected override sealed void OnDispose()
{
UnhookWindowsHookEx(hook);
AfterDispose();
}
protected virtual void AfterDispose()
{
}
}
public enum GlobalHookTypes
{
BeforeWindow = 4, //WH_CALLWNDPROC
AfterWindow = 12, //WH_CALLWNDPROCRET
KeyBoard = 2, //WH_KEYBOARD
KeyBoard_Global = 13, //WH_KEYBOARD_LL
Mouse = 7, //WH_MOUSE
Mouse_Global = 14, //WH_MOUSE_LL
JournalRecord = 0, //WH_JOURNALRECORD
JournalPlayback = 1, //WH_JOURNALPLAYBACK
ForeGroundIdle = 11, //WH_FOREGROUNDIDLE
SystemMessages = 6, //WH_SYSMSGFILTER
MessageQueue = 3, //WH_GETMESSAGE
ComputerBasedTraining = 5, //WH_CBT
Hardware = 8, //WH_HARDWARE
Debug = 9, //WH_DEBUG
Shell = 10, //WH_SHELL
}
public abstract class FinalizerBase : IDisposable
{
protected readonly AppDomain domain;
public FinalizerBase()
{
System.Windows.Forms.Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
domain = AppDomain.CurrentDomain;
domain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
domain.DomainUnload += new EventHandler(domain_DomainUnload);
}
private bool disposed;
public bool IsDisposed{get{return disposed;}}
public void Dispose()
{
if (!disposed)
{
GC.SuppressFinalize(this);
if (domain != null)
{
domain.ProcessExit -= new EventHandler(CurrentDomain_ProcessExit);
domain.DomainUnload -= new EventHandler(domain_DomainUnload);
System.Windows.Forms.Application.ApplicationExit -= new EventHandler(Application_ApplicationExit);
}
disposed = true;
OnDispose();
}
}
void Application_ApplicationExit(object sender, EventArgs e)
{
Dispose();
}
void domain_DomainUnload(object sender, EventArgs e)
{
Dispose();
}
void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Dispose();
}
protected abstract void OnDispose();
/// Destructor
~FinalizerBase()
{
Dispose();
}
}
}
The last day i've tried to make this work: Wake up my computer from sleep or hibernation, using a WPF application. Nothing i've tried worked.
So far I've tried the most popular examples on the net.. For example:
[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);
public static void SetWaitForWakeUpTime()
{
DateTime utc = DateTime.Now.AddMinutes(2);
long duetime = utc.ToFileTime();
using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, "MyWaitabletimer"))
{
if (SetWaitableTimer(handle, ref duetime, 0, IntPtr.Zero, IntPtr.Zero, true))
{
using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset))
{
wh.SafeWaitHandle = handle;
wh.WaitOne();
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
// You could make it a recursive call here, setting it to 1 hours time or similar
Console.WriteLine("Wake up call");
Console.ReadLine();
}
And the usage:
WakeUp.SetWaitForWakeUpTime();
I've also tried this example (see how I use the method after the code):
public event EventHandler Woken;
private BackgroundWorker bgWorker = new BackgroundWorker();
public WakeUp()
{
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
}
public void SetWakeUpTime(DateTime time)
{
bgWorker.RunWorkerAsync(time.ToFileTime());
}
void bgWorker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (Woken != null)
{
Woken(this, new EventArgs());
}
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
long waketime = (long)e.Argument;
using (SafeWaitHandle handle =
CreateWaitableTimer(IntPtr.Zero, true,
this.GetType().Assembly.GetName().Name.ToString() + "Timer"))
{
if (SetWaitableTimer(handle, ref waketime, 0,
IntPtr.Zero, IntPtr.Zero, true))
{
using (EventWaitHandle wh = new EventWaitHandle(false,
EventResetMode.AutoReset))
{
wh.SafeWaitHandle = handle;
wh.WaitOne();
}
}
else
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}
}
And the usage:
WakeUp w = new WakeUp();
w.Woken += new EventHandler(w_Woken);
w.SetWakeUpTime(alarmDate.Subtract(new TimeSpan(0,0,0,20)));
Nothing seems to wake up my PC.
I know it is possible, as several other alarm clocks can do it. They manage to wake up my computer with no problems, so there must be some mistake.
The problem was not all computers support this issue. There is apparently not much to do if your computer doesn't support it.