ค้นหาว่ากระบวนการใดที่ลงทะเบียนฮอตคีย์ทั่วโลก? (Windows API)


114

เท่าที่ฉันสามารถหาได้ Windows ไม่มีฟังก์ชั่น API เพื่อบอกว่าแอปพลิเคชันใดที่ลงทะเบียนฮอตคีย์ทั่วโลก (ผ่าน RegisterHotkey) ฉันพบได้เฉพาะว่ามีการลงทะเบียนฮอตคีย์หาก RegisterHotkey ส่งคืนเท็จ แต่ไม่ใช่ใคร "เป็นเจ้าของ" ฮอตคีย์

ในกรณีที่ไม่มี API โดยตรงมีทางอ้อมได้ไหม Windows ดูแลจัดการที่เกี่ยวข้องกับคีย์ลัดที่ลงทะเบียนแต่ละอัน - เป็นเรื่องที่น่าขันเล็กน้อยที่ไม่มีทางรับข้อมูลนี้ได้

ตัวอย่างของสิ่งที่ไม่น่าจะใช้งานได้: ส่ง (จำลอง) ฮ็อตคีย์ที่ลงทะเบียนจากนั้นดักจับข้อความฮอตที่ Windows จะส่งไปยังกระบวนการที่ลงทะเบียน อันดับแรกฉันไม่คิดว่าการดักฟังข้อความจะเปิดเผยที่จับหน้าต่างปลายทาง ประการที่สองแม้ว่าจะเป็นไปได้ แต่ก็เป็นเรื่องที่ไม่ดีที่จะทำเนื่องจากการส่งคีย์ลัดจะทำให้เกิดกิจกรรมที่ไม่พึงประสงค์ทุกประเภทจากโปรแกรมต่างๆ

ไม่มีอะไรสำคัญ แต่ฉันเคยเห็นการร้องขอฟังก์ชันดังกล่าวบ่อยครั้งและฉันเองก็ตกเป็นเหยื่อของแอปพลิเคชันที่ลงทะเบียนคีย์ลัดโดยไม่เปิดเผยที่ใดก็ได้ใน UI หรือเอกสาร

(ทำงานในเดลฟีและไม่มากไปกว่าเด็กฝึกงานที่ WinAPI โปรดเมตตา)

คำตอบ:


20

คำถามของคุณกระตุ้นความสนใจของฉันฉันจึงได้ทำการขุดคุ้ยและในขณะที่ฉันไม่มีคำตอบที่เหมาะสมสำหรับคุณฉันคิดว่าฉันจะแบ่งปันสิ่งที่ฉันมี

ฉันพบตัวอย่างการสร้างแป้นพิมพ์ hook (ใน Delphi) ที่เขียนขึ้นในปี 1998 แต่สามารถรวบรวมได้ใน Delphi 2007 ด้วยการปรับแต่งสองสามอย่าง

เป็น DLL ที่มีการโทรไปยังSetWindowsHookExฟังก์ชันการโทรกลับซึ่งสามารถสกัดกั้นจังหวะสำคัญได้: ในกรณีนี้การแก้ไขเพื่อความสนุกสนานเปลี่ยนเคอร์เซอร์ซ้ายไปขวา ฯลฯ จากนั้นแอปง่ายๆจะเรียก DLL และรายงานกลับ ผลลัพธ์ขึ้นอยู่กับเหตุการณ์ TTimer หากคุณสนใจฉันสามารถโพสต์รหัสที่ใช้ Delphi 2007 ได้

มีการบันทึกและแสดงความคิดเห็นไว้เป็นอย่างดีและคุณสามารถใช้เป็นพื้นฐานในการทำงานในตำแหน่งที่การกดปุ่มกำลังดำเนินไป หากคุณสามารถจัดการแอปพลิเคชันที่ส่งจังหวะสำคัญได้คุณสามารถติดตามกลับด้วยวิธีนั้นได้ ด้วยการจัดการดังกล่าวคุณจะสามารถรับข้อมูลที่คุณต้องการได้อย่างง่ายดาย

แอปอื่น ๆ ได้พยายามกำหนดปุ่มลัดโดยใช้ทางลัดเนื่องจากสามารถมีปุ่มทางลัดซึ่งเป็นอีกคำหนึ่งสำหรับปุ่มลัด อย่างไรก็ตามแอปพลิเคชันส่วนใหญ่มักไม่ตั้งค่าคุณสมบัตินี้ดังนั้นจึงอาจไม่ส่งคืนมากนัก หากคุณสนใจในเส้นทางนั้น Delphi สามารถเข้าถึงIShellLinkอินเตอร์เฟส COM ซึ่งคุณสามารถใช้เพื่อโหลดทางลัดขึ้นมาและรับฮอตคีย์ได้:

