Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Wednesday, May 27, 2015

c# - WPF Application for restarting Windows Service

I have windows service that runs on 11 different web & file servers.Every now and then our team has to restart these services. I use the sc command to do this at the command prompt
Example: 
stop service: sc \\server_name stop service_name
start service: sc \\server_name start service_name

It's hard to recollect the command if you are new to managing services.Remote logging in to the server to restart the service on 11 different servers is tedious.So I decided to create a small application that would let my team members to choose the server and restart the service.

I created a new project in Visual Studio,selected WPF application and gave it name RemoteRestartSVC.
Added a ListBox and Button to the XAML.The listbox contains the names of the server.I've added a progressbar to indicate the status(very basic progressbar)

Below is the App form and the XAML.
















<Window x:Class="RemoteWindowsSVCRestarter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Service Restarter" Height="469.762" Width="400" Background="#FFF9F9F9">
    <Grid Margin="0,0,0,391">
        <Label Content="Server Collection" HorizontalAlignment="Left" Margin="25,10,0,-15" VerticalAlignment="Top" FontWeight="Bold" Height="32" FontSize="16"/>
       
        <Button Name="RestartButton" Content="Restart Service" HorizontalAlignment="Left" Margin="131,295,0,-298" VerticalAlignment="Top" Width="135" Height="30" Click="RestartButton_Click" FontWeight="Bold" Background="#FFE8E8E8" RenderTransformOrigin="0.573,1.892" FontSize="14"/>
        <ListBox Name="ServiceListBox" HorizontalAlignment="Left" Height="234" Margin="25,47,0,-254" VerticalAlignment="Top" Width="345">
            <ListBoxItem Content="wk01" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="wk02" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="wk03" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="wk04" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="wk05" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="hf01" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="hf02" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="hf03" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="hf04" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="hf05" FontSize="14"></ListBoxItem>
            <ListBoxItem Content="hf06" FontSize="14"></ListBoxItem>
        </ListBox>
        <Label Content="Status:" HorizontalAlignment="Left" Height="31" Margin="5,351,0,-333" VerticalAlignment="Top" Width="49" FontWeight="Bold"/>
        <ProgressBar Name="RestartProgressBar" Margin="54,351,5,-332" />
    </Grid>
</Window>


Below is the code for the entire Application.It consists of two main methods.Stop Service and Start Service.

Stop Service method creates the process and calls the cmd.exe with the sc command to stop the service.It checks the status of the service and once the service is stopped, it returns a flag that indicates the service was successfully stopped.

Start Service method is similar to Stop Services method and it starts the service once the service status is Stopped.

