如何运行一个Windows批处理文件但隐藏命令窗口?

35

如何在运行Windows批处理文件时隐藏命令窗口?当文件正在执行时,我不希望cmd.exe出现在屏幕上可见。是否有可能实现这个目标?


1
你是如何启动的?通过代码?只是在Windows中运行?还是通过其他脚本? - Taylor Bird
它们是由桌面应用程序调用的Windows shell脚本。 - barfoon
1
这个应用程序是用什么语言编写的? - Helen
这是一个应用服务器 - 一个在Windows Server 2003上运行的Windows可执行文件。 - barfoon
1
你对服务器应用程序有什么控制权?你拥有源代码吗(可以修改并重新编译)?如果你无法控制应用程序的源代码,为了实现你的目标,你愿意采取什么措施,比如编写C++代码在运行时注入应用程序,以拦截CreateProcess并动态更改其dwCreationFlags参数,以便以隐藏或最小化模式生成(某些)子进程等? - vladr
10个回答

41
如果您编写一个不受管理的程序并使用 CreateProcess API,那么您应该初始化类型为 STARTUPINFOlpStartupInfo 参数,以便结构体的 wShowWindow 字段为 SW_HIDE,并且不要忘记在 STARTUPINFOdwFlags 字段中使用 STARTF_USESHOWWINDOW 标志。另一种方法是使用 dwCreationFlags 参数的 CREATE_NO_WINDOW 标志。相同的技巧也适用于 ShellExecuteShellExecuteEx 函数。
如果您编写的是托管应用程序,建议遵循http://blogs.msdn.com/b/jmstall/archive/2006/09/28/createnowindow.aspx中的建议: 使用CreateNoWindow = trueUseShellExecute = false初始化ProcessStartInfo,然后将其作为参数传递。就像在设置属性ProcessStartInfoWindowStyleProcessWindowStyle.Hidden或与CreateNoWindow = true一起使用的情况下一样。
您可以使用一个VBS脚本,并使用wcsript.exe启动它。在脚本内部,您可以使用CreateObject("WScript.Shell"),然后使用0作为第二个(intWindowStyle)参数来运行Run。请参见http://www.robvanderwoude.com/files/runnhide_vbs.txt作为示例。我可以继续使用Kix、PowerShell等等。
如果您不想编写任何程序,可以使用任何现有的实用工具,例如 CMDOW /RUN /HID "c:\SomeDir\MyBatch.cmd", hstart /NOWINDOW /D=c:\scripts "c:\scripts\mybatch.bat", hstart /NOCONSOLE "batch_file_1.bat",它们都可以完成相同的操作。我相信您会发现更多这样的免费实用工具。
在某些情况下(例如从 UNC 路径启动),设置一个工作目录到一些本地路径(%SystemRoot%\system32 始终有效)也很重要。这对于使用上述列出的任何隐藏批处理变体都很重要。

批处理文件是否可以隐藏自己的窗口? - Kyle Delaney
1
@KyleDelaney:是的,这是可能的,但我不确定哪个工具更好推荐给你。对我来说,编写相应的实用程序比找到现有的实用程序更容易。抱歉,答案非常老旧,一些链接(如cmdow上的链接)已经更改了。您可以在https://ritchielawrence.github.io/cmdow/上找到它。我想强调的是,最好(也更安全)*使用某些实用程序*启动隐藏批处理,并从已经启动的批处理中隐藏窗口。 - Oleg

8
使用C#很容易启动批处理命令而不需要打开一个窗口。请看下面的代码示例:
        Process process = new Process();
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.FileName = "doSomeBatch.bat";
        process.Start();

6

对于任何可执行文件,您可以使用带有“c”参数的cmd运行您的程序:

cmd /c "your program address"\"YourFileName".bat  

(->如果是批处理文件!) 作为最终解决方案,我建议您创建一个 .cmd 文件并将此命令放入其中:

cmd /c "your program address"\"YourFileName".bat
exit

现在只需运行这个 .cmd 文件即可。

8
所以,它会打开一个没有窗口的命令行窗口,并启动一个批处理文件? - Oliver Friedrich
由于“c”参数,命令提示符窗口被隐藏,执行后,命令提示符将关闭,并且在执行期间不会显示任何提示符正在运行的迹象,即使您运行命令提示符,它也会以可见形式运行,目前我还没有遇到任何问题。 - rain

