Tuesday, 13 June 2017

How to use C# Delegates?


Writing this mostly for when I need a quick snippet, but in case someone finds this useful.

The C# delegate beast is an object which holds references to methods (think “object-like method” that can be strong typed and therefore checked, unlike C++ function pointers), so this makes them super useful to pass as method parameters or to run a bunch of methods in event callbacks. This particular example uses Reactive Extensions so you will need to install them with Nuget.

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

using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Subjects;

namespace DelegateTest
{

    // Delegate definition. 
    public delegate void ProcessDelegate();

    public class Processor {

        // Reactive observable. 
        public Subject<Task> Observable = new Subject<Task>();

        // Task to process. 
        public void Process(Task Process) {
            Process.Start();
        }

        // Delegate instance. 
        public ProcessDelegate ProcessInstance;

        // Constructor. 
        public Processor(IEnumerable<ProcessDelegate> Processes, ProcessDelegate ProcessCompleted)
        {
            // Initialise delegate instance. 

            // Add process methods. 
            foreach (var Process in Processes)
                ProcessInstance += Process;
            
            // Add process completed method. 
            ProcessInstance += ProcessCompleted; 
        }       

    }







    public class Program
    {

        static void Main(string[] args)
        {

            Console.WriteLine("Starting process test ...");

            // Create test process object. 
            Processor Test = new Processor(

                // Delegate implementations. 
                new List<ProcessDelegate>
                {
                    () => {
                        string Result = "";
                        for(int Index = 0; Index < 100; Index++)
                            Result += Index.ToString();
                        Console.WriteLine("Process 1 finished = " + Result.Substring(0, 10) + " ... ");
                    },
                    () => {
                        string Result = "";
                        for(int Index = 0; Index < 100; Index++)
                            Result += Index.ToString();
                        Console.WriteLine("Process 2 finished = " + Result.Substring(0, 10) + " ... ");
                    },
                    () => {
                        string Result = "";
                        for(int Index = 0; Index < 100; Index++)
                            Result += Index.ToString();
                        Console.WriteLine("Process 3 finished = " + Result.Substring(0, 10) + " ... ");
                    }
                }, 

                () =>
                {
                    Console.WriteLine("Processes completed ... ");
                }

            );


            // Assign processes/delegate to an observable task. 
            Test.Observable.Subscribe(
                Value => Test.Process( Value ), 
                () =>
                {
                    Console.WriteLine("Observable OnCompleted called ... ");
                }
            );

            // Run action on the observable. 
            // Assigning delegate implementations. 
            Test.Observable.OnNext(
                new Task(new Action(Test.ProcessInstance))); 

            Console.WriteLine("Carrying on with some other tasks ..."); 
            

            Console.ReadLine(); 

        }

    }

}


Handy links:


Monday, 20 February 2017

How to stay awake at work (after doing weekend work).

Over the weekend I had to do a bunch of coding and crack my brain for a solution.
Monday morning I was back at it again coding after only a few hours sleep, not to mention having to do boring administration work at work. I always like to get my good 8 hours of ole sleep, so not like I do this all the time!

I knew that I would suffer a lot, because we have to keep up a high level of concentration at work. After some googling I found some stuff that I thought would help inspire me to keep awake, but I then thought to share my own spin on it.

So my top tips are:

1. Switch up your tasks when you feel yourself drifting off.
Work on something else for a bit or something more exciting, stay away from boring stuff.

2. Play music, youtube etc.
I hit the good old tube, I find some chillout mixes to be particularly effective.

3. Take a few breaks throughout the day.
Can take some strategic toilet breaks and close your eyes to rest them.

4. Also stare into the distance/out of a window (so called "eye breaks").

5. Eat some tasty food and drink plenty of water.
Of course glug down a coffee =) Listen to your body, it doesn't have to be super healthy in my books.

6. This my favourite one, sneak a bunch of drawing in your notebook.
Drawing can open up your imagination, it helps you to create ideas, and activates your right brain. This can potentially take the load off your left brain doing all the work and therefore makes you feel less tired.


Friday, 17 February 2017

Creating XML, XSD, validating Test Instance XML and Text (Native) Files, and tips for Biztalk project issues in Visual Studio 2013/5

This is just a quick memo for myself regarding XML, XSD and creating/validating test instances of XML and Text files.

XML (Extensible Markup Language) is pretty much like a text file and can be opened as such, but with the addition of tags to describe the text information. Extensible here means that even if we make modifications to the XML text file, it is still usable by other users and software. In other words changes can be made dynamically to the XML file without it causing problems in software that uses the XML. More info here: www.w3schools.com/xml/xml_whatis.asp

