Changeset 2002


Ignore:
Timestamp:
5/1/2010 12:13:55 PM (4 years ago)
Author:
lowjoel
Message:

Implemented response file support to allow for very long command lines.

Location:
trunk/eraser
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser/Eraser.Util/NativeMethods/Kernel.cs

    r1874 r2002  
    899899            out WindowsEditions pdwReturnedProductType); 
    900900 
     901        /// <summary> 
     902        /// Frees the specified local memory object and invalidates its handle. 
     903        /// </summary> 
     904        /// <param name="hMem">A handle to the local memory object. This handle is 
     905        /// returned by either the LocalAlloc or LocalReAlloc function. It is not 
     906        /// safe to free memory allocated with GlobalAlloc.</param> 
     907        /// <returns>If the function succeeds, the return value is NULL. 
     908        ///  
     909        /// If the function fails, the return value is equal to a handle to the 
     910        /// local memory object. To get extended error information, call 
     911        /// GetLastError.</returns> 
     912        /// <remarks>If the process tries to examine or modify the memory after 
     913        /// it has been freed, heap corruption may occur or an access violation 
     914        /// exception (EXCEPTION_ACCESS_VIOLATION) may be generated. 
     915        ///  
     916        /// If the hMem parameter is NULL, LocalFree ignores the parameter and 
     917        /// returns NULL. 
     918        ///  
     919        /// The LocalFree function will free a locked memory object. A locked 
     920        /// memory object has a lock count greater than zero. The LocalLock 
     921        /// function locks a local memory object and increments the lock count 
     922        /// by one. The LocalUnlock function unlocks it and decrements the lock 
     923        /// count by one. To get the lock count of a local memory object, use 
     924        /// the LocalFlags function. 
     925        ///  
     926        /// If an application is running under a debug version of the system, 
     927        /// LocalFree will issue a message that tells you that a locked object 
     928        /// is being freed. If you are debugging the application, LocalFree will 
     929        /// enter a breakpoint just before freeing a locked object. This allows 
     930        /// you to verify the intended behavior, then continue execution.</remarks> 
     931        [DllImport("Kernel32.dll", SetLastError = true)] 
     932        public static extern IntPtr LocalFree(IntPtr hMem); 
    901933    } 
    902934} 
  • trunk/eraser/Eraser.Util/NativeMethods/Shell.cs

    r1802 r2002  
    3030    { 
    3131        /// <summary> 
     32        /// Parses a Unicode command line string and returns an array of pointers to the command 
     33        /// line arguments, along with a count of such arguments, in a way that is similar to 
     34        /// the standard C run-time argv and argc values. 
     35        /// </summary> 
     36        /// <param name="lpCmdLine">Pointer to a null-terminated Unicode string that contains 
     37        /// the full command line. If this parameter is an empty string the function returns the 
     38        /// path to the current executable file.</param> 
     39        /// <param name="pNumArgs">Pointer to an int that receives the number of array elements 
     40        /// returned, similar to argc.</param> 
     41        /// <returns>A pointer to an array of strings, similar to argv.</returns> 
     42        /// <remarks>The address returned by CommandLineToArgvW is the address of the first 
     43        /// element in an array of LPWSTR values; the number of pointers in this array is 
     44        /// indicated by pNumArgs. Each pointer to a null-terminated Unicode string represents 
     45        /// an individual argument found on the command line. 
     46        ///  
     47        /// CommandLineToArgvW allocates a block of contiguous memory for pointers to the 
     48        /// argument strings, and for the argument strings themselves; the calling application 
     49        /// must free the memory used by the argument list when it is no longer needed. To free 
     50        /// the memory, use a single call to the LocalFree function. 
     51        ///  
     52        /// For more information about the argv and argc argument convention, see Argument 
     53        /// Definitions and Parsing C++ Command-Line Arguments. 
     54        ///  
     55        /// The GetCommandLineW function can be used to get a command line string that is 
     56        /// suitable for use as the lpCmdLine parameter. 
     57        ///  
     58        /// This function accepts command lines that contain a program name; the program name 
     59        /// can be enclosed in quotation marks or not. 
     60        ///  
     61        /// CommandLineToArgvW has a special interpretation of backslash characters when they 
     62        /// are followed by a quotation mark character ("), as follows: 
     63        ///  
     64        ///     * 2n backslashes followed by a quotation mark produce n backslashes 
     65        ///       followed by a quotation mark. 
     66        ///     * (2n) + 1 backslashes followed by a quotation mark again produce n 
     67        ///       backslashes followed by a quotation mark. 
     68        ///     * n backslashes not followed by a quotation mark simply produce n 
     69        ///       backslashes. 
     70        /// </remarks> 
     71        [DllImport("Shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     72        public static extern IntPtr CommandLineToArgvW(string lpCmdLine, out int pNumArgs); 
     73 
     74        /// <summary> 
    3275        /// Truncates a path to fit within a certain number of characters by 
    3376        /// replacing path components with ellipses. 
  • trunk/eraser/Eraser.Util/Shell.cs

    r1895 r2002  
    2323using System.Collections.Generic; 
    2424using System.Text; 
     25 
     26using System.Runtime.InteropServices; 
    2527using Microsoft.Win32; 
    2628 
     
    6466            } 
    6567        } 
     68 
     69        /// <summary> 
     70        /// Parses the provided command line into its constituent arguments. 
     71        /// </summary> 
     72        /// <param name="commandLine">The command line to parse.</param> 
     73        /// <returns>The arguments specified in the command line</returns> 
     74        public static string[] ParseCommandLine(string commandLine) 
     75        { 
     76            int argc = 0; 
     77            IntPtr argv = NativeMethods.CommandLineToArgvW(commandLine, out argc); 
     78            string[] result = new string[argc]; 
     79 
     80            //Get the pointers to the arguments, then read the string. 
     81            for (int i = 0; i < argc; ++i) 
     82                result[i] = Marshal.PtrToStringUni(Marshal.ReadIntPtr(argv, i * IntPtr.Size)); 
     83 
     84            //Free the memory 
     85            NativeMethods.LocalFree(argv); 
     86 
     87            return result; 
     88        } 
    6689    } 
    6790} 
  • trunk/eraser/Eraser/Program.cs

    r1973 r2002  
    105105        /// </summary> 
    106106        [STAThread] 
    107         static int Main(string[] commandLine) 
    108         { 
    109             //Immediately parse command line arguments 
    110             ComLib.BoolMessageItem argumentParser = Args.Parse(commandLine, 
     107        static int Main(string[] rawCommandLine) 
     108        { 
     109            //Immediately parse command line arguments. Start by substituting all 
     110            //response files ("@filename") arguments with the arguments found in the 
     111            //file 
     112            List<string> commandLine = new List<string>(); 
     113            foreach (string argument in rawCommandLine) 
     114            { 
     115                if (argument[0] == '@' && File.Exists(argument.Substring(1))) 
     116                { 
     117                    //The current parameter is a response file, parse the file 
     118                    //for arguments and substitute it. 
     119                    using (TextReader reader = new StreamReader(argument.Substring(1))) 
     120                    { 
     121                        commandLine.AddRange(Shell.ParseCommandLine(reader.ReadToEnd())); 
     122                    } 
     123                } 
     124            } 
     125 
     126            string[] finalCommandLine = commandLine.ToArray(); 
     127            ComLib.BoolMessageItem argumentParser = Args.Parse(finalCommandLine, 
    111128                CommandLinePrefixes, CommandLineSeparators); 
    112129            Args parsedArguments = (Args)argumentParser.Item; 
     
    122139                parsedArguments.Positional[0] != parsedArguments.Raw[0]) 
    123140            { 
    124                 GUIMain(commandLine); 
     141                GUIMain(finalCommandLine); 
    125142            } 
    126143            else 
    127144            { 
    128                 return CommandMain(commandLine); 
     145                return CommandMain(finalCommandLine); 
    129146            } 
    130147 
Note: See TracChangeset for help on using the changeset viewer.