导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2017/6/7 15:45:11
标题:
Delphi 如何将cmd的命令窗口嵌入到form里来?
浏览:2515
加入我的收藏
楼主:
我想让cmd这个界面随系统启动而启动,且随系统关闭而关闭。 因此把这个cmd界面直接嵌入到form是最好的方法 一般通过很多方法可以将exe嵌入到form上,但是无法将这个cmd命令界面嵌入到form里面来,各位有什么好的处理办法?
----------------------------------------------
-
作者:
2017/6/7 15:47:53
1楼:
// 窗体枚举函数 function EnumWindowsProc(Wnd: hWnd; ProcWndInfo: PProcessWindow): BOOL; stdcall; var WndProcessID: Cardinal; begin GetWindowThreadProcessId(Wnd, @WndProcessID); if WndProcessID = ProcWndInfo^.ProcessID then begin ProcWndInfo^.FoundWindow := Wnd; Result := False; // 已找到,故停止 EnumWindows end else Result := True; // 继续查找 end; 这个方法无法找到cmd的界面,所以没有返回句柄,就没法将这个cmd窗体嵌入到form....没找到好方法,哪位大侠有办法?
----------------------------------------------
-
作者:
2017/6/7 16:03:05
2楼:
然而, 你想做什么? 你系统刚启动的时候, 肯定是不会启动cmd虚拟机的. 你可以自己去创建一个cmd进程. 然后嵌入到你的程序.. 如果你只想调用cmd来执行一些脚本并获取输出信息的话, 直接用管道做就可以了. 并不需要去折腾那个界面.
----------------------------------------------
--
作者:
2017/6/7 16:03:08
2楼:
自己仿写一个cmd窗口如何?没试过。 用winexec执行输入内容dos命令,在输入的dos命令后面添加重定向管道符——为把输出定向到某txt文件——把txt文件的内容写到你的模拟dos窗口里。
----------------------------------------------
-
作者:
2017/6/7 16:07:46
3楼:
一般流程 开一个管道 然后用户输入传输到管道内 管道的返回,显示到你的 FORM 上。
----------------------------------------------
(C)(P)Flying Wang
作者:
2017/6/7 18:00:17
4楼:
to bahamut8348 : 谢谢你的回答,因为有个服务是用cmd命令来控制启动的,这个服务是软件的内嵌服务,必须在cmd环境下执行。 随软件启动而启动,随软件关闭而关闭。都由cmd命令来执行的。 因此,我想嵌入在软件的一个panel上,更加直观。 我确实是创建一个cmd进程来打开,但是现在无法嵌入到程序的panel或者form上,因为我没取到句柄。 因为这个cmd界面是不能关掉的,一直是在后台运行,所以用管道貌似是不成
----------------------------------------------
-
作者:
2017/6/7 18:03:37
5楼:
因为作为cmd会启动一个类似服务的cmd程序... 一直在cmd的界面直接,关掉,这个服务也就关掉了... 因此我把整个cmd嵌入在这form或者panel上,不允许它关闭。 如果在外部执行,很容易被客户操作而叉掉,且多一个界面也不好看,所以,我就想着直接嵌入在程序的某个panel上,这个panel放在pagecontrol的某个页面里。 这样子好控制,我也可以隐藏它,也可以让管理员登录进去看到运行的样子。
----------------------------------------------
-
作者:
2017/6/7 18:05:42
6楼:
现在的问题,能用启动一个进程去启动cmd,网上很多类似这样的代码。 但是唯一的问题是,找不到cmd窗口的句柄,导致无法嵌入在panel或者form上... 谢谢各位
----------------------------------------------
-
作者:
2017/6/7 18:11:49
7楼:
win 下面那么多服务,没见过,关了 cmd 程序就退的。 但是 控制台程序 有各种特点,这种就不是服务了。 控制台程序 如果只有 输出,没有输入,就完全可以用 WinExec 启动,然后隐藏,不显示。 如果需要输入,就必须用 命名管道 。
----------------------------------------------
(C)(P)Flying Wang
作者:
2017/6/7 21:08:59
9楼:
兰州要搞清楚一个概念,cmd只是一个虚拟机。你把他理解成一个容器就可以了。 不知道你所谓的通过cmd启动和停止是什么意思。。但是只要你知道服务名就可以直接用api去控制他。 而且服务程序本身和你当前登录的账户不是在同一个session上的。低版本的系统可能没有感觉,但是高版本的系统里限制很大的。这个和cmd没什么关系。也不可能关闭cmd就停止服务了。
----------------------------------------------
--
作者:
2017/6/8 8:33:13
10楼:
楼上各位,其实楼主所谓的服务,并不是windows服务。是个dos进程而已。
----------------------------------------------
-
作者:
2017/6/8 8:44:03
11楼:
好吧,我说错了,不是服务,是类似服务的一个进程。 wk_knife 说得对,我没有描述好,是dos的一个进程,关掉窗口进程也就关掉了。 所以,wang_80919 大侠说的解决方案是可行,但是感觉不直观。 我上面聊到过,我还是希望有个cmd的界面嵌入在我的系统里,这样更直观 如果隐藏在后台,虽然可以到达目的,但是不那么直接地给使用者感受了 其实现在的问题就是,如何将这个cmd的进程界面嵌入到我的系统一个form上而已。 至于原因,我想还是不要深究了吧。
----------------------------------------------
-
作者:
2017/6/8 9:09:54
12楼:
那不需要去嵌入那个窗口. 前面说了, cmd只是一个容器, 而你的那个进程实际只是一个控制台的程序而已吧. 控制台无所谓的, 直接用createprocess去启动和关闭. 如果你一定要获取输出信息或者需要输入信息的话, 用管道通信就可以了. 当然只是给你一个建议而已, 因为如果你把别的程序嵌入到你自己的窗口中, 到时候你会发现需要处理的细节更多. 至于怎么去把控制台嵌入到你的程序里, 也简单, 同样是用cmd做宿主启动你要启动的进程, 然后用getconsole还是getconsolewindow这个函数去获取当前控制台窗口的句柄就可以嵌入了.
----------------------------------------------
--
作者:
2017/6/8 9:17:58
12楼:
命名管道 说了多少遍了,爱信不信。
----------------------------------------------
(C)(P)Flying Wang
作者:
2017/6/8 9:46:33
13楼:
好的,多谢大侠们的教导。
----------------------------------------------
-
作者:
2017/6/8 10:17:21
14楼:
10多年前就做过,貌似就是用的命名管道。
----------------------------------------------
-
作者:
dorry (littlecat)
★☆☆☆☆
-
盒子活跃会员
2017/6/8 10:34:41
14楼:
程序代码如下,已经在使用。 使用方法: AProgram := 'cmd /K Dir D:'; // using /K for keeping console alive RunAppInPanel(AProgram,Panel1.Handle,FHWD); ---------- type // 存储窗体信息 PProcessWindow = ^TProcessWindow; TProcessWindow = record ProcessID: Cardinal; FoundWindow: hWnd; end; // 窗体枚举函数 function EnumWindowsProc(Wnd: HWND; ProcWndInfo: PProcessWindow): BOOL; stdcall; var WndProcessID: Cardinal; begin GetWindowThreadProcessId(Wnd, @WndProcessID); if WndProcessID = ProcWndInfo^.ProcessID then begin ProcWndInfo^.FoundWindow := Wnd; Result := False; // 已找到,故停止 EnumWindows end else Result := True; // 继续查找 end; // 由 ProcessID 查找窗体 Handle function GetProcessWindow(ProcessID: Cardinal): HWND; var ProcWndInfo: TProcessWindow; begin ProcWndInfo.ProcessID := ProcessID; ProcWndInfo.FoundWindow := 0; EnumWindows(@EnumWindowsProc, Integer(@ProcWndInfo)); // 查找窗体 Result := ProcWndInfo.FoundWindow; end; function RunAppInPanel(const AppFileName: string; ParentHandle: HWND; var WinHandle: HWND): Boolean; var si: STARTUPINFO; pi: TProcessInformation; begin Result := False; // 启动进程 FillChar(si, SizeOf(si), 0); FillChar(pi, SizeOf(pi), 0); si.cb := SizeOf(TStartupInfo); si.dwFlags := STARTF_USESHOWWINDOW; si.wShowWindow :=SW_HIDE;// SW_SHOWNORMAL; if not CreateProcess(nil, PChar(AppFileName), nil, nil, true, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, nil, si, pi) then Exit; try // 等待进程启动 WaitForInputIdle(pi.hProcess, 10000); Sleep(200); // 取得进程的 Handle WinHandle := GetProcessWindow(pi.dwProcessID); if WinHandle > 0 then begin // 设定父窗体 Windows.SetParent(WinHandle, ParentHandle); ShowWindow(WinHandle, SW_MAXIMIZE); // 设定窗体位置 SetWindowPos(WinHandle, 0, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOZORDER); // 去掉标题栏 SetWindowLong(WinHandle, GWL_STYLE, GetWindowLong(WinHandle, GWL_STYLE) and (not WS_CAPTION) and ( WS_BORDER) and (not WS_THICKFRAME)); Result := True; end; finally // 释放 Handle CloseHandle(pi.hProcess); CloseHandle(pi.hThread); end; end;
----------------------------------------------
泱泱华夏十亿兵,国耻期待儿孙平,愿提十万虎狼旅,跃马扬刀灭东京!
作者:
dorry (littlecat)
★☆☆☆☆
-
盒子活跃会员
2017/6/8 10:35:49
15楼:
// 退出时向内嵌程序发关闭消息 if FHWD > 0 then PostMessage(FHWD, WM_CLOSE, 0, 0);
----------------------------------------------
泱泱华夏十亿兵,国耻期待儿孙平,愿提十万虎狼旅,跃马扬刀灭东京!
作者:
joypan (joypan)
★☆☆☆☆
-
盒子活跃会员
2017/6/8 10:54:18
16楼:
请教大家一下,怎么把ffplay打开的视频窗口嵌入到窗口的panel里面?
----------------------------------------------
-
作者:
2017/6/9 9:07:14
17楼:
用一个Memo模拟就行了,用管道把输入输出反映到Memo上就行了
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2017/6/15 15:24:11
18楼:
delphi cmd(4个例子都是通过管道取得) http://www.cnblogs.com/findumars/p/5338766.html function RunDosCommand(Command: string): string; function RunCommand(const cmd: string): string; procedure CmdExecAndView(FileName: string; memo: TMemo);
----------------------------------------------
-