سؤال

أنا باستخدام وحدة التحكم.WriteLine() من بسيط جدا WPF اختبار التطبيق ، ولكن عند تنفيذ التطبيق من سطر الأوامر ، أنا أرى شيء كتب إلى وحدة التحكم.لا أحد يعرف ما يمكن أن يحدث هنا ؟

أنا يمكن أن تتكاثر عن طريق إنشاء تطبيق WPF في مقابل 2008 ببساطة إضافة وحدة التحكم.WriteLine("text") في أي مكان على تنفيذها.أي أفكار ؟

كل ما أحتاجه الآن هو شيء بسيط مثل وحدة التحكم.WriteLine().أنا أدرك أنني يمكن استخدام log4net أو بعض أخرى تسجيل الحل, ولكن أنا حقا لا تحتاج إلى أن الكثير من وظائف هذا التطبيق.

تحرير: يجب أن نتذكر أن وحدة التحكم.WriteLine() هو تطبيقات وحدة التحكم.حسنا, لا أسئلة غبية, صحيح ؟ :-) أنا فقط استخدام النظام.تشخيص.تتبع.WriteLine() و DebugView الآن.

هل كانت مفيدة؟

المحلول

سيكون لديك لإنشاء إطار وحدة التحكم يدويا قبل كنت في الواقع استدعاء أي وحدة التحكم.كتابة الأساليب.التي من شأنها تهيئة وحدة التحكم تعمل بشكل صحيح دون تغيير نوع المشروع (والتي تطبيق 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);
    }
} 

نصائح أخرى

انقر بزر الماوس الأيمن على المشروع "خصائص", "تطبيقات" علامة التبويب تغيير "نوع الإخراج" إلى "تطبيق وحدة التحكم" ثم ثم فإنه سيتم أيضا التحكم.

يمكنك استخدام

Trace.WriteLine("text");

هذا الإخراج إلى "إخراج" نافذة في Visual Studio (عند التصحيح).

تأكد من أن يكون التشخيص الجمعية شملت:

using System.Diagnostics;

على الرغم من أن جون Leidegren تحافظ على إسقاط فكرة براين هو الصحيح.لقد حصلت على عمل في Visual Studio.

أن يكون واضحا تطبيق WPF لا إنشاء إطار وحدة التحكم بشكل افتراضي.

لديك لإنشاء تطبيق WPF ثم تغيير OutputType إلى "تطبيق وحدة التحكم".عند تشغيل المشروع سوف ترى نافذة وحدة التحكم مع WPF نافذة أمامه.

أنها لا تبدو جميلة جدا, ولكنني وجدت أنه من المفيد كما أردت بلدي التطبيق ليتم تشغيلها من سطر الأوامر مع ردود الفعل في بعض خيارات الأمر أود أن عرض نافذة WPF.

فمن الممكن أن نرى الناتج المقصود من وحدة التحكم باستخدام سطر الأوامر إعادة توجيه.

على سبيل المثال:

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

سوف أكتب كل المحتوى output.txt الملف.

آخر العمر ، ولكن صادفت هذا حتى إذا كنت في محاولة إخراج ما خرج في WPF المشروع في Visual Studio المعاصر الطريقة:

وتشمل هذه:

using System.Diagnostics;

ثم:

Debug.WriteLine("something");

يمكنني استخدام وحدة التحكم.WriteLine() للاستخدام في إطار الإخراج...

لقد خلق حل مختلطة المعلومات من فريوس] آخر.

لها نموذج يحتوي على تسمية مربع نص واحد.وحدة الإخراج هو توجيهك إلى مربع نص.

هناك أيضا فئة تسمى ConsoleView التي تطبق ثلاثة الجماهير طرق:عرض () ، وثيقة () ، Release().آخر واحد هو ترك فتح وحدة التحكم وتفعيل إغلاق زر عرض النتائج.

أشكال يسمى 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
}

آمل أن يكون هذا نتيجة مفيدة.

تحقق من هذا المنصب ، كان مفيدا جدا لنفسي.تحميل نموذج التعليمات البرمجية:

http://www.codeproject.com/Articles/335909/Embedding-a-Console-in-a-C-Application

بقدر ما أعرف, وحدة التحكم.WriteLine() هو فقط من أجل تطبيقات وحدة التحكم.أعتقد أن هذه هي المشكلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top