Monday, December 15, 2008

Sharepoint, MOSS custom project/solution

I had some work recently in creating a custom solution for sharepoint and I had never worked in sharepoint before. I thought just like you find a lot of solutions and books of other technologies, I would be able to find similar things for sharepoint too .. But sadly that was not the case. There are lots of artcles, books on sharepoint administration/customization, but very less on actual development. You will find examples for creating web parts, adding custom lists etc. But my requirement has something more than all this

I had to create a package which could be given to a client, who could then install it into his sharepoint server. Then my new sharepoint "site" must be added as a "site" within sharepoint and the users must be able to see a customzed solution which queries my database and does various other things ..

This involved ..
- creating a solution
- creating a package
- adding custom web parts
- adding these custom web parts to the "default.aspx" page
- installing this package as a "solution" in sharepoint
- having this installed soltuon as a "template" in the template list while creating new "site"
- after creating this new site, the site must have my setting for the default.aspx page and follow my styles defined

How did I do all of these. Hopefully I get time to write it soon .. If there is anyone out there who needs a answer right now, do write to me .. or I will hopefully post all that I did in the next coupld of weeks

I am not sure whether the approach I took was the best one, but at least it worked for me ..

Rejo

SSIS - debug a "script component" control

If you are reading this, you might also have faced a situation where you added a breakpoint and thought of debugging a script component in SSIS package ..

Ok, I found this is not possible. At least I could not do it in SQL 2005. Maybe its possible in 2008. Do note that you can debug scripts in a "Script task" control but not within a "script component" control within a data flow section.

I tried everything .. changing the "Precompile" property to false/true, changing the script control's name (in the design script window - changed the default generated control name from ScriptComponent_7dac1823375d4ad0bddf242bed9e1391 to ScriptComponent) etc .. but nothing worked ..

So maybe this post will save someone's time .. I copied my code to script task and I could manage to debug part of the code (the part I needed to check) .. after that I deleted the script task and returned back to my original flow/code of using the "script component"

Rejo

System.Object(), SSIS, Active directory and MemeberOf property

For the last couple of months I have working on sharepoint solutions and one of the requirement involved in fetching all users and groups from active directory. The data fetched had to be then inserted into a local SQL databaseb. As this information changes with time, the process had to be run once daily. So I opted on using SSIS to automate the whole process

It seemed pretty straight forward. I used a OLEDB connection of "Microsoft data services" to read the data from active directory. As a test I fetched couple of fields like the cn, name etc and everything worked fine, till I decieded to get the groups that the users belong to. I knew that it would be part of the "memberof" property. I used the same approach and I noticed that value gets inserted as "System.Object[]" into the database. I figured out that the value is returned as a blobcolumn and anyway I tried to parse it, it always gave me the same value. I tried

Dim lByte() As Byte = CType(dataRow(0), Byte()) .. where datarow(0) is the memberof field
System.Text.Encoding.Unicode.GetChars(lByte)

... also tried converting the column to string, collection, byte etc etc ..

and many other options .. all gave me the same result or an error .. I was really getting frustrated and I searched the net for solution. There are some examples on using SSIS and active directory and no where do they talk about how to read value from this column. So I came back to trying it on the own. I wanted to check the type of this column. But I could not add a breakpoint into a "script component" (and that is another story) .. I learned that I could add a breakpoint into a "script task" and so I copied my code over there and added breakpoint to see what data is fetched.

I saw that the column actually contains a array value. I had never seen this before .. The content of a single column looked like
(0) CN=CN1,OU=OU1,DC=corp1,DC=corp2
(1) CN=CN2,OU=OU1,DC=corp1,DC=corp2
(2) CN=CN3,OU=OU1,DC=corp1,DC=corp2

so i converted the column value to "system.array". and got the information that I needed ...

Hope this helps some people out there .. and not have to spend hours or days looking for a solution.

Rejo

Monday, June 2, 2008

Mapping varchar(max) - using micorosoft application data blocks (No mapping exists from DbType .. to a known SqlDbType ....)

I have been happily using application blocks for various tasks in my project and the data blocks was one of them. I had code like this which worked fine ..

Dim lDatabase As Database = DatabaseFactory.CreateDatabase()
Dim lCommand As DbCommand = lDatabase.GetStoredProcCommand("dbo.pr_service_WriteLog")
lCommand.CommandType = CommandType.StoredProcedure
'-- add the parameters
lDatabase.AddInParameter(lCommand, "@CreatedOn", SqlDbType.DateTime, DateTime.Now)
'-- add the error type
lDatabase.AddInParameter(lCommand, "@LogType", SqlDbType.VarChar, EntryType.ToString)
lDatabase.AddInParameter(lCommand, "@LogType", SqlDbType.VarChar, lLogBase.Type.ToString)
'-- add the message
lDatabase.AddInParameter(lCommand, "@LogMessage", SqlDbType.VarChar, lLogBase.Message)

lDatabase.ExecuteNonQuery(lCommand)

