WPF एप्लिकेशन से कंसोल के लिए कोई आउटपुट नहीं?


112

मैं एक बहुत ही सरल WPF टेस्ट एप्लिकेशन से Console.WriteLine () का उपयोग कर रहा हूं, लेकिन जब मैं कमांड लाइन से एप्लिकेशन को निष्पादित करता हूं, तो मुझे कंसोल पर कुछ भी नहीं लिखा दिखाई दे रहा है। क्या किसी को पता है कि यहाँ क्या हो सकता है?

मैं वीएस 2008 में एक WPF एप्लिकेशन बनाकर इसे पुन: उत्पन्न कर सकता हूं, और बस Console.WriteLine ("टेक्स्ट") को जोड़कर कहीं भी निष्पादित हो सकता हूं। कोई विचार?

अभी मुझे सिर्फ Console.WriteLine () के रूप में सरल रूप में कुछ की आवश्यकता है। मुझे लगता है कि मैं log4net या कुछ अन्य लॉगिंग समाधान का उपयोग कर सकता हूं, लेकिन मुझे वास्तव में इस एप्लिकेशन के लिए बहुत अधिक कार्यक्षमता की आवश्यकता नहीं है।

संपादित करें: मुझे याद रखना चाहिए कि कंसोल कंसोल के लिए Console.WriteLine () है। ओह ठीक है, कोई बेवकूफ सवाल नहीं है, है ना? :-) मैं अभी System.Diagnostics.Trace.WriteLine () और DebugView का उपयोग करूँगा।


संभावित डुप्लिकेट यहां और यहां (नए, लेकिन कुछ दिलचस्प जवाबों के साथ कर्नेल 32.dll से AttachConsole का उपयोग करके )
अधिकतम

1
@ मोम, वे प्रश्न इस प्रश्न के डुप्लिकेट संभव हैं । यह सवाल 2-4 साल पहले उन सवालों में से पूछा गया था जिन्हें आपने पोस्ट किया था।
रॉब

जवाबों:


90

आपको वास्तव में किसी भी कंसोल को कहने से पहले आपको मैन्युअल रूप से एक कंसोल विंडो बनानी होगी। यह प्रोजेक्ट प्रकार को बदले बिना कंसोल को ठीक से काम करने के लिए सांत्वना देगा (जो कि WPF एप्लिकेशन के लिए काम नहीं करेगा)।

यहाँ एक संपूर्ण स्रोत कोड उदाहरण है, कि ConsoleManager वर्ग कैसा दिख सकता है, और यह कैसे कंसोल को सक्षम / अक्षम करने के लिए उपयोग किया जा सकता है, परियोजना के प्रकार से स्वतंत्र रूप से।

निम्न वर्ग के साथ, आपको बस ConsoleManager.Show()किसी भी कॉल से पहले कहीं लिखना होगा 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);
    }
} 

5
पहले AttachConsole (-1) को कॉल करने की कोशिश करना संभव है और मूल प्रक्रिया के कंसोल से संलग्न करने के लिए इसके रिटर्न मान की जांच करें; यदि यह गलत है, तो AllocConsole को कॉल करें। हालाँकि, एप्लिकेशन अभी भी पहले 'रिटर्न' करता है और उसके बाद ही कंसोल को आउटपुट करता है, अगर मुझे कोई समाधान मिलता है तो मैं और पोस्ट करूँगा। इसके अलावा, यदि आप WPF ऐप टाइप को कंसोल एप्लिकेशन पर सेट करते हैं, तो समस्या गायब हो जाती है, लेकिन आप कंसोल को अलग नहीं कर सकते बिना इसे स्क्रीन पर संक्षिप्त रूप से दिखा सकते हैं जब प्रोग्राम शुरू किया जाता है, तो यह थोड़े अजीब लगता है (लेकिन अगर आप इसके साथ रह सकते हैं , यह बहुत अच्छा काम करता है)।
एलेक्स पावन