using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace RemoteWindowsSVCRestarter
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void RestartButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                RestartButton.IsEnabled = false;
                RestartProgressBar.IsIndeterminate = true;
                ListBoxItem oServerItem = (ListBoxItem)ServiceListBox.SelectedItem;
                if (oServerItem != null)
                {
                    string sServerName = oServerItem.Content.ToString();

                    if (!string.IsNullOrEmpty(sServerName))
                    {
                        bool bStopFlag = StopService(sServerName);
                        if (!bStopFlag)
                            StartService(sServerName);
                    }
                }
                else
                {
                    MessageBox.Show("Select a server name before clicking restart service");
                }
            }
            catch 
            {
                MessageBox.Show("Unexpected error occurred while restarting the service");
            }
            RestartButton.IsEnabled = true;
            RestartProgressBar.IsIndeterminate = false;
        }

        /// <summary>
        /// Start the service
        /// </summary>
        /// <param name="sServerName"></param>
        private static void StartService(string sServerName)
        {
            ExecuteCommand(string.Format(@"/C sc \\{0} start MyService", sServerName));

            int iStartSeconds = 0;
            bool bStartFlag = false;
            ServiceController oRestartedService = new ServiceController("MyService", sServerName);
            while (oRestartedService != null && oRestartedService.Status != ServiceControllerStatus.Running)
            {
                Thread.Sleep(1000);
                iStartSeconds++;
                //Wait for 30 seconds for the service to start
                if (iStartSeconds == 30)
                {
                    bStartFlag = true;
                    break;
                }
                oRestartedService = new ServiceController("MyService", sServerName);
            }
            if (!bStartFlag)
                MessageBox.Show("Service restarted on server " + sServerName + " successfully");
            else
                MessageBox.Show("Alert: The service restart on server " + sServerName + " failed !");
        }

        /// <summary>
        /// Stop the service
        /// </summary>
        /// <param name="sServerName"></param>
        /// <returns></returns>
        private static bool StopService(string sServerName)
        {
            ExecuteCommand(string.Format(@"/C sc \\{0} stop MyService", sServerName));

            int iStopSeconds = 0;
            bool bStopFlag = false;
            ServiceController oService = new ServiceController("MyService", sServerName);
            while (oService != null && oService.Status != ServiceControllerStatus.Stopped)
            {
                Thread.Sleep(1000);
                iStopSeconds++;
                //Wait for 30 seconds for the service to stop
                if (iStopSeconds == 30)
                {
                    bStopFlag = true;
                    break;
                }
                oService = new ServiceController("MyService", sServerName);
            }
            return bStopFlag;
        }



        /// <summary>

        /// Creates a process and executes a command

        /// </summary>

        /// <param name="sCommand"></param>

        private static void ExecuteCommand(string sCommand)

        {

            Process oProcess = new Process();
            ProcessStartInfo oStartInfo = new ProcessStartInfo();
            oStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            oStartInfo.FileName = "cmd.exe";
            oStartInfo.Arguments = sCommand;
            oProcess.StartInfo = oStartInfo;
            oProcess.Start();
        }
    }
}
































Friday, May 15, 2015

c# - Extract data from Green Plum Warehouse Tables PostGreSql

Below are two ways to extract data from Green Plum Warehouse tables.For tables that are small the code is straightforward.However for tables with millions of rows the steps are a little different.
I have listed the code for both here.

I have used the Npgsql.dll to create the connection to progresql Green Plum Warehouse.Add it as a reference in your C# project.Documentation can be found here http://npgsql.projects.pgfoundry.org/

1) For tables with small number of rows.

using Npgsql;
using System;
using System.Configuration;

namespace GPExtract
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                ExtractData();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            Console.WriteLine("Done !");
            Console.Read();
        }
        private static void ExtractData()
        {
            using (NpgsqlConnection oConn = new                             NpgsqlConnection(ConfigurationManager.AppSettings["GP_CONNECTION_STRING"]))
            {
                       NpgsqlCommand oCmd = new NpgsqlCommand(@"select distinct(id),min(create_ts),max(create_ts) from mytable group by id order by id", oConn);
                       oCmd.CommandTimeout = int.Parse(ConfigurationManager.AppSettings["COMMAND_TIMEOUT"]);
                      NpgsqlDataReader oReader = oCmd.ExecuteReader();

                      using (StreamWriter oWriter = new StreamWriter(ConfigurationManager.AppSettings["OUTPUT_FOLDER_PATH"] + "myoutputfile.txt"))
                      {
                              while (oReader.Read())
                              {
                                        oWriter.WriteLine(string.Format("{0}\t{1}\t{2}", dr.GetValue(0) != null ? dr.GetValue(0).ToString() : "", dr.GetValue(1) != null ? GetFormattedDateTime(dr.GetValue(1).ToString()) : "", dr.GetValue(2) != null ? GetFormattedDateTime(dr.GetValue(2).ToString()) : ""));
                               }
                       }
             }
         }
    }
}

2) In case of millions of rows the extraction of all rows is done by creating file on Green Plum accessible share, a temporary external table and loading the external table with the data from the Green Plum warehouse table. 

using Npgsql;
using System;
using System.Configuration;