This worked fine for quite sometime till I had a new requirement to write a SP which had to insert into a table a fields with the data type defined as varchar(max). To apss this new type from the UI to SP I tried
lDatabase.AddInParameter(lCommand, "@NewParam", SqlDbType.text, MyValue)

It gave the error "No mapping exists from DbType UInt16 to a known SqlDbType." ..
So I tried various other types like Nvarchar etc etc .. but all failed .. Then I started reading about the data types supported by the data block and I came to realise that instead of using SQLDbType, i could use DBtype directly. So I tried DBtype.string and it worked !!!

Hope this helps someone who might get stuck in a similar area ....

Friday, May 16, 2008

"Exception has been thrown by target of invocation" Error

You might face this error and wonder what happened. I had a similar situation today. The code was working fine and all of a sudden I got this error. I am not that kind of person who beleives very strongly that all errors are due to some bad coding, maybe by the developer or maybe thrown bt the tools used for development. Till now, whenever I have been involved in coding or debuging someone's problem , I have managed to at least find out where the issues have been and most of time solve it too. Anyway, so I started tracing my steps backwards and commenting recenlty changed codes. But still was not able to find exactly where the error is occuring.

Finally, during one my debug attempts, I happened to look at the exception object's inner exception and noticed the error was because of a new addition I had on the app.config file. I made the correction and the error was gone. BTW, the change I did was add a "configSections" tag at the end of the app.config file. If you add a "configSections" tag, it has be the first line after the "configuration" tag.

So to conclude, if you get this error ""Exception has been thrown by target of invocation"", look at the inner exceptions. Keep looking recursively into the inner exception's "inner exception" till you see "nothing" and hopefully you see the actual error message and correct the problem.

happy coding !!

Tuesday, May 6, 2008

Public member 'OverRideMethod' on type 'ObjectHandle' not found. [Reflection - Access methods from class dynamically]

I had a hard time with this. Spend around 2-3 hours trying various options till i got a clue from one of the links on the internet.

I had a class library (dll) referenced in a windows project and all the classes in this dll is inherited from a base class. The baseclass is mustinherit and has mustoverride function. My plan was that this windows application would have a list of (dynamically maintained using a XML file in the windows application) classes and its methods that can be executed from this dll. Each of the class within this dll overrides the mustoverride function from the baseclass and does some actions. The reason for this design was to make a "plug and play" kind of application. So if i wanted to add a new functionality, i just need to add a new class to the dll, edit the XML file and the front-end will show this new functionality and it will execute it. There were many other functions that were specific to the project that need not be discussed here .. Anyway, this sounded very simple to me and i started with writing the code..

The first thing that came into my mind was whether i would have to use reflection. But the dll was referenced in the main windows project. So there was no need to load a assembly dynamically and i did not want to go with that approach. Then found from the help about Activator.CreateInstance which has a overloaded function which accepts 2 strings .. the assembly name and the class name .. this was what i wanted. So i wrote this

Dim lObject As Object
lObject = Activator.CreateInstance("Namespace.MyAssembly", "Derived Class Name")
lObject.OverRideMethod

But this kept giving an error on the line where it is executing overriden method.
Public member 'OverRideMethod' on type 'ObjectHandle' not found.

I was sure that the object was getting created because when i changed the assembly or the class name, it gave the error on that line. So what was the issue? I could not get any help in MSDN. So i started searching the net and luckily got a link which said that Activator.CreateInstance does not give a object in return, but returns a object handle. I checked MSDN and it said that it gave back a object. I aklso noticed now that the error I got mentioned that "... on type ObjectHandle not found" So I decided to give it a try.. So I changed the code to

Dim lHandle As System.Runtime.Remoting.ObjectHandle
lHandle = Activator.CreateInstance("Namespace.MyAssembly", "Derived Class Name")
lRulesObject = lHandle.Unwrap()
lRulesObject.OverRideMethod

Lo and behold, it worked !! ..

I also type cast my object to the baseclass so that I can now call the method from the baseclass directly.. So my final code was

Dim lHandle As System.Runtime.Remoting.ObjectHandle
Dim lRulesBase As MyBaseClass
Dim lRulesObject As Object

lHandle = Activator.CreateInstance("Namespace.MyAssembly", "Derived Class Name")
lRulesObject = lHandle.Unwrap()
'-- cast it to the base class
lRulesBase = DirectCast(lRulesObject, MyBaseClass)
'-- call the service method
lRulesBase.OverRideMethod()

I spend some time finding this out and i thought I will post this for others who might have similar issues.

Happy coding !!

Tuesday, April 22, 2008

Icon size in notifyicon

Recently I had a requirement to create a windows service in .net. This service also had to have a "form" like a "dashboard" functionality that showed the status of the service and various options that the user could do to make changes to the service functions. For this, I decided to show a icon in the taskbar when the service starts and onclick of this icon, I would show the form.

