GVKun编程网logo

使用py2exe隐藏Python GUI应用程序的控制台窗口(py2exe隐藏命令行)

10

在这篇文章中,我们将为您详细介绍使用py2exe隐藏PythonGUI应用程序的控制台窗口的内容,并且讨论关于py2exe隐藏命令行的相关问题。此外,我们还会涉及一些关于.net–双击时,是否可以构建

在这篇文章中,我们将为您详细介绍使用py2exe隐藏Python GUI应用程序的控制台窗口的内容,并且讨论关于py2exe隐藏命令行的相关问题。此外,我们还会涉及一些关于.net – 双击时,是否可以构建不显示控制台窗口的控制台应用程序?、delphi – 如何从我的GUI应用程序启动控制台窗口的处理?、python – 使用py2exe打包py文件时“超出最大递归深度”、Python--PyQt一个创建GUI应用程序的工具包的知识,以帮助您更全面地了解这个主题。

本文目录一览:

使用py2exe隐藏Python GUI应用程序的控制台窗口(py2exe隐藏命令行)

使用py2exe隐藏Python GUI应用程序的控制台窗口(py2exe隐藏命令行)

我有一个使用Qt的Python程序(实际上是PyQt4),当我从main.py启动它时,我得到了一个控制台窗口和GUI窗口(当然是在Windows上)。

然后,我用py2exe编译程序,并成功创建main.exe。但是,如果我运行main.exe(程序的用户将执行此操作),Python的控制台窗口仍会出现,并且我所有的调试文本都将输出到该窗口。

我想在我的应用程序运行时隐藏cmd线窗口,并且我希望从.exe文件执行时,我的GUI只对用户可见。

那可能吗?

答案1

小编典典

是的,有可能。

如果我用

setup(console=[''__main__.py''], options={"py2exe":{"includes":["sip"]}})

它创建一个控制台应用程序,但是如果我使用

setup(windows=[''__main__.py''], options={"py2exe":{"includes":["sip"]}})

它不会在.exe文件上显示控制台。但是输出将转储到.exe文件夹中的main.exe.log文件中。小心。

.net – 双击时,是否可以构建不显示控制台窗口的控制台应用程序?

.net – 双击时,是否可以构建不显示控制台窗口的控制台应用程序?

Related:
07000
07001
07002

我想构建一个控制台应用程序,这通常是从命令行运行的。

但是,当从资源管理器中双击(而不是从cmd.exe提示符运行)时,我希望该程序不显示控制台窗口。

我想避免这个:

alt text http://i36.tinypic.com/1088p5s.jpg

可能吗?

编辑我猜另一种方式来问,是否可以让程序知道如何被调用 – 无论是通过双击还是通过命令行?

我在.NET上工作,在Windows上。

编辑2:从this Old New Thing blog post我学到了一些好东西。这是我现在所知道的

在Windows中,EXE文件被标记为GUI或非GUI。使用csc.exe,这是使用/ target:winexe或/ target:exe选择的。在执行该过程的第一条指令之前,Windows内核将设置执行环境。那个时候,如果EXE被标记为GUI,那么内核将进程的stdin / stdout设置为NULL,如果非GUI(命令行),内核创建一个控制台,并将进程的stdin / stdout设置为安慰。

启动该过程时,如果没有stdin / stdout(== / target:winexe),则立即返回。所以,从cmd.exe启动一个gui应用程序,您将立即将您的cmd提示回来。如果有一个stdin / stdout,如果从cmd.exe运行,那么父cmd.exe等待进程退出。

“立即返回”很重要,因为如果您编写一个GUI应用程序来附加到其父级控制台,则可以执行console.writeline等。但是cmd.exe提示符是活动的。用户可以键入新的命令,开始一个新的进程,等等。换句话说,从winexe,只需使用AttachConsole(-1)附加到父控制台就不会将其“变成”一个控制台应用程序。

在这一点上,我认为允许应用程序使用控制台(如果从cmd.exe调用)的唯一方法,如果双击,则不使用它,是将exe定义为常规控制台exe(/ target: exe),并在启动时隐藏窗口(如果适用)。你仍然会看到一个控制台窗口短暂出现。

我还没有想到如何知道是从explorer还是cmd.exe启动,但是我越来越近了

解答

不可能构建不显示控制台窗口的控制台应用程序。

可以构建一个非常快速隐藏其窗口的控制台应用程序,但不会如此快,因为窗口不会出现。

现在,要确定是否从资源管理器启动了控制台应用程序,有些建议您查看正在运行的控制台
(mgb’s answer和KB article 99115):

int left = Console.CursorLeft;
  int top = Console.CursorTop;
  bool ProcessWasRunFromExplorer = (left==0 && top==0);

这将告诉您进程是否在其自己的控制台中启动,而不是它是否是explorer。浏览器中的双击将会执行此操作,但是来自应用程序中的Start.Process()也将执行相同的操作。

如果要以不同的方式对待这些情况,请使用此方法来了解父进程的名称:

