I am trying to do something like the question asked in this post in win10 with C# SendInput to minimized window while you're working on other windows.
I followed the best answer to do and I find it didn't work as "GetProcessIdOfThread" always return 0.
Here is the code:
public MainWindow()
{
InitializeComponent();
IntPtr NotepadHandle = FindWindow("Notepad", "Untitled - Notepad");
if (NotepadHandle == IntPtr.Zero)
{
MessageBox.Show("Notepad is not running.");
return;
}
uint noteid = GetProcessIdOfThread(NotepadHandle);
uint selfid = GetCurrentThreadId();
bool attach = AttachThreadInput(selfid, noteid, true);
if (attach == false)
{
MessageBox.Show("attach fail");
return;
}
}
Did I misunderstood anything?
Thank you!
MSDN about GetProcessIdOfThread:
Retrieves the process identifier of the process associated with the
specified thread.
You are passing handle of a window (HWND) instead of handle of a thread to the function. That's why it returns zero. You need to get handle of the thread first or you can directly call the GetWindowThreadProcessId function to get process id from HWND.
IntPtr notepadHandle = FindWindow("Notepad", "Untitled - Notepad");
if (notepadHandle == IntPtr.Zero) {
MessageBox.Show("Notepad is not running.");
return;
}
uint noteId;
uint threadId = GetWindowThreadProcessId(notepadHandle , out noteId);
if (threadId != 0) {
// Succeed
}
...
Related
I am trying to open a tradingview url and then invoking a goto date. alt-g. i found this thread which i thought might work. Handle the KeyDown Event when ALT+KEY is Pressed. this has the following code below. (i added SendAltKey by looking at another random thread.).
The first example works. Second trying to invoke alt-g in tradingview does not. There is no url date querystring. Any ideas?
ChromeWrapper chrome = new ChromeWrapper(#"https://stackoverflow.com");
Thread.Sleep(1000);
chrome.SendKey((char)9);// tab
chrome.SendKey((char)13);//enter
// open trading view and bring up goto date dialogue.
// end game to navigate to an actual date, but cannot get past this point.
chrome = new ChromeWrapper(#"https://www.tradingview.com/chart/?symbol=NASDAQ%3AMSFT");
Thread.Sleep(10000);
chrome.SendAltKey('G'); // doesn't work.
SendKeys.Send("%G"); // doesn't work either.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Meh
{
public class ChromeWrapper
{
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
// the keystroke signals. you can look them up at the msdn pages
private static uint WM_KEYDOWN = 0x100, WM_KEYUP = 0x101;
// the reference to the chrome process
public Process chromeProcess;
public ChromeWrapper(string url)
{
chromeProcess = new Process();
chromeProcess.StartInfo = new ProcessStartInfo("chrome.exe", url);
chromeProcess.StartInfo.UseShellExecute = true;
chromeProcess.Start(); //no need to keep reference to this process, because if chrome is already opened, this is NOT the correct reference.
Thread.Sleep(600); //without this behavior is altered (tap key presses operate on other objects on the page)
Process[] procsChrome = Process.GetProcessesByName("chrome");
foreach (Process chrome in procsChrome)
{
if (chrome.MainWindowHandle == IntPtr.Zero)// the chrome process must have a window
continue;
chromeProcess = chrome; //now you have a handle to the main chrome (either a new one or the one that was already open).
return;
}
}
public void SendKey(char key)
{
try
{
if (chromeProcess.MainWindowHandle != IntPtr.Zero)
{
// send the keydown signal
SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYDOWN, (IntPtr)key, IntPtr.Zero);
// give the process some time to "realize" the keystroke
Thread.Sleep(30); //On my system it works fine without this Sleep.
// send the keyup signal
SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYUP, (IntPtr)key, IntPtr.Zero);
}
}
catch (Exception e) //without the GetProcessesByName you'd get an exception.
{
}
}
public void SendAltKey(char key)
{
try
{
if (chromeProcess.MainWindowHandle != IntPtr.Zero)
{
uint lparam = (0x01 << 28);
SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYDOWN, (IntPtr)key, (IntPtr) lparam);
Thread.Sleep(30);
SendMessage(chromeProcess.MainWindowHandle, ChromeWrapper.WM_KEYUP, (IntPtr)key, (IntPtr) lparam);
}
}
catch (Exception e) //without the GetProcessesByName you'd get an exception.
{
}
}
}
}
If the Window is in focus you can use:
System.Windows.Forms.SendKeys.SendWait("%(g)");
the % is alt so %(g) will be Alt+g.
If that's doesn't work or you don't want to use System.Windows.Forms you may look for Robot.cs
I can't get the "Edit" field handle when selecting a photo in a third-party application.
Spy++ shows everything correctly, but FindWindow fails. I can get the handle of the window itself, the parent. I assume I need to look for child windows. I can get some handles with GetWindow but but it's not clear what they are. The window title is empty. FindWindowEx doesn't work at all, returns 0. I indicate it like this:
IntPtr hwndchild = (hwnd, IntPtr.Zero, null, "Edit")
Based on the screenshot you provided, and using just the FindWindow/Ex() functions, you can get the HWND of the Edit control like this:
IntPtr hwndDlg = FindWindow(null, "Choose an image");
IntPtr hwndCBEx = FindWindowEx(hwndDlg, IntPtr.Zero, "ComboBoxEx32", null);
IntPtr hwndCB = FindWindowEx(hwndCBEx, IntPtr.Zero, "ComboBox", null);
IntPtr hwndEdit = FindWindowEx(hwndCB, IntPtr.Zero, "Edit", null);
However, once you have the HWND to the ComboBoxEx control, the correct way to get the HWND of its Edit control is to use the CBEM_GETEDITCONTROL message:
const int CBEM_GETEDITCONTROL = 1031;
IntPtr hwndDlg = FindWindow(null, "Choose an image");
IntPtr hwndCBEx = FindWindowEx(hwndDlg, IntPtr.Zero, "ComboBoxEx32", null);
IntPtr hwndEdit = SendMessage(hwndCBEx, CBEM_GETEDITCONTROL, 0, 0);
Note, for a standard ComboBox control (which you can get from a ComboBoxEx control using the CBEM_GETCOMBOCONTROL message), you can use the CB_GETCOMBOBOXINFO message or the GetComboBoxInfo() function. The HWND of the Edit control is returned in the COMBOBOXINFO.hwndItem field.
If you are looking for a child window of a parent you should use EnumChildWindows. The following is C++ code but could be pinvoked easily: you can marshal delegates as function pointers for the callback.
std::vector<HWND> FindChildrenByClass(HWND parent, const std::string& target_class)
{
struct EnumWndParam {
std::vector<HWND> output;
std::string target;
} enum_param;
enum_param.target = target_class;
EnumChildWindows(
parent,
[](HWND wnd, LPARAM lparam) -> BOOL {
auto param = reinterpret_cast<EnumWndParam*>(lparam);
char class_name[512];
GetClassName(wnd, class_name, 512);
if (param->target == class_name)
param->output.push_back(wnd);
return TRUE;
},
reinterpret_cast<LPARAM>(&enum_param)
);
return enum_param.output;
}
int main()
{
auto windows = FindChildrenByClass( reinterpret_cast<HWND>(0x0061024A), "Edit");
for (auto wnd : windows) {
std::cout << std::hex << wnd << std::endl;
}
}
Note in the above that I do not recursively call FindChildrenByClass in the callback lambda. This is not a mistake. EnumChildWindows already performs this recursion. It runs over a parent window's children and grand children, etc., out of the box without you having to specify this behavior or implement it.
Like someone already assumed. Try the EnumChildWindow method.
Here is an complete sample already on stackoverflow
I need to capture a keypress sequence from a Windows Mobile device to trigger a duress event. If my application was the only thing running I would use a base form event handler to check the keypress BUT... as the application could launch a browser and also uses SOTI, it must also work outside of the main application.
Is it possible to create a TSR application on a Windows Mobile device that can send web service messages (whilst in comms)?
I have written several keyboard hook 'applications' that invoke different functions. You can also use that to do socket or webservice calls: http://www.hjgode.de/wp/?s=hook and http://www.hjgode.de/wp/?s=keytoggle
// The command below tells the OS that this EXE has an export function so we can use the global hook without a DLL
__declspec(dllexport) LRESULT CALLBACK g_LLKeyboardHookCallback(
int nCode, // The hook code
WPARAM wParam, // The window message (WM_KEYUP, WM_KEYDOWN, etc.)
LPARAM lParam // A pointer to a struct with information about the pressed key
)
{
/* typedef struct {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/
// Get out of hooks ASAP; no modal dialogs or CPU-intensive processes!
// UI code really should be elsewhere, but this is just a test/prototype app
// In my limited testing, HC_ACTION is the only value nCode is ever set to in CE
static int iActOn = HC_ACTION;
static bool isShifted=false;
#ifdef DEBUG
static TCHAR str[MAX_PATH];
#endif
PKBDLLHOOKSTRUCT pkbhData = (PKBDLLHOOKSTRUCT)lParam;
//DWORD vKey;
if (nCode == iActOn)
{
//only process unflagged keys
if (pkbhData->flags != 0x00)
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
//check vkCode against forbidden key list
if(pForbiddenKeyList!=NULL)
{
BOOL bForbidden=false;
int j=0;
do{
if(pForbiddenKeyList[j]==(BYTE)pkbhData->vkCode)
{
bForbidden=true;
DEBUGMSG(1, (L"suppressing forbidden key: 0x%0x\n",pkbhData->vkCode));
continue;
}
j++;
}while(!bForbidden && pForbiddenKeyList[j]!=0x00);
if(bForbidden){
return true;
}
}
SHORT sShifted = GetAsyncKeyState(VK_SHIFT);
if((sShifted & 0x800) == 0x800)
isShifted = true;
else
isShifted = false;
//check and toggle for Shft Key
//do not process shift key
if (pkbhData->vkCode == VK_SHIFT){
DEBUGMSG(1, (L"Ignoring VK_SHIFT\n"));
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
//################################################################
//check if the actual key is a match key including the shift state
if ((byte)pkbhData->vkCode == (byte)szVKeySeq[iMatched]){
DEBUGMSG(1 , (L"==== char match\n"));
if (bCharShiftSeq[iMatched] == isShifted){
DEBUGMSG(1 , (L"==== shift match\n"));
}
else{
DEBUGMSG(1 , (L"==== shift not match\n"));
}
}
if( wParam == WM_KEYUP ){
DEBUGMSG(1, (L"---> szVKeySeq[iMatched] = 0x%02x\n", (byte)szVKeySeq[iMatched]));
if ( ((byte)pkbhData->vkCode == (byte)szVKeySeq[iMatched]) && (isShifted == bCharShiftSeq[iMatched]) ) {
//the first match?
if(iMatched==0){
//start the timer and lit the LED
LedOn(LEDid,1);
tID=SetTimer(NULL, 0, matchTimeout, (TIMERPROC)Timer2Proc);
}
iMatched++;
DEBUGMSG(1, (L"iMatched is now=%i\n", iMatched));
//are all keys matched
if (iMatched == iKeyCount){
//show modeless dialog
DEBUGMSG(1, (L"FULL MATCH, starting ...\n"));
PostMessage(g_hWnd, WM_SHOWMYDIALOG, 0, 0);
//reset match pos and stop timer
DEBUGMSG(1, (L"FULL MATCH: Reset matching\n"));
LedOn(LEDid,0);
iMatched=0; //reset match pos
KillTimer(NULL, tID);
//return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
//return -1; //do not forward key?
}
else
{
KillTimer(NULL, tID);
LedOn(LEDid,0);
iMatched=0; //reset match pos
DEBUGMSG(1, (L"FULL MATCH missed. Reseting matching\n"));
}
} //if wParam == WM_KEY..
}
return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam);
}
Looking for a hook example that looks for a key sequence: http://code.google.com/p/keytoggleboot/source/browse/trunk/KeyToggleBoot/ReadMe.txt?spec=svn14&r=14
There are also articles and posts about keyboard hooks in the internet (ie at codeproject).
I recently needed to get a key code from a handheld device and I just created an empty project with 1 textbox, included the following file and add this bit of code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
HookKeys x = new HookKeys();
x.Start();
x.HookEvent += new HookKeys.HookEventHandler(HookEvent);
}
private void HookEvent(HookEventArgs e, KeyBoardInfo keyBoardInfo)
{
textBox1.Text = "vkCode = " + keyBoardInfo.vkCode + Environment.NewLine + textBox1.Text;
}
}
Worked for a windows mobile 6.5 professional
I'm creating a thread that looks for a window. When it finds the window, it overrides its windowproc, and handles WM_COMMAND and WM_CLOSE.
Here's the code that looks for the window and subclasses it:
public void DetectFileDialogProc()
{
Window fileDialog = null;
// try to find the dialog twice, with a delay of 500 ms each time
for (int attempts = 0; fileDialog == null && attempts < 2; attempts++)
{
// FindDialogs enumerates all windows of class #32770 via an EnumWindowProc
foreach (Window wnd in FindDialogs(500))
{
IntPtr parent = NativeMethods.User32.GetParent(wnd.Handle);
if (parent != IntPtr.Zero)
{
// we're looking for a dialog whose parent is a dialog as well
Window parentWindow = new Window(parent);
if (parentWindow.ClassName == NativeMethods.SystemWindowClasses.Dialog)
{
fileDialog = wnd;
break;
}
}
}
}
// if we found the dialog
if (fileDialog != null)
{
OldWinProc = NativeMethods.User32.GetWindowLong(fileDialog.Handle, NativeMethods.GWL_WNDPROC);
NativeMethods.User32.SetWindowLong(fileDialog.Handle, NativeMethods.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(new WindowProc(WndProc)).ToInt32());
}
}
And the windowproc:
public IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
lock (this)
{
if (!handled)
{
if (msg == NativeMethods.WM_COMMAND || msg == NativeMethods.WM_CLOSE)
{
// adding to a list. i never access the window via the hwnd from this list, i just treat it as a number
_addDescriptor(hWnd);
handled = true;
}
}
}
return NativeMethods.User32.CallWindowProc(OldWinProc, hWnd, msg, wParam, lParam);
}
This all works well under normal conditions. But I am seeing two instances of bad behavior in order of badness:
If I do not close the dialog within a minute or so, the app crashes. Is this because the thread is getting garbage collected? This would kind of make sense, as far as GC can tell the thread is done? If this is the case, (and I don't know that it is), how can I make the thread stay around as long as the dialog is around?
If I immediately close the dialog with the 'X' button (WM_CLOSE) the app crashes. I believe its crashing in the windowproc, but I can't get a breakpoint in there. I'm getting an AccessViolationException, The exception says "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." Its a race condition, but of what I don't know. FYI, I had been reseting the old windowproc once I processed the commands, but that was crashing even more often!
Any ideas on how I can solve these issues?
Two points of observation that I can make....
In your DetectFileDialogProc, you are comparing wnd to null, that is an IntPtr type yes? if so, that check for the comparison should be if (wnd > IntPtr.Zero){ .... }
In your WndProc, you are using the this variable for the lock which is a bad thing to do...you should do something like this private readonly object objLock = new object(); and within your WndProc use this lock (objLock){....}
and see if that resolves the issue....
Finally came up with a solution, attacking the problem from a different angle. I was able to set a system-wide hook in managed code using SetWinEventHook, and the option WINEVENT_OUTOFCONTEXT, which amazingly has the property: The callback function is not mapped into the address space of the process that generates the event.
I trap the event EVENT_SYSTEM_DIALOGSTART to receive notifications whenever a dialog is created, and EVENT_SYSTEM_DIALOGEND when its destroyed.
I am working on an application which needs to get the last active window handle. Suppose my application is running then I want to get last active window handle that was just previously open just before my application.
#EDIT1: This is not the duplicate question. I need to get the handle of last active window not the current window.
This is similar to
alternate SO question, I would assume you would just track the active window and upon change you would then know the previously active
Edit, this is basically code copied from the question I linked that was looking for current active window but with logic to persist the lastHandle and identify when you have a new lastHandle. It's not a proven, compilable implementation:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
static IntPtr lastHandle = IntPtr.Zero;
//This will be called by your logic on when to check, I'm assuming you are using a Timer or similar technique.
IntPtr GetLastActive()
{
IntPtr curHandle = GetForeGroundWindow();
IntPtr retHandle = IntPtr.Zero;
if(curHandle != lastHandle)
{
//Keep previous for our check
retHandle = lastHandle;
//Always set last
lastHandle = curHandle;
if(retHandle != IntPtr.Zero)
return retHandle;
}
}
I needed the same thing of the last handle from the previous window I had open. The answer from Jamie Altizer was close, but I modified it to keep from overwriting the previous window when my application gets focus again. Here is the full class I made with the timer and everything.
static class ProcessWatcher
{
public static void StartWatch()
{
_timer = new Timer(100);
_timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
_timer.Start();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
setLastActive();
}
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
public static IntPtr LastHandle
{
get
{
return _previousToLastHandle;
}
}
private static void setLastActive()
{
IntPtr currentHandle = GetForegroundWindow();
if (currentHandle != _previousHandle)
{
_previousToLastHandle = _previousHandle;
_previousHandle = currentHandle;
}
}
private static Timer _timer;
private static IntPtr _previousHandle = IntPtr.Zero;
private static IntPtr _previousToLastHandle = IntPtr.Zero;
}