3
为了自动隐藏已运行的脚本,您需要使用getCmdPid.batwindowoMode.bat。请注意,这些脚本只是为了方便起见,并不提供任何解释。同时,请保留HTML标签。
@echo off

echo self minimizing
call getCmdPid.bat
call windowMode.bat -pid %errorlevel% -mode hidden

echo --other commands--
pause

这里我已经整理了我所知道的所有在批处理中启动隐藏进程的方法,而不需要外部工具。其中包括一些准备好的脚本(其中一些选项非常丰富),并且全部都可以通过命令行使用。在可能的情况下,也会返回PID。使用的工具包括IEXPRESS、SCHTASKS、WScript.Shell、Win32_Process和JScript.Net - 但它们都包装在.bat文件中。


3

以下是Oleg的答案的本地C++编码版本--这是从我参与的项目复制/粘贴而来,遵循Boost软件许可证。

BOOL noError;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInformation;
ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
startupInfo.dwFlags = STARTF_USESHOWWINDOW;
startupInfo.wShowWindow = SW_HIDE;
noError = CreateProcess(
    NULL,                                           //lpApplicationName
    //Okay the const_cast is bad -- this code was written a while ago.
    //should probably be &commandLine[0] instead. Oh, and commandLine is
    //a std::wstring
    const_cast<LPWSTR>(commandLine.c_str()),        //lpCommandLine
    NULL,                                           //lpProcessAttributes
    NULL,                                           //lpThreadAttributes
    FALSE,                                          //bInheritHandles
    CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT,  //dwCreationFlags
    //This is for passing in a custom environment block -- you can probably
    //just use NULL here.
    options.e ? environment : NULL,                 //lpEnvironment
    NULL,                                           //lpCurrentDirectory
    &startupInfo,                                   //lpStartupInfo
    &processInformation                             //lpProcessInformation
);

if(!noError)
{
    return GetLastError();
}

DWORD exitCode = 0;

if (options.w) //Wait
{
    WaitForSingleObject(processInformation.hProcess, INFINITE);
    if (GetExitCodeProcess(processInformation.hProcess, &exitCode) == 0)
    {
        exitCode = (DWORD)-1;
    }
}

CloseHandle( processInformation.hProcess );
CloseHandle( processInformation.hThread );

2
这个小的VBScript来自于Technet,可以解决问题。
Const HIDDEN_WINDOW = 12

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objStartup = objWMIService.Get("Win32_ProcessStartup")

Set objConfig = objStartup.SpawnInstance_
objConfig.ShowWindow = HIDDEN_WINDOW
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
errReturn = objProcess.Create("mybatch.bat", null, objConfig, intProcessID)

编辑mybatch.bat,将其替换为您的bat文件名,另存为vbs,然后运行它。

文档说明它在Win7中未经过测试,但我刚刚测试过了,它可以正常工作。无论您运行什么进程,它都不会显示任何窗口。


1

通过使用右键单击并选择创建快捷方式,为您的bat文件创建一个快捷方式。 右键单击您创建的快捷方式,然后点击属性。 点击运行下拉框,选择最小化。


0

使用Bat To Exe Converter并将Bat文件编译为可执行文件。

步骤:

  1. 打开Bat to Exe Converter
  2. 选择您的Bat文件
  3. 在选项中选择“不可见应用程序”
  4. 完成后按下编译按钮

0

你可以编写一个 Windows 服务,仅用于执行批处理文件。由于服务在自己的桌面会话中运行,因此用户看不到命令窗口。


-2

1、下载批处理文件转换成可执行文件的工具并安装。 2、运行批处理文件转换成可执行文件的应用程序。 3、如果想要制作外观良好的可执行文件,则下载 .pco 图像文件。 4、指定批处理文件的位置(例如:c:\my.bat)。 5、指定可执行文件保存的位置(例如:c:/my.exe)。 6、选择版本信息选项卡。 7、选择图标文件(下载的 .pco 图像文件)。 8、如果需要,填写版本、公司名称等信息。 9、切换到选项选项卡。 10、选择隐藏应用程序(这将在运行应用程序时隐藏命令提示符)。 11、选择 32 位(如果选择 64 位,可执行文件仅适用于 32 位操作系统)。 12、编译。 13、将可执行文件复制到批处理文件正确执行的位置。 14、运行可执行文件。


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