Dailycode.info

Short solution for short problems

WSS Quiz webpart

Today, for the second time in a very short period, I had a request of making a quiz in WSS.

These was no budget for this, so I had to do this between the potatos and soup ;-)

The only default list that could handle this was a survey, but then a survey is not a quiz. You do not get the score at the end. Also the WSS survey has the annoying save button on the bottom which allows users to save their answer and complete it later.

You can find more on this here!

I hope to get a satisfying result in a few months, depens on how much time God allows me to spend on this.

 


SharePoint Designer not showing workflow folder, access denied when creating a workflow

When you open a site in Sharepoint designer and the workflow folder is not showing, it could have several reasons. 1 is that sometimes when the user which you are logged in with, is not a member of the Site collection administrators. Still your user can have Full control, but the workflow folder is not showing up. When you try to create a workflow folder you get access denied. There are 2 solutions which you can use. I'll explain these later in this post.

The other problem and solution is explained in a different post on this blog: try here! You will not get a access denied error but error: Unexpected error on server associating the workflow!

So now lets discuss the solutions to the first problem.

The first and easiest is to make your user a member of the site collection admins. Should solve the access denied error and show the workflow folder.

Second, when you do not want your user to be a member of the site collection admins:

Open a command window.

Use following command to open SharePoint Designer with a different user (which is a member of the site collection admins).

SharePoint designer is now opened with a different user and will show up the Workflow folder. It's not a solution actually, but a workaround.  


ListView Column Sorting

If you use a listview in windows forms, its columns are not sortable by default. So you'll have to write your own column sorter.

Let's take 3 steps:

Step 1: Create the ListViewColumnSorterIt's very easy; just create a new class that implements the IComparer interface. The class should look like this: 

/// <summary>
        /// This class is an implementation of the 'IComparer' interface.
        /// </summary>
        public class ListViewColumnSorter : IComparer
        {
            /// <summary>
            /// Specifies the column to be sorted
            /// </summary>
            private int ColumnToSort;
            /// <summary>
            /// Specifies the order in which to sort (i.e. 'Ascending').
            /// </summary>
            private SortOrder OrderOfSort;
            /// <summary>
            /// Case insensitive comparer object
            /// </summary>
            private CaseInsensitiveComparer ObjectCompare;
 
            /// <summary>
            /// Class constructor.  Initializes various elements
            /// </summary>
            public ListViewColumnSorter()
            {
                // Initialize the column to '0'
                ColumnToSort = 0;
 
                // Initialize the sort order to 'none'
                OrderOfSort = SortOrder.None;
 
                // Initialize the CaseInsensitiveComparer object
                ObjectCompare = new CaseInsensitiveComparer();
            }
 
            /// <summary>
            /// This method is inherited from the IComparer interface.  
//It compares the two objects passed using a case insensitive comparison.
            /// </summary>
            /// <param name="x">First object to be compared</param>
            /// <param name="y">Second object to be compared</param>
            /// <returns>The result of the comparison. "0" if equal,
// negative if 'x' is less than 'y' and positive if 'x' 
//is greater than 'y'</returns>
            public int Compare(object x, object y)
            {
                int compareResult;
                ListViewItem listviewX, listviewY;
 
                // Cast the objects to be compared to ListViewItem objects
                listviewX = (ListViewItem)x;
                listviewY = (ListViewItem)y;
 
                // Compare the two items
                compareResult = 
ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, 
listviewY.SubItems[ColumnToSort].Text);
 
                // Calculate correct return value based on 
//object comparison
                if (OrderOfSort == SortOrder.Ascending)
                {
                    // Ascending sort is selected, return normal 
//result of compare operation
                    return compareResult;
                }
                else if (OrderOfSort == SortOrder.Descending)
                {
                    // Descending sort is selected, 
//return negative result of compare operation
                    return (-compareResult);
                }
                else
                {
                    // Return '0' to indicate they are equal
                    return 0;
                }
            }
 
            /// <summary>
            /// Gets or sets the number of the column to which 
