在C#应用程序中隐藏命令窗口

15

在你说这是一个重复问题之前,请允许我解释一下(因为我已经阅读了所有类似的帖子)。

我的应用程序具有以下两个设置:

  procStartInfo.CreateNoWindow = true;
  procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
并且输出类型也是 WindowsApplication。当我调用命令行命令时,黑色窗口仍然会弹出。除了隐藏窗口之外,我还能做些什么吗?并非所有命令都会出现这种情况,XCOPY 是一个会出现黑色窗口的情况。这只会发生在我复制到的目标已经包含该文件并且正在提示我是否要替换它的情况下。即使我传递了 /Y,它也会短暂地闪烁。
如果可以的话,我愿意使用 vbscript,但还有其他想法吗?
客户端将调用我的可执行文件,然后传入命令行命令,例如:
C:\MyProgram.exe start XCOPY c:\Test.txt c:\ProgramFiles\
这是应用程序的完整代码:
class Program
{
    static void Main(string[] args)
    {      
            string command = GetCommandLineArugments(args);

            // /c tells cmd that we want it to execute the command that follows and then exit.
            System.Diagnostics.ProcessStartInfo procStartInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe", "/c " + command);

            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;

            // Do not create the black window.
            procStartInfo.CreateNoWindow = true;
            procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo = procStartInfo;
            process.Start();

        }

    private static string GetCommandLineArugments(string[] args)
    {
        string retVal = string.Empty;

        foreach (string arg in args)
            retVal += " " + arg;


        return retVal;
    }
}

你能否发布你的Process/ProcessStartInfo代码的其余部分? - Tim Robinson
3
@fletcher:问题中指定了输出类型为 Windows 应用程序而不是控制台。我已经测试了输出类型设置为 Windows 应用程序,它可以正常工作。 @snow:我建议您再次检查 OutputType 设置。 - Matt B
@fletcher 这实际上是个问题!我希望窗口根本不显示! - mint
@fletcher 可能会有一个黑色窗口闪现出某种消息,但由于闪得太快,我无法阅读它。有没有办法抑制STDOUT消息? - mint
如果你想尝试读取标准输出/标准错误信息,你可以通过以下方式将其重定向到字符串:procStartInfo.RedirectStandardOutput = true; procStartInfo.RedirectStandardError = true;...string stdout = process.StandardOutput.ReadToEnd(); string stderr = process.StandardError.ReadToEnd(); - James Sulak
显示剩余4条评论
5个回答

9
问题在于您正在使用cmd.exe。只有它的控制台窗口会被隐藏,而不是您要求它启动的进程的控制台窗口。除非您试图执行它本身实现的一些命令,否则使用cmd.exe没有多大意义。比如COPY。
如果您需要cmd.exe,仍然可以抑制窗口,您将不得不使用Start的/B选项。在命令提示符下键入start /?以查看选项。请注意,这并没有帮助,您无法使用START COPY。
xcopy.exe还有一个特定的怪癖,可能会让您困惑。如果您不重定向输入,它就不会执行。它只是在没有诊断的情况下无法运行。

/B 对于 xcopy 命令有效,说实话这可能就是我们所需要的。 - mint

5
我看到你正在调用 cmd 并将命令作为参数传递。相反,直接调用该命令。
例如:
    System.Diagnostics.ProcessStartInfo procStartInfo = new System.DiagnosticsProcessStartInfo("xcopy", "<sourcedir> <destdir> <other parameters>");

procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

我可能应该在问题中说明这一点,但是客户将传递任何命令行命令给我的程序,因此我不能硬编码xcopy,但我还是会给你点赞! - mint
1
@Snow,你仍然可以按照他的建议操作,ProcessStartInfo procStartInfo = new ProcessStartInfo(Arg[0], String.Join(" ", Arg.Skip(1).ToArray()); - Scott Chamberlain
@snow xcopy 只是举例说明。 - ajay_whiz

4
您可以尝试添加 <\p>。
process.StartInfo.UseShellExecute = false; 

到你的流程中


2
只是为了澄清答案。您需要 process.StartInfo.UseShellExecute = false;process.StartInfo.CreateNoWindow = false;。这两个一起将隐藏进程窗口。 - Rémi
2
@Rémi:你需要 process.StartInfo.CreateNoWindow = true; - Sjoerd222888
我收到了错误消息“系统找不到指定的文件。”尽管我已经将自定义命令添加到系统PATH变量中。 - Najeeb

1

如果你在C#代码中调用cmd.exe,并通过标准的input.WriteLine传递命令,而且你不想每次运行代码时弹出CMD窗口,你可以简单地写入此命令:

 test.StartInfo.FileName = "cmd.exe";
 test.StartInfo.CreateNoWindow = true;

通过将create no window设置为false,我们可以在后台运行发送到CMD的命令且结果不会显示给用户。将其设置为false,则CMD窗口会弹出。


0

我有一个类似的任务 - 可以通过API调用在创建后隐藏窗口。 (在您的情况下,您可能需要一个辅助线程。)

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

如果你知道新窗口的句柄,你就可以调用它。
ShowWindow(hWnd, 0);

0 隐藏窗口,1 显示窗口

要获取窗口的句柄,请查看:

pinvoke.net enumwindows(user32)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接