【问题标题】:C# - Command window appears a tenth of a second before disappearC# - 命令窗口在消失前出现十分之一秒
【发布时间】:2016-04-27 14:53:38
【问题描述】:

我试图在进程启动时隐藏命令窗口。我使用此 ProcessStartInfo 配置启动 McAfee 病毒扫描:

ProcessStartInfo procInfo = new ProcessStartInfo();
procInfo.FileName = args[0];
...
procInfo.RedirectStandardOutput = true;
procInfo.WindowStyle = ProcessWindowStyle.Hidden;
procInfo.CreateNoWindow = false;
procInfo.UseShellExecute = false;
process.StartInfo = procInfo;

然后,我试试:

process.Start();
process.CloseMainWindow();

还有:

process.Start();
while (process.MainWindowHandle == IntPtr.Zero)
{
   process.Refresh();
}
var handle = process.MainWindowHandle;
ShowWindow(handle, 0) //ShowWindow from user32.dll

但在这两种情况下,命令窗口都会出现,在它完全显示之前,它会消失(就像最大化窗口并立即最小化它一样)。我也玩过所有可能的 ProcessStartInfo 属性组合。我不需要在任何时候显示窗口。我怎么能做到这一点?提前致谢!

【问题讨论】:

  • 在任务计划程序中安排您的 EXE
  • 设置 CreateNoWindow = false;是真的吗?
  • @techspider,这是更大过程的一部分,我无法安排它:(
  • @BugFinder,行为与 CreateNoWindow 设置为 false 或 true 相同。
  • 如果您将其最小化启动,您是否只会在任务栏中看到一个图标?我猜它的编码总是表明它只是在做坏事。

标签: c# visual-studio-2010


【解决方案1】:

对于您问题中显示的代码块,行为是正常的。

让我们看看它们......

//[...]
procInfo.CreateNoWindow = false; //That's not what you meant
procInfo.UseShellExecute = false;
process.Start(); //Will show up the console window
process.CloseMainWindow(); //Will close the main window (probably also the whole application)

process.Start();process.CloseMainWindow(); 之间是一个很短的时间范围,应用程序是可见的。

如@BugFinder 所述,将CreateNoWindow 值从false 编辑为true 就足够了。
检查是否有效。

你的第二次尝试让你走得更远:

process.Start();
while (process.MainWindowHandle == IntPtr.Zero)
{
   process.Refresh(); //Let's do this as long as there is no window...
}
var handle = process.MainWindowHandle; //This occurs, when there is *already* a window.
ShowWindow(handle, 0) //ShowWindow from user32.dll

使用Shell Functions的想法基本上还不错,但是这段代码和上面的代码是一样的(而且也是非托管的)。

让我们尝试不同的方式,从PInvoke.Net获取C#示例:(不比 ShowWindow() 更受管理...)

public static void StartupNotepad()
{
     const uint NORMAL_PRIORITY_CLASS = 0x0020;
     const uint STARTF_USESHOWWINDOW = 0x1;     //IMPORTANT for you
     bool retValue;
     string Application = Environment.GetEnvironmentVariable("windir") + @"\Notepad.exe";
     string CommandLine = @" c:\boot.ini";  //Funny
     PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
     STARTUPINFO sInfo = new STARTUPINFO();
     sInfo.wShowWindow = 0;                     //IMPORTANT for you - See http://pinvoke.net/default.aspx/Enums/ShowWindowCommand.html
     sInfo.dwFlags = STARTF_USESHOWWINDOW;      //IMPORTANT for you
     SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
     SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES();
     pSec.nLength = Marshal.SizeOf(pSec);
     tSec.nLength = Marshal.SizeOf(tSec);
     retValue = CreateProcess(Application,CommandLine,
     ref pSec,ref tSec,false,NORMAL_PRIORITY_CLASS,
     IntPtr.Zero,null,ref sInfo,out pInfo);

     Console.WriteLine("Process ID (PID): " + pInfo.dwProcessId);
     Console.WriteLine("Process Handle : " + pInfo.hProcess);
}

此示例以非常静态的方式演示了 CreateProcess(底部的 MSDN 链接)的使用。
我建议您编写一个更动态的函数并使用它。 PROCESS_INFORMATION 结构允许您稍后在应用程序中操作新创建的进程。如果使用 CreateProcess() 调用仍然存在问题,则需要检查启动的应用程序是否对自身做了一些棘手的事情。最后但并非最不重要的一点是,问题是否不仅出现在您的计算机上...

这里还有一些参考资料:

编辑:

可能是一种解决方法,但如果您的第 3 方应用程序旨在显示一个窗口并试图忽略您的请求,STARTUPINFO 也有dwXdwY,如果dwFlags 指定@,则设置窗口的位置987654351@。 dwXSizedwYSize 相同。

如果所有其他方法都失败了,您可以试一试并传递位置和大小,这会使过程看起来不可见。干杯。

【讨论】:

  • 启动 McAfee Scan 比记事本更复杂,以便捕获和重定向输出、关闭进程或捕获 Windows 处理程序。感谢您提供有关CreateProcess() 的线索。 :)
  • in order to catch and redirect outputs 这就是 PROCESS_INFORMATION 的引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-29
相关资源
最近更新 更多