开仓放粮了: delphi在命令行执行命令时的2个问题?

本文解答了在Delphi中如何等待命令行命令执行完成及如何捕获并处理命令执行时产生的错误。提供了使用WaitForSingleObject等待命令完成的方法,并介绍了通过重定向标准输出和错误输出来捕获命令行错误的具体实现。
开仓放粮了: delphi在命令行执行命令时的2个问题? Delphi / Windows SDK/API
http://www.delphi2007.net/DelphiAPI/html/delphi_20061120203959190.html
1:   怎么等待命令执行完后再执行下面的语句  
  2:   怎么捕获命令产生的错误,并提示出来?

第2个问题值150分啊

1   用WaitForSingleObject  
   
  2   var   a:TStringList;  
  begin  
          a:=TStringList.Create;  
            try  
                  a.LoadFromFile('123.txt');   //不存在这个文件  
                except  
                        on     E:     Exception     do  
                              Showmessage('出错:'     +     E.message);  
                        a.Free  
                end;  
  end;

用WaitForSingleObject可行。。

try    
   
  except  
      on   e:   exception   do  
          showmessage(e.message)  
  end;      
   
  这种方法是可行的  
   
  还有一种办法在你程序的界面放一个ApplicationEvents   这个控件    
   
  在它的Exception事件里写代码  
   
  procedure   Tfrmo1.ApplicationEvents1Exception(Sender:   TObject;  
      E:   Exception);  
   
  Sender就是你的对象   而Exception就是异常

第一个问题用sleep(1000)   就可以解决了吧~~~    
   
 

可参考下<delphi源代码分析>  
 

1.用WaitForSingleObject  
  procedure   TForm1.Button1Click(Sender:   TObject);  
  var  
      MutexHandle:THandle;  
  begin  
      WaitForSingleObject(MutexHandle,INFINITE);  
      //do   your   code  
      CloseHandle(MutexHandle);  
  end;  
   
   
  2.var    
          List:TStringList;  
      begin  
          List:=TStringList.Create;  
            try  
                  //do   something   error  
                except  
                        on     E:     Exception     do  
                              Showmessage(E.message);  
                        a.Free  
                end;  
  end;  
   
 

JF。。.

第2个问题用debug  
  有错的话就debug

抢分!

JF。。。。

路过。

jf

1   用WaitForSingleObject  
   
  2   try  
                except  
                        on     E:     Exception

大家怎么不看楼主是几个星星的~~~  
    try    
     
    except  
   
  他会不知道〉?

如果楼主的命令是指DOS命令行的话,   则必须使用  
  CreateProcess   建议命令进程  
  然后使用Wait函数(如:   WaitForSingleObject)   等待进程的Handle  
 

接粮

接粮

再接粮

接分  
 

第1个问题:  
  function   WinExecAndWait32(  
      FileName:   string;   Visibility:   integer):   integer;  
  var  
      zAppName:   array[0..512]   of   char;  
      zCurDir:   array[0..255]   of   char;  
      WorkDir:   string;  
      StartupInfo:   TStartupInfo;  
      ProcessInfo:   TProcessInformation;  
      ExitCode:   DWORD;  
  begin  
      StrPCopy(zAppName,   FileName);  
      GetDir(0,   WorkDir);  
      StrPCopy(zCurDir,   WorkDir);  
      FillChar(StartupInfo,   Sizeof(StartupInfo),   #0);  
      StartupInfo.cb   :=   Sizeof(StartupInfo);  
      StartupInfo.dwFlags   :=   STARTF_USESHOWWINDOW;  
      StartupInfo.wShowWindow   :=   Visibility;  
      if   not   CreateProcess(nil,   zAppName,  
          {   pointer   to   command   line   string   }  
          nil,   {   pointer   to   process   security   attributes   }  
          nil,   {   pointer   to   thread   security   attributes   }  
          false,   {   handle   inheritance   flag   }  
          CREATE_NEW_CONSOLE   or   {   creation   flags   }  
          NORMAL_PRIORITY_CLASS,  
          nil,   {   pointer   to   new   environment   block   }  
          nil,   {   pointer   to   current   directory   name   }  
          StartupInfo,   {   pointer   to   STARTUPINFO   }  
          ProcessInfo)   then   Result   :=   -1  
          {   pointer   to   PROCESS_INF   }  
      else   begin  
          WaitforSingleObject(ProcessInfo.hProcess,   INFINITE);  
          GetExitCodeProcess(ProcessInfo.hProcess,   ExitCode);  
          Result:=ExitCode;  
      end;  
  end;  
   
  第2个没试过

procedure   CaptureConsoleOutput(DosApp   :   string;AMemo   :   TMemo);  
  const  
      ReadBuffer   =   1048576;     //   1   MB   Buffer  
  var  
      Security                         :   TSecurityAttributes;  
      ReadPipe,WritePipe     :   THandle;  
      start                               :   TStartUpInfo;  
      ProcessInfo                   :   TProcessInformation;  
      Buffer                             :   Pchar;  
      TotalBytesRead,  
      BytesRead                       :   DWORD;  
      Apprunning,n,  
      BytesLeftThisMessage,  
      TotalBytesAvail   :   integer;  
  begin  
      with   Security   do  
      begin  
          nlength                             :=   SizeOf(TSecurityAttributes);  
          binherithandle               :=   true;  
          lpsecuritydescriptor   :=   nil;  
      end;  
   
      if   CreatePipe   (ReadPipe,   WritePipe,   @Security,   0)   then  
      begin  
          //   Redirect   In-   and   Output   through   STARTUPINFO   structure  
   
          Buffer     :=   AllocMem(ReadBuffer   +   1);  
          FillChar(Start,Sizeof(Start),#0);  
          start.cb                     :=   SizeOf(start);  
          start.hStdOutput     :=   WritePipe;  
          start.hStdInput       :=   ReadPipe;  
          start.dwFlags           :=   STARTF_USESTDHANDLES   +   STARTF_USESHOWWINDOW;  
          start.wShowWindow   :=   SW_HIDE;  
   
          //   Create   a   Console   Child   Process   with   redirected   input   and   output  
   
          if   CreateProcess(nil             ,PChar(DosApp),  
                                            @Security,@Security,  
                                            true           ,CREATE_NO_WINDOW   or   NORMAL_PRIORITY_CLASS,  
                                            nil             ,nil,  
                                            start         ,ProcessInfo)   then  
          begin  
              n:=0;  
              TotalBytesRead:=0;  
              repeat  
                  //   Increase   counter   to   prevent   an   endless   loop   if   the   process   is   dead  
                  Inc(n,1);  
   
                  //   wait   for   end   of   child   process  
                  Apprunning   :=   WaitForSingleObject(ProcessInfo.hProcess,100);  
                  Application.ProcessMessages;  
   
                  //   it   is   important   to   read   from   time   to   time   the   output   information  
                  //   so   that   the   pipe   is   not   blocked   by   an   overflow.   New   information  
                  //   can   be   written   from   the   console   app   to   the   pipe   only   if   there   is  
                  //   enough   buffer   space.  
   
                  if   not   PeekNamedPipe(ReadPipe                 ,@Buffer[TotalBytesRead],  
                                                            ReadBuffer             ,@BytesRead,  
                                                            @TotalBytesAvail,@BytesLeftThisMessage)   then   break  
                  else   if   BytesRead   >   0   then  
                      ReadFile(ReadPipe,Buffer[TotalBytesRead],BytesRead,BytesRead,nil);  
                  TotalBytesRead:=TotalBytesRead+BytesRead;  
              until   (Apprunning   <>   WAIT_TIMEOUT)   or   (n   >   150);  
   
              Buffer[TotalBytesRead]:=   #0;  
              OemToChar(Buffer,Buffer);  
              AMemo.Text   :=   AMemo.text   +   StrPas(Buffer);  
          end;  
          FreeMem(Buffer);  
          CloseHandle(ProcessInfo.hProcess);  
          CloseHandle(ProcessInfo.hThread);  
          CloseHandle(ReadPipe);  
          CloseHandle(WritePipe);  
      end;  
  end;  
 

 
  我来回答第二个问题。 上边回答的都是自己的程序出异常,实际中,你在调用外部程序发生异常后出错时,一般的程序都会将错误输出到标准错误(STDERR),所以,你只要能读到他的STDERR或STDOUT(标准输出)就行了.    
   
  读取方法:  
  1.象楼上那样,用一个命名管道    
  2.有一个控件的,名字不记得了....  
  3.加上命令行参数,将标准输出和错误输出存到文件中....如下:  
   
  mCommand   :=   "test.exe   >a.txt   2>b.txt";  
  winexec(mCommand);  
   
  这样在执行过后,标准输出就写入了   a.txt,   错误输出就写入了b.txt    
   
  不一定能帮上你的忙,只是提供一个思路.

<think>我们正在处理关于Git命令历史的问题。用户想知道如何查看在某个代码仓库中执行过的Git命令历史。 根据引用[2]中提到,有一个命令`git reflog`可以查看命令历史。但是,请注意,`git reflog`通常用于查看本地仓库的引用日志(例如分支的提交历史),而不是直接记录用户在终端中执行的所有命令。 然而,用户的问题是关于“执行过的git命令历史”,这实际上有两种理解: 1. 用户想要查看在这个仓库中执行过的所有Git命令(即用户在终端中键入的命令历史)。 2. 用户想要查看Git仓库的操作历史(如引用日志,记录的是HEAD和分支的变更历史)。 对于第一种情况(终端命令历史),这通常是由用户的shell(如bash)维护的,而不是Git。因此,我们可以通过查看shell的历史记录来获取,例如使用`history`命令,或者查看用户主目录下的`.bash_history`文件(对于bash)。但是,这并不局限于某个特定的仓库,而是全局的。 对于第二种情况(Git仓库的操作历史),我们可以使用`git reflog`来查看仓库中的引用变更历史,例如提交、重置、合并等操作。但是,这并不记录所有的git命令,只记录那些改变了引用的操作(如HEAD、分支等)。 因此,我们需要澄清用户的需求。但是,根据问题描述,用户指定了“某个代码仓”,所以可能是第二种情况。另外,引用[2]中明确提到了`git reflog`用于查看命令历史(虽然这里可能指的是Git操作的内部命令历史)。 但是,我们注意到引用[2]中是这样写的: 查看命令历史:git reflog 所以,我们可以这样回答: 在Git中,可以使用`git reflog`命令来查看本地仓库的操作历史记录。它记录了分支的切换、提交、重置等操作。但是,它并不记录所有的Git命令(例如`git status`就不会被记录)。 如果用户想要查看在终端中执行的所有命令(包括Git命令和其他命令),那么需要使用shell的历史记录功能。例如,在bash中,可以使用`history`命令,或者查看`~/.bash_history`文件。但是,这个历史记录是全局的,并不针对特定仓库。 因此,我们分两种情况回答: 1. 查看Git仓库的操作历史(如提交、重置、合并等): ```bash git reflog ``` 2. 查看在终端中执行过的所有命令(包括git命令): ```bash history ``` 或者,为了查找特定仓库目录下执行过的命令,可以在仓库目录下执行: ```bash history | grep git ``` 但这只能显示当前终端会话中执行过的命令(如果使用多个终端,可能不完整)。更完整的方法是查看shell的历史记录文件,但需要知道该仓库路径下执行的命令,可能需要自己过滤。 另外,需要注意的是,`git reflog`只针对当前仓库,而`history`是全局的。 考虑到用户的问题是在Git仓库中执行过的Git命令历史,我们重点在Git提供的记录上。但是,Git本身并不记录用户执行的每一个命令,所以`git reflog`只能提供部分信息。 还有一种方法是使用Git的审计日志功能,但这需要事先配置。默认情况下,Git不会记录每个命令的执行。 因此,我们给出以下回答: 在Git中,可以通过以下方式查看命令历史: - **`git reflog`**: 显示本地仓库的引用日志,包括HEAD和分支的更改(如提交、重置、合并等)。它可以帮助你恢复丢失的提交或分支。 示例: ```bash $ git reflog e0a1b5c (HEAD -> main) HEAD@{0}: commit: Update README 3d4f2a1 HEAD@{1}: checkout: moving from feature to main ``` - **`history`命令(Shell内置)**: 查看当前用户在终端中执行的所有命令历史。你可以通过管道过滤出git命令: ```bash $ history | grep git ``` 但是,`history`命令依赖于Shell,且记录的是全局命令历史。如果你想要查看特定仓库目录下执行过的命令,你可能需要在该目录下执行命令,Shell才会记录(但不会自动标记目录)。 另外,如果你想要更详细的Git操作日志,可以考虑开启Git的审计功能(需要配置),但这不是默认开启的。 因此,对于大多数情况,`git reflog`可以满足查看仓库重要操作历史的需求,而`history`可以查看用户执行过的所有命令(包括Git命令)。 根据引用[2]中提到的,我们还可以看到`git log`系列命令用于查看提交历史,但提交历史并不等同于命令历史。 所以,我们总结如下: 要查看在某个Git仓库中执行过的Git命令历史,最直接的方式是使用`git reflog`查看仓库的操作记录,或者使用Shell的`history`命令查看全局命令历史(并过滤出git命令)。 相关问题: 1. `git reflog`和`git log`有什么区别? 2. 如何配置Git以记录详细的命令执行历史? 3. 如何从`git reflog`中恢复丢失的提交? 4. 如何清除`git reflog`记录? 5. 如何永久保存Shell命令历史并按照目录分类? 注意:在回答中,我们引用了引用[2]中关于`git reflog`的说明。</think>### 如何查看 Git 仓库中执行过的命令历史 在 Git 中查看命令历史主要涉及两种场景,具体方法如下: #### 1. **查看全局终端命令历史(所有命令)** - 使用 Shell 内置的 `history` 命令可查看当前用户的所有终端命令历史(包括 Git 命令): ```bash history ``` - 配合 `grep` 过滤出 Git 命令: ```bash history | grep "git " ``` - **注意**: 此方法记录的是**整个系统的命令历史**,不局限于特定仓库。历史记录保存在 `~/.bash_history`(Bash)或 `~/.zsh_history`(Zsh)中。 #### 2. **查看 Git 仓库操作历史(推荐)** - **`git reflog`**: 记录本地仓库的**引用变更历史**(如提交、重置、分支切换等操作),这是最接近"命令历史"的 Git 原生记录: ```bash git reflog ``` 输出示例: ``` e0a1b5c (HEAD -> main) HEAD@{0}: commit: Update README 3d4f2a1 HEAD@{1}: checkout: moving from feature to main ``` - 每行包含操作类型、提交哈希、分支状态和操作描述[^2]。 - **`git log`**: 查看**提交历史**(仅记录提交操作): ```bash git log --oneline # 简洁模式 git log --graph # 显示分支合并拓扑[^2] ``` --- ### 关键区别说明 | **方法** | **范围** | **记录内容** | **是否仓库专属** | |----------------|----------------|----------------------------------|------------------| | `history` | 全局系统 | 所有终端命令(含 `git`) | ❌ | | `git reflog` | 当前本地仓库 | 引用变更操作(提交、重置、切换等) | ✅ | | `git log` | 当前本地仓库 | 提交记录 | ✅ | --- ### 应用场景建议 - ✅ **恢复误操作**: 用 `git reflog` 找到操作前的提交哈希,通过 `git reset --hard <hash>` 恢复[^2]。 - ✅ **审计仓库变更**: 结合 `git log --graph` 查看分支演进过程[^3]。 - ❌ **精确命令记录**: Git 不原生存储完整的命令行历史,需依赖 Shell 的 `history`。 --- ### 相关问题 1. `git reflog` 和 `git log` 的输出有何本质区别? 2. 如何利用 `git reflog` 恢复被误删的分支或提交? 3. Shell 的 `history` 命令默认保存多少条记录?如何修改上限? 4. 为什么 `git status` 这类只读操作不会出现在 `git reflog` 中? 5. 如何将特定 Git 仓库的操作历史导出为文件? [^1]: 子仓库更新需通过 `git subtree pull` 实现,但操作记录仍由 `git reflog` 跟踪。 [^2]: `git reflog` 是 Git 引用日志,记录了所有分支和 HEAD 的变更历史。 [^3]: `git log --graph` 可可视化分支合并关系,帮助理解仓库演进。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值