2008-10-02 33 views
81

Tôi đang sử dụng Console.WriteLine() từ một ứng dụng thử nghiệm WPF rất đơn giản, nhưng khi tôi thực thi ứng dụng từ dòng lệnh, tôi thấy không có gì được ghi vào bàn điều khiển. Có ai biết điều gì có thể xảy ra ở đây không?Không có đầu ra cho bàn điều khiển từ một ứng dụng WPF?

Tôi có thể tạo lại bằng cách tạo ứng dụng WPF trong VS 2008 và chỉ cần thêm Console.WriteLine ("văn bản") vào bất kỳ nơi nào được thực hiện. Bất kỳ ý tưởng?

Tất cả những gì tôi cần bây giờ là một cái gì đó đơn giản như Console.WriteLine(). Tôi nhận ra tôi có thể sử dụng log4net hoặc đôi khi giải pháp đăng nhập khác, nhưng tôi thực sự không cần nhiều chức năng cho ứng dụng này.

Chỉnh sửa: Tôi nên nhớ rằng Console.WriteLine() dành cho các ứng dụng bảng điều khiển. Ồ, không có câu hỏi ngu ngốc, phải không? :-) Tôi sẽ chỉ sử dụng System.Diagnostics.Trace.WriteLine() và DebugView cho bây giờ.

+0

bản sao có thể xảy ra [ tại đây] (http://stackoverflow.com/questions/3057852/how-do-i-write-to-command-line-from-a-wpf-application/3058921#3058921) và [tại đây] (http: // stackoverflow.com/questions/10415807/output-console-writeline-from-wpf-windows-applications-to-actual-console) (mới hơn, nhưng với một số câu trả lời thú vị bằng cách sử dụng [AttachConsole từ Kernel32.dll] (https: // msdn .microsoft.com/en-us/library/windows/desktop/ms681952% 28v = vs.85% 29.aspx)) – Max

+1

@Max, những câu hỏi đó có thể trùng lặp với câu hỏi * này *. Câu hỏi này được hỏi 2-4 năm trước một trong những câu hỏi mà bạn đã đăng. –

Trả lời

78

Bạn sẽ phải tạo ra một cửa sổ Console bằng tay trước khi bạn thực sự gọi bất kỳ phương thức Console.Write nào. Điều đó sẽ bắt đầu bàn điều khiển để hoạt động đúng mà không thay đổi loại dự án (đối với ứng dụng WPF sẽ không hoạt động).

Dưới đây là một ví dụ mã nguồn hoàn chỉnh, về cách một lớp ConsoleManager có thể trông như thế nào và cách nó có thể được sử dụng để bật/tắt Bàn điều khiển, độc lập với loại dự án.

Với lớp sau, bạn chỉ cần viết ConsoleManager.Show() ở đâu đó trước khi bất kỳ cuộc gọi đến Console.Write ...

[SuppressUnmanagedCodeSecurity] 
public static class ConsoleManager 
{ 
    private const string Kernel32_DllName = "kernel32.dll"; 

    [DllImport(Kernel32_DllName)] 
    private static extern bool AllocConsole(); 

    [DllImport(Kernel32_DllName)] 
    private static extern bool FreeConsole(); 

    [DllImport(Kernel32_DllName)] 
    private static extern IntPtr GetConsoleWindow(); 

    [DllImport(Kernel32_DllName)] 
    private static extern int GetConsoleOutputCP(); 

    public static bool HasConsole 
    { 
     get { return GetConsoleWindow() != IntPtr.Zero; } 
    } 

    /// <summary> 
    /// Creates a new console instance if the process is not attached to a console already. 
    /// </summary> 
    public static void Show() 
    { 
     //#if DEBUG 
     if (!HasConsole) 
     { 
      AllocConsole(); 
      InvalidateOutAndError(); 
     } 
     //#endif 
    } 

    /// <summary> 
    /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown. 
    /// </summary> 
    public static void Hide() 
    { 
     //#if DEBUG 
     if (HasConsole) 
     { 
      SetOutAndErrorNull(); 
      FreeConsole(); 
     } 
     //#endif 
    } 

    public static void Toggle() 
    { 
     if (HasConsole) 
     { 
      Hide(); 
     } 
     else 
     { 
      Show(); 
     } 
    } 

    static void InvalidateOutAndError() 
    { 
     Type type = typeof(System.Console); 

     System.Reflection.FieldInfo _out = type.GetField("_out", 
      System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); 

     System.Reflection.FieldInfo _error = type.GetField("_error", 
      System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); 

     System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError", 
      System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); 

     Debug.Assert(_out != null); 
     Debug.Assert(_error != null); 

     Debug.Assert(_InitializeStdOutError != null); 

     _out.SetValue(null, null); 
     _error.SetValue(null, null); 

     _InitializeStdOutError.Invoke(null, new object[] { true }); 
    } 

    static void SetOutAndErrorNull() 
    { 
     Console.SetOut(TextWriter.Null); 
     Console.SetError(TextWriter.Null); 
    } 
} 
+0

Tôi thích điều này, nó hoạt động, và tôi có thể sử dụng điều này trong các dự án khác. Tuy nhiên, vì nó khởi chạy một cửa sổ giao diện điều khiển mới, nó gây ra một vấn đề với một dự án hiện tại. Nếu tôi vượt qua trong các tùy chọn dòng lệnh muốn có thể xuất ra giao diện điều khiển mà nó đã được khởi chạy để người dùng nhận được kết quả đầu ra ở đó.Trong ứng dụng của tôi nếu tùy chọn dòng lệnh được cung cấp, nó vẫn là một ứng dụng giao diện điều khiển và sau đó thực hiện công việc của nó rồi thoát ra. Điều này cho phép ứng dụng được tự động hóa và lên lịch để thực hiện các tác vụ hoặc người dùng chỉ có thể thực hiện điều gì đó nhanh chóng và thoát ra. Tuy nhiên tôi muốn xuất ra một số thứ, giống như công cụ trợ giúp sử dụng, v.v. –

