I am creating this memory editor, but the subroutine ReadProcessMemory fails; so does WriteProcessMemory. I have tried to get the last error by using the GetLastError subroutine but it returns 0 which is ERROR_SUCCESS. Here is the code of both the program and the class.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Memedit;
using System.Runtime.InteropServices;
namespace Memory_Editor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
{
e.Effect = DragDropEffects.All;
}
}
private void textBox1_DragDrop(object sender, DragEventArgs e)
{
string[] data = e.Data.GetData(DataFormats.FileDrop, false) as string[];
process.Text = data[0];
}
private void button1_Click(object sender, EventArgs e)
{
MemoryEditor editor = new MemoryEditor(process.Text);
int addr;
if (int.TryParse(address1.Text, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out addr))
{
result.Text = editor.ReadString(addr, 1000, isunicode.Checked);
}
else
{
MessageBox.Show("Error: It is not a real number!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button2_Click(object sender, EventArgs e)
{
MemoryEditor editor = new MemoryEditor(process.Text);
int addr;
if (int.TryParse(address1.Text, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out addr))
{
result.Text = Convert.ToString(editor.ReadInt32(addr), 16);
}
else
{
MessageBox.Show("Error: It is not a real number!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
MemoryEditor Class
using System;
using System.Text;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Memedit
{
public class MemoryEditor
{
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UIntPtr nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("Kernel32.dll")]
static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);
string pname = "";
IntPtr hand;
public MemoryEditor(string ProcName)
{
pname = ProcName.Replace(".exe", "");
Process[] proclist = Process.GetProcesses();
foreach (Process pr in proclist)
{
if (pr.ToString() == "System.Diagnostics.Process (" + pname + ")")
{
hand = pr.Handle;
}
}
}
public bool Write(int Address, byte[] data)
{
bool success = false;
Process[] proclist = Process.GetProcesses();
IntPtr bytesout;
success = WriteProcessMemory(hand, (IntPtr)Address, data, (UIntPtr)data.Length, out bytesout);
return success;
}
public byte[] Read(int Address, int length)
{
byte[] ret = new byte[length];
uint o = 0;
ReadProcessMemory(hand, (IntPtr)Address, ret, (UInt32)ret.Length, ref o);
return ret;
}
public int ReadInt32(int Address)
{
return BitConverter.ToInt32(Read(Address, 4), 0);
}
public float ReadSingle(int Address)
{
return BitConverter.ToSingle(Read(Address, 4), 0);
}
public string ReadString(int Address, int length, bool isUnicode)
{
if (isUnicode)
{
UnicodeEncoding enc = new UnicodeEncoding();
return enc.GetString(Read(Address, length));
}
else
{
ASCIIEncoding enc = new ASCIIEncoding();
return enc.GetString(Read(Address, length));
}
}
}
}
For ReadProcessMemory you need PROCESS_VM_READ permission and for WriteProcessMemory you need PROCESS_VM_OPERATION permission.
see http://msdn.microsoft.com/en-us/library/ms680553%28v=vs.85%29.aspx
and http://msdn.microsoft.com/en-us/library/ms681674%28v=vs.85%29.aspx
Very likely you need Administrator rights, perhaps even SeDebugPrivilege (which you would need to elevate your process to even with Administrator rights)...
Related
An object reference is required for the non-static field, method, or property 'injector.SI(uint, string)' I dont really understand what is the error or the mistake (Visual Studio C# windows form app it would be a really big help if anyone can fix this because I cant find the solution at all Ive been searching for quite a bit of time but still cant find any solution
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Hoshiyomi.functions
{
public partial class injector : Form
{
public injector()
{
InitializeComponent();
Process[] PC = Process.GetProcesses().Where(p => (long)p.MainWindowHandle !=0).ToArray();
comboBox1.Items.Clear();
foreach (Process p in PC)
{
comboBox1.Items.Add(p.ProcessName);
}
}
private void injector_Load(object sender, System.EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.FixedSingle;
}
private static string DLLP { get; set; }
private void flatButton1_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog OFD = new OpenFileDialog();
OFD.InitialDirectory = #"C:\";
OFD.Title = "NotWeeb | Locate DLL";
OFD.DefaultExt = "dll";
OFD.Filter = "DLL Files (*.dll)|*.dll";
OFD.CheckFileExists = true;
OFD.CheckPathExists = true;
OFD.ShowDialog();
textBox1.Text = OFD.FileName;
DLLP = OFD.FileName;
}
catch (Exception ed)
{
MessageBox.Show(ed.Message);
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
DLLP = textBox1.Text;
}
private void flatButton3_Click(object sender, EventArgs e)
{
Process[] PC = Process.GetProcesses().Where(p => (long)p.MainWindowHandle != 0).ToArray();
comboBox1.Items.Clear();
foreach (Process p in PC)
{
comboBox1.Items.Add(p.ProcessName);
}
}
static readonly IntPtr INTPTR_ZERO = (IntPtr)0;
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr OpenProcess(uint dwDesiredAccess, int bInheritHandle, GraphicsUnit dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr Module, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpBaseAddress, byte[] Buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern int WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, uint size, int lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttribute, IntPtr dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
public static int Inject(string PN, string DLLP)
{
if (!File.Exists(DLLP)) { return 1; } //1 not exist
uint _procId = 0;
Process[] _procs = Process.GetProcesses();
for (int i = 0; i < _procs.Length; i++)
{
if (_procs[i].ProcessName == PN)
{
_procId = (uint)_procs[i].Id;
}
}
if (_procId == 0) { return 2; } //2 not exist
if (!SI(_procId, DLLP))
{
return 3; //3 inject fail
}
return 4; //4 inject success
}
public bool SI(uint P, string DLLP)
{
IntPtr hndProc = OpenProcess((0x2 | 0x8 | 0x10 | 0x20 | 0x400), 1, P);
if (hndProc == INTPTR_ZERO) { return false; }
IntPtr lpAddress = VirtualAllocEx(hndProc, (IntPtr)null, (IntPtr)DLLP.Length, (0x1000 | 0x2000), 0x40);
if (lpAddress == INTPTR_ZERO)
{
return false;
}
byte[] bytes = Encoding.ASCII.GetBytes(DLLP);
if (WriteProcessMemory(hndProc, lpAddress, bytes, (uint)bytes.Length, 0) == 0)
{
return false;
}
CloseHandle(hndProc);
return true;
}
private IntPtr OpenProcess(int v1, int v2, uint p)
{
throw new NotImplementedException();
}
private IntPtr VirtualAllocEx(IntPtr hndProc, IntPtr intPtr, IntPtr length, int v1, int v2)
{
throw new NotImplementedException();
}
private void flatButton2_Click(object sender, EventArgs e)
{
int Result = Inject(comboBox1.Text, DLLP);
if (Result == 1)
{
MessageBox.Show("File doesn't exist");
}
else if (Result == 2)
{
MessageBox.Show("Process doesn't exist");
}
else if (Result == 3)
{
MessageBox.Show("Injection fail");
}
else if (Result == 4)
{
MessageBox.Show("Injection Succeeded");
}
}
}
}
enter image description here
I'm trying to make a little application to enumerate in console every window name from each process thread.
I'm currently using this code that works fine on a windows 7 machine but for some reason it stucks at windows 10 without any stack trace or error message, I tried to add almost everything inside a try-catch but I didn't get any message as well so I'm lost.
Here is the code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
static void Main(string[] args)
{
Process[] processes = Process.GetProcesses();
Console.WriteLine("Detected: " + processes.Length + " processes.");
foreach (Process process in processes)
{
IEnumerable<IntPtr> windowHandles = null;
try
{
windowHandles = EnumerateProcessWindowHandles(process);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
Console.WriteLine("Checking process" + process.ProcessName);
foreach (var handle in windowHandles)
{
StringBuilder message = new StringBuilder();
try
{
SendMessage(handle, 0x000D, message.Capacity, message);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
if (message.Length == 0)
{
continue;
}
Console.WriteLine("Window name: " + message.ToString());
}
}
Console.WriteLine("Finished!");
Console.ReadLine();
}
private static IEnumerable<IntPtr> EnumerateProcessWindowHandles(Process process)
{
List<IntPtr> handles = new List<IntPtr>();
ProcessThreadCollection threads = null;
try
{
threads = process.Threads;
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return handles;
}
foreach (ProcessThread thread in threads)
{
try
{
EnumThreadWindows(thread.Id, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
}
return handles;
}
}
}
Any idea about why it could stuck?
UPDATE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr handle);
static void Main(string[] args)
{
Process[] processes = Process.GetProcesses();
Console.WriteLine("Detected: " + processes.Length + " processes.");
foreach (Process process in processes)
{
IEnumerable<IntPtr> windowHandles = null;
try
{
windowHandles = EnumerateProcessWindowHandles(process);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
Console.WriteLine("Checking process: " + process.ProcessName);
foreach (IntPtr handle in windowHandles)
{
if (handle == null)
{
continue;
}
if (!IsWindowVisible(handle))
{
continue;
}
StringBuilder message = new StringBuilder();
int capacity = 0;
try
{
capacity = message.Capacity;
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
try
{
SendMessage(handle, 0x000D, capacity, message);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
if (message.Length == 0)
{
continue;
}
Console.WriteLine("Window name: " + message.ToString());
}
}
Console.WriteLine("Finished!");
Console.ReadLine();
}
private static IEnumerable<IntPtr> EnumerateProcessWindowHandles(Process process)
{
List<IntPtr> handles = new List<IntPtr>();
ProcessThreadCollection threads = null;
try
{
threads = process.Threads;
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
return handles;
}
foreach (ProcessThread thread in threads)
{
if (thread == null)
{
continue;
}
int threadId = 0;
try
{
threadId = thread.Id;
}
catch(Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
try
{
EnumThreadWindows(threadId, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
continue;
}
}
return handles;
}
}
}
Thank you all.
Try running your console application as administrator if the problem still arises I suggest using the API GetLastError that's what it does:
Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other's last-error code.
Try reading the value to know the problem , try this link for guidence on how to use it:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
Using .net 4.0 in a console application
I am trying to move files from local computer to a shared drive and this code gives me the error at the using statement.
The credentials are valid. What could be going wrong.
namespace UploadList
{
class Program
{
static void Main(string[] args)
{
MoveFiles();
}
public static void MoveFiles()
{
try
{
NetworkCredential readCredentials = new
NetworkCredential(#"gktrs\PRDSys", "P#ssw0rd123");
string filepath = "\\\\10.60.90.1\\D$";
//error at the using statement
//ERROR : *Error connecting to remote share*
using (new NetworkConnection(filepath, readCredentials))
{
}
}
catch(Exception ex)
{
}
}
}
}
public class NetworkConnection : IDisposable
{
string _networkName;
public NetworkConnection(string networkName,
NetworkCredential credentials)
{
_networkName = networkName;
var netResource = new NetResource()
{
Scope = ResourceScope.GlobalNetwork,
ResourceType = ResourceType.Disk,
DisplayType = ResourceDisplaytype.Share,
RemoteName = networkName
};
var result = WNetAddConnection2(
netResource,
credentials.Password,
credentials.UserName,
0);
if (result != 0)
{
throw new Win32Exception(result, "Error connecting to remote share");
}
}
~NetworkConnection()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
WNetCancelConnection2(_networkName, 0, true);
}
[DllImport("mpr.dll")]
private static extern int WNetAddConnection2(NetResource netResource,
string password, string username, int flags);
[DllImport("mpr.dll")]
private static extern int WNetCancelConnection2(string name, int flags,
bool force);
}
[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
public ResourceScope Scope;
public ResourceType ResourceType;
public ResourceDisplaytype DisplayType;
public int Usage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
public enum ResourceScope : int
{
Connected = 1,
GlobalNetwork,
Remembered,
Recent,
Context
};
public enum ResourceType : int
{
Any = 0,
Disk = 1,
Print = 2,
Reserved = 8,
}
public enum ResourceDisplaytype : int
{
Generic = 0x0,
Domain = 0x01,
Server = 0x02,
Share = 0x03,
File = 0x04,
Group = 0x05,
Network = 0x06,
Root = 0x07,
Shareadmin = 0x08,
Directory = 0x09,
Tree = 0x0a,
Ndscontainer = 0x0b
}
Here's something I cobbled together from other Stack overflow answers to solve a similar problem of reading a file on a share in MVC. basically C# dosnt make it easy
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;
namespace UnitTestProject2
{
/// <summary>
/// MVC 5 dosnt support impersonation via web.config for good reasons microsoft decided one day
/// </summary>
internal static class NativeMethods
{
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
}
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true)
{
}
protected override bool ReleaseHandle()
{
return NativeMethods.CloseHandle(handle);
}
}
class Class6
{
public void readfile(string filename, string Username, string DomainName, string Password)
{
const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;
SafeTokenHandle safeTokenHandle;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = NativeMethods.LogonUser(
Username,
DomainName,
Password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
out safeTokenHandle);
if (!returnValue)
{
throw new Exception("unable to login as specifed user :" + Username);
}
using (WindowsIdentity id = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
using (WindowsImpersonationContext wic = id.Impersonate())
{
if (File.Exists(filename))
{
//good to go
}
}
}
}
}
I wrote a little program to close my notebook screen when the lid closes and turn the screen on when the lid opens.
I tried a lot, but there is still something wrong in my code. The function "OnLidPowerEvent" doesn't work.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Runtime.InteropServices;
namespace DeviceWatcher
{
public partial class Service1 : ServiceBase
{
[DllImport("User.dll", CharSet = CharSet.Unicode)]
public static extern int SendMessage(int hWnd,int Msg,int wParam,int lParam);
public const int HWND_BROADCAST = 0xffff;
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MONITORPOWER = 0xf170;
// Broadcast Msg to close screen
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern int RegisterPowerSettingNotification(IntPtr Recipient, Guid guid, int flags);
static Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);
public const int DEVICE_NOTIFY_SERVICE_HANDLE = 1;
// using DEVICE_NOTIFY_SERVICE_HANDLE as flag
public delegate int callbackEx(int control, int eventType, IntPtr eventData, IntPtr context);
callbackEx hamster = OnLidPowerEvent;
[DllImport("Advapi32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr RegisterServiceCtrlHandlerEx(string lpServiceName, callbackEx lpHandlerProc, IntPtr lpContext);
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
private static POWERBROADCAST_SETTING pos = new POWERBROADCAST_SETTING();
public Service1()
{
InitializeComponent();
//this.CanHandlePowerEvent = true;
// C# Service can not deal GUID_LIDSWITCH_STATE_CHANGE
this.ServiceName = "DeviceWatcher";
IntPtr serviceControlHandle = RegisterServiceCtrlHandlerEx("DeviceWatcher", hamster, IntPtr.Zero);
RegisterPowerSettingNotification(serviceControlHandle,GUID_LIDSWITCH_STATE_CHANGE,DEVICE_NOTIFY_SERVICE_HANDLE);
// should I using this.serviceHandle or this.ServiceHandle
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Service Init.");
}
}
private static int OnLidPowerEvent(int control, int eventType, IntPtr eventData, IntPtr context)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "PowerFunc Called.");
}
// never reach this Function when my Notebook Lid Closes. :-(
// below need some check on pos data
pos = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(eventData, typeof(POWERBROADCAST_SETTING));
if (pos.PowerSetting == GUID_LIDSWITCH_STATE_CHANGE)
{
if (pos.Data == 0)
{
SendMessage(HWND_BROADCAST,WM_SYSCOMMAND,SC_MONITORPOWER,2);
// when lid Closes,turn screen off
}
else if (pos.Data == 1)
{
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, -1);
// when lid opens ,turn screen on
}
}
return 0;
}
protected override void OnStart(string[] args)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Service Start Func.");
}
}
protected override void OnStop()
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("C:\\log.txt", true))
{
sw.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ") + "Service Stop Func.");
}
}
}
}
The answer is simple:
1st : Windows Service can't send message,using a common application will working fine.
2nd : C# service maybe somehow different from C/C++ service,by using RegisterPowerSettingNotification() will never make it work.
After I find the reasons,I wrote a pure C and Winapi program.
It works perfect.
Thanks a lot for those people concerned about this question!
The program is working at background and listening keyboard(like keylogger)
First I select a string on pdf or etc. Then I pressed the ctrl + rbutton the program must be pop up and it can be get my selected string.
For this;
[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
[DllImport("User32.dll")]
private static extern short GetAsyncKeyState(System.Int32 vKey);
string key = "";
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Interval = 5;
foreach (System.Int32 i in Enum.GetValues(typeof(Keys)))
{
int x = GetAsyncKeyState(i);
if ((x == 1) || (x == -32767))
{
keyBuffer += Enum.GetName(typeof(Keys), i);
}
}
if (keyBuffer != "")
{
keyBuffer = keyBuffer.ToLower();
if (keyBuffer.Contains("lcontrolkeyrbutton"))
{
// do somethings
keyBuffer = "";
}
}
}
But after first performing, ctrl + rbutton it doesn't work. What's the wrong? And how can i get the selected string into my program?
Sounds like you want a clipboard hook (in addition to your global key hook). Take a look here: Clipboard event C#
If you want to capture the string without the user copying it into the clipboard manually, you could send ctrl+c to the application yourself: http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
You need to SendKeyEvent(Ctrl+C) of MainWindowsHandle First, then Using Clipboard capture your text to your Project.
Here is the program funcional and tested
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CtrLetterCopy
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
const int WM_COMMAND = 0x111;
enum KeyModifier
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
WinKey = 8
}
public Form1()
{
InitializeComponent();
this.ShowInTaskbar = false;
int id_Ctrl = 0; // The id of the hotkey.
RegisterHotKey(this.Handle, id_Ctrl, (int)KeyModifier.Control, Keys.R.GetHashCode());
}
protected override void WndProc(ref Message m)
{
//const int WM_HOTKEY = 0x0312;
if (m.Msg == 0x0312)
{
if (m.WParam.ToInt32() == 0)
{
//do what you want here
SendKeyEvent();
}
}
base.WndProc(ref m);
}
private void SendKeyEvent()
{
SendKeys.SendWait("^c");
Thread.Sleep(500);
string test3 = Clipboard.GetText();
MessageBox.Show(test3);
}
}
}
Download and check out this code here:
http://www.codeproject.com/KB/cs/globalhook.aspx
Pre-tested, well-written and fully functional.
Best of luck!