시스템 트레이에있는 모든 아이콘을 읽으려면 Perl에서 스크립트를 작성하려고합니다. 좌표를 가져와 &을 소유하고있는 사람을 찾습니다. 나는 거의 번역하려고 노력하고있다 this code here. 나는 시스템 트레이 핸들을 얻을하는 AutoIt COM DLL을 사용하고Perl을 사용하면 Windows의 작업 표시 줄 알림 영역에있는 아이콘에 대한 정보를 어떻게 얻을 수 있습니까?
use strict;
use warnings;
use Win32::API;
use Win32::OLE qw(in);
use Data::Dumper;
use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;
use constant SYNCHRONIZE => 0x00100000;
use constant STANDARD_RIGHTS_REQUIRED => 0x000F0000;
use constant PROCESS_ALL_ACCESS => (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF);
my $TB_BUTTONCOUNT = 0x0418;
my $TB_GETBUTTONTEXT = 0x041B;
my $TB_GETBUTTONINFO = 0x0441;
my $TB_GETITEMRECT = 0x041D;
my $TB_GETBUTTON = 0x0417;
sub get_windows_details {
my ($self) = @_;
my $ret;
my $objWMIService =
Win32::OLE->GetObject("winmgmts:\\\\localhost\\root\\CIMV2")
or die "WMI connection failed.\n";
my $colItems =
$objWMIService->ExecQuery("SELECT * FROM Win32_OperatingSystem",
"WQL",
wbemFlagReturnImmediately | wbemFlagForwardOnly);
my $objItem;
foreach $objItem (in $colItems) {
$ret->{'osname'} = $objItem->{Caption};
}
$colItems =
$objWMIService->ExecQuery("SELECT * FROM Win32_Processor",
"WQL",
wbemFlagReturnImmediately | wbemFlagForwardOnly);
foreach $objItem (in $colItems) {
$ret->{'osbit'} = $objItem->{AddressWidth};
}
return $ret;
}
sub get_autoit_tray_handle {
my $autoit = Win32::OLE->new("AutoItX3.Control")
or return 0;
my $tray_hwnd = $autoit->ControlGetHandle("[Class:Shell_TrayWnd]", "", "[Class:ToolbarWindow32;Instance:1]");
return hex $tray_hwnd;
}
sub get_tray_icon_count {
#my $hWnd = get_tray_handle();
my $hWnd = get_autoit_tray_handle();
my $send_message = Win32::API->new("user32", "SendMessage", "NNII", "I");
return $send_message->Call($hWnd, $TB_BUTTONCOUNT, 0, 0);
}
# Randomly chosen icon index.
my $iIndex = 6;
my $os = get_windows_details();
if ($os->{'osbit'} == 64) {
Win32::API::Struct->typedef('TBBUTTON', qw { int iBitmap;
int idCommand;
BYTE fsState;
BYTE fsStyle;
BYTE bReserved[6];
DWORD_PTR dwData;
INT_PTR iString;
}
) or die "Typedef error $!\n";
} else {
Win32::API::Struct->typedef('TBBUTTON', qw { int iBitmap;
int idCommand;
BYTE fsState;
BYTE fsStyle;
BYTE bReserved[2];
DWORD_PTR dwData;
INT_PTR iString;
}
) or die "Typedef error $!\n";
}
# Get tray handle & it's proc id
my $tb_button = Win32::API::Struct->new('TBBUTTON');
my $tray_hwnd = get_autoit_tray_handle();
print "tray hwnd: $tray_hwnd\n";
my $window_thread_proc_id = Win32::API->new('user32', "GetWindowThreadProcessId", 'LP', 'N');
my $lpdwPID = pack 'L', 0;
my $pid = $window_thread_proc_id->Call($tray_hwnd, $lpdwPID);
my $dwPID = unpack 'L', $lpdwPID;
print "proc id: $dwPID\n";
# read the tray process memory to get the tray button info
my $open_process = Win32::API->new('kernel32', 'OpenProcess', 'NIN', 'N') || die $!;
my $proc_hwnd = $open_process->Call(PROCESS_ALL_ACCESS, 0, $dwPID);
print "proc hwnd: $proc_hwnd\n";
my $virtual_alloc = Win32::API->new('kernel32', 'VirtualAllocEx', 'NNLNN', 'N');
my $lp_data = $virtual_alloc->Call($proc_hwnd, 0, $tb_button->sizeof(), 0x1000, 0x04);
print "Error allocating memory: $!\n" if $!;
print "Allocated addresss: $lp_data\n";
my $send_message = Win32::API->new('user32', 'SendMessage', 'NNIN','I');
my $get_button_status = $send_message->Call($tray_hwnd, $TB_GETBUTTON, $iIndex, $lp_data);
print "TB_GETBUTTON Status: $get_button_status\n";
my $read_process = Win32::API->new('kernel32', 'ReadProcessMemory', 'NNSNP','I');
my $bytes_read = pack 'L', 0;
$read_process->Call($proc_hwnd, $lp_data, $tb_button, $tb_button->sizeof(), $bytes_read);
print "dwData: $tb_button->{'dwData'} \n";
:
여기에 지금까지 내 코드입니다. 나는이 트레이 핸들을 가지고 일단, 나는 그 다음 다음과 같이 정의된다 TBBUTTON structure를 얻을 수있는 프로세스 메모리를 읽을 프로세스 ID &의 얻으려고 :if ($os->{'osbit'} == 64) {
Win32::API::Struct->typedef('TBBUTTON', qw { int iBitmap;
int idCommand;
BYTE fsState;
BYTE fsStyle;
BYTE bReserved[6];
DWORD_PTR dwData;
INT_PTR iString;
}
) or die "Typedef error $!\n";
} else {
Win32::API::Struct->typedef('TBBUTTON', qw { int iBitmap;
int idCommand;
BYTE fsState;
BYTE fsStyle;
BYTE bReserved[2];
DWORD_PTR dwData;
INT_PTR iString;
}
) or die "Typedef error $!\n";
}
최소한에, 위의 코드를 실행
내 시스템은 다음과 같습니다.tray hwnd: 401922
proc id: 11040
proc hwnd: 704
Allocated addresss: 32702464
TB_GETBUTTON Status: 1
dwData: 10293610267052867588
"dwData"는 잘못된 것 같습니다. 여기 내가 뭔가 잘못하고있는 것처럼 보입니다.
my $read_process = Win32::API->new('kernel32', 'ReadProcessMemory', 'NNSNP','I');
my $bytes_read = pack 'L', 0;
$read_process->Call($proc_hwnd, $lp_data, $tb_button, $tb_button->sizeof(), $bytes_read);
print "dwData: $tb_button->{'dwData'} \n";
내가 잘못하고있는 것에 대한 제안 사항이 있습니까? 감사.
하지만 전혀하지 [이] (http://stackoverflow.com/a/1013870/100754) 도움? –
Win32 :: Process :: Memory를 사용할 수 있다고 생각합니다. 그렇다면 Win32 :: API :: Struct를 사용하여 TBBUTTON 구조체를 버리고 전체 구조체를 직접 포장해야합니다. 나는이 옵션을 확실히 탐구 할 것이다. 그러나 관계없이, 나는 트레이 (Tray) 프로세스에서 버퍼로 프로세스를 진행할 때 내 코드에서 어떤 일이 일어나고 있는지를 알고 싶다. 이것이 바로 마지막 코드 블록이 성취하고자하는 단계입니다. –
아무도 대답이 없으면 내일 볼 것입니다. 내가하지 않으면 나를 찌르십시오. 취침. – ikegami