System.Console.WriteLine("Process id: {0}",Process.GetCurrentProcess().Id);
  string name = Process.GetCurrentProcess().ProcessName ;
  System.Console.WriteLine("Process name: {0}",name);
  PerformanceCounter pc = new PerformanceCounter("Process","Creating Process Id",name);
  Process p = Process.GetProcessById((int)pc.RawValue);
  System.Console.WriteLine("Parent Process id: {0}",p.Id);
  System.Console.WriteLine("Parent Process name: {0}",p.ProcessName);

  // p.ProcessName == "cmd" or "Explorer" etc

要在进程启动后快速隐藏窗口,请使用以下命令:

private static readonly int SW_HIDE= 0;

  [System.Runtime.InteropServices.DllImport("user32.dll")]
  private static extern Boolean ShowWindow(IntPtr hWnd,Int32 nCmdshow);

  ....
  {
    IntPtr myHandle = Process.GetCurrentProcess().MainWindowHandle;
    ShowWindow(myHandle,SW_HIDE);
  }

如果您生产winexe(WinForms应用程序),并且可选地在AttachConsole(-1)的情况下附加到父控制台,则不会得到相应的常规控制台应用程序。对于winexe,父进程(如cmd.exe)将在启动GUI应用程序后立即返回到命令提示符。换句话说,命令提示符处于活动状态并准备好进行输入,而刚刚启动的进程可能会发出输出。这是令人困惑的,可能仅适用于调试winforms应用程序。

这对我有用

见 Can a Win32 console application detect if it has been run from the explorer or not?

或者我认为官方的方法是检查父进程是cmd.exe还是explorer.exe

delphi – 如何从我的GUI应用程序启动控制台窗口的处理?

delphi – 如何从我的GUI应用程序启动控制台窗口的处理?

在我的GUI应用程序中,我运行控制台应用程序,需要其窗口的处理.我尝试使用Enum Windows(),看下面的代码,但它不起作用.在列表中没有我的控制台应用程序
type
  TEnumWindowsData = record
    ProcessId: Cardinal;
    WinHandle: THandle;
    List: TStrings;                 // For test only
  end;
  PEnumWindowsData = ^TEnumWindowsData;

function FindWindow(hWnd: THandle; lParam: LParaM): BOOL; stdcall;
var
  ParamData: TEnumWindowsData;
  ProcessId: Cardinal;
  WinTitle: array[0..200] of Char;  // For test only
begin
  ParamData := PEnumWindowsData(lParam)^;
  GetwindowThreadProcessId(hWnd,ProcessId);
  if ProcessId <> ParamData.ProcessId then
    Result := True
  else begin
    ParamData.WinHandle := hWnd;
    Result := False;
  end;
  // For test only
  GetwindowText(hWnd,WinTitle,Length(WinTitle) - 1);
  ParamData.List.Add(IntToStr(ProcessId) + ' ' + IntToStr(hWnd) + ' ' + WinTitle);
end;

procedure TForm1.Button1Click(Sender: TObject);

  function RunApp(const AProgram: string): Cardinal;
  var
    StartupInfo: TStartupInfo;
    Processinformation: TProcessinformation;
  begin
    Result := 0;
    ...
    if CreateProcess(nil,PChar(AProgram),nil,False,norMAL_PRIORITY_CLASS,StartupInfo,Processinformation)
    then
      Result := Processinformation.dwProcessId;
    ...
  end;

var
  ParamData: TEnumWindowsData;
begin
  ParamData.ProcessId := RunApp('cmd.exe /C D:\TMP\TEST.exe');
  ParamData.WinHandle := 0;
  ParamData.List := Memo1.Lines;
  EnumWindows(@FindWindow,THandle(@ParamData));

  FWindowHandle := ParamData.WinHandle;
end;

解决方法

以下代码只是创建进程(控制台应用程序),将您的进程通过 AttachConsole功能附加到新创建的控制台,并从该连接的控制台使用 GetConsoleWindow功能使用窗口句柄.

以下代码最大的缺点是CreateProcess函数在此时立即返回,当控制台尚未完全初始化时,当您尝试立即附加控制台后,您将失败.不幸的是,没有WaitForInputIdle功能for console applications,所以作为一种可能的解决办法,我会选择尝试在一些有限的循环计数中附加控制台,一旦成功,获取句柄并分离控制台.

在代码中可能如下所示. RunApp函数应该返回控制台窗口的句柄(假设您只能运行控制台应用程序),并且应该等待大约. 1秒钟的控制台应用程序你开始可以附加.您可以通过更改尝试变量的初始值和/或更改睡眠间隔来修改此值.

function GetConsoleWindow: HWND; stdcall;
  external kernel32 name 'GetConsoleWindow';
function AttachConsole(dwProcessId: DWORD): BOOL; stdcall;
  external kernel32 name 'AttachConsole';

function RunApp(const ACmdLine: string): HWND;
var
  CmdLine: string;
  Attempt: Integer;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessinformation;