This can be done using notifyicon control in .net and its pretty straightforward. But the issue I was facing was with the icon been shown in the taskbar. It was never clear and after trying various options like different size etc, i searched the net and found this article which was useful - http://www.hhhh.org/cloister/csharp/icons/

------ from the above link ------
"A reader asked for a quick-reference table at the top of this document, showing the default icon versions used by Windows Forms applications in different circumstances, so here it is. Detailed explanations are provided below if you're interested

Circumstance: Icon Version:
Control Box 16x16x256
Taskbar 16x16x256
Notify Icon 32x32x256, shrunk down (see below)
Desktop Shortcut 32x32x256 (Normal sized icons)
48x48x256 (Large sized icons)
Add/Remove Programs 16x16x256
Folder Browse dialog 16x16x256

Notify IconIf you add a NotifyIcon control to your application's Form object, then your application will display an icon in the tray area of the taskbar. The rendered size of the notify icon is the same as for the Control Box and Taskbar icons: 16x16 pixels, potentially stretched to accomodate the height of the system tray, which is dependent on the height of the Taskbar. Oddly, however, Windows does not use the 16x16x256 bitmap for this circumstance; it uses the 32x32x256 bitmap by default, and squashes it down to the required size. I can think of no particularly good reason for this difference--using the 32x32 version for the notify icon, but 16x16 for taskbar and control box--but there it is.

16x16 Notify Icon 18x18 Notify Icon


Notice that the text on my 32x32x256 icon is barely readable when shrunk down to 16x16 size. The same will be true for any one-pixel-wide details you include in your 32x32x256 bitmap, unless you are very careful about where you put them. The reason for this is clear: a 16x16 bitmap has only one-quarter as many pixels as a 32x32 bitmap. Consequently, three-quarters of the information in the 32x32 bitmap is thrown away when shrinking it down to 16x16. What to do about it is less clear.

To get a more optimal appearance for your NotifyIcon, you need to know which pixels out of the 32x32 bitmap are the ones that will be displayed at 16x16 size. Fortunately, the mapping is straightforward. Windows throws out all the even-numbered rows and columns, and keeps what's left. Shown here at double-size is a 32x32x256 bitmap, where the black pixels are the ones that will be seen when the bitmap is shrunk down to 16x16 on a NotifyIcon, and the actual NotifyIcon image that this bitmap turns into in the system tray:
Before: ...and after:
As you can see in these two images, the black pixels in the 32x32 image are the ones that are actually displayed at 16x16 size. The yellow has disappeared because the even-numbered rows and columns are thrown away. Pixels in the even-numbered rows and columns are important for the appearance of desktop shortcut icons, but are irrelevant for NotifyIcon objects.

Thursday, April 10, 2008

Custom validator controls : Change style of label when error occurs

ASP.net

We had this unique requirement from a client that when a validation failure occurs like "required field is not filled", the corresponding label must be highlighted with a different color. As all of you might already be aware, we attach the validator controls to the control that needs to be validated and not the label. For eg, if you have a "Customer name" field with a textbox (txtCustomer) which is mandatory, you add a requiredFieldValidator with its ControlToValidate property = txtCustomer.

So how do you now highlight the label "Customer name" .. lets say with a different background color. Ofcourse, doing that on the server is easy, but that negates the reason of using validator controls which does everything on the client (browser). So I decided to build a custom control by inheriting from the standard requriedFieldValidator control. I added a new property called LabelToHighlight which will accept a control name whose styles needs to be changed when an error occurs. I reaserched on how to allow user (consumer the control) to be able to select a label (like you selecting controls when setting the ControlToValidate property) and not just type in a control name and I came across typeconvertor settings available for properties .. anyway, given below is some of the code .. you can write to me for more explanation if needed ..


'Created by Rejo on Aug 23rd 2007
' Standard field validators has just the controltovalidate property which can be set to specify which
' controls needs to be validated. But the delivery.com project requires the errors to highlight the label
' of the control which is been validated.
' This custom validator does just that.
' A new property added gives option to the developer to select a control which gets highlighted with a different style.
' The styles are set as embeded resource and should be changed as per the requirement of the project
' The styles too could have been exposed as public properties, but that would be each control will have to manually
' set by the developer.
' The javascript which changes the style is also embeded into the project
' ONLY THE DLL NEEDS TO BE REFERENCED IN THE MAIN PROJECT which will consume these controls

Imports Microsoft.VisualBasic
Imports System.Web.UI
Imports System.ComponentModel
Imports System.Web.UI.WebControls

Namespace Controls

_
Public Class CustomRequiredValidator
Inherits System.Web.UI.WebControls.RequiredFieldValidator
Dim lstrLabelToHighlight As String

_
Public Property LabelToHighlight() As String
'property to hold the name of the label control which would be highlighted when the error occurs
Get
Return lstrLabelToHighlight
End Get
Set(ByVal value As String)
lstrLabelToHighlight = value
End Set
End Property

Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter)
'set the display property to none
Me.Display = ValidatorDisplay.None
MyBase.AddAttributesToRender(writer)
'add the custom properties
writer.AddAttribute("LabelToHighlight", Me.LabelToHighlight)
End Sub

