none
Why is ShellExecute returning error 2?

    Question

  • I'm developing in .NET 3.5 using C# on a Win 10 x64 system, making a call to ShellExecute. The call returns a 2 (ERROR_FILE_NOT_FOUND) even though the item passed in is a folder and it definitely exists.

    Here's the code:

    // Program.cs:
    
    namespace TestQuickAccessFavorites
    {
        class Program
        {
            static void Main( string[] args )
            {
                QuickAccessFavorites qaf = new QuickAccessFavorites();
            }
        }
    }
    
    
    // TestQuickAccessFavorites.cs:
    
    using System;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;
    
    namespace TestQuickAccessFavorites
    {
    
        public class QuickAccessFavorites
        {
            // Performs an operation on a specified file.
            [DllImport( "shell32.dll" )]
            public static extern IntPtr ShellExecute(
            IntPtr hwnd,
            [MarshalAs( UnmanagedType.LPTStr )]
            String lpOperation,
            [MarshalAs( UnmanagedType.LPTStr )]
            String lpFile,
            [MarshalAs( UnmanagedType.LPTStr )]
            String lpParameters,
            [MarshalAs( UnmanagedType.LPTStr )]
            String lpDirectory,
            Int32 nShowCmd );
    
    
            public enum ShowCommands : int
            {
                SW_HIDE            = 0,
                SW_SHOWNORMAL      = 1,
                SW_NORMAL          = 1,
                SW_SHOWMINIMIZED   = 2,
                SW_SHOWMAXIMIZED   = 3,
                SW_MAXIMIZE        = 3,
                SW_SHOWNOACTIVATE  = 4,
                SW_SHOW            = 5,
                SW_MINIMIZE        = 6,
                SW_SHOWMINNOACTIVE = 7,
                SW_SHOWNA          = 8,
                SW_RESTORE         = 9,
                SW_SHOWDEFAULT     = 10,
                SW_FORCEMINIMIZE   = 11,
                SW_MAX             = 11
            }
    
    
            public QuickAccessFavorites()
            {
                UpdateFavorites();
            }
    
    
            private void UpdateFavorites()
            {
                // ShellExecute returns
                // Value greater than 32 if successful.
                // 0 - Out of memory.
                // 2 - ERROR_FILE_NOT_FOUND.
                // 3 - ERROR_PATH_NOT_FOUND.
                // 11 - ERROR_BAD_FORMAT
                // 5 - SE_ERR_ACCESSDENIED
                // 27 - SE_ERR_ASSOCINCOMPLETE
                // 30 - SE_ERR_DDEBUSY
                // 29 - SE_ERR_DDEFAIL
                // 28 - SE_ERR_DDETIMEOUT
                // SE_ERR_INF
                // 31 - SE_ERR_NOASSOC
                // SE_ERR_OOM
                // SE_ERR_PNF
                // SE_ERR_SHARE
    
                int iRetVal;
                iRetVal = (int)ShellExecute(
                    IntPtr.Zero,
                    "pintohome",
                    @"C:\Users\Hagga\PreVeil-haggard@msn.com",
                    "",
                    "",
                    (int)ShowCommands.SW_HIDE );
            }
        }
    }
    
    What is wrong with the simple code?



    Richard Lewis Haggard

    Friday, March 09, 2018 2:00 AM

Answers

  • Ah. That was unexpected. Change the SW_HIDE to SW_SHOW and it works just fine.

     iRetVal = (int)ShellExecute(
                   
    IntPtr.Zero,
                   
    "pintohome",
                   
    @"C:\Users\Hagga\PreVeil-haggard@msn.com",
                   
    "",
                   
    "",
                   
    (int)ShowCommands.SW_SHOW );


    Richard Lewis Haggard

    Friday, March 09, 2018 1:52 PM

All replies

  • Your are marshaling strings as ascii strings (not unicode) to unmanaged code.  But are you calling ShellExecuteA or ShellExecuteW?
    Friday, March 09, 2018 2:41 AM
  • Why do you say it is 8 bit narrow ASCII? According to the definition for an LPTStr:

    A platform-dependent character string: ANSI on Windows 98, and Unicode on Windows NT and Windows XP. This value is supported only for platform invoke and not for COM interop, because exporting a string of type LPTStr is not supported.

    Since this is a Win 10 x64 system in .NET shouldn't that make it UNICODE?

    As for your other question. I was just assuming that that the call would go to the UNICODE variation because that's what all of the other PInvokes do unless otherwise specified.

    By the way, I tried telling Notepad to open using the same syntax. That worked. That makes me suspect that there is something about pintohome that is different.


    Richard Lewis Haggard

    Friday, March 09, 2018 2:51 AM
  • You're right about UnManaged.LPTStr -- I missed the "T".  My other question was predicated on the notion that the code was invoking ShellExecuteW but receiving an ASCII string, so it's not pertinent.

    I'm not familiar with the "pintohome" verb.

    • Edited by RLWA32 Friday, March 09, 2018 8:51 AM
    Friday, March 09, 2018 8:45 AM
  • This works on my OS (Windows 10) =>

    [DllImport("Shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);
    
    int iRetVal;
    iRetVal = (int)ShellExecute(
        IntPtr.Zero,
        "",
        "notepad",
        "",
        "",
        (int)ShowCommands.SW_SHOW);



    • Edited by Castorix31 Friday, March 09, 2018 1:54 PM
    Friday, March 09, 2018 8:47 AM
  • Since you are using C# you can probably use the Process class instead of ShellExecute but since you have done as much as you have done you probably want to get it done using ShellExecute directly. Hopefully when you have it working using ShellExecute you can convert that to the Process class.

    See winapi - Is it possible programmatically add folders to the Windows 10 Quick Access panel in the explorer window? - Stack Overflow. At the bottom is C++ code that does what you are doing and it claims to work. The following is the C++ code.

    ShellExecute(0, L"pintohome", folder.c_str(), L"", L"", SW_HIDE);

    Perhaps it is just a matter of how you are providing the folder name.



    Sam Hobbs
    SimpleSamples.Info

    Friday, March 09, 2018 12:16 PM
  • How would Process work with a Verb? Had it been obvious to me how to do that I would have gone that route in the first place.


    Richard Lewis Haggard


    • Edited by Richard.Haggard Friday, March 09, 2018 2:19 PM incorrect statement removed.
    Friday, March 09, 2018 1:40 PM
  • Aren't 'verbs' supposed to be in 'operation'? 

    Richard Lewis Haggard

    Friday, March 09, 2018 1:43 PM
  • Ah. That was unexpected. Change the SW_HIDE to SW_SHOW and it works just fine.

     iRetVal = (int)ShellExecute(
                   
    IntPtr.Zero,
                   
    "pintohome",
                   
    @"C:\Users\Hagga\PreVeil-haggard@msn.com",
                   
    "",
                   
    "",
                   
    (int)ShowCommands.SW_SHOW );


    Richard Lewis Haggard

    Friday, March 09, 2018 1:52 PM
  • How would Process work with a Verb? Had it been obvious to me how to do that I would have gone that route in the first place.


    Richard Lewis Haggard


    See Process.StartInfo Property (System.Diagnostics). The ProcessStartInfo Class is used by the Start method. It has a ProcessStartInfo.UseShellExecute Property. Also see ProcessStartInfo.Verb Property. I assume you can use that for this.


    Sam Hobbs
    SimpleSamples.Info

    Friday, March 09, 2018 6:51 PM