+0

Đòn tấn công đẹp với cài đặt _out và _error thành null. Thông minh! – BFree

+0

Có thể nhúng cửa sổ bảng điều khiển trong một cửa sổ WPF bằng cách sử dụng kỹ thuật này hay bất kỳ kỹ thuật nào khác không? – InfinitiesLoop

-14

Theo như tôi biết, Console.WriteLine() chỉ dành cho các ứng dụng bảng điều khiển. Tôi nghĩ rằng đây là vấn đề của bạn.

+1

Tôi không biết về WPF, nhưng điều này chắc chắn không phải là trường hợp cho WinForms. Console.WriteLine hoạt động tốt ở đó, nhưng, tất nhiên, bạn sẽ không thấy giao diện điều khiển, bạn sẽ thấy nó trong cửa sổ đầu ra Debugger và nếu bạn nghe đầu ra tiêu chuẩn. –

+2

bạn có thể đặt dự án thành ứng dụng Console và ứng dụng này vẫn chạy dưới dạng ứng dụng Windows nhưng cũng sẽ có bảng điều khiển hiển thị –

+0

Không đúng, quá trình xây dựng ứng dụng không điều khiển không đính kèm bảng điều khiển bởi deffault. Bạn có thể làm điều này bằng tay bằng cách gọi hàm AllcConsole() Win32 API trước bất kỳ lệnh gọi nào đến Console.Write, lớp Console sau đó sẽ được khởi tạo để làm việc với cửa sổ Console đó. –

102

Nhấp chuột phải vào dự án, tab "Thuộc tính", "Ứng dụng", thay đổi "Loại đầu ra" thành "Ứng dụng giao diện điều khiển" và sau đó nó cũng sẽ có bảng điều khiển.

+1

Vấn đề duy nhất với điều đó là bạn sẽ có một cmd mở trong nền, nhưng nó hoạt động :). – ykatchou

+4

Tuyệt vời, nhưng cửa sổ dòng lệnh sẽ được tạo khi ứng dụng không được thực hiện từ cmd.exe (hai cửa sổ được tạo cho một ứng dụng). Nhưng đối với điều này cũng có giải pháp: bạn có thể ẩn cửa sổ cmd bằng ShowWindow (hWnd, 0). http://stackoverflow.com/a/10416180/1457197. Sử dụng giải pháp này, bạn sẽ thấy văn bản trong giao diện điều khiển chỉ khi ứng dụng WPF được thực hiện từ dòng lệnh. – CoperNick

+0

Lưu ý bạn sẽ phải chuyển nó về "Window Application" khi làm việc trong Blend, vì nó chỉ hiển thị XAML (không có quyền truy cập vào Design View) cho các kiểu "Console Application". (tính theo Blend 2013) –

91

Bạn có thể sử dụng

Trace.WriteLine("text"); 

chí sản lượng này vào cửa sổ "Output" trong Visual Studio (khi gỡ lỗi).

hãy chắc chắn để có chẩn đoán lắp ráp bao gồm:

using System.Diagnostics; 
+0

Dễ dàng, đơn giản. Thx – rluks

+7

đây là câu trả lời hay nhất, nhưng chưa xếp hạng cao nhất – kiltek

+0

Tôi đồng ý - đây chính xác là những gì op đang yêu cầu. Thay thế tuyệt vời cho Console.WriteLine() - giải pháp được đánh dấu là câu trả lời là một bài tập gọn gàng nhưng không hợp lý để đưa vào một ứng dụng sản xuất. – nocarrier

3

tôi sử dụng Console.WriteLine() để sử dụng trong cửa sổ Output ...

+4

Đó là một câu hỏi cũ 4 năm đã được chỉnh sửa rất nhiều kể từ lần đầu tiên tôi nhìn thấy nó. Bây giờ tất nhiên câu hỏi đã được diễn đạt tốt hơn và phản ứng của tôi đã được thực hiện không liên quan. – erodewald

9

Mặc dù John Leidegren giữ bắn hạ các ý tưởng, Brian là đúng. Tôi đã có nó làm việc trong Visual Studio.

Để rõ ràng, ứng dụng WPF không tạo cửa sổ Bảng điều khiển theo mặc định.

Bạn phải tạo một ứng dụng WPF và sau đó thay đổi OutputType thành "Console Application". Khi bạn chạy dự án, bạn sẽ thấy một cửa sổ giao diện điều khiển với cửa sổ WPF của bạn ở phía trước của nó.

Nó trông không đẹp, nhưng tôi thấy nó hữu ích khi tôi muốn ứng dụng của tôi được chạy từ dòng lệnh với phản hồi trong đó, và sau đó cho một số tùy chọn lệnh tôi sẽ hiển thị cửa sổ WPF.

+1

Hoàn hảo. Làm công việc. – frostymarvelous

8

Có thể xem đầu ra dành cho bảng điều khiển bằng cách sử dụng command line redirection.

Ví dụ:

C:\src\bin\Debug\Example.exe > output.txt 

sẽ viết tất cả các nội dung để output.txt tập tin.

4

Cũ bưu điện, nhưng tôi chạy vào này vì vậy nếu bạn đang cố gắng để ra một cái gì đó để ra trong một dự án WPF trong Visual Studio, các phương pháp hiện đại là:

này bao gồm:

using System.Diagnostics; 

Và sau đó:

Debug.WriteLine("something"); 
Các vấn đề liên quan