Private Sub CustomRequiredValidator_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
Dim ctlParent As System.Web.UI.Control = Me.Parent
Dim lLableHighlight As Label = TryCast(ctlParent.FindControl(LabelToHighlight), Label)

While lLableHighlight Is Nothing
ctlParent = ctlParent.Parent
If ctlParent IsNot Nothing Then
lLableHighlight = TryCast(ctlParent.FindControl(LabelToHighlight), Label)
Else
Throw New Exception("Control to highlight is not found.")
End If
End While

LabelToHighlight = lLableHighlight.ClientID

'check if the script is already present and if not, then add it
If Not Me.Page.ClientScript.IsClientScriptIncludeRegistered("ControlsCommon.js") Then
Dim lstrScriptLocation As String = Page.ClientScript.GetWebResourceUrl(Me.GetType(), "Delivery.ControlsCommon.js")
Page.ClientScript.RegisterClientScriptInclude("ControlsCommon.js", lstrScriptLocation)

' add the style .. assumming that the style too would be added only once along with the js file

Dim lstrLocation As String = Page.ClientScript.GetWebResourceUrl(Me.GetType(), "Delivery.ControlStyle.css")
Dim lobjIncludeLiteral As LiteralControl = New LiteralControl(String.Format(lstrTemplate, lstrLocation))
CType(Page.Header, HtmlControls.HtmlHead).Controls.Add(lobjIncludeLiteral)

'register submit script which will call the script which will highlight the control if there is a error
Me.Page.ClientScript.RegisterOnSubmitStatement(Me.GetType(), "HighlightLabelSubmit", "UpdateErrorLabel();")
End If
End Sub
End Class
End Namespace



Code from the COMMON.js file



Function UpdateErrorLabel()
{
var lobjValidator;
//first reset all the existing validators to default style
for (i = 0; i < Page_Validators.length; i++)
{
lobjValidator = document.getElementById(document.getElementById(Page_Validators[i].id).getAttribute('LabelToHighlight'));
if (lobjValidator != null)
{
lobjValidator.className = 'lblnormal';
}
}


//change the style for all error labels
for (i = 0; i < Page_Validators.length; i++)
{
if (!Page_Validators[i].isvalid)
{
//lobjValidator = document.getElementById(Page_Validators[i].LabelToHighlight);
lobjValidator = document.getElementById(document.getElementById(Page_Validators[i].id).getAttribute('LabelToHighlight'));
if (lobjValidator != null)
{
//lobjValidator.setAttribute('class', 'lblerror');
//lobjValidator.setAttribute('className', 'lblerror');
lobjValidator.className = 'lblerror';
}
}
}
}



This does have some flaws which I have learnt to overcome like sometimes when you add the this control, the highlight does not work. As you can see from the code, I have to add on to the standard validation code that asp.net generates which checks for the isvalid property and then change the style when it is false. Some my functions get added to the front and so this js always finds the isvalid = true and does not validate. For these cases, I just remove the Custimvalidator and add it again and it works .. :-) ..

Note, you will need the style 'lblError' etc to be available in your stylesheet referred by the page ..

This line is not getting accepted by this blogpost when added in my code above..

it must be in the prerender event .. i will try and make some changes to the code so that this post gets accepted
Dim lstrTemplate As String = "<link rel='stylesheet' text='text/css' href='{0}' CLOSING TAGS"

Include files (.js, .css) in master pages or base page

We always use master page and basepage implementation for our asp.net projects.

Even after master pages were introduced in VS2005, i continued using basepage.vb file which inherits from system.web.ui.page. I inherit this in all my pages. Its just that I found more flexibility and control by using basepages and master page. basepage contains all the codes that need to fired for each page like authentication, validations etc,. and the masterpage just contains the UI framework ..

anyway, maybe I can explain my reasons for this implementation in some other post .. let me continue with the reason for this post .. Now there was this requirement to inlude some common .js files in all my webpages. I thought I could do this in master page. But it did not work ..

so finally I got it to work using this statement in the load of my basepage.vb class.

MyBase.ClientScript.RegisterClientScriptInclude("CommonJS", "~/Common/Scripts/Common.js")

where Common.js resides in the Root\Scripts directory of the project ..

WebControl - Embed javascript in control

I had to build a custom control which had to use javascript on the borwser and change some setting. For this, I used the clientscripts.register... methods to emit the javascript to the browser. I was not happy about this because it meant that every page will now need to emit the same code and it is not cached. So I thought of using a .js file with the same javascript code and register that within the control. But now the issue was the path of the .js file. I wanted a generic solution where the project consuming this control need not worry about where the js files needs to be picked from. That is when I came to know about embedding .js files into web controls.

Use these statement to do it and you will no longer need to distribute the .js file with your control