2
एह, वास्तव में नहीं, मुझे नहीं लगता कि यह दोनों तरीकों से संभव है; कंसोल एप्लिकेशन को इसके पीई हेडर में CUI के रूप में चिह्नित किया गया है और इस प्रकार यह स्वचालित रूप से CMD के साथ अच्छा सहयोग करता है। दूसरी तरफ एक GUI एप्लिकेशन सीएमडी पर तुरंत नियंत्रण लौटाता है, और भले ही यह कंसोल को रीटच कर सकता है, पढ़ना और लिखना पाइपलाइन में अगले आउटपुट के साथ इंटरलेज किया जाएगा, जो स्पष्ट रूप से बहुत खराब है। यदि दूसरी ओर आप एप्लिकेशन को कंसोल एप्लिकेशन के रूप में चिह्नित करते हैं, तो आपको केवल एप्लिकेशन स्टार्टअप पर संक्षिप्त रूप से सीएमडी के साथ रहना होगा; फिर आप FreeConsole का उपयोग करने के लिए अलग कर सकते हैं और बाद में संलग्न / संलग्न कर सकते हैं
एलेक्स

1
ऐसा क्यों करते हैं जब ब्रायन से जवाब के रूप में अच्छी तरह से और बहुत आसान काम करता है।
राउटर जेंसेंस

2
स्पष्ट हो सकता है, लेकिन मैंने पाया कि Console.WriteLine अभी भी विजुअल स्टूडियो डिबगर संलग्न होने पर इस तकनीक का उपयोग करके काम नहीं करता था। जब मैंने वीएस के बाहर ऐप चलाया तो इसने एक ट्रीट का काम किया। धन्यवाद।
aboy021

2
@Mark हाँ, लेकिन यह काम नहीं करता है ... एक ऐसा SetConsoleCtrlHandlerफ़ंक्शन है जो CTRL_CLOSE_EVENTघटना होने पर अधिसूचित होने की अनुमति देता है लेकिन आप इसके साथ कुछ भी नहीं कर सकते, ऐसा कुछ भी नहीं है जो आपके एप्लिकेशन को जारी रखने की अनुमति दे। तुम बंद हो जाओगे। यदि आप हैकिंग की तरह महसूस करते हैं, तो आप शायद कंसोल संदेश विंडो हैंडलर को कंसोल प्रक्रिया के लिए स्वैप कर सकते हैं और बस WM_CLOSE संदेश को छोड़ सकते हैं, मैंने कभी यह कोशिश नहीं की है लेकिन यह काम कर सकता है। यह सिर्फ एक और खिड़की है लेकिन इसके साथ ही कहा गया है, जब तक आप इस विचार का मनोरंजन नहीं करना चाहते हैं कि आप प्रयास कुछ और करने में बेहतर है।
जॉन लेडग्रेन

130

प्रोजेक्ट, "गुण", "एप्लिकेशन" टैब पर राइट क्लिक करें, "आउटपुट प्रकार" को "कंसोल एप्लिकेशन" में बदलें, और फिर इसमें कंसोल भी होगा।


2
एकमात्र समस्या यह है कि आपके पास पृष्ठभूमि में एक cmd खुला होगा, लेकिन यह काम करता है :)।
ykatchou

5
जब cmd.exe से एप्लिकेशन निष्पादित नहीं किया जाता है, तो महान, लेकिन कमांड-लाइन विंडो बनाई जाएगी (एक अनुप्रयोग के लिए बनाई गई दो खिड़कियां)। लेकिन इसके लिए भी समाधान है: आप cmW विंडो को ShowWindow (hWnd, 0) द्वारा छिपा सकते हैं। stackoverflow.com/a/10416180/1457197 । इस समाधान का उपयोग करके आप कंसोल में केवल तभी देखेंगे जब WPF एप्लिकेशन को कमांड-लाइन से निष्पादित किया जाता है।
CoperNick