namespace GPExtract
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string sGpFilePath = ConfigurationManager.AppSettings["GP_FILE_PATH"];
                string sOutputFilePath = ConfigurationManager.AppSettings["OUTPUT_FILE_PATH"];
                ExtractData(sGpFilePath,sOutputFilePath);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            Console.WriteLine("Done !");
            Console.Read();
        }
        private static void ExtractData(string sGpFilePath,string sOutputFilePath)
        {
                if(!File.Exists(sGPFilePath)
               {
                          //Create a file for GP to load from external table
                          File.Create(sGpFilePath);

                          string sSql = @"CREATE WRITABLE EXTERNAL TEMP TABLE temp_mytable (  id character varying(22),
  min_create_dt integer,
  max_create_dt integer)LOCATION (
                'gpfdist://server-1:8082/mylogin/DATA/myfile.txt',
                'gpfdist://server-1:8083/mylogin/DATA/myfile.txt',
                'gpfdist://server-1:8084/mylogin/DATA/myfile.txt',
                'gpfdist://server-1:8085/mylogin/DATA/myfile.txt')
                FORMAT 'text' (delimiter E'\t' null '' )
                ENCODING 'LATIN9'
                DISTRIBUTED randomly;
            insert into temp_mytable
                select distinct(id),min(create_dt),max(create_dt) from  mytable group by id order by id;";

            using (NpgsqlConnection oConn = new NpgsqlConnection(ConfigurationManager.AppSettings["GP_CONNECTION_STRING"]))
            {
                oConn.Open();
                NpgsqlCommand oCmd = new NpgsqlCommand(sSql, oConn);
                oCmd.ExecuteNonQuery();
            }
             //Move the file from GP share to server
              File.Move(sGpFilePath, sOutputFilePath);
        }
    }
}

Note: The second program is parallel extract across ports 8082-8085 and is faster.

Tuesday, May 5, 2015

c# - Call exe with incremental filenames as command line arguements

I work on projects involving data processing and more often than not, we end up processing files created over months.This requires that the data processing program is called over number of times.Instead of doing it manually I created this small utility program to automate the processing of these files.