If Not Me.Page.ClientScript.IsClientScriptIncludeRegistered("ControlsCommon.js") Then
Dim lstrScriptLocation As String = Page.ClientScript.GetWebResourceUrl(Me.GetType(), "ControlsCommon.js")
Page.ClientScript.RegisterClientScriptInclude("ControlsCommon.js", lstrScriptLocation)
End if

where ControlsCommon.js is the file that I need to include and it resides in the same directory where the controls is present (in the development environment). No need for this .js file when the control is consumed in another project

IVR calls using .Net

Lots of research was done by one my collegue on this and we narrowed down to VBVoice from Pronexus using Dialogic boards (http://www.pronexus.com/english/view.asp?x=1).

There were other options like some product from microsft too (I think it was communication server), but it was still in beta and we do not trust microsoft beta versions :-) ..

An update : I realised that Pronexus has its own limitations. It has something called a VBVFrame and all controls are supposed to added within this frame. Unfortunately you cannot have 2 vbvframes running on the same machine at the same time. As told by their support, it interacts with the dialogic boards to make the call and it cannot handle more than one frame active at any one time. So my whole ides of multi-threading went down the drain. Anyway, vbvoice has its own way supoprt for multithreading. It is not actually threading as you would like it, but its kind-of for our requirement.

In short, even though they have .net support, it looks like all the controls were build really fast as wrappers on top of COM objects that they had created earlier. So i do not think that it is really leveragin the use of the .net framework. I would recommend that you continue searching for somthing better and you might want to come back to this if others options do not have all the functionalities that you need. VBVoice does seem to have a lot of options, but their help file is really bad ..

How to Fax using .Net - HTML to TIFF

I had to build a fax soltution for one of my application. So again as usual, I started my research by searching on the net. Another collegue of my mine suggested using microsoft fax server. We were also using a third party software for "Interactive voice response" requirement from pronexus and this software also had faxing capabilities. So I narrowed down on these 2 application. Now my issues started.

I had fax information that I was reading from my database. The information had to be formatted. So I thought of faxing HTML documents. That is when I realised that Fax expects images or text files as the source document. The image has to be in TIFF format and it has to have specific encoding. I started with microsoft fax server, and the encoding requirements for this server is not very strict and it kind of accepts all types of TIFF images. But our requirement was to be able send multiple faxes at the same time (through multiple phone lines) and be able to process them in parallel. So this meant using multiple modems or getting a hardware which behaves as a modem for fax server. I was not too sure about this implementation and so I moved to VBFax (from pronexus)

We had already purchased dialogic boards for the IVR solution and I wanted to use this same boards to fax. The development board had 4 ports and in production we will be having a sigle bpard with 48 ports so that we can processes 48 requests in parallel. Now that I had narrowed down my hardware, the issue in hand was how to convert HTMl to TIFF format

There are lots of solutions available for this. But all of them is implemeted as printers i.e. you install it as a printer and you fire a print command (using code or any application File->print menu) and select this printer and it converts the currently opened file into TIFF. I was not too happy with this solutions because HTML files by default are opened by IE (or any browser) and when you print a opened document, it shows the print dialogbox. Now this has to be implemented as server and there cannot a user sitting and hitting the "ok" button. So how to avoid this print dialog. By the way, this was another reason why I moved away from Microsoft Fax server because its fax client also gets installed a printer. So again more reasearch and I found some other solutions like the ones from black ice software (http://www.blackice.com/), Informatik Image Driver 3.50 (http://www.informatik.com/), Zan image printer (http://www.zan1011.com/) and lots of others .. Some even like the one from back ice had .Net support which I needed. But it costs around $2000 .. what???? yes, too expensive

Luckily I found another software which converts HTML strings to TIFF.This was eactly what I wanted. So now I could just read the database and create a TIFF file directly. No need to create the HTML file and send it to the "Image" printers which would have been an expensive (with respect to time) affair .. This software was from Guangmingsoft called "HTMLSnapshot". I did have to talk a lot with their support to get the created TIFF iamge to work with my dialogic boards. Their support (David) was very helpful too. I finally have managed to get it working and hopefully everything works smoothly .. Its still under development .. I will update as we proceed ..

Please wait ... message in ASP.net

I have heard lots of questions on how to implement this and these links seems to provide the answers ..

Loading Progress and Status Displays in ASP.NET http://www.informit.com/articles/article.asp?p=174363&rl=1

Building a Better Busy Box - Ver 1.2(Processing… Please Wait)http://blogs.crsw.com/mark/articles/642.aspx

Javascript "Please Wait" Message Boxes -
http://aspalliance.com/38
gives the complete code using jaascript .. u could implement the same script for a page load too by not encapsulating the code within the function but directly within script tags .. remember the page is buffered by default is asp.net i.e. the page is not diplayed till the whole thing is not processed and so the browaser waits for it to complete and then receives the complet page .. so u could try and use response.flush in the page load to load the initial scripts ..

PleaseWaitButton ASP.NET Server Control
http://www.codeproject.com/aspnet/PleaseWaitButton.asp

Validation control using AJAX .. check for duplicate email id using customvalidator

This is a question that I particiapated in and thought that this might be a helpful post for some of you .. so have a look here ..

http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_22949725.html

To use remoting, sockets or web service??

I had to take this decision again for the requirement I have mentioned in my previous post (Therading in .Net). The requirement was to just listen to a port and accept requests and process it. As many of us might do, I started of thinking that remoting is what I should be doing. I did some research comparing remoting with web service and started with writing the code using .Net remoting. As I proceeded further I realised that remoting is not what I wanted. It seemed like a overkill.

I just wanted to listen to a port and accept requests. I do not want to respond back to the client or keep chatting. I can just disconnect if I am able to accept the request properly. I also realised that with remoting, you need to create an instance of the object with the client and the server. This was the turning point for me. I did not want the client to be dependent on the server. So I started looking at sockets and realised that this is what I want.

With some help from from http://www.dnrtv.com/, I managed to get it working for me. I will post some of the code that I used to get this working. As always, this is the exact code that worked for me and I do not expect you to just copy and paste and have it working for you. You will have to tweek it as per your needs

SERVER code

Public Sub StartServer()
Try
'-- initialize variables
mStopFlag = False
mClients.Clear()
'-- Is the listener still active somehow?
If mListener IsNot Nothing Then
StopServer()
End If
mListenThread = Nothing
'-- get the ip address of the current machine
'-- get the first IP address from the list
Dim lIPAddress As IPAddress = Dns.GetHostEntry(My.Computer.Name).AddressList(0)
'-- get the port from the configuration file
Dim lPort As String = ConfigurationManager.AppSettings("ListenAtPort").ToString
'-- Make sure we have specified an IP Address and Port
If lIPAddress Is Nothing Then
Throw New ApplicationException("The IPAddress is not found. Check your machine settings")
End If
If lPort Is Nothing Then
Throw New ApplicationException("The Port properties cannot be found. Please check the config file.")
End If
'-- get the maximum clients that will be processed by this server
mMaxQueue = Convert.ToInt32(ConfigurationManager.AppSettings("MaxQueue").ToString)
If mMaxQueue = 0 Then
Throw New ApplicationException("The Maximum queue (MaxQueue) cannot be read from the config file")
End If
'-- get the maximum receive buffer from clients
mBufferSize = Convert.ToInt32(ConfigurationManager.AppSettings("BufferSize").ToString)
If mBufferSize = 0 Then
Throw New ApplicationException("The receive buffer size (BufferSize) cannot be read from the config file")
End If
'-- Create a new listener
mListener = New TcpListener(lIPAddress, lPort)
Logger.LogInformation("Listening on " & lIPAddress.ToString & ":" & lPort.ToString)
'-- Start the worker thread for the server
'-- this thread will the server that will listen and accepts new clients
'-- these clients are stored into the collection (arraylist)
mListenThread = New Thread(AddressOf StartServerThread)
mListenThread.Start()
Logger.LogInformation("New server thread started")
'-- This is the thread that listens for incoming messages from connected clients
'-- we plan to receive only one message and that is the order id for
'-- which we need to send the fax
'-- the request is then processed in seperate threads and each thread will respond
'-- back to the client about success or failure
Dim lprocessThread As New Thread(AddressOf ProcessClientRequest)
lprocessThread.Start()
Catch ex As Exception
ExceptionHandler.HandleException(ex)
StopServer() '-- shutdown server if already started
End Try
End Sub
Public Sub StopServer()
Try
mstrCurrentProcedureName = System.Reflection.MethodBase.GetCurrentMethod.Name()
Logger.LogAudit("At the start of StopServer procedure")
mStopFlag = True '-- Tells ProcessClientRequest() to abort
If mListener IsNot Nothing Then
Try
mListener.Stop() '-- Causes StartServerThread to abort
Catch ex As Exception
Logger.LogAudit(mstrCurrentProcedureName + ": error while tring to stop listening - " + ex.Message)
End Try
End If
Thread.Sleep(mThreadSleep) '-- Just to be sure everything is done
SyncLock mClients
'-- Shutdown each client/socket
For Each lClient As Client In mClients
'-- Use a try block in case it's already shut down
Try
If Not lClient Is Nothing Then
lClient.Shutdown()
End If
Catch
'-- if already shutdown, nothing to do. Continue with the loop
End Try
Next
End SyncLock
'-- Clean up
mClients.Clear()
mListener = Nothing
mListenThread = Nothing
mStopFlag = True
'-- Tell the UI we have no more connections
'SafeOnConnectionChange(0)
Catch ex As Exception
ExceptionHandler.HandleException(ex)
Finally
Logger.LogAudit("At the end of StopServer procedure")
End Try
End Sub

#End Region
#Region "Private methods/functions"
'this is the thread for the server that listens at the port and accepts new connections
Private Sub StartServerThread()
Dim lClient As Client
Dim lSocket As Socket
'-- Start listening
mListener.Start()
mStopFlag = False
Try
'-- Loop to handle multiple connection requests
Do
'-- AcceptSocket blocks until a connection is established
lSocket = mListener.AcceptSocket
If Not lSocket Is Nothing Then
'-- lock the list and add the ClientContext
SyncLock mClients
'-- check if the max clients that can be serviced is reached or not
Logger.LogAudit("Received new request: " + DateTime.Now.ToString())
If mClients.Count < lclient =" New" isconnected =" False" deleted =" True" mstopflag =" True" deleted =" False"> 0 Then
If lClient.Status = Client.ClientStatus.Pending Then '-- process only if pending
ProcessClient(lClient)
End If
End If
End If
End If
End If
'-- is the server still up?
If mStopFlag = True Then
Exit Do
End If
'-- sleep to prevent CPU overload
Thread.Sleep(mThreadSleep)
Next
End SyncLock
'-- remove all deleted clients from list
SyncLock mClients
'-- Remove any dead clients - disconnected clients/sockets
Dim removed As Boolean
Dim curCount As Int32 = mClients.Count
Do
removed = False
For i As Int32 = 0 To mClients.Count - 1
If CType(mClients(i), Client).Deleted = True Then
SyncLock mProcessedClients
'-- add the client to the processed client list
mProcessedClients.Insert(mCurrentProcessedOrderCount, mClients(i))
End SyncLock
'-- increment the count and if more than the max then reset
mCurrentProcessedOrderCount += 1
If mCurrentProcessedOrderCount >= mMaxProcessedOrders Then
mCurrentProcessedOrderCount = 1 '-- start overwriting
End If
'-- remove client from main client collection
mClients.Remove(mClients(i))
removed = True
Exit For
End If
Next
Loop Until removed = False
'If clients.Count <> curCount Then
' SafeOnConnectionChange(clients.Count)
'End If
End SyncLock
'-- is the server still up?
'SyncLock stopSyncObj
If mStopFlag = True Then
Exit Do
End If
'End SyncLock
'-- sleep to prevent CPU overload
Thread.Sleep(mThreadSleep)
Loop ' do
Catch ex As Exception
ExceptionHandler.HandleException(ex)
'Again should the server be shutdown when an exception occcurs?
End Try
End Sub

#End Region

CLIENT CODE

Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
If cbOverride.Checked = True Then
If mCurrentOrderIndex = mOrders.Count Then
If MessageBox.Show("All Orders send. Reset and start again?", "Reset?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
GetOrders()
Connect()
End If
Else
Connect()
End If
Else
Connect()
End If
End Sub
Private Sub Connect()
If btnConnect.Text = "Disconnect" Then
Try
SyncLock ClientSocket
ClientSocket.Shutdown(SocketShutdown.Both)
ClientSocket.Close()
End SyncLock
DisconnectedUI()
Catch
End Try
Else
ClientSocket = New Socket(AddressFamily.InterNetwork, _
SocketType.Stream, ProtocolType.Tcp)
Dim address As IPAddress = _
System.Net.Dns.GetHostEntry(txtAddress.Text).AddressList(0)
Dim endpoint As New IPEndPoint(address, CInt(txtPort.Text))
If cbOverride.Checked = True Then
UpdateStatus(vbCrLf + "Requesting connection for order : " + mOrders(mCurrentOrderIndex).ToString)
Else
UpdateStatus("Requesting connection for order in xml")
End If
ClientSocket.BeginConnect(endpoint, AddressOf Connected, Nothing)
End If
End Sub
Public Sub Connected(ByVal ar As IAsyncResult)
Try
ClientSocket.EndConnect(ar)
'-- Call ConnectedUI
Dim cb As New SimpleCallback(AddressOf ConnectedUI)
Me.Invoke(cb)
' '-- Start Receiving Data
ClientSocket.BeginReceive(recvBuffer, 0, recvBuffer.Length, _
SocketFlags.None, AddressOf ReceivedData, Nothing)
Catch ex As Exception
'-- Call DisconnectedUI
CallDisconnectedUI()
MessageBox.Show(ex.Message)
End Try
End Sub
Public Sub ReceivedData(ByVal ar As IAsyncResult)
Dim numBytes As Int32
Try
SyncLock ClientSocket
numBytes = ClientSocket.EndReceive(ar)
End SyncLock
Catch ex As Exception
CallDisconnectedUI()
Return
End Try
If numBytes = 0 Then
'-- Disconnected!
CallDisconnectedUI()
Return
End If
'-- We have data!
Dim data As String = _
System.Text.ASCIIEncoding.ASCII.GetString(recvBuffer, 0, numBytes)
CallDisplayTextCallback(data)
'-- Start Receiving Data Again!
ClientSocket.BeginReceive(recvBuffer, 0, recvBuffer.Length, _
SocketFlags.None, AddressOf ReceivedData, Nothing)
End Sub
Private Sub CallDisplayTextCallback(ByVal Text As String)
Dim cb As New DisplayTextCallback(AddressOf DisplayText)
Dim args() As Object = {Text}
Me.Invoke(cb, args)
End Sub
Private Delegate Sub DisplayTextCallback(ByVal Text As String)
Public Sub DisplayText(ByVal Text As String)
'txtDisplay.AppendText(Text)
'txtDisplay.SelectionStart = txtDisplay.Text.Length
End Sub
Private Sub CallDisconnectedUI()
Dim cb As New SimpleCallback(AddressOf DisconnectedUI)
Me.Invoke(cb)
End Sub
Private Delegate Sub SimpleCallback()
Public Sub ConnectedUI()
btnConnect.Text = "Disconnect"
btnSend.Enabled = True
Me.AcceptButton = btnSend
UpdateStatus("Connected")
End Sub
Public Sub DisconnectedUI()
btnConnect.Text = "Connect"
btnSend.Enabled = False
Me.AcceptButton = Nothing
End Sub
Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
Try
If cbOverride.Checked = False Then
SendMessage(txtSend.Text)
UpdateStatus("Completed request for order in the order xml")
Else
'tbStatus.Clear()
Dim lSendText As String = txtSend.Text
Dim lxml As New XmlDocument
lxml.LoadXml(lSendText)
lxml.GetElementsByTagName("OrderId").Item(0).InnerXml = mOrders(mCurrentOrderIndex).ToString
SendMessage(lxml.InnerXml)
UpdateStatus("Completed request for order " + mOrders(mCurrentOrderIndex).ToString)
mCurrentOrderIndex += 1
If mCurrentOrderIndex = mOrders.Count Then
MessageBox.Show("All Orders send. Reset and start again if needed.")
End If
'txtSend.Focus()
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub SendMessage(ByVal pMessage As String)
If pMessage.EndsWith(vbCrLf) = False Then
pMessage &= vbCrLf
End If
Dim bytes() As Byte = _
System.Text.ASCIIEncoding.ASCII.GetBytes(pMessage)
SyncLock ClientSocket
ClientSocket.Send(bytes, bytes.Length, SocketFlags.None)
End SyncLock
End Sub

Threading in .Net - Unable to get the window handle for the 'xxxxxx' control. Windowless ActiveX controls are not supported

We currently have this requirement to create a server which listens at a particular port and does some process. To be able to server multiple requests and be able to perfom efficiently, I decided to use threads. One of the step in this process was to send fax (I used pronexus - VBFax). This has .net controls that can be used. But sadly, you require a form where it can be placed and cannot be created on the fly (more on pronexus later i.e if I ever get to discussing it :-) ) .. so when the server starts a new thread for each request and calls the form using
dim MyForm as form = new FormWithPronexusControls
it gives the error
Unable to get the window handle for the 'VBVFrame' control. Windowless ActiveX controls are not supported

Now I searched left and right trying to find solutions and some solutions mentioned about this been a inherent problem with VS 2005. I even contacted pronexus support who are yet to get back with a solution. By the way, this works fine in VS2003. Some said about creating a custom control with a panel and adding my controls within it. I tried and it did not work. I saw another aticle about DEP (http://blogs.msdn.com/ed_maurer/archive/2007/12/14/nxcompat-and-the-c-compiler.aspx). I did not try it. But as I was reading it, I do not not why, but I thought of running the binary directly instead of running the debug version (i.e using VS2005 IDE). When I ran the exe directly, it suddenly started working.

So for now, it seems to be working and I will update this post if I get it working completely.

Why did I start this blog

I have created more than couple of blogs before this one and unfortunately never been able to consistently post on them. Anyway, I thought I will try again with this one.

From the days when I started programming (more than 12 yrs), I have been stuck in many technical problems. I started my programming days with BASIC, FORTRAN, dBase, Foxpro 2.5 (DOS), Foxpro 2.6 (windows), VB 3,4,5,6, ASP and then finally landed into the .Net world. I also did some work on Unisys mainframes. So as you can see, my life mostly revolved around the Microsoft arena. Like any other software, Microsoft technology too has its limitations and I have learnt to live with it or work around it, As I say, it's my bread and butter as I earn writing code on MS tech. I hate when others crib about the issues with Microsoft technology and at the same time continue to work onn them and earn their living too. What I want to tell them is to move on to some other technology instead of just complaining and continuing to stay there  ..

Anyway, back to "what am I planning to do in this blog". As the title suggests, I will try to post solutions to issues I have faced. I will not say that my solutions are the best and will always work for you too. But I will try to post my version of the solution. I hope that it will at the very least guide you into solving your problem. My posts may have reference to other sites (because I also google a lot for solutions :-) ) and I do not want to take credit to other's work. Please excuse me, if, in time these links stop working.

All the very best !! Do post some comments if my blog helps you or does not help you ..