नोट आपको ब्लेंड में काम करते समय इसे "विंडो एप्लिकेशन" पर वापस स्विच करना होगा, क्योंकि यह "कंसोल एप्लिकेशन" प्रकारों के लिए केवल XAML (डिज़ाइन दृश्य के लिए कोई एक्सेस नहीं) दिखाता है। (ब्लेंड 2013 के अनुसार)

1
सही नहीं ans। मुख्य विंडोज छुपाता है। बस कंसोल आता है।
यश

129

आप उपयोग कर सकते हैं

Trace.WriteLine("text");

यह Visual Studio (जब डीबगिंग) में "आउटपुट" विंडो के लिए आउटपुट होगा।

डायग्नोस्टिक्स असेंबली को शामिल करना सुनिश्चित करें:

using System.Diagnostics;

9
यह सबसे अच्छा उत्तर है, लेकिन उच्चतम रेटिंग नहीं है
किल्टेक

मैं सहमत हूँ - यह वही है जो ऑप के लिए पूछ रहा है। Console.WriteLine () - जवाब के रूप में चिह्नित समाधान के लिए एक बढ़िया विकल्प एक उत्पादन अनुप्रयोग में शामिल करने के लिए एक अनुचित व्यायाम है, लेकिन अनुचित है।
nocarrier

4
Windows स्टोर ऐप्स (Windows रनटाइम) के लिए PS ट्रेस के बराबर है। VriteLine Debug.WriteLine ()
nocarrier

यह एक सरल, साफ समाधान है, हालांकि मेरे लिए काम नहीं किया। अद्यतन डेटाबेस के दौरान इकाई ढांचे के बीज विधि में काम नहीं किया। अन्यथा, हर जगह काम करता है!
चार्ल्स डब्ल्यू

यह सबसे अच्छा उपाय है। बेहतर होगा यदि उत्तर यह भी समझाया जाए कि Console.WriteLineडब्ल्यूपीएफ अनुप्रयोगों के लिए बिल्कुल भी इरादा नहीं है, और यह केवल कमांड-लाइन एप्लिकेशन के लिए है।
एंड्रयू कोस्टर

12

हालांकि जॉन लेडिग्रेन विचार की शूटिंग जारी रखता है, ब्रायन सही है। मैंने अभी इसे विजुअल स्टूडियो में काम किया है।

स्पष्ट करने के लिए एक WPF अनुप्रयोग डिफ़ॉल्ट रूप से कंसोल विंडो नहीं बनाता है।

आपको एक WPF Application बनाना है और फिर OutputType को "Console Application" में बदलना है। जब आप प्रोजेक्ट चलाते हैं, तो आप उसके सामने अपनी WPF विंडो के साथ एक कंसोल विंडो देखेंगे।

यह बहुत सुंदर नहीं लगता है, लेकिन मुझे यह मददगार लगा क्योंकि मैं चाहता था कि मेरा ऐप कमांड लाइन से फीडबैक के साथ चलाया जाए, और फिर कुछ कमांड विकल्पों के लिए मैं WPF विंडो प्रदर्शित करूंगा।


1
उत्तम। नौकरी करता है।
frostymarvelous

10

कमांड लाइन पुनर्निर्देशन का उपयोग करके कंसोल के लिए इरादा आउटपुट देखना संभव है ।

उदाहरण के लिए:

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

output.txtफाइल करने के लिए सभी सामग्री लिखेंगे ।


सबसे अच्छा जवाब यह सरल है और स्रोत में बदलाव की आवश्यकता नहीं है
बकरी

9

पुरानी पोस्ट, लेकिन मैं इसमें भाग गया, यदि आप Visual Studio में WPF प्रोजेक्ट में आउटपुट के लिए कुछ आउटपुट करने की कोशिश कर रहे हैं, तो समकालीन तरीका यह है:

इसे शामिल करें:

using System.Diagnostics;

और तब:

Debug.WriteLine("something");

4

मैं आउटपुट विंडो में उपयोग के लिए Console.WriteLine () का उपयोग करता हूं ...


4
यह एक 4 साल पुराना सवाल है जिसे मैंने पहली बार देखे जाने के बाद से बहुत अधिक संपादित किया है। अब निश्चित रूप से प्रश्न को बेहतर ढंग से लिखा गया है और मेरी प्रतिक्रिया अप्रासंगिक हो गई है।
erodewald

1

मैंने एक समाधान बनाया है, जिसमें वेरियस पोस्ट की जानकारी मिली है।

इसका एक रूप, जिसमें एक लेबल और एक टेक्स्टबॉक्स होता है। कंसोल आउटपुट को टेक्स्टबॉक्स पर पुनर्निर्देशित किया गया है।

ConsoleView नामक एक वर्ग भी है जो तीन सार्वजनिक विधियों को लागू करता है: दिखाएँ (), बंद (), और रिलीज़ ()। अंतिम एक कंसोल खोलने के लिए है और दृश्य परिणामों के लिए बंद बटन को सक्रिय करें।

रूपों को FrmConsole कहा जाता है। यहाँ XAML और c # कोड हैं।

उपयोग बहुत सरल है:

ConsoleView.Show("Title of the Console");

कंसोल खोलने के लिए। उपयोग:

System.Console.WriteLine("The debug message");

कंसोल के आउटपुट टेक्स्ट के लिए।

उपयोग:

ConsoleView.Close();

कंसोल को बंद करें।

ConsoleView.Release();

पत्तियां कंसोल को खोलती हैं और क्लोज बटन को सक्षम करती हैं

XAML

<Window x:Class="CustomControls.FrmConsole"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:CustomControls"
    mc:Ignorable="d"
    Height="500" Width="600" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Topmost="True" Icon="Images/icoConsole.png">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="40"/>
    </Grid.RowDefinitions>
    <Label Grid.Row="0" Name="lblTitulo" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" FontFamily="Arial" FontSize="14" FontWeight="Bold" Content="Titulo"/>
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="10"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="10"/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="1" Name="txtInner" FontFamily="Arial" FontSize="10" ScrollViewer.CanContentScroll="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" TextWrapping="Wrap"/>
    </Grid>
    <Button Name="btnCerrar" Grid.Row="2" Content="Cerrar" Width="100" Height="30" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center"/>
</Grid>

विंडो का कोड:

partial class FrmConsole : Window
{
    private class ControlWriter : TextWriter
    {
        private TextBox textbox;
        public ControlWriter(TextBox textbox)
        {
            this.textbox = textbox;
        }

        public override void WriteLine(char value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value.ToString());
                textbox.AppendText(Environment.NewLine);
                textbox.ScrollToEnd();
            }));
        }

        public override void WriteLine(string value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value);
                textbox.AppendText(Environment.NewLine);
                textbox.ScrollToEnd();
            }));
        }

        public override void Write(char value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value.ToString());
                textbox.ScrollToEnd();
            }));
        }

        public override void Write(string value)
        {
            textbox.Dispatcher.Invoke(new Action(() =>
            {
                textbox.AppendText(value);
                textbox.ScrollToEnd();
            }));
        }

        public override Encoding Encoding
        {
            get { return Encoding.UTF8; }

        }
    }

    //DEFINICIONES DE LA CLASE
    #region DEFINICIONES DE LA CLASE

    #endregion


    //CONSTRUCTORES DE LA CLASE
    #region CONSTRUCTORES DE LA CLASE

    public FrmConsole(string titulo)
    {
        InitializeComponent();
        lblTitulo.Content = titulo;
        Clear();
        btnCerrar.Click += new RoutedEventHandler(BtnCerrar_Click);
        Console.SetOut(new ControlWriter(txtInner));
        DesactivarCerrar();
    }

    #endregion


    //PROPIEDADES
    #region PROPIEDADES

    #endregion


    //DELEGADOS
    #region DELEGADOS

    private void BtnCerrar_Click(object sender, RoutedEventArgs e)
    {
        Close();
    }

    #endregion


    //METODOS Y FUNCIONES
    #region METODOS Y FUNCIONES

    public void ActivarCerrar()
    {
        btnCerrar.IsEnabled = true;
    }

    public void Clear()
    {
        txtInner.Clear();
    }

    public void DesactivarCerrar()
    {
        btnCerrar.IsEnabled = false;
    }

    #endregion  
}