Below I have listed the code for sequential/batch processing of files using a program as well as parallel processing of files using the same program.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IncrementCmdLineArgs
{
    class Program
    {
        static void Main(string[] args)
        {
            int iStartCounter = int.Parse(ConfigurationManager.AppSettings["START_COUNTER"]);
            int iEndCounter = int.Parse(ConfigurationManager.AppSettings["END_COUNTER"]);
            string sInputFile = ConfigurationManager.AppSettings["INPUT_FILENAME"];
            string sOutputFile = ConfigurationManager.AppSettings["OUTPUT_FILENAME"];
            string sExeName = ConfigurationManager.AppSettings["EXE_NAME"];
            string sWorkingDir = ConfigurationManager.AppSettings["WORKING_DIR"];
            string sInputParam = ConfigurationManager.AppSettings["INPUT_PARAM_NAME"];
            string sOutputParam = ConfigurationManager.AppSettings["OUTPUT_PARAM_NAME"];

            try
            {
                for (int iCounter = iStartCounter; iCounter <= iEndCounter; iCounter++)
                {
                    Process oProc = new Process();
                    oProc.StartInfo.FileName = sExeName;
                    oProc.StartInfo.WorkingDirectory = sWorkingDir;
                    oProc.StartInfo.CreateNoWindow = true;
                    oProc.StartInfo.Arguments = string.Format(" {0}={1} {2}={3}", sInputParam, sInputFile + iCounter + ".txt", sOutputParam, sOutputFile + iCounter + ".txt");
                    Console.WriteLine(string.Format(" {0}={1} {2}={3}", sInputParam, sInputFile + iCounter + ".txt", sOutputParam, sOutputFile + iCounter + ".txt"));
                    oProc.Start();
                    oProc.WaitForExit();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            Console.Write("Done.Press any key to exit !");
            Console.Read();
        }
    }
}


The parallel version is below

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IncrementCmdLineArgs
{
    class Program
    {
        static void Main(string[] args)
        {
            int iStartCounter = int.Parse(ConfigurationManager.AppSettings["START_COUNTER"]);
            int iEndCounter = int.Parse(ConfigurationManager.AppSettings["END_COUNTER"]);
            string sInputFile = ConfigurationManager.AppSettings["INPUT_FILENAME"];
            string sOutputFile = ConfigurationManager.AppSettings["OUTPUT_FILENAME"];
            string sExeName = ConfigurationManager.AppSettings["EXE_NAME"];
            string sWorkingDir = ConfigurationManager.AppSettings["WORKING_DIR"];
            string sInputParam = ConfigurationManager.AppSettings["INPUT_PARAM_NAME"];
            string sOutputParam = ConfigurationManager.AppSettings["OUTPUT_PARAM_NAME"];

            try
            {
                 Parallel.For(iStartCounter, iEndCounter, iCounter =>
                {
                    Process oProc = new Process();
                    oProc.StartInfo.FileName = sExeName;
                    oProc.StartInfo.WorkingDirectory = sWorkingDir;
                    oProc.StartInfo.CreateNoWindow = true;
                    oProc.StartInfo.Arguments = string.Format(" {0}={1} {2}={3}", sInputParam, sInputFile + iCounter + ".txt", sOutputParam, sOutputFile + iCounter + ".txt");
                    Console.WriteLine(string.Format(" {0}={1} {2}={3}", sInputParam, sInputFile + iCounter + ".txt", sOutputParam, sOutputFile + iCounter + ".txt"));
                    oProc.Start();
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            Console.Write("Done.Press any key to exit !");
            Console.Read();
        }
    }
}

Monday, December 8, 2014

c# - Create child processes in parallel and wait till all child processes terminate

In one of my projects I had to invoke an external exe in parallel for carrying out simple command to execute a script in Hadoop. The parent process had to wait till all the child processes would complete execution on HDFS and then would carry on other steps.

Below is a simple example to achieve the same.In this example I have created an exe to write to a file i.e. SimpleWrite.exe. I call this exe in parallel (5 instances in parallel) and pass in an argument.The parent process that calls this exe waits till all instances of SimpleWrite completes and then continues its steps.


Program to call external exes in Parallel

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProcessWait

{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {

                Console.WriteLine("Parent process started executing...");

                Console.WriteLine("Parent process is starting child processes...");
                Parallel.For(0, 5, iIndex =>
                {
                    Console.WriteLine("Child process {0} started",iIndex);
                    NewProcess(iIndex);
                });
                Console.WriteLine("All child processes completed.Waiting for user to press the enter key !!!");
                Console.Read();
                Console.WriteLine("Parent process to continue execution.");
                for (int iIndex = 0; iIndex < 10000; iIndex++)
                {
                    Console.WriteLine(iIndex.ToString());
                }
                Console.WriteLine("Parent process completed execution.");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.Read();
        }

        private static void NewProcess(int iIndex)

        {
            Process oRunIndex = new Process();
            oRunIndex.StartInfo.FileName = "SimpleWrite.exe";
            oRunIndex.StartInfo.WorkingDirectory = @"c:\Data\";
            oRunIndex.StartInfo.CreateNoWindow = true;
            oRunIndex.StartInfo.Arguments = string.Format("{0}",iIndex);
            
            oRunIndex.Start();
            oRunIndex.WaitForExit();
        }
    }

}



SimpleWrite.exe code

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace SimpleWrite

{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                string sIndex = args[0];
                using(StreamWriter oWriter = new StreamWriter(@"c:\Data\" + sIndex +".txt"))
                {
                    for (int iIndex = 0; iIndex < 100000; iIndex++)
                    {
                        Console.WriteLine(iIndex.ToString());
                        oWriter.WriteLine(iIndex.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.Read();
            }
        }
    }
}


Output

















Friday, November 21, 2014

c# - Using Custom Partition in Task Parallel Library TPL

For one of my project I wanted to take all the files in a folder and merge 100 files together into 1 file resulting in a smaller set of files more or else of similar sizes.I had around 30 thousand files which are merged to 300 files.I used custom partitioner in TPL to do this.Below is the sample code that I started with.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CustomPartitioner

{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                int iFileNumber = 0;
                string sInputFolderPath =ConfigurationManager.AppSettings["INPUT_FOLDER_PATH"];
                string[] sFileList = Directory.GetFiles(sInputFolderPath, "*.gz");
               
                var rangePartitioner = Partitioner.Create(0, sFileList.Length, 100);//100 is the merge size
               
                Parallel.ForEach(rangePartitioner, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (range, loopState) =>
               {
                        try
                       {
                                using (StreamWriter oWriter = new StreamWriter(@"c:\Index_"+ Interlocked.Increment(ref iFileNumber)+".txt"))
                               {
                                    for (int iIndex = range.Item1; iIndex < range.Item2; iIndex++)
                                   {
                                        try
                                       {
                                               oWriter.WriteLine(string.Format("{0}\t{1}", sFileList[iIndex], iIndex));
                                        }
                                        catch (Exception ex)
                                       {
                                            Console.WriteLine(ex.Message);
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                                Console.WriteLine(ex.InnerException);
                                Console.WriteLine(ex.StackTrace);
                            }
                 });           
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.InnerException);
                Console.WriteLine(ex.StackTrace);
            }
            Console.WriteLine("Done !!!");
            Console.Read();
        }
    }
}

c# - Load large text files to database

Two ways to load a large text files to a table in the database are using
  • bcp command with xp_cmdShell enabled on the database server
  • bulk insert
The files I load are in the range of 10-15 GB tab delimited text files.These files are created by daily processes and are stored on file servers running Windows Server 2008.After the files are created they are loaded to SQL Server Database.

bcp command with xp_cmdShell


using System;
using System.Text;
using System.Configuration;
using System.IO;
using System.Data.SqlClient;

public class LoadLargeFileToDB

{ 
          static void Main()
          {
                 string sConnectionString = "server=MyServer;database=MyDatabase;uid='username';pwd='password'";
                 string sServer = "MyServer";
                 string sTableName = "MyTable";
                 string sImportFilePath = @"\\Servername\DriveName\SharedFolder\FileName.txt";


                 try
                 {
                      if (!File.Exists(sImportFilePath))
                              throw new Exception("Error importing BCP file = " + sImportFilePath + ". File does not exists.");
                                     
                      using (SqlConnection oSqlConnection = new SqlConnection(sConnectionString))
                      {
                             oSqlConnection.Open();
                             SqlCommand oSqlCommand = new SqlCommand("exec xp_cmdShell 'bcp " + sTableName + " in " + sImportFilePath + " -c -T -S " + sServer + "'", oSqlConnection);
                             oSqlCommand.CommandTimeout = 120000;
                             oSqlCommand.ExecuteNonQuery();
                      }
                }
                catch (Exception ex)
                {
                      Console.Error(ex.Message);
                      Console.Error(ex.InnerException);
                      Console.Error(ex.StackTrace);
                }
         }
}


Bulk insert

using System;
using System.Text;
using System.Configuration;
using System.IO;
using System.Data.SqlClient;

public class LoadLargeFileToDB

{ 
          static void Main()
          {
                 string sConnectionString = "server=MyServer;database=MyDatabase;uid='username';pwd='password'";
                 string sServer = "MyServer";
                 string sTableName = "MyTable";
                 string sImportFilePath = @"\\Servername\DriveName\SharedFolder\FileName.txt";


                 try
                 {
                      if (!File.Exists(sImportFilePath))
                              throw new Exception("Error importing BCP file = " + sImportFilePath + ". File does not exists.");
                                     
                      using (SqlConnection oSqlConnection = new SqlConnection(sConnectionString))
                      {
                             oSqlConnection.Open();
                             SqlCommand oSqlCommand = new SqlCommand("bulk insert "+ sTableName +" from '"+ sImportFilePath +"'";, oSqlConnection);
                             oSqlCommand.CommandTimeout = 120000;
                             oSqlCommand.ExecuteNonQuery();
                      }
                }
                catch (Exception ex)
                {
                      Console.Error(ex.Message);
                      Console.Error(ex.InnerException);
                      Console.Error(ex.StackTrace);
                }
         }
}