1. ShellExecute function wrapper

Forked from Re: RedyCode 0.9.0 officially released!

ryanj said...
dcuny said...

I downloaded the latest version, unzipped it, and launched it.

I opened up a project, told it to run the program... and boom. All the windows closed.

Opening it up again didn't give me any hint as to what might have gone wrong. sad

Uh-oh. What OS are you using? Is there no ex.err anywhere?

I am beginning to suspect a rare problem with the ShellExecute() wrapper, but it's not something that i have been able to reproduce.

From https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx:


Return value

Type: HINSTANCE

If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the failure. The return value is cast as an HINSTANCE for backward compatibility with 16-bit Windows applications. It is not a true HINSTANCE, however. It can be cast only to an int and compared to either 32 or the following error codes below.


What does that mean?

I have

xShellExecute = link_c_func(shell32, "ShellExecuteA", 
    {C_HWND, C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_INT}, C_HWND) 
 
public function ShellExecute(atom WinHwnd, sequence filename, sequence parameter, sequence verb = "", sequence workingdir = "") 
    atom result,szapp,szpara,szaction,szdirectory 
 
    szaction=allocate_string(verb) 
    szapp=allocate_string(filename) 
    szpara=allocate_string(parameter) 
    szdirectory=allocate_string(workingdir) 
    result=c_func(xShellExecute,{WinHwnd,szaction,szapp,szpara,szdirectory,SW_SHOWNORMAL}) 
    free(szaction) 
    free(szpara) 
    free(szapp) 
 
    if result > 32 then  --If the function succeeds, it returns a value greater than 32. 
        return 1 --success 
    else 
        return 0 --failure 
    end if 
end function 

Should it be changed to this? Or does it matter?

xShellExecute = link_c_func(shell32, "ShellExecuteA", 
    {C_HWND, C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_INT}, C_INT) 
new topic     » topic index » view message » categorize

2. Re: ShellExecute function wrapper

Hi

Not running eu4.05 by any chance, somehow or other?

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

3. Re: ShellExecute function wrapper

ryanj said...

From https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153%28v=vs.85%29.aspx:


Return value

Type: HINSTANCE

If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the failure. The return value is cast as an HINSTANCE for backward compatibility with 16-bit Windows applications. It is not a true HINSTANCE, however. It can be cast only to an int and compared to either 32 or the following error codes below.


What does that mean?

That means that in the C code, one might call ShellExecute like this:

// call ShellExecute function 
HINSTANCE hResult = ShellExecute( handle, _T("open"), _T("my file"), NULL, NULL, SW_SHOWDEFAULT ); 
 
// cast result to int value 
int result = (int)hResult; 
 
// check result value 
if ( result < 32 ) { 
    return 1; 
} 
else { 
    return 0; 
} 

One thing to note, is that optional parameters should be NULL, not an empty string. There's a difference. I don't know if this is affecting the behavior of the function call, but it's certainly counter to how the documentation describes the optional paramters.

If the parameter is NULL, that means there is no pointer; you're not pointing to anything. If you pass an empty string, you're still passing a pointer into memory, but its value is of zero length. So in your wrapper code, you should check for empty strings and pass NULL instead of an allocated empty string. Or, what I prefer to do, is accept objects and then allocate strings on the fly and pass atoms as-is.

ryanj said...

I have

*snip*

Should it be changed to this? Or does it matter?

xShellExecute = link_c_func(shell32, "ShellExecuteA", 
    {C_HWND, C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_INT}, C_INT) 

Using C_INT would be correct since we're expecting a signed value back. AFAIK, C_HWND is unsigned because it's a pointer.

This is how my wrapper for ShellExecute would look. I always try to match the documented API to avoid confusion.

constant xShellExecute = link_c_func( shell32, "ShellExecuteA", {C_HWND,C_POINTER,C_POINTER,C_POINTER,C_POINTER,C_INT}, C_INT ) 
 
public function ShellExecute( atom hwnd, object lpOperation, object lpFile, object lpParameters = NULL, object lpDirectory = NULL, atom nShowCmd = SW_SHOWNORMAL ) 
 
    -- allocate strings if necessary and free them automatically 
    if sequence( lpOperation )  then lpOperation  = allocate_string( lpOperation, 1 )  end if 
    if sequence( lpFile )       then lpFile       = allocate_string( lpFile, 1 )       end if 
    if sequence( lpParameters ) then lpParameters = allocate_string( lpParameters, 1 ) end if 
    if sequence( lpDirectory )  then lpDirectory  = allocate_string( lpDirectory, 1 )  end if 
 
    return c_func( xShellExecute,{hwnd,lpOperation,lpFile,lpParameters,lpDirectory,SW_nShowCmd} ) 
end function 
 
sequence verb = "open", file = "myfile.txt" 
 
if ShellExecute( hwnd, verb, file ) > 32 then 
  -- success 
else 
  -- failure 
end if 
 

You had also forgot to free szdirectory.

-Greg

new topic     » goto parent     » topic index » view message » categorize

4. Re: ShellExecute function wrapper

I don't know what i was thinking when i wrote that wrapper. I get confused sometimes looking at all those C structures and data types. Thanks, Greg. I'll try your code.

By the way, i borrowed from your Enumerate Fonts wrapper, too. smile

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu