Dec 15, 2008

Cannot Uninstall / Install Windows Service App

Project: A windows Service and a Windows Service Installer Project.
Problem: When after some code changes I tried to uninstall the Windows service, I got the following error message
"An exception occurred while uninstalling. This exception will be ignored and the uninstall will continue. however, the application might not be fully uninstalled after the uninstall is complete.--> The specified service does not exist as an installed service"

Cause: From the internet I came to know that it could be for various reasons.
1. Somewhere along the way, I might have a ServiceInstaller object. and gave the ServiceInstaller a name which looks like this: serviceInstaller1.ServiceName = "Hello-World Service 1";
When you renamed your service in Windows Explorer, you did not rename theServiceName in the code. The system is attempting to overwrite the sameservice.Rename this value as well.

2. Make sure your install and uninstall code is 100% (not 99.999995%) exception proof. If an exception is thrown during the install or uninstall process your system may be left in a permanently unstable position [twice in the last three years I had to do a complete wipe and re-format to properly cleanup a service that had thrown an exception.....
3. I didn't stop my service before uninstalling it and things got ugly.
Solution:
Links: 1. http://hardware.mcse.ms/archive97-2005-7-159894.html
2. http://social.microsoft.com/Forums/en-US/netfxbcl/thread/cdd24c4c-ad3e-4704-ae5e-7749cdae7521

1. Open the CPrompt
2. Move to the folder containing the msi file

3. invoke msiexec /fv install_filename.msi
where install_filename is the name of your msi install file.
/fv - is a repair option that tells the installer to "run from source and recache locl package"
for a list of all the msiexec commands just type in msiexec at the command prompt.



Nov 5, 2008

Problem: in VS.Net IDE the "Server Explorer" doesn't appear

Problem:
1. In the Vs.net IDE, on clicking the View>Server Explorer, the "Server Explorer" tab doesn't appear. Neither does anything happen when clicking on Tools>Connect To Server or Tools>Connect To Database.

Solution:
1.Open VS command prompt
2.Type - devenv /resetuserdata
Wait for sometime since it would take some time.

Aug 29, 2008

Nullable types in C# 2.0

1. Nullable types in C# 2.0: http://www.dotnet-friends.com/articles/csharp/artincsa181af45-b7bf-4800-9b25-519e5f4e7943.aspx
2. What's New in the C# 2.0 Language and Compiler : http://msdn.microsoft.com/en-us/library/7cz8t42e(VS.80).aspx
3. C Sharp (programming language) in Wikipedia: http://en.wikipedia.org/wiki/C_Sharp_(programming_language)
4. C# in Answers.com : http://www.answers.com/topic/c-sharp-programming-language

Equating Nullable Types : strange ways

C# has some interesting rules for operators on nullable types. Given:
int? x ; int? y ;
Laws of transitivity tells us that if x is equal to y, (x == y), then x<= y would be true too. Well not in C#. With this function:
static void test(int? arg1, int? arg2)

{
Console.WriteLine("arg1 == arg2 returns {0}", (arg1 == arg2));
Console.WriteLine("arg1 <= arg2 returns {0}", (arg1 <= arg2));
}

The output in some cases will be:
arg1 == arg2 returns True

arg1 <= arg2 returns False



A comparison operator (==, !=, <, >, <=, >=) has a lifted form when the operand types are both non-nullable value types and the result type is bool. The lifted form of a comparison operator is formed by adding a ? modifier to each operand type (but not to the result type). Lifted forms of the == and != operators consider two null values equal, and a null value unequal to a non-null value. Lifted forms of the <, >, <=, and >= operators return false if one or both operands are null.


When one of the operands of the == or != operator is the null literal, the other operand may be of any nullable type regardless of whether the underlying value type actually declares that operator. In cases where no operator == or != implementation is available, a check of the operand’s HasValue property is substituted. The effect of this rule is that statements such as
if (x == null) Console.WriteLine("x is null");

if (x != null) Console.WriteLine("x is non-null");

are permitted for an x of any nullable type or reference type, thus providing a common way of performing null checks for all types that can be null.

May 29, 2008

Customized SqlServer Project Type

This is 'bout a C# projectype which Niels has created to help facilitate SQLServer projects.
Link: http://nielsb.wordpress.com/sqlclrproject/sqlclrdl/





FeatureSQLCLRProjectBuilt-in
Specific VS project type and item templatesYesYes
Automatic deployment of assemblies and creation of T-SQL objectsYesYes
Debugging support objectsYesYes
Automatic creation of T-SQL deployment scriptsYes-
Automatic creation of T-SQL DML scripts for testing of the created objectsYes-
Create objects in a non-default schemaYes-
Define parameters in the .NET methods to have default values in T-SQLYes-
Define parameters in .NET to be created with different names in T-SQL
Yes-
Redeploying an UDT without manually dropping tables/columns depending on the UDTYes-

May 25, 2008

Vs.Net IDE Designer view Error : Object of Type "Xcannot be converted to type "X""




If this error occurs the Designer won't be able to show the controls of the form but will be able to show them at runtime, to eradicate this problem, close the designer view from the IDE, delete the .resx file associated with the .cs file of the form, then clean and rebuild the project.

The designer view will now be able to be loaded in the IDE.
Sometimes, even after the designer loads the UI, the resx file is missing, to correct this, just change any value of any control in the designer view and then change it back to the original value (like the text of a label)

Mar 6, 2008

New INTERSECT and EXCEPT operators in Sql Server 2005 T-SQL

INTERSECT

Let say you have a products table. I’m going to use the products table from the AdventureWorks database. Now let’s say you imported a list of products into the database into a table called productduplicates. Just for a reason, let’s say you manufacturer sent you a full list of products, and you need to see which products you already have in your database.

Normally, if you didn’t have matching primary keys on both tables, like a productId, you would do an inner join on some columns that uniquely identify the rows, as such:



INNER JOINselect a.[name], a.productnumber
from production.product a
inner join production.productduplicates b
on a.[name] = b.[name]
and a.productnumber = b.productnumber


Execution plan for inner join

Hash Match(Inner Join, HASH:([b].[Name], [b].[ProductNumber])=([a].[Name], [a].[ProductNumber]), RESIDUAL:([AdventureWorks].[Production].[Product].[Name] as [a].[Name]=[AdventureWorks].[Production].[productduplicates].[Name] as [b].[Name] AND [AdventureWorks].[Production].[Product].[ProductNumber] as [a].[ProductNumber]=[AdventureWorks].[Production].[productduplicates].[ProductNumber] as [b].[ProductNumber]))
--Table Scan(OBJECT:([AdventureWorks].[Production].[productduplicates] AS [b]))
--Clustered Index Scan(OBJECT:([AdventureWorks].[Production].[Product].[PK_Product_ProductID] AS [a]))

Now you can replace this with a simple INTERSECT statement like the following:

INTERSECTselect [name], productnumber from production.product
intersect
select [name], productnumber from production.productduplicates


Execution plan for INTERSECT

Hash Match(Right Semi Join, HASH:([AdventureWorks].[Production].[productduplicates].[Name], [AdventureWorks].[Production].[productduplicates].[ProductNumber])=([AdventureWorks].[Production].[Product].[Name], [AdventureWorks].[Production].[Product].[ProductNumber]), RESIDUAL:([AdventureWorks].[Production].[Product].[Name]=[AdventureWorks].[Production].[productduplicates].[Name] AND [AdventureWorks].[Production].[Product].[ProductNumber]=[AdventureWorks].[Production].[productduplicates].[ProductNumber]))
--Table Scan(OBJECT:([AdventureWorks].[Production].[productduplicates]))
--Clustered Index Scan(OBJECT:([AdventureWorks].[Production].[Product].[PK_Product_ProductID]))

Just like if you were using a UNION for two select statements, the same number of columns must exist in both select statements, and they must be of the same datatype. In both above examples, you get a list of products that exist in both tables, so you know which products from the manufacturer you already have listed.

I haven’t seen any performance difference in the two, but I’ve only played with this on small tables. The execution plan does show that while you are doing a hash match inner join on the first query, the second query performs a hash match right semi join. Both hash matches perform 50% of the work in the query. The other 50% is split evenly between the table scan and index scan in both queries. So what does the fact that a right semi match is performed when using INTERSECT? I tells me its doing the same thing as if we were to use the EXISTS, like so:


EXISTS

select a.[name], a.productnumber
from production.product a
where exists(select b.[name], b.productnumber from production.productduplicates b
where a.[name] = b.[name]
and a.productnumber = b.productnumber)

EXCEPT

Same scenario, if you wanted to know which products you have that do not exist in the duplicates table, you would normally do a NOT EXISTS like so:


NOT EXISTS

select a.[name], a.productnumber
from production.product a
where not exists(select b.[name], b.productnumber from production.productduplicates b where a.[name] = b.[name]
and a.productnumber = b.productnumber)


Execution plan for NOT EXISTS

Hash Match(Right Anti Semi Join, HASH:([b].[Name], [b].[ProductNumber])=([a].[Name], [a].[ProductNumber]), RESIDUAL:([AdventureWorks].[Production].[Product].[Name] as [a].[Name]=[AdventureWorks].[Production].[productduplicates].[Name] as [b].[Name] AND [AdventureWorks].[Production].[Product].[ProductNumber] as [a].[ProductNumber]=[AdventureWorks].[Production].[productduplicates].[ProductNumber] as [b].[ProductNumber]))
--Table Scan(OBJECT:([AdventureWorks].[Production].[productduplicates] AS [b]))
--Clustered Index Scan(OBJECT:([AdventureWorks].[Production].[Product].[PK_Product_ProductID] AS [a]))


And you get back the list of products that you have that aren’t in the duplicates list. You can flip this around to figure out which products are in the duplicates that you don’t have in your products.

Let’s simply the code a little bit by using the EXCEPT operator. This looks identical to the INTERSECTS query:
EXCEPT

select [name], productnumber from production.product
except
select [name], productnumber from production.productduplicates

Execution plan for except

Hash Match(Right Anti Semi Join, HASH:([AdventureWorks].[Production].[productduplicates].[Name], [AdventureWorks].[Production].[productduplicates].[ProductNumber])=([AdventureWorks].[Production].[Product].[Name], [AdventureWorks].[Production].[Product].[ProductNumber]), RESIDUAL:([AdventureWorks].[Production].[Product].[Name]=[AdventureWorks].[Production].[productduplicates].[Name] AND [AdventureWorks].[Production].[Product].[ProductNumber]=[AdventureWorks].[Production].[productduplicates].[ProductNumber]))
--Table Scan(OBJECT:([AdventureWorks].[Production].[productduplicates]))
--Clustered Index Scan(OBJECT:([AdventureWorks].[Production].[Product].[PK_Product_ProductID]))


Again, can’t find a performance difference. In all queries shows, the reads and duration all average out to be virtually identical. You’d have to test this on some large tables (high number of rows) to figure out if there is a performance difference at all.

Looking at the execution plans for everything, it doesn’t seem that there is a any gain from using INTERSECT and EXCEPT over JOINS or EXISTS/NOT EXISTS except for one big thing: Much simpler code!

Feb 8, 2008

Tech code Blogs

1. Brianpeek.com - (x64 Development with .NET, eye candies etc.. )

Feb 7, 2008

Give permissions to your apps to write to custom event log source

1. Create your Log source by code (You may not see it reflected in the event viewer)
2. Run Regedit
3. Travel to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\[your created Log source]
4. Right click and select properties
5. Give the access rights
6. Close the reg hive
7. Refresh the event viewer
8. The newly added log source will appear

Feb 6, 2008

Windows Services, services.msc and the "This Service is marked for deletion" error.

In my current project, we have a windows service that we are developing and debugging, which involves a lot of installing/uninstalling the service. One common problem when uninstalling a service is that while the uninstallation is successful, you still see the service listed in the Services console(services.msc). If you try to start it, stop it or uninstall it again (using installutil.exe or sc delete) you get an uninformative "This service has been marked for deletion".

The KB article (http://support.microsoft.com/kb/823942) about this problem suggests you restart the computer, which is pretty much overkill. Sure, it'll work, but you'll never find out what caused it in the first place. Turns out it's a pretty simple affair: just make sure you close the Services console, which apparently holds a handle of some sort to it. You don't have to do it before you uninstall. The minute you close the console, all services marked for deletion will be deleted, and all will be well.

When doing it on a server, it's important to make sure you've closed all Services consoles on all active sessions. I've seen this error happen when no console was open, and it was fixed by running Task Manager and killing all instances of mmc.exe. I could have logged on to the other sessions and closed it gracefully, but I was lazy. Did the trick.

Jan 3, 2008

A MSMQ Listener

The 2 following classes are used to get the desired effect.
The MSMQListener Class as the name suggests is the main class, while the Form1.cs is a windows forms which invokes this class and shows a popup when a message is queued. Additionally, this form also is used to post messages to the queue

----------------------------------------------------
1. MSMQListener Class
----------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Messaging;

namespace MyQueue
{
public delegate void MessageReceivedEventHandler(object sender, MessageEventArgs args);

public class MSMQListener
{
private bool _listen;
private Type[] _types;
private MessageQueue _queue;

public event MessageReceivedEventHandler MessageReceived;

public Type[] FormatterTypes
{
get { return _types; }
set { _types = value; }
}

public MSMQListener(string queuePath)
{
this.ConstructorCommon(queuePath);
}

public MSMQListener(string queuePath, System.Messaging.IMessageFormatter formatter)
{
this.ConstructorCommon(queuePath);
this._queue.Formatter = formatter; // Customize the formatter type
}

private void ConstructorCommon(string queuePath)
{
_queue = new MessageQueue(queuePath);
}


public void Start()
{
_listen = true;

if (_types != null && _types.Length > 0)
{
// Using only the XmlMessageFormatter. You can use other formatters as well
_queue.Formatter = new XmlMessageFormatter(_types);
}

_queue.PeekCompleted += new PeekCompletedEventHandler(OnPeekCompleted);
_queue.ReceiveCompleted += new ReceiveCompletedEventHandler(OnReceiveCompleted);

StartListening();
}

public void Stop()
{
_listen = false;
_queue.PeekCompleted -= new PeekCompletedEventHandler(OnPeekCompleted);
_queue.ReceiveCompleted -= new ReceiveCompletedEventHandler(OnReceiveCompleted);

}

private void StartListening()
{
if (!_listen)
{
return;
}

// The MSMQ class does not have a BeginRecieve method that can take in a
// MSMQ transaction object. This is a workaround - we do a BeginPeek and then
// recieve the message synchronously in a transaction.
// Check documentation for more details
if (_queue.Transactional)
{
_queue.BeginPeek();
}
else
{
_queue.BeginReceive();
}
}

private void OnPeekCompleted(object sender, PeekCompletedEventArgs e)
{
_queue.EndPeek(e.AsyncResult);
MessageQueueTransaction trans = new MessageQueueTransaction();
Message msg = null;
try
{
trans.Begin();
msg = _queue.Receive(trans);
trans.Commit();

StartListening();

FireRecieveEvent(msg.Body);
}
catch
{
trans.Abort();
}
}

private void FireRecieveEvent(object body)
{
if (MessageReceived != null)
{
MessageReceived(this, new MessageEventArgs(body));
}
}

private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
Message msg = _queue.EndReceive(e.AsyncResult);

StartListening();

FireRecieveEvent(msg.Body);
}

}

public class MessageEventArgs : EventArgs
{
private object _messageBody;

public object MessageBody
{
get { return _messageBody; }
}

public MessageEventArgs(object body)
{
_messageBody = body;

}
}
}



-----------------------------------------------------------------------------
2. Form1.cs
-----------------------------------------------------------------------------

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Messaging;
using System.Threading;

namespace MyQueue
{
///
/// Summary description for Form1.
///

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox txtMsg;
private System.Windows.Forms.Button btnMsg;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ListBox MsgBox;
private System.Windows.Forms.Label Messages;
private System.Windows.Forms.Button btnRcv;
///
/// Required designer variable.
///

private System.ComponentModel.Container components = null;
public System.Messaging.MessageQueue mq;
public static Int32 j=0;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//

//Q Creation
if(MessageQueue.Exists(@".\Private$\MyQueue"))
mq = new System.Messaging.MessageQueue(@".\Private$\MyQueue");
else
mq = MessageQueue.Create(@".\Private$\MyQueue");

Queue2 q2 = new Queue2();
q2.Show();


///////
MSMQListener msmq = new MSMQListener(@".\Private$\MyQueue", new System.Messaging.XmlMessageFormatter(new string[] {"System.String"}));
msmq.MessageReceived += new MessageReceivedEventHandler(msmq_MessageReceived);
msmq.Start();
}

void msmq_MessageReceived(object sender, MessageEventArgs args)
{
MessageBox.Show(args.MessageBody.ToString());
}

///
/// Clean up any resources being used.
///

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///

private void InitializeComponent()
{
this.txtMsg = new System.Windows.Forms.TextBox();
this.btnMsg = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.MsgBox = new System.Windows.Forms.ListBox();
this.Messages = new System.Windows.Forms.Label();
this.btnRcv = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// txtMsg
//
this.txtMsg.Location = new System.Drawing.Point(112, 16);
this.txtMsg.Name = "txtMsg";
this.txtMsg.Size = new System.Drawing.Size(280, 20);
this.txtMsg.TabIndex = 0;
this.txtMsg.Text = "";
//
// btnMsg
//
this.btnMsg.Location = new System.Drawing.Point(200, 48);
this.btnMsg.Name = "btnMsg";
this.btnMsg.TabIndex = 1;
this.btnMsg.Text = "&Send";
this.btnMsg.Click += new System.EventHandler(this.btnMsg_Click);
//
// label1
//
this.label1.Location = new System.Drawing.Point(8, 16);
this.label1.Name = "label1";
this.label1.TabIndex = 4;
this.label1.Text = "Enter Message :";
//
// MsgBox
//
this.MsgBox.Location = new System.Drawing.Point(8, 136);
this.MsgBox.Name = "MsgBox";
this.MsgBox.Size = new System.Drawing.Size(392, 173);
this.MsgBox.TabIndex = 2;
//
// Messages
//
this.Messages.Location = new System.Drawing.Point(16, 104);
this.Messages.Name = "Messages";
this.Messages.Size = new System.Drawing.Size(160, 23);
this.Messages.TabIndex = 3;
this.Messages.Text = "Messages : ";
//
// btnRcv
//
this.btnRcv.Location = new System.Drawing.Point(200, 88);
this.btnRcv.Name = "btnRcv";
this.btnRcv.TabIndex = 5;
this.btnRcv.Text = "&Receive";
this.btnRcv.Click += new System.EventHandler(this.btnRcv_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(408, 317);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.btnRcv,
this.Messages,
this.MsgBox,
this.label1,
this.btnMsg,
this.txtMsg});
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Queue1";
this.ResumeLayout(false);

}
#endregion

///
/// The main entry point for the application.
///

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void btnMsg_Click(object sender, System.EventArgs e)
{
// SendMessage(Handle, 1, 0, IntPtr.Zero);
System.Messaging.Message mm = new System.Messaging.Message();
mm.Body = txtMsg.Text;
mm.Label = "Msg" + j.ToString();
j++;
mq.Send(mm);
}

private void btnRcv_Click(object sender, System.EventArgs e)
{
System.Messaging.Message mes;
string m;

try
{
mes = mq.Receive(new TimeSpan(0, 0, 3));
mes.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib"});
m = mes.Body.ToString();
}
catch
{
m = "No Message";
}
MsgBox.Items.Add(m.ToString());
}
}
}

-----------------------------------------------------------------------------