Well it turns out that a Solution in C was required. Windows automagically supplies shared memory for the original 16 bit controls.

Listboxes, however are 32 bit controls!!! So I had to implement the select function to allocate, use and deallocate memory inside the foreign process.

Here is the bare bones perl module and XS code I used. Sorry about the long time between updates ... but school and work interfere.

If you like this or use it and want to donate you can paypal me at Steven_swenson@sbcglobal.net. I can always use pizza/gas money :) I attached the code below:

perlmodule

package ListViewEx; use 5.006; use strict; use warnings; use Carp; require Exporter; require DynaLoader; use AutoLoader; our @ISA = qw(Exporter DynaLoader); # Items to export into callers namespace by default. Note: do not expo +rt # names by default without a very good reason. Use EXPORT_OK instead. # Do not simply export all your public functions/methods/constants. # This allows declaration use ListViewEx ':all'; # If you do not need this, moving things directly into @EXPORT or @EXP +ORT_OK # will save memory. our %EXPORT_TAGS = ( 'all' => [ qw( lvGetItem lvSelectItem ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); our $VERSION = '0.01'; sub AUTOLOAD { # This AUTOLOAD is used to 'autoload' constants from the constant( +) # XS function. If a constant is not found then control is passed # to the AUTOLOAD in AutoLoader. my $constname; our $AUTOLOAD; ($constname = $AUTOLOAD) =~ s/.*:://; croak "& not defined" if $constname eq 'constant'; local $! = 0; my $val = constant($constname, @_ ? $_[0] : 0); if ($! != 0) { if ($! =~ /Invalid/ || $!{EINVAL}) { $AutoLoader::AUTOLOAD = $AUTOLOAD; goto &AutoLoader::AUTOLOAD; } else { croak "Your vendor has not defined ListViewEx macro $constname +"; } } { no strict 'refs'; # Fixed between 5.005_53 and 5.005_61 if ($] >= 5.00561) { *$AUTOLOAD = sub () { $val }; } else { *$AUTOLOAD = sub { $val }; } } goto &$AUTOLOAD; } bootstrap ListViewEx $VERSION; # Preloaded methods go here. # Autoload methods go after =cut, and are processed by the autosplit p +rogram. 1; __END__ # Below is stub documentation for your module. You better edit it! =head1 NAME ListViewEx - Perl extension for Accessing a ListView Object outside yo +ur own process space =head1 SYNOPSIS use ListViewEx; lvGetItem($listview_handle,$item,$subItem); lvSelectItem ($listview_handle, $item); =head1 DESCRIPTION ListViewEX provides two subroutines to access a listview control's tex +t and select that item for a listview that belongs to a different process than the one that Perl is running in. =head2 EXPORT None by default. =head1 AUTHOR Steven Swenson<lt>Steven_Swenson@sbcglobal.netE<gt> =head1 SEE ALSO L<perl>. =cut

The XS Code

