在c#中向应用程序发送击键(sendkeys、postmessage、sendmessage均不工作)

在c#中向应用程序发送击键(sendkeys、postmessage、sendmessage均不工作),c#,.net,windows,keyboard-events,sendkeys,C#,.net,Windows,Keyboard Events,Sendkeys,我正在尝试执行以下操作之一 1.打开所需的程序并按编程键 2.找到打开的程序窗口并按一个键 (两者都可以) 我尝试了许多SendKeys.SendWait()、PostMessage()和SendMessage()的实现,但都没有成功。下面是我的代码片段 //included all these for attempts [DllImport("User32.dll")] static extern IntPtr FindWindow(string lpClassNa

我正在尝试执行以下操作之一 1.打开所需的程序并按编程键 2.找到打开的程序窗口并按一个键 (两者都可以)

我尝试了许多SendKeys.SendWait()、PostMessage()和SendMessage()的实现,但都没有成功。下面是我的代码片段

    //included all these for attempts 
    [DllImport("User32.dll")] 
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);  

    [DllImport("User32.dll")] 
    static extern int SetForegroundWindow(IntPtr hWnd);

    [DllImport("User32.Dll", EntryPoint = "PostMessageA")]
    static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

    [DllImport("user32.dll")]
    static extern byte VkKeyScan(char ch);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
获取sendmessage/postmessage/sendkeys使用的窗口、变量的句柄

IntPtr ptrOBS = proc.Handle;//this works properly, proc is instantiated properly
//IntPtr ptrOBS = FindWindow(null, "Open Broadcaster Software v0.472b");
SetForegroundWindow(ptrOBS);
const UInt32 WM_CHAR = 0x0102;
const uint WM_KEYDOWN = 0x100;
const int VK_R = 0x52; // taken from http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
const int VK_S = 0x53;
发送消息尝试:

SendMessage(ptrOBS, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1);//tried both WM_CHAR and WM_KEYDOWN
string message = "rs";
bool sent = PostMessage(ptrOBS, WM_KEYDOWN, VkKeyScan(message[0]), 0);
邮件发送尝试:

SendMessage(ptrOBS, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1);//tried both WM_CHAR and WM_KEYDOWN
string message = "rs";
bool sent = PostMessage(ptrOBS, WM_KEYDOWN, VkKeyScan(message[0]), 0);
发送密钥尝试:

SendKeys.SendWait("{r}");
尝试在父窗口(应用程序)和子窗口上设置焦点(按键触发,im尝试发送):

对于NSGaga:

    string windowName = "Open Broadcaster Software v0.472b";
IntPtr outerPtr = FindWindow(null, windowName);
IntPtr ptrOBS = (IntPtr)527814;//button that im trying to trigger keypress on
SetForegroundWindow(outerPtr);
SetForegroundWindow(ptrOBS);
SetFocus(outerPtr, "OBSWindowClass");//SetFocus(ptrOBS, "Button");
const UInt32 WM_CHAR = 0x0102;
const int VK_R = 0x52; // taken from http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
const int VK_S = 0x53;

//SetForegroundWindow(ptrOBS);
System.Threading.Thread.Sleep(3000);
SendKeys.SendWait("{r}");
SendMessage(outerPtr, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1);
PostMessage(outerPtr, WM_KEYDOWN, VkKeyScan('r'), 0);
。它们不是为这个而设计的。这些消息(
WM_CHAR
WM_KEYDOWN
等)是低级子系统在接收、处理键盘输入并转发给相应收件人时发出的通知。自己发送或发布这些信息就像恶作剧一样

SendKeys
(与所有其他输入合成器方法一样,包括明确设计用于合成键盘输入的功能,并且至少在某些实现中是
SendKeys
在引擎盖下实际使用的功能)仅当您希望接收键盘输入的窗口具有焦点时才起作用。在Windows中,只有聚焦(活动)窗口接收输入事件

因此,如果你想让它正常工作(或者调用
SendInput
及其所有相关结构),那么
SendKeys
可能是一个不错的选择,但是你需要注意收件人窗口必须有焦点。否则,它什么也得不到

从示例代码中可以看出,您试图使用该函数来满足此前提条件。不幸的是,您正在传递一个无效的值,并且没有执行任何可能提醒您此错误的错误检查。具体而言,该代码是错误的:

IntPtr ptrOBS = proc.Handle;//this works properly, proc is instantiated properly
SetForegroundWindow(ptrOBS); // WRONG, ptrOBS is not a window handle
即使我信任您正确初始化了
ptrOBS
,这也使它成为进程的有效句柄,这与窗口的有效句柄截然不同。除了明显的名义差异外,进程可以有多个窗口,只有一个窗口可以有焦点(即“在前景中”)

在调用
setforegroughindow
之前,您需要获得特定窗口的句柄,并且我们知道一个进程可以有多个窗口,这可能会很棘手。你需要一些可靠的方法来确定你想要哪个窗口。很多人通过将窗口的名称硬编码为字符串来实现这一点,在目标应用程序重新编译并且实现细节发生变化之前,这一点非常有效。我能想到的唯一防弹方法是让用户单击目标窗口,然后让代码检索当前位于鼠标指针下的窗口句柄


当然,所有这些都假设您已经遵守了链接SDK文档“备注”部分中列举的对使用
SetForegroundWindow
的限制。

为了使其正常工作,有很多尝试和错误
这是我之前发布的一段代码,你可能想试试(还有更多的附加信息)

尝试先设置焦点(使用上述机制),然后使用
SendKeys
SendInput

下面是一些有关
SendInput
的详细代码


目标进程是否被提升了?如果是这样的话,我会大发雷霆,不会有什么不同。请参阅:IntPtr ptrOBS=FindWindow(null,“开放式广播软件v0.472b”);也不起作用,我假设FindWindow返回的是实际的窗口句柄,而不是进程句柄?但谢谢你指出我需要关注和改变的事情。现在,我将继续用一个真正的窗口句柄敲打SendKeys方法。@ahein您是否验证了
FindWindow
实际上返回了一个句柄?正确的手柄?使用Spy++通过将它与您感兴趣的窗口的实际句柄进行比较来验证这一点。它确实返回应用程序的实际父窗口。我还尝试硬编码子窗口的IntPtr hex=>decimal值,该子窗口包含我想用keypress(热键按下的按钮)运行的操作。使用其中一个/两个窗口都不起作用。我尝试过实现SetFocus(将通过我的尝试更新OP)。您是否成功地对目标窗口中的任何内容
SetFocus
——使用我提出的方法(必须严格遵守)——这是第一步。我做过很多次这样的工作。然而,有些应用程序是特定的。如果有帮助,也可以尝试提升你的应用程序(作为管理员)。或者尝试发布你的最终代码(使用这种方法)-我将复制粘贴并在此处运行(调整),并尝试查看我尝试的时间AllowSetFocus实现是否在上面;你想让我发布我的win32 api函数声明,还是只调用setfocus然后sendkeys?最好的完整复制(只需减少到最小值-例如,使用记事本或其他东西进行尝试)-这是最容易使用的(常见示例),我看到:)我会确定地看一看(等我找到时间,稍后或明天)-告诉我你有没有试过其他程序-比如我提到的w/Notepad?我认为你在发送钥匙方面出了问题——这是一个棘手的部分