From: eugene on 6 Aug 2010 10:22 Hello everybody. I'm trying to use Ffidl package and currently stuck with a problem. Particularly, I need to call ShellExecuteEx function (its description can be found here: http://msdn.microsoft.com/en-us/library/bb762154%28v=VS.85%29.aspx). The problem is that it takes a pointer to SHELLEXECUTEINFO structure, and I just can't grasp the ways to work with pointers and structures in Ffidl. Digging the internet I found the following working perl code snippet here: http://code.activestate.com/lists/perl-win32-users/5702/ use strict; use Win32::API; my $ShellExecuteEx = new Win32::API('shell32.dll', 'ShellExecuteEx', ['P'], 'N') or die 'Get ShellExecuteEx: ' . Win32::FormatMessage(Win32::GetLastError()); my $lpVerb = pack 'A*', 'open'; my $lpFile = pack 'A*', 'C:\\path\\readme.txt'; print $lpVerb, $lpFile; my $args = pack 'LLLPPPPLLLPLLLL'; $args = pack 'LLLPPPPLLLPLLLL', length $args, 12, 0, $lpVerb, $lpFile, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0; my $ret = $ShellExecuteEx->Call($args) or die 'Call ShellExecuteEx: ' . Win32::FormatMessage(Win32::GetLastError()); I tried to "translate" from perl to Tcl and here's the result: package require Ffidl package require Ffidlrt ::ffidl::typedef SEI long long long pointer pointer pointer pointer long long long pointer long long long ::ffidl::callout ShellExecuteEx pointer long [ ::ffidl::symbol shell32.dll ShellExecuteEx ] set verb [ binary format a* open ] set file [ binary format a* {c:\\path\\readme.txt} ] set args [ binary format [ ::ffidl::info format SEI ] [ ::ffidl::info sizeof SEI ] 12 0 [ ::ffidl::get-string verb ] [ ::ffidl::get-string file ] 0 0 5 0 0 0 0 0 0 0 ] ShellExecuteEx $args However, it spews the error on the last line: "expected integer but got 8" I suppose the variable $args is not formatted as expected by ShellExecuteEx, but I'm out of ideas how to fix it. Can anybody experienced in dealing with Ffidl and complex structures give me a hint what's missing/wrong in my code?
From: Alexandre Ferrieux on 6 Aug 2010 12:15 On Aug 6, 4:22 pm, eugene <eugene.mind...(a)gmail.com> wrote: > Hello everybody. > I'm trying to use Ffidl package and currently stuck with a problem. > Particularly, I need to call ShellExecuteEx function (its description > can be found here:http://msdn.microsoft.com/en-us/library/bb762154%28v=VS.85%29.aspx). > The problem is that it takes a pointer to SHELLEXECUTEINFO structure, > and I just can't grasp the ways to work with pointers and structures > in Ffidl. > Digging the internet I found the following working perl code snippet > here:http://code.activestate.com/lists/perl-win32-users/5702/ > > use strict; > use Win32::API; > > my $ShellExecuteEx = new Win32::API('shell32.dll', 'ShellExecuteEx', > ['P'], 'N') or die 'Get ShellExecuteEx: ' . > Win32::FormatMessage(Win32::GetLastError()); > > my $lpVerb = pack 'A*', 'open'; > my $lpFile = pack 'A*', 'C:\\path\\readme.txt'; > print $lpVerb, $lpFile; > > my $args = pack 'LLLPPPPLLLPLLLL'; > $args = pack 'LLLPPPPLLLPLLLL', length $args, 12, 0, $lpVerb, $lpFile, > 0, 0, 5, 0, 0, 0, 0, 0, 0, 0; > > my $ret = $ShellExecuteEx->Call($args) or die 'Call ShellExecuteEx: > ' . Win32::FormatMessage(Win32::GetLastError()); > > I tried to "translate" from perl to Tcl and here's the result: > > package require Ffidl > package require Ffidlrt > > ::ffidl::typedef SEI long long long pointer pointer pointer pointer > long long long pointer long long long > ::ffidl::callout ShellExecuteEx pointer long [ ::ffidl::symbol > shell32.dll ShellExecuteEx ] > > set verb [ binary format a* open ] > set file [ binary format a* {c:\\path\\readme.txt} ] > > set args [ binary format [ ::ffidl::info format SEI ] [ ::ffidl::info > sizeof SEI ] 12 0 [ ::ffidl::get-string verb ] [ ::ffidl::get-string > file ] 0 0 5 0 0 0 0 0 0 0 ] > ShellExecuteEx $args > > However, it spews the error on the last line: "expected integer but > got 8" > I suppose the variable $args is not formatted as expected by > ShellExecuteEx, but I'm out of ideas how to fix it. > Can anybody experienced in dealing with Ffidl and complex structures > give me a hint what's missing/wrong in my code? Random shot, maybe unrelated: since the SHELLEXECUTEINFO struct is _inout, shouldn't you be using the pointer-var type ? You'd call [ShellExecuteEx args] in this case, and the modified byte array would be available in args afterwards. I admit the error message doesn't hint at that at all though... -Alex
From: David Gravereaux on 6 Aug 2010 14:05 Aside from Ffidl, there's other ways to call ShellExecuteEx. 1) Twapi or 2) write a C extension. I'll even donate the code: http://tomasoft.cvs.sourceforge.net/viewvc/tomasoft/winutils/Shell.c?revision=1.6&view=markup --
From: eugene on 7 Aug 2010 08:41 On Aug 6, 8:15 pm, Alexandre Ferrieux <alexandre.ferri...(a)gmail.com> wrote: > > Random shot, maybe unrelated: since the SHELLEXECUTEINFO struct is > _inout, shouldn't you be using the pointer-var type ? You'd call > [ShellExecuteEx args] in this case, and the modified byte array would > be available in args afterwards. I admit the error message doesn't > hint at that at all though... > > -Alex Alex, you're right, thanks. However, that wasn't the source of the problem :) Actually, in this case there's two ways to call ShellExecuteEx (provided that args structure is filled correctly): 1. If the function is imported like you suggested: ::ffidl::callout ShellExecuteEx pointer-var long [ ::ffidl::symbol shell32.dll ShellExecuteEx ] Then it indeed can be called like this: ShellExecuteEx args 2. But one can still use my original definition: ::ffidl::callout ShellExecuteEx pointer long [ ::ffidl::symbol shell32.dll ShellExecuteEx ] In this case the call looks like this: ShellExecuteEx [ ::ffidl::get-bytearray $args ] The actual problems with my original Tcl code snippet were: 1. I inadvertently missed one structure field in SEI type definition. 2. I should have passed variable value, not its name to ::ffidl::get- string. So, the working Tcl code: package require Ffidl package require Ffidlrt ::ffidl::typedef sei long long long pointer pointer pointer pointer long long long pointer long long long long ::ffidl::callout ShellExecuteEx pointer-var long [ ::ffidl::symbol shell32.dll ShellExecuteEx ] set verb open set file {C:\\path\\readme.txt} set args [ binary format [ ::ffidl::info format sei ] [ ::ffidl::info sizeof sei ] 12 0 [ ::ffidl::get-string $verb ] [ ::ffidl::get-string $file ] 0 0 5 0 0 0 0 0 0 0 ] ShellExecuteEx args
From: eugene on 7 Aug 2010 09:05 On Aug 6, 10:05 pm, David Gravereaux <davyg...(a)pobox.com> wrote: > Aside from Ffidl, there's other ways to call ShellExecuteEx. > > 1) Twapi or > > 2) write a C extension. I'll even donate the code: > > http://tomasoft.cvs.sourceforge.net/viewvc/tomasoft/winutils/Shell.c?... > > -- > > signature.asc > < 1KViewDownload Yes David, I'm aware of different ways to call Windows API functions from Tcl, however, my application already uses Ffidl for other purposes so I just decided to try using it to the maximum extent. This ShellExecuteEx though became a major showstopper for me :) First I tried to use your winutils package and its shell function worked flawlessly with simple verbs like "open", but when I tried to use other ones, like "properties" for example, it failed with error "File association is not available". I suppose some verbs require setting the correct fMask field in SHELLEXECUTEINFO structure and I haven't found the way to do it in winutils.
|
Next
|
Last
Pages: 1 2 Prev: Xft : please explain me ! Next: exec fails but re-directed stdout and stdlog is empty |