ConsoleView वर्ग का कोड

static public class ConsoleView
{
    //DEFINICIONES DE LA CLASE
    #region DEFINICIONES DE LA CLASE
    static FrmConsole console;
    static Thread StatusThread;
    static bool isActive = false;
    #endregion

    //CONSTRUCTORES DE LA CLASE
    #region CONSTRUCTORES DE LA CLASE

    #endregion

    //PROPIEDADES
    #region PROPIEDADES

    #endregion

    //DELEGADOS
    #region DELEGADOS

    #endregion

    //METODOS Y FUNCIONES
    #region METODOS Y FUNCIONES

    public static void Show(string label)
    {
        if (isActive)
        {
            return;
        }

        isActive = true;
        //create the thread with its ThreadStart method
        StatusThread = new Thread(() =>
        {
            try
            {
                console = new FrmConsole(label);
                console.ShowDialog();
                //this call is needed so the thread remains open until the dispatcher is closed
                Dispatcher.Run();
            }
            catch (Exception)
            {
            }
        });

        //run the thread in STA mode to make it work correctly
        StatusThread.SetApartmentState(ApartmentState.STA);
        StatusThread.Priority = ThreadPriority.Normal;
        StatusThread.Start();

    }

    public static void Close()
    {
        isActive = false;
        if (console != null)
        {
            //need to use the dispatcher to call the Close method, because the window is created in another thread, and this method is called by the main thread
            console.Dispatcher.InvokeShutdown();
            console = null;
            StatusThread = null;
        }

        console = null;
    }

    public static void Release()
    {
        isActive = false;
        if (console != null)
        {
            console.Dispatcher.Invoke(console.ActivarCerrar);
        }

    }
    #endregion
}

मुझे उम्मीद है कि यह परिणाम उपयोगी है।



-17

जहाँ तक मुझे पता है, Console.WriteLine () केवल कंसोल अनुप्रयोगों के लिए है। मुझे लगता है कि यह आपकी समस्या है।


1
मैं WPF के बारे में नहीं जानता, लेकिन यह निश्चित रूप से WinForms के मामले में नहीं है। Console.WriteLine वहाँ ठीक काम करता है, लेकिन, निश्चित रूप से, आप कंसोल को नहीं देखेंगे, आप इसे डिबगर आउटपुट विंडो में देखेंगे और यदि आप मानक आउटपुट को सुनेंगे।
जेफ येट्स

2
आप प्रोजेक्ट को एक कंसोल एप्लिकेशन पर सेट कर सकते हैं और यह अभी भी विंडोज ऐप के रूप में चलेगा, लेकिन इसमें एक विज़ुअल कंसोल भी होगा
मार्क सिडैड

यह गलत है, एक गैर कंसोल एप्लिकेशन की बिल्ड प्रक्रिया डीफॉल्ट द्वारा कंसोल को संलग्न नहीं करती है। आप कंसोल से किसी भी कॉल से पहले AllocConsole () Win32 API फ़ंक्शन को कॉल करके मैन्युअल रूप से ऐसा कर सकते हैं। कंसोल कंसोल को फिर उस कंसोल विंडो के साथ काम करने के लिए आरंभीकृत किया जाएगा।
जॉन लेडिग्रेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.