帮助在C#中使用CreateProcessWithLogonW

时间:2009-12-29 02:42:05

标签: c# asp.net winapi

我正在尝试在Windows XP上使用asp.net(C#)中的参数执行控制台应用程序。我已经尝试过diagnostics.Process但是我无法让它工作,所以我切换到CreateProcessWithLogonW。我使用了来自http://www.pinvoke.net/default.aspx/advapi32.createprocesswithlogonw的代码示例,但控制台应用程序似乎没有运行,并且CreateProcessWithLogonW api调用的返回值为false。

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

在C#代码中,我在程序名称之前和之后添加双引号。当代码运行时,我注意到任务管理器进程计数​​没有增加第二次我运行它告诉我应用程序没有运行。 processInfo结构全部为0。

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

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

3 个答案:

答案 0 :(得分:1)

来自pInvoke的一个例子是defenitelly有效,你能先用像ping一样的smth来试试吗?我已经修改了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);
}

希望这有帮助,尊重

答案 1 :(得分:1)

答案 2 :(得分:0)

如果进程根本没有运行,你应该得到一个例外。你打电话的时候会得到一个例外,如果是的话,那个例外是什么? (请在您的问题中添加此附加信息)。

如果你没有得到异常,几乎可以肯定的是,应用程序正在执行,但是在该应用程序内部出现了一些问题 - 并且它正在快速退出,以至于你看不到它正在执行。要验证或排除这种可能性,您可以添加一个Thread.Sleep(20000)调用作为mycommand.exe应用程序的第一行,这应该让应用程序保持20秒左右,这样您就可以通过任务管理器发现它并转移您的调试调用者应用程序到被调用者应用程序的努力。

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

回答#2:是的,你可以做到这一点,但是一旦你回答了第一个更紧迫的问题,你可能会把它分成一个单独的SO问题。