XSD (XML Schema Definition) and can be used to control how exactly an XML document can appear. XML files do not need XSD files, but if you want a mechanism to check the structure and information is correct within an XML file, then an XSD file can be used. For example, an XSD file can define what tags are allowed including their nesting structure, the names of the tags and the order in which they appear in an XML file. The XSD file can also define what type of information the tags can contain, as well as their default value or an expected (fixed) value.

Creating an XSD file 
There are two ways to create an XSD file, firstly by hand, for example in Visual Studio you can use the Schema Editor and using an XML file or other reference create the structure.
  creating-new-xsd

The second method involves generating the XSD file from an XML file. This method will not give you control of what values and information the tags can contain. This can be added later using the Schema Editor, once the file is generated.

Validating / Testing the XSD 
Once you have created the XSD you can do a simple schema check in Visual Studio, right-click the XSD file and select Validate Schema.

validate-an-xsd-file

Creating a Test Instance XML/Text (Native) file 
Once your XSD has been created, you can in Visual Studio set the name of the test instance file and select type as either XML or Native Text file in the XSD properties. Then right-click the XSD and click Generate Instance.

generating-a-test-instance

Validating / Testing the Test Instance XML/Text (Native) file 
Similarly, once you have a test instance of the XML or Text (Native) file you can then test and validate it against your XSD file. Click your XSD file in Visual Studio, under Properties, go to General > Input Instance Filename and set it to the file name of the test instance or an XML file you created. Then set General > Validate Instance Input Type to XML or Native file depending on the type of file. Right-click the XSD and click Validate Instance to test your XSD file definitions against the XML or Text (Native) file.

validating-a-test-instance

Tips:

Flat File Schemas 
https://msdn.microsoft.com/en-us/library/aa561057.aspx?f=255&MSPPError=-2147217396

Unexpected data found while looking for: $Delimited$ 
https://social.msdn.microsoft.com/Forums/en-US/be46c68d-c36c-4713-b2ff-f79cda93ba7d/unexpected-data-found-while-looking-for-delimited?forum=biztalkgeneral

Postfix, prefix and infix 
 http://biztalk06.blogspot.co.uk/2008/10/postfix-infix-and-prefix.html

Early Termination with Position Flat Files
https://blogs.msdn.microsoft.com/skaufman/2004/05/07/early-termination-with-position-flat-files/

BizTalk Server: Teach me something new about Flat Files (or not) – Delimited Flat File Schema Optimizations 
https://blog.sandro-pereira.com/2015/10/23/biztalk-server-teach-me-something-new-about-flat-files-or-not-delimited-flat-file-schema-optimizations/

Viewing XSD as code 
http://stackoverflow.com/questions/3265971/viewing-xsd-as-code

Problem deploying Biztalk Application - Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) 
http://stackoverflow.com/questions/3460750/problem-deploying-biztalk-application-access-is-denied-exception-from-hresul

Wednesday, 2 November 2016

Using Sql Profiler 2014 to debug SqlCommand in C#

I found the SqlCommand C# class is tricky to debug in Visual Studio if you are using SqlParameter and you want to see the exact statement being executed on the server.

First of all, run a test query on a table in the database, you will need to run your C# application to generate the query. This will create an entry in the process list for that database, which you can filter in Sql Profiler 2014.

select * from master..sysdatabases
select * from master.sysprocesses where dbid = 11

Look for the database id (dbid) of the database you ran the query on, and then find all processes running for that database. In my case, the dbid was 11 and I ran the query to get all processes for that database.

Scroll to the program_name and copy the value.
Note: Remove any extra spaces, as the Sql field in the result will be padded with spaces.

Getting program name.jpg



Open up the Profiler, create a new trace. In my case, I only want to see the final command being executed, so I ticked SQL:BatchCompleted only, and unticked all the other events.

Click 'Column Filters...', under 'ApplicationName' paste in the value you got from the process list (program_name).

Remember to remove any extra spaces, otherwise the Profiler will not be able to match it correctly, this is a common mistake!


New trace settings.jpg 


Run your trace and execute your Sql commands either from a test query or your C# application.

Trace completed2.jpg


You should notice that the commands are easily checked in Sql Profile 2014 now and you can test your C# application by matching its program_name from master..sysprocesses.

You can filter the events neatly to only show the application you are debugging by ticking SQL:BatchCompleted event and filtering by Column item ApplicationName.


Thursday, 13 October 2016

The "Bus Factor"

I had not heard this before but a bus factor is the risk that if one of the developers in the team were to be hypothetically hit by a bus, then this reflects on how it would affect a project.

One of the obvious factors would be an immediate deficit in knowledge and experience. But it also highlights the problem of a single point of failure, where only one person is responsible for particular areas of the project.

