Tuesday, April 30, 2013

How can I see the Assembly code for a C++ Program?

Approach 1
If you are building the program yourself, you can ask your compiler to emit assembly source. For most UNIX compilers use the -S switch.
If you are using the GNU assembler, compiling with -g -Wa,-alh will give intermixed source and assembly on stdout (-Wa asks compiler driver to pass options to assembler, -al turns on assembly listing, and -ah adds "high-level source" listing):
g++ -g -c -Wa,-alh foo.cc
For Visual Studio, use /FAsc.
If you have compiled binary, use objdump -d a.out on UNIX (also works for cygwin), dumpbin /DISASM foo.exe on Windows.
Debuggers could also show disassebly. Use disas command in GDB, or the disassembly window of Visual Studio on Windows.

Approach 2

Whatever debugger you're using should have an assembly view (VS, Borland IDE, gdb, etc). If you are not using a debugger and you merely want to see what assembly is in a program you can use a disassembler or alternatively, run the program and attach to it with a debugger and do the dump from there. See references to disassemblers for info on options.

Approach 3

As someone else mentioned, your platform's debugger is a good starting point. For the jackhammer of all debuggers and disassemblers, take a look at IDA Pro.
On Unix/Linux platforms (including Cygwin) you can use objdump --disassemble .
If there is an option to have the compiler generate the assembler (like gcc -S, or the VS /FA option below), that is preferable over disassembly. It is more symbolic.
Sure, if you have the source.
By the way, you'd be surprised how much symbol information can be deduced by IDA Pro.
Approach 4
In Visual Studio
  1. set a breakpoint
  2. run the program until it stops at the breakpoint
  3. rightclick on the sourcecode and pick "show dissasembly"
Approach 5

In GCC/G++, compile with -S. That will output a something.s file with the assembly code.
Edit: If you want the output to be in Intel syntax (which is IMO, much more readable, and most assembly tutorials use it), compile with -masm=intel.
add also -fverbose-asm option
Approach 6
Most compilers have an option to output an assembly listing. E.g. with VisualStudio you can use something like:
cl.exe /FAfile.asm file.c
For best readability though, most debuggers will offer a view that interleaves the disassembly with the original source, so you can compare your code with the compiler's output line by line.
Approach 7
Lots of people already told how to emit assembly code with a given compiler. Another solution is to compile an object file and dump it with a tool such objdumpreadelf (on Unix) or DUMPBIN(link) (on Windows). You can also dump an executable, but it will be more difficult to read the output.
This has the advantage of working the same way with any compiler.
Approach 8
PE Explorer Disassembler for 32-bit PE files. IDA for others.
Approach 9
For gcc/g++
gcc -save-temps -fverbose-asm prog.c
This will generate prog.s with some comments on variables used in every asm line:
    movl    $42, -24(%ebp)  #, readme
    movl    -16(%ebp), %eax # pid, pid
    movl    %eax, 4(%esp)   # pid,
    movl    $.LC0, (%esp)   #,
    call    printf  #


NASM is pure assembly, but MASM is high level Assembly?

