December 14, 2008

Using Process

// Starting a windows program with Process
private void StartXXX()
{
 string dir = @"C:\CODE\blahblahblah\Server\XXX\bin";
 string exe = "XXX.exe";

 Process shellRunProcess = new Process();
 shellRunProcess.StartInfo.FileName = exe;
 shellRunProcess.StartInfo.WorkingDirectory = dir;
 shellRunProcess.StartInfo.Arguments = "-c";
 shellRunProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
 shellRunProcess.Start();
}


// Terminating a process
private void TerminateXXX()
{
 // Remove the '.exe' extension when looking for the process
 Process[] processes = Process.GetProcessesByName("XXX"); 
 foreach (Process p in processes)
 {
  p.CloseMainWindow();
 }
}
When running a batch file or console type application, you can start if like so and have the output redirected to a control in your form. See this link for more information Launching A Console Process And Redirecting the Output
private void StartProcessWithoutWindow()
{
 Process process = new Process();
 process.StartInfo.UseShellExecute = false;
 process.StartInfo.RedirectStandardOutput = true;
 process.StartInfo.RedirectStandardError = true;
 process.StartInfo.CreateNoWindow = true;
 process.StartInfo.FileName = FileName;
 process.StartInfo.Arguments = Arguments;
 process.StartInfo.WorkingDirectory = WorkingDirectory;
 process.Start();
}

String Formatting

String Formatting Concise blog on c# string formatting Padding a number out with spaces or zeroes
public void TestNumberPaddingForString()
{
 int x = 1017;
 string msg = "->" + x.ToString("D8") + "<-";
 string msg2 = "->" + string.Format("{0:D8}", x) + "<-";
 Console.WriteLine(msg);
 Console.WriteLine(msg2);
 msg = "->" + x.ToString().PadLeft(8) + "<-";
 msg2 = "->" + string.Format("{0:D}", x).PadLeft(8) + "<-";
 Console.WriteLine(msg);
 Console.WriteLine(msg2);
 msg = "->" + x.ToString().PadRight(8) + "<-";
 msg2 = "->" + string.Format("{0}", x).PadRight(8) + "<-";
 Console.WriteLine(msg);
 Console.WriteLine(msg2);
}
Produces output:

->00001017<-
->00001017<-
->    1017<-
->    1017<-
->1017    <-
->1017    <-

Setting Form or Application Icon

To set the Icon of a WinForm application go to the Project properties and set the icon to use within the 'Application' tab. If you are using 'Icon and Manifest' option you can select the Icon into the text box. Setting a Form Icon Set this with the 'Icon' property of the form

Adding App Icon To Taskbar

Adding you WinForm app to the taskbar Some missing points 1. As it is, when minimized, the window will appear both in the taskbar (minimised) in the system tray. To fix this set the main form property 'ShowInTaskbar' to false;
public XXXForm()
{
 InitializeComponent();
 this.ShowInTaskbar = false;
}
Change the 'notifyIcon_DoubleClick':
private void notifyIcon_DoubleClick(object sender, EventArgs e)
{
 Show();
 ShowInTaskbar = true;
 WindowState = FormWindowState.Normal;
}
Also I prefer to override the resize rather than pick up an event
protected override void OnResize(EventArgs e)
{
 base.OnResize(e);
 // Hide the form when it is minimised
 if (FormWindowState.Minimized == WindowState)
  Hide();
}
I also added a menu timer to ensure that when the mouse leaves the context menu the menu dissappears after a short time (3 seconds). Aagh, next bit is for WPF based taskbar app.
using System.Windows.Threading;
...
public partial class AppMainWindow : Window
{
...
  private DispatcherTimer timer = null;
...
    public AppMainWindow ()
    {
      InitializeComponent();
...
      contextMenu = (ContextMenu)this.FindResource("NotifierContextMenu");
      contextMenu.Closed += new RoutedEventHandler(menu_Closed);
      contextMenu.Opened += new RoutedEventHandler(menu_Opened);
      CreateMenuTimer();
    }
...
  #region Timer

  private void CreateMenuTimer()
  {
    const int MILLISECOND = 10000;
    timer = new DispatcherTimer();
    // Disable (stop) it 
    timer.IsEnabled = false;
    // Set timer event interval
    timer.Interval = new TimeSpan((long)(3000 * MILLISECOND));
    // Timer events
    timer.Tick += new EventHandler(timer_Tick);
  }