#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include <windows.h> #include <commctrl.h> #include <string.h> HV* lvGetItem ( SV* handle, SV* item, SV* subitem ) { /* Var */ HWND ihandle; int iItem; int iSubItem; int textlength; BOOL Success; HANDLE hProcess; DWORD dwProcessId; LV_ITEM* plvi; LV_ITEM lvi; TCHAR text[100]; DWORD* bytes; SV* sv; HV* hv; /* Process Arguments, get handle */ ihandle = (HWND) SvIV(handle); iItem = SvIV ( item); iSubItem = SvIV ( subitem); #ifdef DEBUG_CHECK printf ("Made it to GetItem handle %d\n", ihandle); #endif /* Open a handle to the remote process's kernel object '*/ if ( GetWindowThreadProcessId( ihandle, &dwProcessId) == NULL ) { croak ("Got a NULL reference for the process or thread han +dles\n"); } hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PR +OCESS_VM_WRITE, FALSE, dwProcessId); /* check that we got a valid process handle */ if ( hProcess == NULL ) { croak ("Got a NULL reference for the process handle\n"); } #ifdef DEBUG_CHECK printf ("Successfully Received a Process handle and readied the pr +ocess for a memory operation.\n"); #endif /* Allocate memory in the remote process's address space.'*/ plvi = (LV_ITEM*) VirtualAllocEx(hProcess, NULL, 4096, MEM_RESERVE + | MEM_COMMIT, PAGE_READWRITE); #ifdef DEBUG_CHECK printf ("Successfully Allocated Memory%d.\n",(long)plvi); #endif /* Initialize a local LV_ITEM structure */ lvi.mask = LVIF_TEXT; lvi.iItem = iItem; lvi.iSubItem = iSubItem; /* NOTE: The text data immediately follows the LV_ITEM structure * +/ /* in the memory block allocated in the remote process. */ lvi.pszText = (LPTSTR) (plvi + sizeof(lvi)+1); lvi.cchTextMax = 100; /* Write the local LV_ITEM structure to the remote memory block */ Success = WriteProcessMemory(hProcess, plvi, &lvi, sizeof(lvi), NU +LL); if ( ! Success ) { croak ("Did Not write request to memory\n"); } #ifdef DEBUG_CHECK else { printf ("Successfully copied local structure\n"); printf ("The size of an lvi struct is %d bytes \n", sizeof(lvi +)); } #endif /* Tell the ListView control to fill the remote LV_ITEM structure +*/ Success = ListView_GetItem( ihandle, plvi); if (!Success) { croak ("The remote process failed to fill the LV structure\n") +; } #ifdef DEBUG_CHECK else { printf("The remote Process has filled the LV_ITEM STRUCTURE\n" +); } #endif /* Get the Text */ memset(text, 0, 100); Success = ReadProcessMemory(hProcess, (plvi + sizeof(lvi) + 1) , t +ext, 100, &textlength ); if (!Success) { printf("Last Error was error:%d\n", GetLastError() ); croak ("ReadProcess Memory Failed!!!!\n"); } #ifdef DEBUG_CHECK printf ("Got '%s' of length %d for Item %d, %d\n", text,textlength +, iItem,iSubItem); #endif /* Free the memory in the remote process's address space'*/ Success = VirtualFreeEx (hProcess, plvi, 0, MEM_RELEASE); if (!Success) { printf("Last Error was error:%d\n", GetLastError() ); croak ("Free Memory Failed!!!!\n"); } #ifdef DEBUG_CHECK else { printf("Freed foreign process memory block\n"); } #endif /* Cleanup */ CloseHandle(hProcess); /* put result on perlstack */ textlength = strlen ( text); sv = newSVpvn(text,textlength); hv = newHV(); hv_store (hv,"-text",5,sv, 0); /* Need to return state and image index as well to be equive to W +in32::Gui version */ return (hv); } int lvSelectItem( SV * hw, SV * in){ /* SelectItem macro uses a pointer address so needs a cross-process + set-up */ /* Var */ HWND ihandle; int iItem; int textlength; BOOL Success; HANDLE hProcess; DWORD dwProcessId; LV_ITEM* plvi; LV_ITEM lvi; NM_LISTVIEW* plvnm; NM_LISTVIEW lvnm; TCHAR text[100]; DWORD* bytes; SV* sv; HV* hv; /* Process Arguments, get handle */ ihandle = (HWND) SvIV(hw); iItem = (int) SvIV ( in); #ifdef DEBUG_CHECK printf ("Made it to Select Item handle %d\n", ihandle); #endif /* Open a handle to the remote process's kernel object '*/ if ( GetWindowThreadProcessId( ihandle, &dwProcessId) == NULL ) { croak ("Got a NULL reference for the process or thread han +dles\n"); } hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PR +OCESS_VM_WRITE, FALSE, dwProcessId); /* check that we got a valid process handle */ if ( hProcess == NULL ) { croak ("Got a NULL reference for the process handle\n"); } #ifdef DEBUG_CHECK printf ("Successfully Received a Process handle and readied the pr +ocess for a memory operation.\n"); #endif /* Allocate memory in the remote process's address space.'*/ plvi = (LV_ITEM*) VirtualAllocEx(hProcess, NULL, 4096, MEM_RESERVE + | MEM_COMMIT, PAGE_READWRITE); #ifdef DEBUG_CHECK printf ("Successfully Allocated Memory%x.\n",(long)plvi); #endif /* Initialize a local LV_ITEM structure */ lvi.mask = LVIF_STATE; lvi.state = LVIS_FOCUSED | LVIS_SELECTED; lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED; lvi.iItem = iItem; lvi.iSubItem = 0; /* NOTE: The text data immediately follows the LV_ITEM structure * +/ /* in the memory block allocated in the remote process. */ lvi.pszText = (LPTSTR) (plvi + sizeof(lvi)+1); lvi.cchTextMax = 100; /* Write the local LV_ITEM structure to the remote memory block */ Success = WriteProcessMemory(hProcess, plvi, &lvi, sizeof(lvi), NU +LL); if ( ! Success ) { croak ("Did Not write request to memory\n"); } #ifdef DEBUG_CHECK else { printf ("Successfully copied local structure\n"); printf ("The size of an lvi struct is %d bytes \n", sizeof(lvi +)); } #endif /* SetItemState(nItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LV +IS_SELECTED) /* Tell the ListView control to fill the remote LV_ITEM structure */ Success = SendMessage ( ihandle, LVM_SETITEMSTATE, iItem, plvi ); #ifdef DEBUG_CHECK if (Success) { printf("Selected Item %d \n",iItem); } else { printf("Failed to select Item %d\n",iItem); return (0); } #endif /* Free the memory in the remote process's address space'*/ Success = VirtualFreeEx (hProcess, plvi, 0, MEM_RELEASE); if (!Success) { printf("Last Error was error:%d\n", GetLastError() ); croak ("Free Memory Failed!!!!\n"); } #ifdef DEBUG_CHECK else { printf("Freed foreign process memory block\n"); } #endif /* At this point the item should display its new state... but we h +ave to tell mom about the change. */ /* Cleanup */ CloseHandle(hProcess); return (1); } MODULE = ListViewEx PACKAGE = ListViewEx HV* lvGetItem ( handle, item, subitem ) SV* handle SV* item SV* subitem OUTPUT: RETVAL int lvSelectItem( hw, in) SV * hw SV * in OUTPUT: RETVAL

In reply to Re: Automation Problem with Win32::GUI and Win32::GUITest by talwyn
in thread Automation Problem with Win32::GUI and Win32::GUITest by talwyn

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.