C#自带的Process类只能重定向到管道,并且stdout和stderr只能分别接收,无法达到命令提示符的效果。这里实现了一个Cmd类,其中XXXXXXnCmd函数可以运行命令同时返回所有输出。
Cmd.cs:
<code class="language-cs">using System;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;
/// <summary>
/// Summary description for Class1
/// </summary>
public class Cmd
{
public Cmd()
{
//
// TODO: Add constructor logic here
//
}
[StructLayout(LayoutKind.Sequential)]
private class SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[Flags]
private enum STARTF : uint
{
STARTF_USESHOWWINDOW = 0x00000001,
STARTF_USESIZE = 0x00000002,
STARTF_USEPOSITION = 0x00000004,
STARTF_USECOUNTCHARS = 0x00000008,
STARTF_USEFILLATTRIBUTE = 0x00000010,
STARTF_RUNFULLSCREEN = 0x00000020, // ignored for non-x86 platforms
STARTF_FORCEONFEEDBACK = 0x00000040,
STARTF_FORCEOFFFEEDBACK = 0x00000080,
STARTF_USESTDHANDLES = 0x00000100,
}
private const Int16 SW_HIDE = 0;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private class STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public STARTF dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
private class PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 1;
private const uint OPEN_EXISTING = 3;
private const uint FILE_ATTRIBUTE_NORMAL = 0x80;
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile(
string filename,
uint access,
uint share,
[In] SECURITY_ATTRIBUTES securityAttributes,
uint creationDisposition,
uint flagsAndAttributes,
IntPtr templateFile);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
[In] SECURITY_ATTRIBUTES lpProcessAttributes,
[In] SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
[In] STARTUPINFO lpStartupInfo,
[Out] PROCESS_INFORMATION lpProcessInformation);
private const uint INFINITE = 0xFFFFFFFF;
private const uint WAIT_FAILED = 0xFFFFFFFF;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
[DllImport("kernel32.dll", SetLastError = false)]
private static extern IntPtr GetCurrentProcess();
private const uint DUPLICATE_SAME_ACCESS = 2;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool DuplicateHandle(
IntPtr proc1, IntPtr handle1,
IntPtr proc2, out IntPtr handle2,
uint access, bool inheritable, uint flags);
[DllImport("kernel32.dll", SetLastError = false)]
private static extern bool CloseHandle(IntPtr handle);
public static string RunCmd(string cmd)
{
string tmpname = Path.GetTempFileName();
// WIN32 section starts
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.nLength = Marshal.SizeOf(sa);
sa.bInheritHandle = true;
sa.lpSecurityDescriptor = IntPtr.Zero;
IntPtr outhandle = CreateFile(tmpname, GENERIC_WRITE, FILE_SHARE_READ, sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
if (outhandle == new IntPtr(-1))
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
IntPtr outhandle2 = new IntPtr(-1);
if (!DuplicateHandle(GetCurrentProcess(), outhandle, GetCurrentProcess(), out outhandle2, 0, true, DUPLICATE_SAME_ACCESS))
{
CloseHandle(outhandle);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.dwFlags = STARTF.STARTF_USESTDHANDLES | STARTF.STARTF_USESHOWWINDOW;
si.hStdInput = new IntPtr(-1);
si.hStdOutput = outhandle;
si.hStdError = outhandle2;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
if (!CreateProcess(null, cmd, null, null, true, 0, IntPtr.Zero, null, si, pi))
{
CloseHandle(outhandle);
CloseHandle(outhandle2);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
CloseHandle(pi.hThread);
CloseHandle(outhandle);
CloseHandle(outhandle2);
if (WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED)
{
CloseHandle(pi.hProcess);
throw new Win32Exception(Marshal.GetLastWin32Error());
}
CloseHandle(pi.hProcess);
// WIN32 section ends
string outstr = File.ReadAllText(tmpname, Encoding.Default);
File.Delete(tmpname);
return outstr;
}
}
</code>
200字以内,仅用于支线交流,主线讨论请采用回复功能。