認識控制臺-控制臺句柄、附著到控制臺、關閉控制臺
附著到一個控制臺
一個進程可以使用 AttachConsole 函數來附著到一個控制臺上,一個進程只能附著一個控制臺。
一個控制臺可以有許多進程附著到它上面,調用 GetConsoleProcessList 函數可以得到附著到一個控制臺的列表。
關閉一個控制臺
進程可以使用 FreeConsole 函數來將其自身從一個控制臺脫離出來。如果其他進程共享這個控制臺,控制臺不會被銷毀,但調用 FreeConsole 函數的進程不能在使用它了,在進程調用 FreeConsole 之后,它可以使用 AllocConsole 來創建一個新的控制臺或 AttachConsole 來附著到另一個控制臺上。
控制在最后一個附著的進程關閉的時候或調用 FreeConsole 的時候被關閉。
控制臺句柄
控制臺進程使用句柄來訪問控制臺的輸入和屏幕緩沖區。一個進程可以使用 GetStdHandle 、 CreateFile 或 CreateConsoleScreenBuffer 函數來打開這些句柄。
GetStdHandle 函數提供一個獲得進程相關的標準輸入( STDIN )、標準輸出( STDOUT )和標準錯誤( STDERR )句柄。在控制臺創建過程中,系統創建這些句柄。最初的 STDIN 是一個指向控制臺輸入緩沖區的句柄, STDOUT 和 STDERR 是控制臺活動屏幕緩沖區的句柄。然而, SetStdHandle 函數可以改變 STDIN 、 STDOUT 、 STDERR 關聯的句柄來重定向標準句柄。因為父進程的標準句柄可以被子進程繼承,后面調用 GetStdHandle 函數返回的是重定向的句柄。 GetStdHandle 返回的句柄可以指向其他的句柄不一定是控制臺 I/O 。例如,在創建子進程之前,父親進程使用 SetStdHandle 來將 STDIN 設置為一個管道句柄,那么這個特性會被子進程繼承。當子進程調用 GetStdHandle 的時候返回的是管道句柄。這意味著父親進程能控制子進程的標準句柄, GetStdHandle 返回的句柄有 GENERIC_READ|GENERIC_WRITE 訪問權限,當然如果在 SetStdHandle 的時候設置較少的訪問權限另外說。
GetStdHandle 返回的句柄值不是 0 , 1 , 2 ,因此在 Stdio.h ( STDIN , STDOUT 和 STDERR )中預定義的流常量不能在需要一個控制臺句柄的函數中使用。
CreateFile
函數即使
STDIN
和
STDOUT
沒有被重定向的情況下,也可以讓一個進程得到輸入緩沖區和活動屏幕緩沖區的句柄。為了打開一個控制臺輸入緩沖區的句柄,需要在調用
CreateFile
的時候指定
CONIN$
值,而指定
CONOUT$
值可以打開一個控制臺活動屏幕緩沖區的句柄。
CreateFile
函數使你可以通過它返回的句柄來讀寫操作。
函數
CreateConsoleScreenBuffer
創建一個新的屏幕緩沖區且返回這個句柄,這個句柄可以在所有接受一個控制輸出作為參數的函數中使用。新的屏幕緩沖區不會是活動的,只有調用
SetConsoleActiveScreenBuffer
函數的時候指定該值才會被設置為活動的。活動屏幕緩沖區的改變不會改變
GetStdHandle
的值,同樣使用
SetStdHandle
改變
STDOUT
句柄也不會影響活動屏幕緩沖區。
CreateFile
和
CreateConsoleScreenBuffer
函數返回的句柄能在任何需要控制臺輸入緩沖區或控制臺屏幕緩沖區作為參數的函數中,
GetStdHandle
返回的句柄只要沒有被重定向為其他的句柄都可以在控制臺函數中使用,如果標準句柄被重定向為指向一個文件或管道,這些句柄只能被
ReadFile
和
WriteFile
函數使用。