?? tut21.html
字號:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.51 [en] (Win95; I) [Netscape]">
<title>Iczelion's Win32 Assembly Tutorial 21: Pipe</title>
</head>
<body text="#C0C0C0" bgcolor="#000000" link="#FFFF68" vlink="#00008B" alink="#FF0000">
<center>
<h1>
<font face="Arial"><font color="#006600">Tutorial 21: Pipe</font></font></h1></center>
<font face="Arial"><font size=-1>In this tutorial, we will explore pipe,
what it is and what we can use it for. To make it more interesting, I throw
in the technique on how to change the background and text color of an edit
control.</font></font>
<br><font face="Arial"><font size=-1>Download the example <a href="files/tut21.zip" STYLE="text-decoration:none">here</a>.</font></font>
<h3>
<font face="Arial"><font size=+0>Theory:</font></font></h3>
<font face="Arial"><font size=-1>Pipe is a communication conduit or pathway
with two ends. You can use pipe to exchange the data between two different
processes, or within the same process. It's like a walkie-talkie. You give
the other party one set and he can use it to communicate with you.</font></font>
<br><font face="Arial"><font size=-1>There are two types of pipes: anonymous
and named pipes. Anonymous pipe is, well, anonymous: that is, you can use
it without knowing its name. A named pipe is the opposite: you have to
know its name before you can use it.</font></font>
<br><font face="Arial"><font size=-1>You can also categorize pipes according
to its property: one-way or two-way. In a one-way pipe, the data can flow
only in one direction: from one end to the other. While in a two-way pipe,
the data can be exchanged between both ends.</font></font>
<br><font face="Arial"><font size=-1>An anonymous pipe is always one-way
while a named pipe can be one-way or two-way. A named pipe is usually used
in a network environment where a server can connect to several clients.</font></font>
<br><font face="Arial"><font size=-1>In this tutorial, we will examine
anonymous pipe in some detail. Anonymous pipe's main purpose is to be used
as a communcation pathway between a parent and child processes or between
child processes.</font></font>
<br><font face="Arial"><font size=-1>Anonymous pipe is really useful when
you deal with a console application. A console application is a kind of
win32 program which uses a console for its input & output. A console
is like a DOS box. However, a console application is a fully 32-bit program.
It can use any GUI function, the same as other GUI programs. It just happens
to have a console for its use.</font></font>
<br><font face="Arial"><font size=-1>A console application has three handles
it can use for its input & output. They are called standard handles.
There are three of them: standard input, standard output and standard error.
Standard input handle is used to read/retrieve the information from the
console and standard output handle is used to output/print the information
to the console. Standard error handle is used to report error condition
since its output cannot be redirected.</font></font>
<br><font face="Arial"><font size=-1>A console application can retrieve
those three standard handles by calling GetStdHandle function, specifying
the handle it wants to obtain. A GUI application doesn't have a console.
If you call GetStdHandle, it will return error. If you really want to use
a console, you can call AllocConsole to allocate a new console. However,
don't forget to call FreeConsole when you're done with the console.</font></font>
<br><font face="Arial"><font size=-1>Anonymous pipe is most frequently
used to redirect input and/or output of a child console application. The
parent process may be a console or a GUI application but the child must
be a console app. for this to work. As you know, a console application
uses standard handles for its input and output. If we want to redirect
the input and/or output of a console application, we can replace the handle
with a handle to one end of a pipe. A console application will not know
that it's using a handle to one end of a pipe. It'll use it as a standard
handle. This is a kind of polymorphism, in OOP jargon. This approach is
powerful since we need not modify the child process in anyway.</font></font>
<br><font face="Arial"><font size=-1>Another thing you should know about
a console application is where it gets those standard handles from. When
a console application is created, the parent process has two choices: it
can create a new console for the child or it can let the child inherit
its own console. For the second approach to work, the parent process must
be a console application or if it's a GUI application, it must call AllocConsole
first to allocate a console.</font></font>
<br><font face="Arial"><font size=-1>Let's begin the work. In order to
create an anonymous pipe you need to call <font color="#FFFF00">CreatePipe</font>.
CreatePipe has the following prototype:</font></font>
<blockquote><b><font face="Arial"><font color="#C0C0C0"><font size=-1>CreatePipe
proto pReadHandle:DWORD, \</font></font></font></b>
<br><b><font face="Arial"><font color="#C0C0C0"><font size=-1>
pWriteHandle:DWORD,\</font></font></font></b>
<br><b><font face="Arial"><font color="#C0C0C0"><font size=-1>
pPipeAttributes:DWORD,\</font></font></font></b>
<br><b><font face="Arial"><font color="#C0C0C0"><font size=-1>
nBufferSize:DWORD</font></font></font></b></blockquote>
<ul>
<li>
<font face="Arial"><font size=-1><font color="#FFFF00">pReadHandle</font>
is a pointer to a dword variable that will receive the handle to the read
end of the pipe</font></font></li>
<li>
<font face="Arial"><font size=-1><font color="#FFFF00">pWriteHandle</font>
is a pointer to a dword variable that will receive the handle to the write
end of the pipe.</font></font></li>
<li>
<font face="Arial"><font size=-1><font color="#FFFF00">pPipeAttributes</font>
points to a SECURITY_ATTRIBUTES structure that determines whether the returned
read & write handles are inheritable by child processes</font></font></li>
<li>
<font face="Arial"><font size=-1><font color="#FFFF00">nBufferSize </font>is
the suggested size of the buffer the pipe will reserve for use. This is
a suggested size only. You can use NULL to tell the function to use the
default size.</font></font></li>
</ul>
<font face="Arial"><font size=-1>If the call is successful, the return
value is nonzero. If it failed, the return value is zero.</font></font>
<br><font face="Arial"><font size=-1>After the call is successful, you
will get two handles, one to read end of the pipe and the other to the
write end. Now I will outline the steps needed for redirecting the standard
output of a child console program to your own process.Note that my method
differs from the one in Borland's win32 api reference. The method in win32
api reference assumes the parent process is a console application and thus
the child can inherit the standard handles from it. But most of the time,
we will need to redirect output from a console application to a GUI one.</font></font>
<ol>
<li>
<font face="Arial"><font size=-1>Create an anonymous pipe with CreatePipe.
Don't forget to set the bInheritable member of SECURITY_ATTRIBUTES to TRUE
so the handles are inheritable.</font></font></li>
<li>
<font face="Arial"><font size=-1>Now we must prepare the parameters we
will pass to CreateProcess since we will use it to load the child console
application. One important structure is the STARTUPINFO structure. This
structure determines the appearance of the main window of the child process
when it first appears. This structure is vital to our purpose. You can
hide the main window and pass the pipe handle to the child console process
with it. Below is the members you must fill:</font></font></li>
<ul>
<li>
<font face="Arial"><font size=-1>cb : the size of STARTUPINFO structure</font></font></li>
<li>
<font face="Arial"><font size=-1>dwFlags : the binary bit flags that determine
which members of the structure are valid also it governs the show/hide
state of the main window. For our purpose, you should use a combination
of STARTF_USESHOWWINDOW and STARTF_USESTDHANDLES</font></font></li>
<li>
<font face="Arial"><font size=-1>hStdOutput and hStdError : the handles
you want the child process to use as standard output/error handles. For
our purpose, we will pass write handle of the pipe as the standard output
and error of the child. So when the child outputs something to the standard
output/error, it actually passes the info via the pipe to the parent process.</font></font></li>
<li>
<font face="Arial"><font size=-1>wShowWindow governs the show/hide state
of the main window. For our purpose, we don't want the console window of
the child to show so we put SW_HIDE into this member.</font></font></li>
</ul>
<li>
<font face="Arial"><font size=-1>Call CreateProcess to load the child application.
After CreateProcess is successful, the child is still dormant. It is loaded
into memory but it doesn't run immediately</font></font></li>
<li>
<font face="Arial"><font size=-1>Close the write pipe handle. This is necessary.
Because the parent process has no use for the write pipe handle, and the
pipe won't work if there are more than one write end, we MUST close it
before reading the data from the pipe. However, don't close the write handle
before calling CreateProcess, your pipe will be broken. You should close
it just after CreateProcess returns and before you read data from the read
end of the pipe.</font></font></li>
<li>
<font face="Arial"><font size=-1>Now you can read data from the read end
of the pipe with ReadFile. With ReadFile, you kick the child process into
running mode. It will start execution and when it writes something to the
standard output handle (which is actually the handle to the write end of
the pipe), the data are sent through the pipe to the read end. You can
think of ReadFile as sucking data from the read end of the pipe. You must
call ReadFile repeatedly until it returns 0 which means there are no more
data to be read. You can do anything with the data you read from the pipe.
In our example, I put them into an edit control.</font></font></li>
<li>
<font face="Arial"><font size=-1>Close the read pipe handle.</font></font></li>
</ol>
<h3>
<font face="Arial"><font size=+0>Example:</font></font></h3>
<blockquote><b><font face="Arial"><font color="#999900"><font size=-1>.386</font></font></font></b>
<br><b><font face="Arial"><font color="#999900"><font size=-1>.model flat,stdcall</font></font></font></b>
<br><b><font face="Arial"><font color="#999900"><font size=-1>option casemap:none</font></font></font></b>
<br><b><font face="Arial"><font color="#999900"><font size=-1>include \masm32\include\windows.inc</font></font></font></b>
<br><b><font face="Arial"><font color="#999900"><font size=-1>include \masm32\include\user32.inc</font></font></font></b>
<br><b><font face="Arial"><font color="#999900"><font size=-1>include \masm32\include\kernel32.inc</font></font></font></b>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -