Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

AttachConsole (kernel32)
 
.
Summary
Attach current process to the console of a specified process, or to the current one by default (see ATTACH_PARENT_PROCESS))

C# Signature:

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool AttachConsole(uint dwProcessId);

VB Signature:

     Declare Function AttachConsole, Lib "kernel32.dll" (dwProcessId as uint) As bool

User-Defined Types:

  • dwProcessId Values

    const uint ATTACH_PARENT_PROCESS = 0x0ffffffff;  // default value if not specifing a process ID

  • GetLastWin32Error Values

    const int ERROR_ACCESS_DENIED = 5; // process was already attached to another console

Alternative Managed API:

There might be one, but it is pretty easy and lightweight just to do it this way, in fact there are many wrapper classes out there to do this. But why when you can make your own in about 2 minutes flat?

Notes:

When running an application that is GUI from a console window, you may want to echo something to that console window (such as command line options when the user specifies /? on the command line), but also don't want a console window popping up when you don't need it (such is the behavior of a windows C# 'Console Application'). In this case these work great, and are fully compatible thereafter with the .NET Console.xxx static functions.

Remarks and Important Stuff

  • Returns True if the attachment succeeded or False if attachment failed. Use GetLastWin32Error to get the error code (see below sample).
  • dwProcessId should be uint.Max (ATTACH_PARENT_PROCESS) or the process' ID that you want to attach to (untested in .NET for me anyway)
  • Do NOT use GetLastError, use Marshal.GetLastWin32Error
  • This stuff shouldnt be needed if you are using a Console Application template
  • You can get away with not calling FreeConsole if you want it gone at termination of the program (if you want it gone earlier than that you do though..)
  • Your program will crash if you try to attach when running from windows and not from a console window.
  • Your program will start in a different console window if you don't use attach, even if you run from one.
  • I didn't try interprocess attach, so if you get it working (i wasnt interested) just add it in here somewhere

Tips & Tricks:

To duplicate the 'Console Application' feel, you can use the below code and call AllocateConsole as soon as Main() is called. This will cause it to act just as a console application would normally. Except you have the freedom to not show the console window at all if you don't want to (ie, if you have a /SHOWGUI option, which you prefer never creates a console in the first place).

Sample Code to Paste in your "Windows Application (C#)" Program.cs right after the lines that say "static class Program { ":

    /// <remarks>
    ///
    ///  USAGE: Place inside your program's main static class
    ///  and call AllocateConsole whenever you want.
    /// </remarks>

    /// <summary>
    /// allocates a new console for the calling process.
    /// </summary>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero.
    /// To get extended error information, call Marshal.GetLastWin32Error.</returns>
    [DllImport("kernel32",SetLastError=true)]
    static extern bool AllocConsole();
    /// <summary>
    /// Detaches the calling process from its console
    /// </summary>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero.
    /// To get extended error information, call Marshal.GetLastWin32Error.</returns>
    [DllImport("kernel32", SetLastError = true)]
    static extern bool FreeConsole();    
    /// <summary>
    /// Attaches the calling process to the console of the specified process.
    /// </summary>
    /// <param name="dwProcessId">[in] Identifier of the process, usually will be ATTACH_PARENT_PROCESS</param>
    /// <returns>If the function succeeds, the return value is nonzero.
    /// If the function fails, the return value is zero.
    /// To get extended error information, call Marshal.GetLastWin32Error.</returns>
    [DllImport("kernel32.dll", SetLastError=true)]
    static extern bool AttachConsole(uint dwProcessId);
    /// <summary>Identifies the console of the parent of the current process as the console to be attached.
    /// always pass this with AttachConsole in .NET for stability reasons and mainly because
    /// I have NOT tested interprocess attaching in .NET so dont blame me if it doesnt work! </summary>
    const uint ATTACH_PARENT_PROCESS = 0x0ffffffff;  
    /// <summary>
    /// calling process is already attached to a console
    /// </summary>
    const int ERROR_ACCESS_DENIED = 5;  
    /// <summary>
    /// Allocate a console if application started from within windows GUI.
    /// Detects the presence of an existing console associated with the application and
    /// attaches itself to it if available.
    /// </summary>
    private static void AllocateConsole()
    {
        //
        // the following should only be used in a non-console application type (C#)
        // (since a console is allocated/attached already when you define a console app.. :) )
        //
        if (!AttachConsole(ATTACH_PARENT_PROCESS) && Marshal.GetLastWin32Error() == ERROR_ACCESS_DENIED)
        {
        // A console was not allocated, so we need to make one.
        if (!AllocConsole())
        {
            MessageBox.Show("A console could not be allocated, sorry!");
            throw new Exception("Console Allocation Failed");
        }
        else
        {
            Console.WriteLine("Is Attached, press a key...");
            Console.ReadKey(true);
            // you now may use the Console.xxx functions from .NET framework
            // and they will work as normal
        }

        }
    }

(un)known issues?

  • Not sure how this interacts with console redirection, didn't try it... i suppose it will work fine but if it doesnt let me know

so I can update/fix the article.

  • Didn't check every last method from Console.xxx static methods. If they dont work, then ditto above.
  • I hope everyone finds this useful, I want to try to fill in these undeveloped pages as much as I can.

Resources

Documentation
AttachConsole,@msdn on MSDN, MSDN Library for VS.NET version v8.0 and PlatformSDK Library v10.0

Author

This Pinvoke Example was written by Gabriel Sharp from scratch and is property of pinvoke.net, and you may use it however you wish wherever you wish without credit to me. Not that I have to say it but theres alot of this going on: don't take full credit for other people's articles! I see alot of this, and it benefits nobody, and just makes you look like an.. you know

Questions or comments on this snippet you can write me:

mailto:Gabriel@paradisim.net

or visit

[http://www.paradisim.net]

or

[http://inversegoogle.paradisim.net/index3.htm]

for a snazzy black google search engine yeah i did say snazzy, i know i know... sheesh.

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Find References
Show Printable Version
Revisions