C# 在C中使用CreateProcessWithLogonW的帮助#

C# 在C中使用CreateProcessWithLogonW的帮助#,c#,asp.net,winapi,C#,Asp.net,Winapi,我试图在Windows XP上执行一个带有asp.net(C#)内参数的控制台应用程序。我尝试过diagnostics.Process,但我就是无法让它工作,所以我切换到CreateProcessWithLogonW。我使用了中的代码示例,但控制台应用程序似乎没有运行,并且CreateProcessWithLogonWAPI调用的返回值为false 我的控制台应用程序语法类似于:“C:\Program Files\business Intelligence\mycommand.exe”arg1

我试图在Windows XP上执行一个带有asp.net(C#)内参数的控制台应用程序。我尝试过diagnostics.Process,但我就是无法让它工作,所以我切换到CreateProcessWithLogonW。我使用了中的代码示例,但控制台应用程序似乎没有运行,并且CreateProcessWithLogonWAPI调用的返回值为false

我的控制台应用程序语法类似于:“C:\Program Files\business Intelligence\mycommand.exe”arg1 arg2 arg3 arg4,如果我在dos窗口中以交互方式运行它,则运行良好

在C代码中,我在程序名之前和之后添加了双引号。当代码运行时,我注意到任务管理器进程数在我运行它的那一秒没有增加,这告诉我应用程序没有运行。processInfo结构具有所有0

我的问题是: 1-用于“CreateProcessWithLogonW”调用的两个“command”参数是否需要双引号?现在,我把整个命令行放在每个命令行中


2-如何捕获标准输出,以便知道发生了什么?

pInvoke的一个示例在防御方面是有效的,您能否先使用smth simple(如ping)进行尝试?我已经修改了pInvoke的代码来执行ping 127.0.0.1,请看下面的代码是否适合您。回答你的问题:1-我想没有必要这样做,但会双向工作,2-你可以这样做,但如果应用程序不启动的地方,它不会帮助你

示例代码:

public const UInt32 Infinite = 0xffffffff;
public const Int32 Startf_UseStdHandles = 0x00000100;
public const Int32 StdOutputHandle = -11;
public const Int32 StdErrorHandle = -12;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct StartupInfo
{
    public int cb;
    public String reserved;
    public String desktop;
    public String title;
    public int x;
    public int y;
    public int xSize;
    public int ySize;
    public int xCountChars;
    public int yCountChars;
    public int fillAttribute;
    public int flags;
    public UInt16 showWindow;
    public UInt16 reserved2;
    public byte reserved3;
    public IntPtr stdInput;
    public IntPtr stdOutput;
    public IntPtr stdError;
}

public struct ProcessInformation
{
    public IntPtr process;
    public IntPtr thread;
    public int processId;
    public int threadId;
}


[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcessWithLogonW(
    String userName,
    String domain,
    String password,
    UInt32 logonFlags,
    String applicationName,
    String commandLine,
    UInt32 creationFlags,
    UInt32 environment,
    String currentDirectory,
    ref   StartupInfo startupInfo,
    out  ProcessInformation processInformation);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetExitCodeProcess(IntPtr process, ref UInt32 exitCode);

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern UInt32 WaitForSingleObject(IntPtr handle, UInt32 milliseconds);

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(IntPtr handle);

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr handle);


private void button1_Click(object sender, RoutedEventArgs e)
{
    StartupInfo startupInfo = new StartupInfo();
    startupInfo.reserved = null;
    startupInfo.flags &= Startf_UseStdHandles;
    startupInfo.stdOutput = (IntPtr)StdOutputHandle;
    startupInfo.stdError = (IntPtr)StdErrorHandle;

    UInt32 exitCode = 123456;
    ProcessInformation processInfo = new ProcessInformation();

    String command = @"c:\windows\system32\ping.exe 127.0.0.1";
    String user = "admin";
    String domain = System.Environment.MachineName;
    String password = "password";
    String currentDirectory = System.IO.Directory.GetCurrentDirectory();

    try
    {
        CreateProcessWithLogonW(
            user,
            domain,
            password,
            (UInt32)1,
            null,
            command,
            (UInt32)0,
            (UInt32)0,
            currentDirectory,
            ref startupInfo,
            out processInfo);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }

    Console.WriteLine("Running ...");
    WaitForSingleObject(processInfo.process, Infinite);
    GetExitCodeProcess(processInfo.process, ref exitCode);

    Console.WriteLine("Exit code: {0}", exitCode);

    CloseHandle(processInfo.process);
    CloseHandle(processInfo.thread);
}

希望这有帮助,如果进程根本没有运行,您应该会得到一个异常。当你调用它时,你会得到一个异常吗?如果是,是哪个异常?(请将此附加信息添加到您的问题中)

如果你没有得到异常,几乎可以肯定的是,应用程序正在执行,但应用程序内部出现了一些故障——它退出的速度很快,以至于你看不到它在执行。要验证或排除这种可能性,您可以添加一个Thread.Sleep(20000)调用作为mycommand.exe应用程序的第一行,该调用将使该应用程序保持20秒,以便您可以使用任务管理器发现它,并将调试工作从调用者应用程序转移到被调用者应用程序

回答您的问题#1:是的,您需要引号,因为您的EXE路径有空格


对你的#2的回答:是的,你可以这样做,但在回答了第一个更紧迫的问题后,你最好把它分成一个单独的SO问题

这篇文章对我很有用


没有例外。mycommand.exe是第三方工具,因此我无法添加任何内容。如果应用程序正在执行,任务管理器中的计数器应至少增加1,然后下降1。。即使是在一秒钟内。当我启动notepad.exe之类的东西时,代码也会工作。但是,我需要从我的应用程序捕获输出。这可以告诉我应用程序是否工作但遇到错误,甚至“未找到文件”是否有用,这可以告诉我我没有正确构造命令。为了重定向标准输出,您必须设置StartupInfo结构的stdInput、stdOutput、stdError字段。您可以使用reflector检查System.Diagnostics.Process类的StartWithCreateProcess方法,以获取如何执行此操作的示例。简言之,您需要创建管道(CreatePipe api调用),将管道的句柄分配给StartupInfo的stdInput、stdOutput和stdError字段,然后使用FileStreamsI从管道读取\写入\数据,我知道,但这样不会让您在24小时内接受自己的答案,我还有7小时要走。