  void timer_Tick(object sender, EventArgs e)
  {
    if (contextMenu.IsOpen)
    {
      if (contextMenu.IsMouseOver && contextMenu.IsMouseDirectlyOver)
      {
        contextMenu.IsOpen = false;
      }
    }
    else
    {
      timer.Stop(); 
    }
  }

  void menu_Opened(object sender, RoutedEventArgs e)
  {
    timer.Start();
  }

  void menu_Closed(object sender, RoutedEventArgs e)
  {
    timer.Stop(); 
  }

  #endregion Timer



November 11, 2008

Cool Commands

Cool commands for VS2008 OR Alternative or use CoolCommands here. 1. Unzip coolcommandsrtm.zip (ie: c:\coolcommands ) 2. Open VS 2005 command prompt 3. run c:\coolcommands\install.bat but download from here.

IEnumerable, IEnumerator and foreach Implementation

IEnumerable - Provides an IEnumerator that can traverse a collection

public IEnumerator GetEnumerator();

IEnumerator - Methods to traverse a collection

public object Current;
public bool MoveNext();
// Ignore the next method, it should be marked as [Obsolete], just use GetIterator()
public void Reset(); 

This code shows in a simplistic manner how foreach is implemented using iterators. See here for more details

// foreach Implementation
IEnumerable enumerable = (IEnumerable)targObject;
IEnumerator it = enumerable.GetEnumerator();
while(it.MoveNext())
{
    DoSomething(it.Current);
}

Configuring Log4Net Programmatically

Configuring Log4Net Programmatically Set the logging level of the logger
public string LoggingLevel
{
 get
 {
  log4net.Repository.Hierarchy.Logger logger = (log4net.Repository.Hierarchy.Logger)m_log.Logger;
  return logger.Level.Name;
 }
 set
 {
  if (!string.IsNullOrEmpty(value))
  {
   log4net.Repository.Hierarchy.Logger logger = (log4net.Repository.Hierarchy.Logger)m_log.Logger;
   logger.Level = logger.Hierarchy.LevelMap[value];
  }
 }
}
Example configuring Appenders for a log
#region log4net

internal class LoggingConfigurer
{
    public static readonly string DefaultLayoutPattern = "%d [%t]%-5p %c [%x] - %m%n ";
    public static readonly string DefaultFileName = "XXXLog.txt";
    public static readonly string FileAppendarName = "XXXRFA";

    // Configure the logger programmatically. 
    public static void ConfigureLogging(ILog log)
    {
        bool isConfigured = log.Logger.Repository.Configured;
        if (!isConfigured)
        {
            // Setup RollingFileAppender
            RollingFileAppender rollingFileAppender = new RollingFileAppender();
            rollingFileAppender.Layout = new PatternLayout(DefaultLayoutPattern);
            rollingFileAppender.MaximumFileSize = "100KB";
            rollingFileAppender.MaxSizeRollBackups = 5;
            rollingFileAppender.RollingStyle = RollingFileAppender.RollingMode.Size;
            rollingFileAppender.AppendToFile = true;
            rollingFileAppender.File = DefaultFileName;
            rollingFileAppender.Name = FileAppendarName;
            rollingFileAppender.ActivateOptions(); // IMPORTANT, creates the file
            BasicConfigurator.Configure(rollingFileAppender);
#if DEBUG
            // Setup TraceAppender
            TraceAppender ta = new TraceAppender();
            ta.Layout = new PatternLayout(DefaultLayoutPattern);
            BasicConfigurator.Configure(ta);
#endif
        }
    }
}

#endregion log4net  
usage, when initialising your logger:
log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
LoggingConfigurer.ConfigureLogging(log);
Here is an example where the log file name is changed:
private static void RenameLogFile(string newLogFileName)
{
    var rfa = LogManager.GetRepository().GetAppenders().
         OfType<RollingFileAppender>().
         FirstOrDefault(appender => 
            appender.Name == LoggingConfigurer.FileAppendarName);
    if (rfa != null)
    {
        rfa.File = newLogFileName + ".txt";
        rfa.ActivateOptions();
    }
}