[DllImport("shell32.dll")]
static extern IntPtr CommandLineToArgvW(
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs);
Declare Function CommandLineToArgv Lib "shell32.dll" Alias "CommandLineToArgvW" ( _
ByVal lpCmdLine As String, _
ByRef pNumArgs As Integer) As Long
None.
Minimum DLL Version | Shell32.dll version 6.0 or later |
Minimum operating systems | Windows NT Workstation 3.5, Windows NT Server 3.5, Windows 2000 Professional, Windows 2000 Server, Windows XP, Windows Server 2003 |
Unicode | This function is implemented as Unicode. |
Please add some!
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace CmdLineToArgvW
{
class MainModule
{
static void Main(string[] args)
{
Console.WriteLine( "args.Length: {0}", args.Length );
for ( int i = 0; i < args.Length; i++ )
{
Console.WriteLine( "args[{0}]={1}", i, args[i] );
}
Console.WriteLine();
int argc;
IntPtr argvPtr = IntPtr.Zero;
try
{
argvPtr = CommandLineToArgvW( Environment.CommandLine, out argc );
// CommandLineToArgvW will list the executable as argv[0].
// I want to see the same count as you get from "string[] args".
Console.WriteLine( "argc: {0}", argc - 1 );
// argvPtr is a pointer to a pointer; dereference it
IntPtr argPtr = Marshal.ReadIntPtr( argvPtr );
for ( int i = 0; i < argc; i++ )
{
string arg = Marshal.PtrToStringUni( argPtr );
// CommandLineToArgvW will list the executable as argv[0].
// I want to get the same output that "string[] args" yields,
// so I'll skip the output for i = 0
if ( i > 0 )
{
Console.WriteLine( "argv[{0}]={1}", i - 1, arg );
}
// Increment the pointer address by the number of Unicode bytes
// plus one Unicode character for the string's null terminator
int unicodeByteCount =
Encoding.Unicode.GetByteCount( arg ) +
Encoding.Unicode.GetByteCount( new char[] { Char.MinValue } );
argPtr = new IntPtr( argPtr.ToInt32() + unicodeByteCount );
}
}
finally
{
LocalFree( argvPtr );
}
}
// Here's an wrapper to CommandLineToArgvW I found useful (csells@sellsbrothers.com)
public static IEnumerable<string> CommandLineToExeAndArgs() {
return CommandLineToExeAndArgs(Environment.CommandLine);
}
public static IEnumerable<string> CommandLineToExeAndArgs(string cmdline) {
List<string> args = new List<string>();
IntPtr argvPtr = IntPtr.Zero;
try {
int argc;
argvPtr = CommandLineToArgvW(cmdline, out argc);
// argvPtr is a pointer to a pointer; dereference it
IntPtr argPtr = Marshal.ReadIntPtr(argvPtr);
// CommandLineToArgvW will list the executable as argv[0], so skip it
for( int i = 0; i < argc; i++ ) {
string arg = Marshal.PtrToStringUni(argPtr);
args.Add(arg);
// Increment the pointer address by the number of Unicode bytes
// plus one Unicode character for the string's null terminator
int unicodeByteCount = Encoding.Unicode.GetByteCount(arg) + Encoding.Unicode.GetByteCount(new char[] { Char.MinValue });
argPtr = new IntPtr(argPtr.ToInt32() + unicodeByteCount);
}
}
finally {
LocalFree(argvPtr);
}
return args.ToArray();
}
[DllImport("shell32.dll")]
static extern IntPtr CommandLineToArgvW(
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine,
out int pNumArgs);
[DllImport("kernel32.dll")]
static extern IntPtr LocalFree(IntPtr hMem);
}
}
Do you know one? Please contribute it!