My recommendation purely from a "reverse engineering" perspective is to understand how a compiler translates high-level concepts into assembly language instructions in the first place. The understanding of how register allocation is done in various compilers and how various optimizations will obscure the high-level representation of nested loops (et.al.) is more important than being able to write one particular dialect of assembly input.
Your best bet is to start with the assembly language intermediate files from source code that you write (seethis question for more information). Then you can change the source and see how it affects the intermediate files. The other place to start is by using an interactive disassembler like IDA Pro.
Actually writing assembly language programs and learning the syntax of NASM, MASM, gas, of as is the easiest part and it does not really matter which one you learn. They are very similar because the syntax of the source language is very basic. If you are planning to learn how to disassemble and understand what a program is doing, then I would completely ignore macro assemblers since the macros completely disappear during translation and you will not see them when looking at disassembler output.
Diatribe on Learning Assembly
Learning an assembly language is different than learning a higher level programming language. There are fewer syntactical constructs if you ignore macro assemblers. The problem is that every compiler chain has a slightly different representation so you have to concentrate on the concepts such as supported address modes, register restrictions, etc. These aren't part of the language per se as they are dictated by the hardware.
The approach that I took (partially because the university forced me to), is to explore and understand the hardware itself (e.g., # of registers, size of registers, type of branch instructions supported, etc.) and slightly more academic concepts such as interrupts and using bitwise manipulation for integer match before you start to write assembly language programs. This is a much longer route but results in a rich understanding of assembly and how to write high performance programs.
The interesting thing is that in the time that I spent learning assembly and compiler construction (which is intrinsically related), I actually wrote very few assembly programs. More often, I am required to write little snippets of inline assembly here and there (e.g. setting up index registers when the runtime loader didn't). I have spent an enormous amount of time dissecting crash dumps from a memory location, loader map file, and assembler output listings. I can honestly say that the syntax of each assembler is dramatically different as well as what various compilers will do to muddle the intent into fast or small code.
Learning how to write assembly programs was the least worthwhile part of the education process. It was necessary to understand how source is translated into the bits and bytes that the computer executes, but it really was not what I really needed to reverse engineer from a raw binary (disassembler -> assembly listing -> best guess of high level intent) or a memory dump. I do more of the latter, but the requirements of the job are the same.
  1. You really have to understand what the constraints of the architecture are.
  2. You have to know the very basic syntax of the assembler in question - how are address modes indicated, how are registers indicated, what is the order of arguments for a move
  3. What transformations a compiler does to go from if (a > 0) to mov.b r0,d0 ... bnz $L
Start by learning about computer architecture (e.g., read something from Andrew Tanenbaum), then how an OS actually loads and runs a program (Levine's Linkers & Loaders), then compile simple programs in C/C++ and look at the assembly language listings.

But for understanding the disassembly... don't I need to learn assembly?

@questions: I think the best way to learn assembly is to look at disassembled code and figure out what it does. But that's my personal opinion.

Monday, April 29, 2013

use mutt command to send email with attachment

# cd /usr/ports/mail/mutt ; make install clean
# cd /usr/ports/mail/mutt-lite ; make install clean


Monday, April 22, 2013

Saturday, April 20, 2013

Dynamically add multiple buttons to wpf grid?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;

namespace WpfApplication2
    /// Interaction logic for MainWindow.xaml
    public partial class MainWindow : Window
        public MainWindow()

            for (int i = 0; i < 10; i++)
              g1.RowDefinitions.Add(new RowDefinition());
              g1.ColumnDefinitions.Add(new ColumnDefinition());

            Button[] MyButtonList = new Button[100];
            int count = 0;

            for (int i = 0; i < 10; i++)
                for (int j = 0; j < 10; j++)
                  Button b = new Button()
                      Name = "btn" + i + j,
                      Content = "gan " + i + "" + j,
                      Tag = "tagg " + i + j
                  b.Click += new RoutedEventHandler(button_Click);

                  MyButtonList[count] = b;

                  Grid.SetRow(b, i);
                  Grid.SetColumn(b, j);


            // remove a button

        void button_Click(object sender, RoutedEventArgs e)
            //Debug.WriteLine("you clicked {0}", (sender as Button).Name);
            Debug.WriteLine("you clicked {0}", (sender as Button).Name, null);
            Debug.WriteLine(string.Format("you clicked {0}", (sender as Button).Name));
            Debug.WriteLine("you clicked " + (sender as Button).Name);
            Debug.Print("you clicked " + (sender as Button).Name);
            Debug.WriteLine("you clicked {0}", (sender as Button).Content);
            Debug.WriteLine("you clicked {0}", (sender as Button).Tag);

            //Window1 w1 = new Window1();



所以從和她合租的第一天起,我就扮演起了媽媽的角色。她不買菜,不做飯,不打掃房間,不刷碗,甚至不刷廁所。除了洗自己的內衣褲,她簡直過得像一個公主。 後來有一次我生病了,在床上躺了三天,她就讓屋子亂了三天,第四天我忍無可忍的爬起來把屋子打掃了一遍,扔掉了所有的垃圾,洗乾淨了所有她用過的杯子和 碗。兩個小時以後她回家了,帶了外賣回來,吃完之後,照例把用過的碗筷堆在了洗碗池裡。

我忍無可忍的生氣了,後果是之後的一個星期裡,她四處告訴所有的 人,我是一個多麼不近人情的人。你看,她那麼可憐,從小都沒有獨立生活過,長這麼大第一次離開爸爸媽媽,本來就方寸大亂。而我,從小就獨立生活,有嫻熟的 生活技巧,卻不肯對她有任何包容。於是有人來告訴我,你應該寬容一點,善良一點。我瞠目結舌,氣得回家哭。

我有個朋友,被男友劈腿了。幾年之後,男友和新歡結婚了,但是過得不幸福,是他們自己生病了,還是孩子生病了我已經忘記了,反正結果就是,他們回來找我的 朋友借錢,說是救命。我朋友二話不說的拒絕了,於是也有人告訴她,你應該善良一點,無論當年發生過什麼,這畢竟是一條命。朋友跟我吃飯的時候敲看桌子大 罵。我知道她為什麼要罵,當年她失戀以後萬念俱灰,喝酒喝到酒精中毒進醫院,她自己也是一條人命。


好比你去買東西,一個比你歲數大的人插隊在你前面,如果你和他爭吵,那麼可能就會有人說你斤斤計較,不吃虧。好比你去坐瀏覽車,一個老人提出要和你交換上 下的位置,你如果拒絕了,可能就會有人說你小小年紀不懂得敬老,這麼點方便都不肯行。如果你的工作夥伴不負責 任,給你造成了巨大的困擾,而你生氣的時候他抹看眼淚從你的辦公室裡一路飛奔出去,那麼不要半天,你「嘴不饒人,把人活生生罵哭」的名聲可能就會傳遍全公 司。如果你過得還算不錯,而一個窮人侵犯了你的利益,那麼在你對他追究責任的時候,就可能會有人罵你為富不仁。


後來有了網絡,我發現這種善良的人越來越多了。好比說,你總會看到殺人搶劫的新聞裡,有人在悲天憫人的說:如果有足夠的錢,誰會去搶劫呢。可是後來我發現 了一件很有趣的事,這些號稱別人被搶劫,被欺騙,被背叛,被壓榨,都仍舊應該心存寬仁的人,當自己利益被觸犯的時候,往往也是跳腳最快的那些人。

我親眼見過一個告訴我們「搶匪也是生計所迫才會去搶劫,值得同情」的人,在自己錢包丟了以後咒小偷全家去死。我也親眼見過一個指責我「你比我有錢多了,幹 嘛不肯幫我買單」的人,因為朋友找他借了個包,卻晚還了一天,就此和朋友翻了臉。從此我就明白了,原來那些整天都把善良掛在嘴邊的人,和善良兩個字實在沒 什麼關係。他們有些是希望世界上有越來越多的不懂得反抗和據理力爭的人,這樣,在他們想要不講道理佔便宜的時候,就會越發順遂。




所以在我想通了這個道理以後,我就選擇不要做一個「善良」的人了。 我只要做一個講道理,也負責任的人。我在意真相,我在意道理,我在意在一件事情裡真正付出努力並最後被辜負的那個人。我也在意一件事情裡無辜被傷害卻甚至不能為自己討個公道的那個人。



惡人的最大幫兇, 也常常是那些根本不需要為自己所標榜的「善良」做出任何實際付出的「善人」。

Wednesday, April 17, 2013

Performance differences between debug and release builds

The C# compiler itself doesn't alter the emitted IL a great deal in the Release build. Notable is that it no longer emits the NOP opcodes that allow you to set a breakpoint on a curly brace. The big one is the optimizer that's built into the JIT compiler. I know it makes the following optimizations:

  • Method inlining. A method call is replaced by the injecting the code of the method. This is a big one, it makes property accessors essentially free.

  • CPU register allocation. Local variables and method arguments can stay stored in a CPU register without ever (or less frequently) being stored back to the stack frame. This is a big one, notable for making debugging optimized code so difficult. And giving the volatile keyword a meaning.

  • Array index checking elimination. An important optimization when working with arrays (all .NET collection classes use an array internally). When the JIT compiler can verify that a loop never indexes an array out of bounds then it will eliminate the index check. Big one.

  • Loop unrolling. Short loops (up to 4) with small bodies are eliminated by repeating the code in the loop body. Avoids the branch misprediction penalty.

  • Dead code elimination. A statement like if (false) { /.../ } gets completely eliminated. This can occur due to constant folding and inlining. Other cases is where the JIT compiler can determine that the code has no possible side-effect. This optimization is what makes profiling code so tricky.

  • Code hoisting. Code inside a loop that is not affected by the loop can be moved out of the loop.
  • Common sub-expression elimination. x = y + 4; z = y + 4; becomes z = x;

  • Constant folding. x = 1 + 2; becomes x = 3; This simple example is caught early by the compiler, but happens at JIT time when other optimizations make this possible.

  • Copy propagation. x = a; y = x; becomes y = a; This helps the register allocator make better decisions. It is a big deal in the x86 jitter because it has so few registers to work with. Having it select the right ones is critical to perf.

These are very important optimizations that can make a great deal of difference when, for example, you profile the Debug build of your app and compare it to the Release build. That only really matters though when the code is on your critical path, the 5 to 10% of the code you write that actually affects the perf of your program. The JIT optimizer isn't smart enough to know up front what is critical, it can only apply the "turn it to eleven" dial for all the code.

The effective result of these optimizations on your program's execution time is often affected by code that runs elsewhere. Reading a file, executing a dbase query, etc. Making the work the JIT optimizer does completely invisible. It doesn't mind though :)

The JIT optimizer is pretty reliable code, mostly because it has been put to the test millions of times. It is extremely rare to have problems in the Release build version of your program. It does happen however. Both the x64 and the x86 jitters have had problems with structs. The x86 jitter has trouble with floating point consistency, producing subtly different results when the intermediates of a floating point calculation are kept in a FPU register at 80-bit precision instead of getting truncated when flushed to memory.


To monitor detect slow performance of C# .NET framework application

You need to use profilers:
- Redgate ANTS Performance Profiler
- CLR Profiler for .NET Framework 4
- Visual Studio 2010 Performance Tools with Service Pack 1
- http://en.wikipedia.org/wiki/Code_profiler#Use_of_profilers

Update: You can also write messages in control points using Debug.Write. Then you need to load DebugView application that displays all your debug string with precise time stamp. It is freeware and very good for quick debugging and profiling.

Profilers are great for measuring.

But your question was "How can I determine where the slow parts of my code are?".

That is a different problem. It is diagnosis, not measurement.

I know this is not a popular view, but it's true.

It is like a business that is trying to cut costs.

One approach (top down) is to measure the overall finances, then break it down by categories and departments, and try to guess what could be eliminated. That is measurement.

Another approach (bottom up) is to walk in at random into an office, pick someone at random, and ask them what they are doing at that moment and (importantly) why, in detail.

Do this more than once.

That is what Harry Truman did at the outbreak of WW2, in the US defense industry, and immediately uncovered massive fraud and waste, by visiting several sites. That is diagnosis.

In code you can do this in a very simple way: "Pause" it and ask it why it is spending that particular cycle. Usually the call stack tells you why, in detail.

Do this more than once.

This is sampling. Some profilers sample the call stack. But then for some reason they insist on summarizing time spent in each function, inclusive and exclusive. That is like summarizing by department in business, inclusive and exclusive.

It loses the information you need, which is the fine-grain detail that tells if the cycles are necessary.

To answer your question:

Just pause your program several times, and capture the call stack each time. If your code is very slow, the wasteful function calls will be on nearly every stack. They will point with precision to the "slow parts of your code".

ADDED: RedGate ANTS is getting there. It can give you cost-by-line, and it is quite spiffy. So if you're in .NET, and can spare 3 figures, and don't mind waiting around to install & learn it, it can tell you much of what your Pause key can tell you, and be much more pretty about it.


How to trace and debug in Visual C#

This article describes how to use the Debug and the Trace classes. These classes are available in the Microsoft .NET Framework. You can use these classes to provide information about the performance of an application either during application development, or after deployment to production. These classes are only one part of the instrumentation features that are available in the .NET Framework. 


The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Microsoft Windows 2000 or Microsoft Windows XP or Microsoft Windows Server 2003
  • Microsoft Visual C#
This article also assumes that you are familiar with program debugging.

Description Of Technique

The steps in the Create a Sample with the Debug Class section demonstrate how to create a console application that uses theDebug class to provide information about the program execution. 

When the program is run, you can use methods of the Debug class to produce messages that help you to monitor the program execution sequence, to detect malfunctions, or to provide performance measurement information. By default, the messages that the Debug class produces appear in the Output window of the Visual Studio Integrated Development Environment (IDE). 

The sample code uses the WriteLine method to produce a message that is followed by a line terminator. When you use this method to produce a message, each message appears on a separate line in the Output window. 

When you use the Assert method of the Debug class, the Output window displays a message only if a specified condition evaluates to false. The message also appears in a modal dialog box to the user. The dialog box includes the message, the project name, and the Debug.Assert statement number. The dialog box also includes the following three command buttons: 
  • Abort: The application stops running.
  • Retry: The application enters debug mode.
  • Ignore: The application proceeds.
The user must click one of these buttons before the application can continue. 

You can also direct output from the Debug class to destinations other than the Output window. The Debug class has a collection named Listeners that includes Listener objects.

Each Listener object monitors Debug output and directs the output to a specified target. 

Each Listener in the Listener collection receives any output that the Debug class generates. Use the TextWriterTraceListenerclass to define Listener objects. You can specify the target for a TextWriterTraceListener class through its constructor. 

Some possible output targets include the following:
  • The Console window by using the System.Console.Out property.
  • A text (.txt) file by using the System.IO.File.CreateText("FileName.txt") statement.
After you create a TextWriterTraceListener object, you must add the object to the Debug.Listeners collection to receive Debug output. 

Create a Sample with the Debug Class

  1. Start Visual Studio or Visual C# Express Edition.
  2. Create a new Visual C# Console Application project named conInfo. Class1 is created in Visual Studio .NET. Program.cs is created in Visual Studio 2005.
  3. Add the following namespace at top in Class1 or Program.cs.

    using System.Diagnostics;
  4. To initialize variables to contain information about a product, add the following declaration statements to Main method:

    string sProdName = "Widget";
    int iUnitQty = 100;
    double dUnitCost = 1.03;
  5. Specify the message that the class produces as the first input parameter of the WriteLine method. Press the CTRL+ALT+O key combination to make sure that the Output window is visible.

    Debug.WriteLine("Debug Information-Product Starting ");
  6. For readability, use the Indent method to indent subsequent messages in the Output window:

  7. To display the content of selected variables, use the WriteLine method as follows:

    Debug.WriteLine("The product name is " + sProdName);
    Debug.WriteLine("The available units on hand are" + iUnitQty.ToString());
    Debug.WriteLine("The per unit cost is " + dUnitCost.ToString());
  8. You can also use the WriteLine method to display the namespace and the class name for an existent object. For example, the following code displays the System.Xml.XmlDocument namespace in the Output window:

    System.Xml.XmlDocument oxml = new System.Xml.XmlDocument();
  9. To organize the output, you can include a category as an optional, second input parameter of the WriteLine method. If you specify a category, the format of the Output window message is "category: message." For example, the first line of the following code displays "Field: The product name is Widget" in the Output window:

    Debug.WriteLine("The product name is " + sProdName,"Field");
    Debug.WriteLine("The units on hand are" + iUnitQty,"Field");
    Debug.WriteLine("The per unit cost is" + dUnitCost.ToString(),"Field");
    Debug.WriteLine("Total Cost is  " + (iUnitQty * dUnitCost),"Calc");
  10. The Output window can display messages only if a designated condition evaluates to true by using the WriteLineIfmethod of the Debug class. The condition to be evaluated is the first input parameter of the WriteLineIf method. The second parameter of WriteLineIf is the message that appears only if the condition in the first parameter evaluates to true.

    Debug.WriteLineIf(iUnitQty > 50, "This message WILL appear");
    Debug.WriteLineIf(iUnitQty < 50, "This message will NOT appear");
  11. Use the Assert method of the Debug class so that the Output window displays the message only if a specified condition evaluates to false:

    Debug.Assert(dUnitCost > 1, "Message will NOT appear");
    Debug.Assert(dUnitCost < 1, "Message will appear since dUnitcost < 1 is false");
  12. Create the TextWriterTraceListener objects for the Console window (tr1) and for a text file named Output.txt (tr2), and then add each object to the Debug Listeners collection:

    TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
    TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
  13. For readability, use the Unindent method to remove the indentation for subsequent messages that the Debug class generates. When you use the Indent and the Unindent methods together, the reader can distinguish the output as group.

    Debug.WriteLine("Debug Information-Product Ending");
  14. To make sure that each Listener object receives all its output, call the Flush method for the Debug class buffers:


Using the Trace Class

You can also use the Trace class to produce messages that monitor the execution of an application. The Trace and Debugclasses share most of the same methods to produce output, including the following:
  • WriteLine
  • WriteLineIf
  • Indent
  • Unindent
  • Assert
  • Flush
You can use the Trace and the Debug classes separately or together in the same application. In a Debug Solution Configuration project, both Trace and Debug output are active. The project generates output from both of these classes to allListener objects. However, a Release Solution Configuration project only generates output from a Trace class. The Release Solution Configuration project ignores any Debug class method invocations.

Trace.WriteLine("Trace Information-Product Starting ");

Trace.WriteLine("The product name is "+sProdName);
Trace.WriteLine("The product name is"+sProdName,"Field" );
Trace.WriteLineIf(iUnitQty > 50, "This message WILL appear");
Trace.Assert(dUnitCost > 1, "Message will NOT appear");
Trace.WriteLine("Trace Information-Product Ending");



Verify That It Works

  1. Make sure that Debug is the current solution configuration.
  2. If the Solution Explorer window is not visible, press the CTRL+ALT+L key combination to display this window.
  3. Right-click conInfo, and then click Properties.
  4. In the left pane of the conInfo property page, under the Configuration folder, make sure that the arrow points toDebugging.

    Note In Visual C# 2005 and in Visual C# 2005 Express Edition, click Debug in the conInfo page.
  5. Above the Configuration folder, in the Configuration drop-down list box, click Active (Debug) or Debug, and then click OK. In Visual C# 2005 and in Visual C# 2005 Express Edition, click Active (Debug) or Debug in the Configurationdrop-down list box in the Debug page, and then click Save on the File menu.
  6. Press CTRL+ALT+O to display the Output window.
  7. Press the F5 key to run the code. When the Assertion Failed dialog box appears, click Ignore.
  8. In the Console window, press ENTER. The program should finish, and the Output window should display the output that resembles the following

    Debug Information-Product Starting 
        The product name is Widget
        The available units on hand are100
        The per unit cost is 1.03
        Field: The product name is Widget
        Field: The units on hand are100
        Field: The per unit cost is1.03
        Calc: Total Cost is  103
        This message WILL appear
        ---- DEBUG ASSERTION FAILED ----
    ---- Assert Short Message ----
    Message will appear since dUnitcost  < 1 is false
    ---- Assert Long Message ----
        at Class1.Main(String[] args)  <%Path%>\class1.cs(34)
        The product name is Widget
        The available units on hand are100
        The per unit cost is 1.03
    Debug Information-Product Ending
    Trace Information-Product Starting 
        The product name is Widget
        Field: The product name isWidget
        This message WILL appear
    Trace Information-Product Ending
  9. The Console window and the Output.txt file should display the following output:

    The product name is Widget
        The available units on hand are 100
        The per unit cost is 1.03
    Debug Information-Product Ending
    Trace Information-Product Starting 
        The product name is Widget
        Field: The product name is Widget
        This message WILL appear
    Trace Information-Product Ending   
Note The Output.txt file is located in the same directory as the conInfo executable (conInfo.exe). Typically, this is the \bin folder where the project source is stored. By default, this is C:\Documents and Settings\User login\My Documents\Visual Studio Projects\conInfo\bin. In Visual C# 2005 and in Visual C# 2005 Express Edition, the Output.txt file is located in the following folder:
C:\Documents and Settings\User login\My Documents\Visual Studio 2005\Projects\conInfo\conInfo\bin\Debug

Complete Code Listing

using System;
   using System.Diagnostics;

   class Class1
      static void Main(string[] args)
         string sProdName = "Widget";
         int iUnitQty = 100;
         double  dUnitCost = 1.03;
         Debug.WriteLine("Debug Information-Product Starting ");
         Debug.WriteLine("The product name is "+sProdName);
         Debug.WriteLine("The available units on hand are"+iUnitQty.ToString());
         Debug.WriteLine("The per unit cost is "+ dUnitCost.ToString());

         System.Xml.XmlDocument oxml = new System.Xml.XmlDocument();

         Debug.WriteLine("The product name is "+sProdName,"Field");
         Debug.WriteLine("The units on hand are"+iUnitQty,"Field");
         Debug.WriteLine("The per unit cost is"+dUnitCost.ToString(),"Field");
         Debug.WriteLine("Total Cost is  "+(iUnitQty * dUnitCost),"Calc");

         Debug.WriteLineIf(iUnitQty > 50, "This message WILL appear");
         Debug.WriteLineIf(iUnitQty < 50, "This message will NOT appear");

         Debug.Assert(dUnitCost > 1, "Message will NOT appear");
         Debug.Assert(dUnitCost < 1, "Message will appear since dUnitcost  < 1 is false");

         TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
         TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
         Debug.WriteLine("The product name is "+sProdName);
         Debug.WriteLine("The available units on hand are"+iUnitQty);
         Debug.WriteLine("The per unit cost is "+dUnitCost);
         Debug.WriteLine("Debug Information-Product Ending");
         Trace.WriteLine("Trace Information-Product Starting ");

         Trace.WriteLine("The product name is "+sProdName);
         Trace.WriteLine("The product name is"+sProdName,"Field" );
         Trace.WriteLineIf(iUnitQty > 50, "This message WILL appear");
         Trace.Assert(dUnitCost > 1, "Message will NOT appear");

         Trace.WriteLine("Trace Information-Product Ending");




  • If the solution configuration type is Release, the Debug class output is ignored.
  • After you create a TextWriterTraceListener class for a particular target, TextWriterTraceListener receives output from the Trace and the Debug classes. This occurs regardless of whether you use the Add method of the Trace or theDebug class to add TextWriterTraceListener to the Listeners class.
  • If you add a Listeners object for the same target in the Trace and the Debug classes, each line of output is duplicated, regardless of whether Debug or Trace generates the output.

    TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
             TextWriterTraceListener myCreator = new TextWriterTraceListener(System.Console.Out);