uses ShlObj, ComObj, ShellAPI, ActiveX, CommCtrl;

procedure GetShellLinkHotKey;
var
  LinkFile : WideString;
  SL: IShellLink;
  PF: IPersistFile;

  HotKey : Word;
  HotKeyMod: Byte;
  HotKeyText : string;
begin
  LinkFile := 'C:\Temp\Temp.lnk';

  OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL));

  // The IShellLink implementer must also support the IPersistFile
  // interface. Get an interface pointer to it.
  PF := SL as IPersistFile;

  // Load file into IPersistFile object
  OleCheck(PF.Load(PWideChar(LinkFile), STGM_READ));

  // Resolve the link by calling the Resolve interface function.
  OleCheck(SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));

  // Get hotkey info
  OleCheck(SL.GetHotKey(HotKey));

  // Extract the HotKey and Modifier properties.
  HotKeyText := '';
  HotKeyMod := Hi(HotKey);

  if (HotKeyMod and HOTKEYF_ALT) = HOTKEYF_ALT then
    HotKeyText := 'ALT+';
  if (HotKeyMod and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then
    HotKeyText := HotKeyText + 'CTRL+';
  if (HotKeyMod and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then
    HotKeyText := HotKeyText + 'SHIFT+';
  if (HotKeyMod and HOTKEYF_EXT) = HOTKEYF_EXT then
    HotKeyText := HotKeyText + 'Extended+';

  HotKeyText := HotKeyText + Char(Lo(HotKey));

  if (HotKeyText = '') or (HotKeyText = #0) then
    HotKeyText := 'None';

  ShowMessage('Shortcut Key - ' + HotKeyText);
end;

หากคุณสามารถเข้าถึงSafari Books Onlineได้มีส่วนที่ดีเกี่ยวกับการทำงานกับทางลัด / ลิงก์เชลล์ในคู่มือสำหรับนักพัฒนา Borland Delphi 6 โดย Steve Teixeira และ Xavier Pacheco ตัวอย่างของฉันด้านบนเป็นเวอร์ชันที่ถูกฆ่าจากที่นั่นและไซต์นี้

หวังว่าจะช่วยได้!


59

วิธีการหนึ่งที่เป็นไปได้คือการใช้Visual Studio เครื่องมือ Spy ++

ลองดูสิ:

  1. เรียกใช้เครื่องมือ (สำหรับฉันมันอยู่ที่C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\spyxx_amd64.exe)
  2. ในแถบเมนูเลือกSpy -> บันทึกข้อความ ... (หรือกดCtrl+ M)
  3. ตรวจสอบWindows ทั้งหมดในระบบในกรอบWindows เพิ่มเติม
  4. เปลี่ยนไปที่แท็บข้อความ
  5. คลิกล้างทั้งหมดปุ่ม
  6. เลือกWM_HOTKEYในกล่องรายการหรือทำเครื่องหมายที่แป้นพิมพ์ในกลุ่มข้อความ (หากคุณตกลงด้วยเสียงรบกวนที่อาจเกิดขึ้น)
  7. คลิกปุ่มOK
  8. กดปุ่มลัดที่เป็นปัญหา ( ตัวอย่างเช่นWin+ R)
  9. เลือกWM_HOTKEYบรรทัดในหน้าต่างข้อความ (Windows ทั้งหมด)คลิกขวาแล้วเลือกคุณสมบัติ ...ในเมนูบริบท
  10. ในกล่องโต้ตอบคุณสมบัติข้อความคลิกที่ลิงค์Window Handle (นี่จะเป็นจุดจับสำหรับหน้าต่างที่ได้รับข้อความ)
  11. คลิกปุ่มซิงโครไนซ์ในกล่องโต้ตอบคุณสมบัติหน้าต่าง ซึ่งจะแสดงหน้าต่างในหน้าต่างหลักของ Spy ++ Treeview
  12. ในกล่องโต้ตอบคุณสมบัติของหน้าต่างเลือกแท็บกระบวนการ
  13. คลิกลิงก์รหัสกระบวนการ นี้จะแสดงกระบวนการ (ในของฉันWin+ Rกรณี: EXPLORER)

6
ตอบโจทย์มาก! โปรดทราบว่าSpy ++ รุ่น 64 บิตจับเฉพาะข้อความสำหรับแอปพลิเคชัน 64 บิตดังนั้นหากคุณไม่เห็นWM_HOTKEYข้อความในบันทึกข้อความหลังจากกดปุ่มลัดคุณอาจต้องเรียกใช้ Spy ++ เวอร์ชัน 32 บิต .
David Ferenczy Rogožan

ขอบคุณมาก!!! โดยพื้นฐานแล้วฉันยอมแพ้กับการใช้ทางลัดบางอย่างจนกระทั่งฉันพบสิ่งนี้
thewindev

3
ในขั้นตอนที่ 8 จะไม่ขอฮอตคีย์หน้าต่างข้อความจะยังคงว่างเปล่าหลังจากกดฮอตคีย์ใด ๆ ใช้เวอร์ชัน 32 และ 64 บิตจากgithub.com/westoncampbell/SpyPlusPlus (ใน Windows 10)
CoolMind

9

หลังจากการวิจัยปรากฏว่าคุณจำเป็นต้องเข้าถึงโครงสร้างภายในที่ MS ใช้ในการจัดเก็บปุ่มลัด ReactOS มีการใช้งานแบบคลีนรูมที่ดำเนินการGetHotKeyโทรโดยการทำซ้ำรายการภายในและแยกฮอตคีย์ที่ตรงกับพารามิเตอร์ของการโทร

ขึ้นอยู่กับความใกล้ชิดของการใช้งาน ReactOS กับการใช้งาน MS คุณอาจสามารถใช้หน่วยความจำเพื่อค้นหาโครงสร้างได้ แต่นั่นก็อยู่เหนือหัวของฉัน ...

BOOL FASTCALL
GetHotKey (UINT fsModifiers,
           UINT vk,
           struct _ETHREAD **Thread,
           HWND *hWnd,
           int *id)
{
   PHOT_KEY_ITEM HotKeyItem;

   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
   {
      if (HotKeyItem->fsModifiers == fsModifiers &&
            HotKeyItem->vk == vk)
      {
         if (Thread != NULL)
            *Thread = HotKeyItem->Thread;

         if (hWnd != NULL)
            *hWnd = HotKeyItem->hWnd;

         if (id != NULL)
            *id = HotKeyItem->id;

         return TRUE;
      }
   }

   return FALSE;
}

ฉันคิดว่าเธรดนี้ใน sysinternalsถูกถามโดยคนที่เกี่ยวข้องกับคำถามนี้ แต่ฉันคิดว่าฉันจะเชื่อมโยงไปยังมันเพื่อให้ทั้งสองเข้าด้วยกัน เธรดดูน่าสนใจมาก แต่ฉันสงสัยว่าการดำน้ำลึกบางอย่างจะต้องเกิดขึ้นเพื่อหาสิ่งนี้โดยไม่ต้องเข้าถึง MS internals


3

คุณอาจลองแจกแจงหน้าต่างทั้งหมดด้วย EnumWindows จากนั้นในการโทรกลับส่ง WM_GETHOTKEY ไปยังแต่ละหน้าต่าง

แก้ไข: ตอนนี้ฉันคิดผิดเกี่ยวกับเรื่องนั้น MSDNมีข้อมูลเพิ่มเติม:

WM_HOTKEY ไม่เกี่ยวข้องกับคีย์ลัด WM_GETHOTKEY และ WM_SETHOTKEY ข้อความ WM_HOTKEY ถูกส่งไปสำหรับคีย์ลัดทั่วไปในขณะที่ข้อความ WM_SETHOTKEY และ WM_GETHOTKEY เกี่ยวข้องกับฮอตคีย์การเปิดใช้งานหน้าต่าง

หมายเหตุ: นี่คือโปรแกรมที่อ้างว่ามีฟังก์ชันที่คุณกำลังมองหา คุณสามารถลองแยกไฟล์ได้


3
ตอนนี้ลิงก์ไปยังโปรแกรมเสียอย่างสมบูรณ์ นั่นคือโปรแกรมอะไร? มีหลายครั้งที่ฉันต้องการทราบว่าโปรแกรมใดลงทะเบียนปุ่มลัดของฉันเพราะจู่ๆมันก็ไม่ทำงานอีกต่อไปหรือทำสิ่งใหม่ที่น่ารำคาญ
เจมส์ Oltmans

(บ่อยครั้งที่ Wayback Machine สามารถช่วยได้ในกรณีที่หน้าเว็บหายไป แต่ที่นี่ก็มีเพียง 404 Not Found เท่านั้นที่ทำมิเรอร์: http://web.archive.org/web/*/tds.diamondcs.com.au/dse/ การตรวจจับ / hotkeys.php )
Aaron Thoma

2

สิ่งนี้ดูเหมือนจะบอกคุณได้มาก: http://hkcmdr.anymania.com/help.html


1
ทำมัน? DLL ปลอมตัวเป็นคนขับ? ฟังก์ชั่น DLL ที่ส่งออกเป็นhooใช้SetWindowHookExเพื่อตั้งค่าสองตะขอหนึ่งWH_KEYBOARD_LLและหนึ่งWH_GETMESSAGE... ส่วนที่เหลือควรได้รับการบันทึกไว้ใน MSDN
0xC0000022L

อย่าใช้แอพนี้บน Windows 8 หรือ 10
Jeff Lange

1

เธรดอื่นกล่าวถึงเบ็ดแป้นพิมพ์ระดับ NT ทั่วโลก:

กำหนดใหม่ / แทนที่ฮอตคีย์ (Win + L) เพื่อล็อคหน้าต่าง

บางทีคุณอาจได้รับการจัดการของกระบวนการที่เรียกว่า hook ในลักษณะนั้นซึ่งคุณสามารถแก้ไขชื่อกระบวนการได้

(ข้อจำกัดความรับผิดชอบ: ฉันมีในบุ๊คมาร์คของฉันยังไม่ได้ลอง / ทดสอบ)


0

ฉันรู้ว่าคุณสามารถสกัดกั้นสตรีมข้อความในหน้าต่างใดก็ได้ภายในกระบวนการของคุณเอง - สิ่งที่เราใช้เรียกคลาสย่อยใน VB6 (แม้ว่าฉันจะจำฟังก์ชันนี้ไม่ได้ แต่อาจเป็น SetWindowLong?) ฉันไม่แน่ใจว่าคุณสามารถทำสิ่งนี้กับ windows นอกกระบวนการของคุณเองได้หรือไม่ แต่เพื่อประโยชน์ของโพสต์นี้สมมติว่าคุณหาวิธีทำเช่นนั้น จากนั้นคุณสามารถสกัดกั้นข้อความสำหรับหน้าต่างระดับบนสุดทั้งหมดตรวจสอบข้อความ WM_HOTKEY คุณจะไม่สามารถรู้คีย์ทั้งหมดได้ทันทีจากค้างคาว แต่เมื่อกดแล้วคุณสามารถทราบได้อย่างง่ายดายว่าแอปพลิเคชันใดใช้อยู่ หากคุณยืนยันผลลัพธ์ของคุณไปยังดิสก์และโหลดซ้ำทุกครั้งที่เรียกใช้แอปพลิเคชันจอภาพของคุณคุณสามารถเพิ่มประสิทธิภาพของแอปพลิเคชันของคุณได้ตลอดเวลา


-1

สิ่งนี้ไม่ได้ตอบโจทย์ในส่วนของคำถามเกี่ยวกับ Windows API อย่างตรงไปตรงมา แต่เป็นการตอบคำถามเกี่ยวกับรายการคีย์ลัดส่วนกลางและแอปพลิเคชันที่ "เป็นเจ้าของ"

Hotkey Explorer ฟรีที่http://hkcmdr.anymania.com/จะแสดงรายการฮอตคีย์ทั่วโลกทั้งหมดและแอปพลิเคชันที่เป็นเจ้าของ สิ่งนี้ช่วยให้ฉันทราบว่าเหตุใดปุ่มลัดเฉพาะแอปพลิเคชันจึงหยุดทำงานและวิธีแก้ไข (โดยการกำหนดค่าฮ็อตคีย์ส่วนกลางที่ลงทะเบียนใหม่ในแอปที่ลงทะเบียนไว้แล้ว) ภายในไม่กี่วินาที


4
ติดตั้งและทำหน้าที่เหมือนไวรัสอย่างน้อยโปรแกรมที่มีห้างสรรพสินค้าเหมือนเป็นเรื่องตลกร้าย การเปิดหน้าต่างทุกประเภทการเปิดใช้งานโปรแกรมควบคุมเสียง ฯลฯ
Flion

3
@Flion: การอภิปรายเห็นในsuperuser.com/a/191090/3617 โดยทั่วไปการใช้งานคีย์ลัดบางตัวจะทำงานโดยการตรวจสอบคีย์ผสมที่เป็นไปได้ทั้งหมด ใน Windows 8+ (และในระดับที่น้อยกว่าใน Windows 7) เทคนิคการตรวจสอบนี้จะทริกเกอร์การรวมคีย์ทั้งหมดแทนที่จะเป็นเพียงการสืบค้น
Brian

@ Flion FWIW ฉันใช้มันบน Win7 ด้วยความสำเร็จ แต่ถ้าฉันเข้าใจ Brian อย่างถูกต้องสิ่งนี้อาจใช้ไม่ได้กับเวอร์ชันที่ใหม่กว่าและการทำงานได้ดีเพียงใดอาจขึ้นอยู่กับคีย์ลัดที่กำหนดเองที่กำหนดไว้
Gerhard
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.