//to apply the sorting operation (Defaults to '0').
            /// </summary>
            public int SortColumn
            {
                set
                {
                    ColumnToSort = value;
                }
                get
                {
                    return ColumnToSort;
                }
            }
 
            /// <summary>
            /// Gets or sets the order of sorting to 
//apply (for example, 'Ascending' or 'Descending').
            /// </summary>
            public SortOrder Order
            {
                set
                {
                    OrderOfSort = value;
                }
                get
                {
                    return OrderOfSort;
                }
            }
 
        }

This is the class you will instantiate and assing to the ListViewItemSorter property.

Step 2: declare and instantiate the listviewcolumnsorter:

 

private ListViewColumnSorter lvwColumnSorter;
 
InitializeComponent();
lvwColumnSorter = new ListViewColumnSorter();
lstMyListView.ListViewItemSorter = lvwColumnSorter;
 

Step 3: Now on the column click event insert this logic and your finished, all columns are sortable:   

 

private void lstContacts_ColumnClick(object sender, ColumnClickEventArgs e)
{
// Determine if clicked column is already the column that is 
//being sorted.
      if (e.Column == lvwColumnSorter.SortColumn)
      {
            // Reverse the current sort direction for this column.
            if (lvwColumnSorter.Order == SortOrder.Ascending)
            {
                  lvwColumnSorter.Order = SortOrder.Descending;
}
            else
            {
                  lvwColumnSorter.Order = SortOrder.Ascending;
}
}
      else
      {
            // Set the column number that is to be sorted; default to 
//ascending.
            lvwColumnSorter.SortColumn = e.Column;
            lvwColumnSorter.Order = SortOrder.Ascending;
}
 
      // Perform the sort with these new sort options.
      this.lstContacts.Sort();
 
}
 
I based this article on this post : http://support.microsoft.com/kb/319401 Just tried it myself and then blogged it, so I have this solution archieved. Microsoft tends to delete certain content now and then ;-)

 


TcpListener .AcceptSocket() hangs

 First I will sketch the situation. We have a number of devices connected to the network through RS32. Devices like a barcode scanner, weigh scales, RFID scanners … When a user uses a device, the data gets send through the network using TCP. When the data is sent on the network it needs to be received by client pc. There is mapping data stored in the database that controls what devices should communicate with which client pc. This is where the device manager comes in place. 

The device manager polls the port from the devices and passes the received information to the client devices. The device manager is a .Net service on that runs continuously on a server.  

The problem that kept occurring was that when a socket could not be reached the TCPClient hanged. The only possibility was to restart the service. On some cases we had to reboot the server because the service could not be stopped and we couldn’t stop the task with task management.   

The line of code that was giving the problem was this: 

try
{
      	if (_tcpListener != null)      
      	{
            	_tcpListener.Stop();
      	}
	_tcpListener = new TcpListener(IPAddress.Any, _inTcpPort);
	_tcpListener.Start();
       _socket = _tcpListener.AcceptSocket();
       return (_socket.Connected);
}
catch (Exception exc)
{
	ExceptionManager.Publish(exc);
      	return false;

}

 

When the socket can not be reached it will keep looking for it and blocks the thread. I tried to look for a solution on the internet but couldn’t find a decent one. So I started to test with multi threading. I created a multi threading solution with a timeout releasing the objects if the timeout was reached. While looking I managed to use a part of the threading logic that was exposed by the TCPListener itself. The main thread will be synchronic, so we will never try to poll 2 sockets at the same time. It is possible, when you have 1000’s of devices to run the socket connections asynchrone, but you’ll have to change the socket connected checking. Since we are using no more the 50 devices it will take a few minutes to start up the service, which is very acceptable and easy manageable. 

The line of code I presented above changed into this piece of code:

if (_tcpListener != null)
{
_tcpListener.Stop();
}
_tcpListener = new TcpListener(IPAddress.Any, _inTcpPort);
_tcpListener.Start();
if (!_tcpListener.Pending())
{
            //This is were we start the socket connection logic in a different thread.
IAsyncResult ar = 
_tcpListener.BeginAcceptSocket(new AsyncCallback(DoAcceptSocketCallback), _tcpListener);
 
//Here I’ll wait for 5 seconds, if the socket could not be found, I release the tcpListener 
Thread.Sleep(5000);
 
 
if (_socket != null && _socket.Connected)
{
// these parameters are only of use after the socket is connected.
_socket.SendTimeout = 20000;
// If the device you are polling sends and recieves commands/information then 
// do not use this parameter._socket.Blocking = false;
return (_socket.Connected);
}
else
{
if (_socket != null)
{
_socket.Close();
}
if (_tcpListener != null)
{
_tcpListener.Stop();
_tcpListener = null;
}
return false;
}
}

 It is actually the BeginAcceptSocket who starts a asychronous proces to listen to the port. This proces looks like this: 

// Process the client connection.
public void DoAcceptSocketCallback(IAsyncResult ar)
{
try
{
// Get the listener that handles the client request.
TcpListener listener = (TcpListener)ar.AsyncState;
 
if (listener != null)
{
            //Here we connect to the socket.
_socket = listener.EndAcceptSocket(ar);
 
string message = string.Format("Device {0} {1}: 'Startpolling()' success.", 
_deviceType, _inTcpPort);
EventLogWriter.Instance.WriteToLog(message, EventLogEntryType.Information);
}
}
catch
{
_socket = null;
}
}

 So the system tries to connect to the socket in a different thread and the main thread is set to sleep for about 5 sec (I’ll put this in a config file to make it configurable). If the _socket is not connected after these 5 seconds, I release the tcplistener with this code: 

if (_socket != null)
{
_socket.Close();
}
if (_tcpListener != null)
{
_tcpListener.Stop();
_tcpListener = null;
}

 When you release the tcplistener the DoAcceptSocketCallback function will be called, so make your check if its not null. Now the system is stable. I haven’t had 1 hang or instability. It always stops and starts perfect and when a device fails to connect, I write a nice entry in the eventlog explaning which device on which port and to which client PC failed to connect. 

//The StartCommunication() function calls the logic where I call the BeginAcceptSocket method mentioned in the 
//beginning of the post. It will return socket.Connected or 
//in case of error (socket could not be found or reached or is not free) it return false. Before I call the 
//device.StartCommunication I write a log entry to inform that the  
//system will try to connect socket ... on device ... and with destination ...
if (device.StartCommunication())
{
 
message = string.Format("Added device.\rName: {0} ({3})\rDestination / port: {1} / {2}", name, 
DestinationIp, tcpPort, (DeviceType)Type);
EventLogWriter.Instance.WriteToLog(message, EventLogEntryType.Information);
}
else
{
message = string.Format("Device {0}-{1}: 'Startpolling()' failed on port: {2}.", device.Guid, 
device.Name, device.TCPPort);
EventLogWriter.Instance.WriteToLog(message, EventLogEntryType.Error);
}

 Works great!!! 

InstallUtil troubleshoot

When I was un/installing a service on a server I had to use the installutil utility from the .Net framework. I encoutered some problems with this.

1)  'Installutil' is not recognized as an internal or external command,
operable program or batch file.

Solution: The .NET path is not added to the environment variable by default. To use
this tool either navigate to the folder where .NET is installed into (i.e.
c:\windows\Microsoft.NET\framework\..), or open the command prompt that is installed
with VS.NET which sets the environment correctly.

Source: http://bytes.com/groups/net-c/253392-installutil-exe-not-recognized-internal

2) Exception occurred while initializing the installation:
System.BadImageFormatException: The format of the file 'device_manager.exe'
 is invalid.

This means that the installutil that is used by default is the wrong version of the .Net framework. You can browse to the folder of the correct framework and run the installutil from there.

There are several folders available for the different frameworks. Use the highest version your assembly is compiled in. The folders are situated under: (systemdrive):\WINDOWS\Microsoft.NET\Framework and can be the following:

v1.0.3705
v1.1.4322
v2.0.50727
v3.0
v3.5


Ctrl-Alt-Del in remote desktop

This is one of these simple posts that serve as a reminder for myself.

I use Remote Desktop a lot to log in to the servers and development environment. So when I want to hit Ctrl-Alt-Del the menu of my pc pops up. So the solution is to choose Ctrl-Alt-End.

That's it.