I thought about this and it seems to me that there should be more paired programming, so that junior members are exposed to the processes of the more experienced developers. Over time and with experienced supervision, in a kind of mentor relationship, both parties will exchange important practical knowledge and experience until juniors could perform similar work as more experienced developers.

The idea is to have as many people as possible with practical knowledge about the project, so that anyone can jump in and take up the slack when the 'person hit by the bus' is not available.



Wednesday, 14 September 2016

Disappearing TabPage Title Text when adding to a SplitContainer Panel

On a project we had a problem where TabPage title text would disappear when a TabPage was added to a SplitContainer Panel. For a while I did not know how to solve this issue because it was not obvious what was causing it.

disappearing-tab-headertitle-text-in-splitcontainer

After some research, it appeared to be a known Microsoft issue as described in this post: https://bytes.com/topic/c-sharp/answers/457492-tabpage-text-disapearing

However, I was not convinced this would be an ideal solution. I wanted something quick and simple. I ran a test and noticed when adding TabPages to the test SplitContainer, that the TabPage title did not disappear. Also the test did not contain a MenuStrip control, which the client app did.

Then I suspected the menu was causing the problem, because it was overlapping the TabPage title, and the title text was not disappearing at all.

To solve it, I simply added some padding to the SplitContainer panel, to push it below the MenuStrip in the client application. Here is some code.

SplitContainer1.Panel1.Padding = new Padding(0, 27, 0, 0); 

27 represents the default height in pixels of a MenuStrip, the top padding on the SplitContainer panel should then clear the menu and the title text will show.

Friday, 26 August 2016

Accessing Microsoft Excel without using Interop

In a recent project, the server we deployed to did not have Microsoft Office installed, it only had Microsoft Excel loaded for some reason.

We could not use the C# Microsoft Interop Services to access Excel, and it came up with the error "Could not load file or assembly 'Microsoft.Office.Interop.Excel', or one of its dependencies. The system cannot find the file specified."


Could not load Interop

After searching and not finding much about accessing Excel without using Interop, I stumbled upon an old post from decades ago about using Visual Basic and its CreateObject, GetType, InvokeMember and CallByName functions in the Interaction interface.

Such a godsend, after a few tests I was then able to access Excel through its COM component.


You can check Workbook member properties here: https://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel._workbook_members.aspx


Here is some code to show the process to access the Excel COM Component, it may need adjusting for your own project.

using System.Windows.Forms;
using Microsoft.VisualBasic;
using System.Reflection;
using Microsoft.Office.Interop;

PrintDialog PrinterForm = new PrintDialog( );
string FileNamePath = "C:\\ExcelFile.xlsx";

// Create COM object to Excel Application.
Object XLApp = Interaction.CreateObject("Excel.Application");

// Get COM object Excel Workbooks interface.
XLApp.GetType().InvokeMember(
"Workbooks", BindingFlags.GetProperty | BindingFlags.Public, 
null, XLApp, null);

// Test getting Workbooks interface from XLApp COM Object.
Object XLWorkbooks = Interaction.CallByName(
XLApp, "Workbooks", Microsoft.VisualBasic.CallType.Get, null);

// Call Open method on Workbooks interface.
// Pass it the filename parameter.
// Excel COM object should then issue command to Excel.
// Excel to open the filename (xlsx).
Interaction.CallByName(XLWorkbooks, "Open", 
Microsoft.VisualBasic.CallType.Method, FileNamePath);

// Debug (Workbooks object).
// string WorkbooksString = XLWorkbooks.ToString();
// MessageBox.Show("WorkbooksString = [" + WorkbooksString + "]", "Debug");
// Show print form to user.
if (PrinterForm.ShowDialog() == DialogResult.OK)
{
// Cast XLWorkbooks to Workbooks collection.
Microsoft.Office.Interop.Excel.Workbooks XLWorkbooks2 = (Microsoft.Office.Interop.Excel.Workbooks)XLWorkbooks;

// Iterate Workbooks collection.
foreach (Microsoft.Office.Interop.Excel.Workbook XLWorkbook in XLWorkbooks2)
{
// Debug (XLWorkbook).
// MessageBox.Show("XLWorkbook String = [" + XLWorkbook.ToString() + "]", "Debug");
// Print workbook to user specified printer.
XLWorkbook.PrintOutEx(
Type.Missing, Type.Missing, Type.Missing, 
Type.Missing, printDialog.PrinterSettings.PrinterName);

// Close workbook.
XLWorkbook.Close(false);
}
}

// Close COM Excel.
Interaction.CallByName(
XLApp, "Quit", 
Microsoft.VisualBasic.CallType.Method, null);