begin
  Result := 0;
  FillChar(StartupInfo,SizeOf(TStartupInfo),0);
  FillChar(ProcessInfo,SizeOf(TProcessinformation),0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_SHOWnorMAL;
  CmdLine := ACmdLine;
  UniqueString(CmdLine);
  if CreateProcess(nil,PChar(CmdLine),CREATE_NEW_CONSOLE,ProcessInfo) then
  begin
    Attempt := 100;
    while (Attempt > 0) do
    begin
      if AttachConsole(ProcessInfo.dwProcessId) then
      begin
        Result := GetConsoleWindow;
        FreeConsole;
        Break;
      end;
      Sleep(10);
      Dec(Attempt);
    end;
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);
  end;
end;

那么你可以以这种方式更改您的lauched应​​用程序的控制台窗口的标题:

procedure TForm1.Button1Click(Sender: TObject);
var
  S: string;
  ConsoleHandle: HWND;
begin
  ConsoleHandle := RunApp('cmd.exe');
  if ConsoleHandle <> 0 then
  begin
    S := 'Hello! I''m your console,how can I serve ?';
    SendTextMessage(ConsoleHandle,WM_SETTEXT,S);
  end;
end;

python – 使用py2exe打包py文件时“超出最大递归深度”

python – 使用py2exe打包py文件时“超出最大递归深度”

几个月前py2exe在同一个py文件上工作得很好.但是当我今天再次尝试它时,通过报告“RuntimeError:超出最大递归深度”失败了.结果我得到一个空的“dist”文件夹.
Py文件正常工作,它无法打包.我猜py文件中导入的模块有问题.但我无法弄明白.有人知道解决方案吗?

我的py文件的开头部分是:

import xlrd
import wx
import wx.lib.filebrowsebutton as filebrowse
from scipy.optimize import fsolve
import math
import threading
from sympy import Symbol
from sympy import solve

cmd窗口的最后几行是:

File "D:\Python27\lib\site-packages\py2exe\mf.py",line 332,in _safe_import_hook
self.import_hook(name,caller,level=level)
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 719,in import_hook
return Base.import_hook(self,name,fromlist,level)
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 137,in import_hook
m = self.load_tail(q,tail)
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 214,in load_tail
m = self.import_module(head,mname,m)
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 724,in import_module
r = Base.import_module(self,partnam,fqname,parent)
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 284,in import_module
m = self.load_module(fqname,fp,pathname,stuff)
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 730,in load_module
r = Base.load_module(self,(suffix,mode,typ))
File "D:\Python27\lib\site-packages\py2exe\mf.py",line 314,in load_module
self.scan_code(co,line 423,in scan_code
self._safe_import_hook(name,m,line 134,in import_hook
self.msg(3,"import_hook",level)
RuntimeError: maximum recursion depth exceeded

D:\Python27\py2exetemp>pause
最佳答案
我试着增加递归深度限制.在文件的开头插入:

import sys
sys.setrecursionlimit(5000)

Python--PyQt一个创建GUI应用程序的工具包

Python--PyQt一个创建GUI应用程序的工具包

Python--PyQt一个创建GUI应用程序的工具包

博客说明

文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢!

介绍

PyQt是一个创建GUI应用程序的工具包。它是Python编程语言和Qt库的成功融合。Qt库是目前最强大的库之一。PyQt是由Phil Thompson 开发

PyQt实现了一个Python模块集。它有超过300类,将近6000个函数和方法。它是一个多平台的工具包,可以运行在所有主要操作系统上,包括UNIX,Windows和Mac。 PyQt采用双许可证,开发人员可以选择GPL和商业许可。在此之前,GPL的版本只能用在Unix上,从PyQt的版本4开始,GPL许可证可用于所有支持的平台

模块

因为可用的类有很多,他们被分成几个模块。 QtCore模块包含核心的非GUI功能。该模块用于时间、文件和目录、各种数据类型、流、网址、MIME类型、线程或进程。QtGui模块包含图形组件和相关的类,例如按钮、窗体、状态栏、工具栏、滚动条、位图、颜色、字体等。QtNetwork模块包含了网络编程的类,这些类允许编写TCP/IP和UDP的客户端和服务器,他们使网络编程更简单,更轻便。QtXml包含使用XML文件的类,这个模块提供了SAX和DOM API的实现。QtSvg模块提供显示的SVG文件的类。可缩放矢量图形(SVG)是一种用于描述二维图形和图形应用程序的XML语言。QtOpenGL模块使用OpenGL库渲染3D和2D图形,该模块能够无缝集成Qt的GUI库和OpenGL库。QtSql模块提供用于数据库的类

中文文档地址

最后贴上一个地址

http://code.py40.com/pyqt5/14.html

感谢

百度百科

以及勤劳的自己

关于使用py2exe隐藏Python GUI应用程序的控制台窗口py2exe隐藏命令行的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于.net – 双击时,是否可以构建不显示控制台窗口的控制台应用程序?、delphi – 如何从我的GUI应用程序启动控制台窗口的处理?、python – 使用py2exe打包py文件时“超出最大递归深度”、Python--PyQt一个创建GUI应用程序的工具包等相关内容,可以在本站寻找。

本文标签: