Ciaran's profileRamblings of a wanna be ...BlogListsNetwork Tools Help

Ramblings of a wanna be developer

try{ Life(); } Catch(TooDifficultException){ throw Toys(); }
August 13

Entity Framework Information

Well its been more than a couple of days since the last new piece of .NET technology was released so it seems its time for another one. The Entity Framework which has been known about in the community for a long time now is just about released and information has been coming out about it a lot recently.
The Entity Framework is a new way in .NET to access and use data in your application.
There is a cool FAQ on Dan Simmons (Dev Team leader for Microsoft on the Entity Framework Team) blog: http://blogs.msdn.com/dsimmons/pages/entity-framework-faq.aspx
 
Plus there is a .NET Rocks show on it and a couple of DNRtv shows on it.
 
If you havent heard of or listened to / watched Dot Net Rocks then you should check it out. Its a great resource to hear about new .NET stuff and the DNRtv is great for seeing the whole process of getting started with technologies like Entity Framework. Its an order of magnitude more helpfull then a written walkthough.
 
Check it out and let me know what you think.
 
Ciaran
July 23

Getting file path with capitals included 2

I previously posted a class that would get a files path including the correct capitals. I have since found a better way to do this by using the shell functions in Windows. I didnt create this method, I FOUND it. Its from a very clever windows programmer who does a site called http://codegator.com/.
To use this method, simple do:
 
CGPidl pidl = new CGPidle(path);
string filesRealPath = pidl.PhysicalPath;
 
How this helps people. It should be a lot faster than the last way I posted.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data.SqlClient;
using System.Data;
using System.Diagnostics;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Collections;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Security.Permissions;
using System.Runtime.InteropServices.ComTypes;
namespace ShellInfo
{

[ComVisible(false)]
sealed class CGPidl : IDisposable
{
private static class NativeMethods
{
[
StructLayout(LayoutKind.Sequential)]
public struct
RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT(
Rectangle r
)
{
left = r.Left;
top = r.Top;
right = r.Right;
bottom = r.Bottom;
}
}
[
Flags]
public enum CSIDL
{
CSIDL_FLAG_CREATE = 0x8000,
CSIDL_ADMINTOOLS = 0x0030,
CSIDL_ALTSTARTUP = 0x001d,
CSIDL_APPDATA = 0x001a,
CSIDL_BITBUCKET = 0x000a,
CSIDL_CDBURN_AREA = 0x003b,
CSIDL_COMMON_ADMINTOOLS = 0x002f,
CSIDL_COMMON_ALTSTARTUP = 0x001e,
CSIDL_COMMON_APPDATA = 0x0023,
CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019,
CSIDL_COMMON_DOCUMENTS = 0x002e,
CSIDL_COMMON_FAVORITES = 0x001f,
CSIDL_COMMON_MUSIC = 0x0035,
CSIDL_COMMON_PICTURES = 0x0036,
CSIDL_COMMON_PROGRAMS = 0x0017,
CSIDL_COMMON_STARTMENU = 0x0016,
CSIDL_COMMON_STARTUP = 0x0018,
CSIDL_COMMON_TEMPLATES = 0x002d,
CSIDL_COMMON_VIDEO = 0x0037,
CSIDL_CONTROLS = 0x0003,
CSIDL_COOKIES = 0x0021,
CSIDL_DESKTOP = 0x0000,
CSIDL_DESKTOPDIRECTORY = 0x0010,
CSIDL_DRIVES = 0x0011,
CSIDL_FAVORITES = 0x0006,
CSIDL_FONTS = 0x0014,
CSIDL_HISTORY = 0x0022,
CSIDL_INTERNET = 0x0001,
CSIDL_INTERNET_CACHE = 0x0020,
CSIDL_LOCAL_APPDATA = 0x001c,
CSIDL_MYDOCUMENTS = 0x000c,
CSIDL_MYMUSIC = 0x000d,
CSIDL_MYPICTURES = 0x0027,
CSIDL_MYVIDEO = 0x000e,
CSIDL_NETHOOD = 0x0013,
CSIDL_NETWORK = 0x0012,
CSIDL_PERSONAL = 0x0005,
CSIDL_PRINTERS = 0x0004,
CSIDL_PRINTHOOD = 0x001b,
CSIDL_PROFILE = 0x0028,
CSIDL_PROFILES = 0x003e,
CSIDL_PROGRAM_FILES = 0x0026,
CSIDL_PROGRAM_FILES_COMMON = 0x002b,
CSIDL_PROGRAMS = 0x0002,
CSIDL_RECENT = 0x0008,
CSIDL_SENDTO = 0x0009,
CSIDL_STARTMENU = 0x000b,
CSIDL_STARTUP = 0x0007,
CSIDL_SYSTEM = 0x0025,
CSIDL_TEMPLATES = 0x0015,
CSIDL_WINDOWS = 0x0024
}
[
StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public Int32 iIcon;
public UInt32 dwAttributes;
[
MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[
MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
public enum SHCONTF
{
SHCONTF_FOLDERS = 0x0020,
SHCONTF_NONFOLDERS = 0x0040,
SHCONTF_INCLUDEHIDDEN = 0x0080,
SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
SHCONTF_NETPRINTERSRCH = 0x0200,
SHCONTF_SHAREABLE = 0x0400,
SHCONTF_STORAGE = 0x0800
}
[
Flags]
public enum SHGFI
{
SHGFI_ICON = 0x000000100,
SHGFI_DISPLAYNAME = 0x000000200,
SHGFI_TYPENAME = 0x000000400,
SHGFI_ATTRIBUTES = 0x000000800,
SHGFI_ICONLOCATION = 0x000001000,
SHGFI_EXETYPE = 0x000002000,
SHGFI_SYSICONINDEX = 0x000004000,
SHGFI_LINKOVERLAY = 0x000008000,
SHGFI_SELECTED = 0x000010000,
SHGFI_ATTR_SPECIFIED = 0x000020000,
SHGFI_LARGEICON = 0x000000000,
SHGFI_SMALLICON = 0x000000001,
SHGFI_OPENICON = 0x000000002,
SHGFI_SHELLICONSIZE = 0x000000004,
SHGFI_PIDL = 0x000000008,
SHGFI_USEFILEATTRIBUTES = 0x000000010,
SHGFI_ADDOVERLAYS = 0x000000020,
SHGFI_OVERLAYINDEX = 0x000000040
}
[
Flags]
public enum SHCIDS : uint
{
SHCIDS_ALLFIELDS = 0x80000000,
SHCIDS_CANONICALONLY = 0x10000000,
SHCIDS_BITMASK = 0xFFFF0000,
SHCIDS_COLUMNMASK = 0x0000FFFF
}
[
Flags()]
public enum SFGAO : uint
{
SFGAO_CANCOPY = 0x000000001,
SFGAO_CANMOVE = 0x000000002,
SFGAO_CANLINK = 0x000000004,
SFGAO_STORAGE = 0x000000008,
SFGAO_CANRENAME = 0x00000010,
SFGAO_CANDELETE = 0x00000020,
SFGAO_HASPROPSHEET = 0x00000040,
SFGAO_DROPTARGET = 0x00000100,
SFGAO_CAPABILITYMASK = 0x00000177,
SFGAO_ENCRYPTED = 0x00002000,
SFGAO_ISSLOW = 0x00004000,
SFGAO_GHOSTED = 0x00008000,
SFGAO_LINK = 0x00010000,
SFGAO_SHARE = 0x00020000,
SFGAO_READONLY = 0x00040000,
SFGAO_HIDDEN = 0x00080000,
SFGAO_DISPLAYATTRMASK = 0x000FC000,
SFGAO_FILESYSANCESTOR = 0x10000000,
SFGAO_FOLDER = 0x20000000,
SFGAO_FILESYSTEM = 0x40000000,
SFGAO_HASSUBFOLDER = 0x80000000,
SFGAO_CONTENTSMASK = 0x80000000,
SFGAO_VALIDATE = 0x01000000,
SFGAO_REMOVABLE = 0x02000000,
SFGAO_COMPRESSED = 0x04000000,
SFGAO_BROWSABLE = 0x08000000,
SFGAO_NONENUMERATED = 0x00100000,
SFGAO_NEWCONTENT = 0x00200000,
SFGAO_CANMONIKER = 0x00400000,
SFGAO_HASSTORAGE = 0x00400000,
SFGAO_STREAM = 0x00400000,
SFGAO_STORAGEANCESTOR = 0x00800000,
SFGAO_STORAGECAPMASK = 0x70C50008
}
[
Flags()]
public enum SHGDN
{
SHGDN_NORMAL = 0,
SHGDN_INFOLDER = 1,
SHGDN_FORADDRESSBAR = 16384,
SHGDN_FORPARSING = 32768
}
[
StructLayout(LayoutKind.Explicit)]
public struct STRRET
{
[
FieldOffset(0)]
UInt32 uType;
[
FieldOffset(4)]
IntPtr pOleStr;
[
FieldOffset(4)]
IntPtr pStr;
[
FieldOffset(4)]
UInt32 uOffset;
[
FieldOffset(4)]
IntPtr cStr;
}
public enum SVUIA_STATUS
{
SVUIA_DEACTIVATE = 0,
SVUIA_ACTIVATE_NOFOCUS = 1,
SVUIA_ACTIVATE_FOCUS = 2,
SVUIA_INPLACEACTIVATE = 3
}
[
StructLayout(LayoutKind.Sequential)]
public struct FOLDERSETTINGS
{
public FOLDERFLAGS ViewMode;
public FOLDERVIEWMODE fFlags;
}
[
Flags]
public enum FOLDERFLAGS
{
FWF_AUTOARRANGE = 0x1,
FWF_ABBREVIATEDNAMES = 0x2,
FWF_SNAPTOGRID = 0x4,
FWF_OWNERDATA = 0x8,
FWF_BESTFITWINDOW = 0x10,
FWF_DESKTOP = 0x20,
FWF_SINGLESEL = 0x40,
FWF_NOSUBFOLDERS = 0x80,
FWF_TRANSPARENT = 0x100,
FWF_NOCLIENTEDGE = 0x200,
FWF_NOSCROLL = 0x400,
FWF_ALIGNLEFT = 0x800,
FWF_NOICONS = 0x1000,
FWF_SHOWSELALWAYS = 0x2000,
FWF_NOVISIBLE = 0x4000,
FWF_SINGLECLICKACTIVATE = 0x8000,
FWF_NOWEBVIEW = 0x10000,
FWF_HIDEFILENAMES = 0x20000,
FWF_CHECKSELECT = 0x40000
}
public enum FOLDERVIEWMODE
{
FVM_FIRST = 1,
FVM_ICON = 1,
FVM_SMALLICON = 2,
FVM_LIST = 3,
FVM_DETAILS = 4,
FVM_THUMBNAIL = 5,
FVM_TILE = 6,
FVM_THUMBSTRIP = 7,
FVM_LAST = 7
}
[
ComImport]
[
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[
Guid("000214E6-0000-0000-C000-000000000046")]
public interface IShellFolder
{
[
PreserveSig]
Int32 ParseDisplayName(
IntPtr hwnd,
IntPtr pbc,
[
MarshalAs(UnmanagedType.LPWStr)]
string pszDisplayName,
ref UInt32 pchEaten,
out IntPtr ppidl,
ref UInt32 pdwAttributes
);
[
PreserveSig]
Int32 EnumObjects(
IntPtr hwnd,
SHCONTF grfFlags,
out IEnumIDList ppenumIDList
);
[
PreserveSig]
Int32 BindToObject(
IntPtr pidl,
IntPtr pbc,
ref Guid riid,
out IntPtr ppv
);
[
PreserveSig]
Int32 BindToStorage(
IntPtr pidl,
IntPtr pbc,
ref Guid riid,
out IntPtr ppv
);
[
PreserveSig]
Int32 CompareIDs(
SHCIDS lParam,
IntPtr pidl1,
IntPtr pidl2
);
[
PreserveSig]
Int32 CreateViewObject(
IntPtr hwndOwner,
ref Guid riid,
out IShellView ppv
);
[
PreserveSig]
Int32 GetAttributesOf(
UInt32 cidl,
[
MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]
IntPtr[] apidl,
ref SFGAO rgfInOut
);
[
PreserveSig]
Int32 GetUIObjectOf(
IntPtr hwndOwner,
UInt32 cidl,
IntPtr[] apidl,
Guid riid,
ref UInt32 rgfReserved,
out IntPtr ppv
);
[
PreserveSig]
Int32 GetDisplayNameOf(
IntPtr pidl,
SHGDN uFlags,
out STRRET pName
);
[
PreserveSig]
Int32 SetNameOf(
IntPtr hwnd,
IntPtr pidl,
[
MarshalAs(UnmanagedType.LPWStr)]
string pszName,
UInt32 uFlags,
out IntPtr ppidlOut
);
}
[
ComImportAttribute()]
[
GuidAttribute("000214F2-0000-0000-C000-000000000046")]
[
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumIDList
{
[
PreserveSig]
int Next(
int celt,
ref IntPtr rgelt,
out int pceltFetched
);
[
PreserveSig]
int Skip(int celt);
[
PreserveSig]
int Reset();
[
PreserveSig]
int Clone(ref IEnumIDList ppenum);
}
[
ComImport()]
[
Guid("000214E3-0000-0000-C000-000000000046")]
[
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellView
{
[
PreserveSig]
int GetWindow(out IntPtr phwnd);
[
PreserveSig]
int ContextSensitiveHelp(bool fEnterMode);
[
PreserveSig]
int TranslateAcceleratorA(IntPtr pmsg);
[
PreserveSig]
int EnableModeless(bool fEnable);
[
PreserveSig]
int UIActivate(SVUIA_STATUS uState);
[
PreserveSig]
int Refresh();
[
PreserveSig]
int CreateViewWindow(
IShellView psvPrevious,
ref FOLDERSETTINGS pfs,
IShellBrowser psb,
ref RECT prcView,
out IntPtr phWnd
);
[
PreserveSig]
int DestroyViewWindow();
[
PreserveSig]
int GetCurrentInfo(
ref FOLDERSETTINGS pfs
);
[
PreserveSig]
int AddPropertySheetPages(
long dwReserved,
ref IntPtr pfnPtr,
int lparam
);
[
PreserveSig]
int SaveViewState();
[
PreserveSig]
int SelectItem(
IntPtr pidlItem,
uint uFlags
);
[
PreserveSig]
int GetItemObject(
uint uItem,
ref Guid riid,
ref IntPtr ppv
);
}
[
ComImport()]
[
Guid("000214E2-0000-0000-C000-000000000046")]
[
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IShellBrowser
{
[
PreserveSig]
int GetWindow(out IntPtr phwnd);
[
PreserveSig]
int ContextSensitiveHelp(bool fEnterMode);
[
PreserveSig]
int InsertMenusSB(
IntPtr hmenuShared,
ref IntPtr lpMenuWidths
);
[
PreserveSig]
int SetMenuSB(
IntPtr hmenuShared,
IntPtr holemenuRes,
IntPtr hwndActiveObject
);
[
PreserveSig]
int RemoveMenusSB(IntPtr hmenuShared);
[
PreserveSig]
int SetStatusTextSB(string pszStatusText);
[
PreserveSig]
int EnableModelessSB(bool fEnable);
[
PreserveSig]
int TranslateAcceleratorSB(
IntPtr pmsg,
short wID
);
[
PreserveSig]
int BrowseObject(
IntPtr pidl,
uint wFlags
);
[
PreserveSig]
int GetViewStateStream(
long grfMode,
ref IStream ppStrm
);
[
PreserveSig]
int GetControlWindow(uint id, ref IntPtr phwnd);
[
PreserveSig]
int SendControlMsg(
uint id,
uint uMsg,
short wParam,
long lParam,
ref long pret
);
[
PreserveSig]
int QueryActiveShellView(
ref IShellView ppshv
);
[
PreserveSig]
int OnViewWindowActive(
IShellView pshv
);
[
PreserveSig]
int SetToolbarItems(
IntPtr lpButtons,
uint nButtons,
uint uFlags
);
}
[
DllImport("shell32.dll", EntryPoint = "#18")]
public static extern IntPtr ILClone(
IntPtr pidl
);
[
DllImport("shell32.dll", EntryPoint = "#25")]
public static extern IntPtr ILCombine(
IntPtr pidlA,
IntPtr pidlB
);
[
DllImport("shell32.dll", EntryPoint = "#17")]
public static extern bool ILRemoveLastID(
IntPtr pidl
);
[
DllImport("shell32.dll")]
public static extern Int32 SHGetDesktopFolder(
out IShellFolder ppshf
);
[
DllImport("shell32.dll")]
public static extern Int32 SHGetFolderLocation(
IntPtr hwndOwner,
CSIDL nFolder,
IntPtr hToken,
UInt32 dwReserved,
out IntPtr ppidl
);
[
DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(
string fileName,
uint dwFileAttributes,
ref SHFILEINFO psfi,
int cbSizeFileInfo,
SHGFI flags
);
[
DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(
IntPtr pidl,
uint dwFileAttributes,
ref SHFILEINFO psfi,
int cbSizeFileInfo,
SHGFI flags
);
[
DllImport("shell32.dll")]
public static extern bool SHGetPathFromIDList(
IntPtr pidl,
StringBuilder pszPath
);
 
 
}
private static readonly NativeMethods.IShellFolder c_desktopFolder;
private static readonly IntPtr c_desktopPidl;
private IntPtr m_pidl;
private string m_displayName;
private string m_typeName;
private string m_physicalPath;
private NativeMethods.SFGAO m_attributes;
public IntPtr Pidl
{
get { return m_pidl; }
}
public string DisplayName
{
get { return m_displayName; }
}
public string TypeName
{
get { return m_typeName; }
}
public string PhysicalPath
{
get { return m_physicalPath; }
}

[
SecurityPermission(
SecurityAction.LinkDemand,
Flags =
SecurityPermissionFlag.UnmanagedCode)]
static CGPidl()
{
// Get a reference to the desktop folder.
NativeMethods.SHGetDesktopFolder(
out c_desktopFolder
);
IntPtr hToken = new IntPtr(-1);
// Get the pidl for the desktop folder.
int hr = NativeMethods.SHGetFolderLocation(
IntPtr.Zero,
NativeMethods.CSIDL.CSIDL_DESKTOP,
hToken,
0,
out c_desktopPidl
);
}
 
 
 
[
SecurityPermission(
SecurityAction.LinkDemand,
Flags =
SecurityPermissionFlag.UnmanagedCode)]
public CGPidl(
string fullPath
)
{
Open(fullPath);
}
public void Dispose()
{
Close();
}
public override bool Equals(object obj)
{
// Recover a reference to the CGPidl object.
CGPidl pidl = obj as CGPidl;
// Sanity check the type first.
if (pidl == null)
return false;
// Ask the desktop to determine if they are equal.
return c_desktopFolder.CompareIDs(
NativeMethods.SHCIDS.SHCIDS_CANONICALONLY,
m_pidl,
pidl.m_pidl
) == 0;
}
public override int GetHashCode()
{
return base.GetHashCode() ^ m_pidl.GetHashCode();
}
public void Open(
IntPtr pidl
)
{
// Clone to pidl.
m_pidl = NativeMethods.ILClone(pidl);
// Initialize the object.
InitializeObject();
}
[
SecurityPermission(
SecurityAction.LinkDemand,
Flags =
SecurityPermissionFlag.UnmanagedCode)]
public void Open(
string fullPath
)
{
uint attr = 0;
uint pchEaten = 0;
// Attempt to get a pidl to the object.
int hr = c_desktopFolder.ParseDisplayName(
IntPtr.Zero,
IntPtr.Zero,
fullPath,
ref pchEaten,
out m_pidl,
ref attr
);
// Did we fail?
if (hr != 0)
Marshal.ThrowExceptionForHR(hr);
// Initialize the object.
InitializeObject();
}
public void Close()
{
// Should we cleanup the pidl?
if (m_pidl != IntPtr.Zero)
Marshal.FreeCoTaskMem(m_pidl);
m_pidl =
IntPtr.Zero;
}
 
[
SecurityPermission(
SecurityAction.LinkDemand,
Flags =
SecurityPermissionFlag.UnmanagedCode)]
private void InitializeObject()
{
NativeMethods.SHFILEINFO shfi =
new NativeMethods.SHFILEINFO();
// Attempt to get the information for the shell object.
NativeMethods.SHGetFileInfo(
m_pidl,
0,
ref shfi,
Marshal.SizeOf(shfi),
NativeMethods.SHGFI.SHGFI_PIDL |
NativeMethods.SHGFI.SHGFI_DISPLAYNAME |
NativeMethods.SHGFI.SHGFI_ATTRIBUTES |
NativeMethods.SHGFI.SHGFI_TYPENAME
);
// Save the information.
m_displayName = shfi.szDisplayName;
m_typeName = shfi.szTypeName;
m_attributes = (
NativeMethods.SFGAO)shfi.dwAttributes;
StringBuilder sb = new StringBuilder(260);
// Get the physical path to the shell object.
NativeMethods.SHGetPathFromIDList(
m_pidl,
sb
);
// Save the path.
m_physicalPath = sb.ToString();
}


}
}
July 10

Getting a files path with capitals included

Came across a post on the Microsoft forum which was looking to find out whether there was a way to get the Path of a file or folder on disk including all the capital letters. Incase you didnt know, the FileInfo and DirectoryInfo use the string you pass in to get them as the FullName property and dont actually check the file on disk at all until you call a function like Exists() which requires them too.
I couldnt see a framework based way to do this so I made this little class to do it. It has a static method you can pass a file or folder path and it will return the path with the case.
Feel free to use it, but please, let me know what you think.
 
public class FileNameGetter
{
[
Serializable,
System.Runtime.InteropServices.
StructLayout
(System.Runtime.InteropServices.LayoutKind.Sequential,
CharSet = System.Runtime.InteropServices.
CharSet.Auto
),
System.Runtime.InteropServices.
BestFitMapping(false)]
private struct WIN32_FIND_DATA
{
public int dwFileAttributes;
public int ftCreationTime_dwLowDateTime;
public int ftCreationTime_dwHighDateTime;
public int ftLastAccessTime_dwLowDateTime;
public int ftLastAccessTime_dwHighDateTime;
public int ftLastWriteTime_dwLowDateTime;
public int ftLastWriteTime_dwHighDateTime;
public int nFileSizeHigh;
public int nFileSizeLow;
public int dwReserved0;
public int dwReserved1;
[System.Runtime.InteropServices.
MarshalAs
(System.Runtime.InteropServices.UnmanagedType.ByValTStr,
SizeConst = 260)]
public string cFileName;
[System.Runtime.InteropServices.
MarshalAs
(System.Runtime.InteropServices.UnmanagedType.ByValTStr,
SizeConst = 14)]
public string cAlternateFileName;
}
 
[System.Runtime.InteropServices.
DllImport
("kernel32.dll",
CharSet = System.Runtime.InteropServices.
CharSet.Auto,
SetLastError =
true)]
private static extern IntPtr FindFirstFile(string pFileName, ref WIN32_FIND_DATA pFindFileData);
[System.Runtime.InteropServices.
DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FindClose(IntPtr hndFindFile);
 
public static string GetCasedFilePath(string fullPath)
{
bool isFile = File.Exists(fullPath);
bool isDir = Directory.Exists(fullPath);
if (isDir && !fullPath.EndsWith("\\")) fullPath += "\\";
if ( !isFile && !isDir) throw new FileNotFoundException("File doesnt exist");
string pathbit = fullPath;

Stack<string> pathStack = new Stack<string>();
string dirName = Path.GetDirectoryName(pathbit);
while (dirName != null)
{
pathStack.Push(dirName);
dirName =
Path.GetDirectoryName(dirName);
}
string realPath = string.Empty;
WIN32_FIND_DATA data = new WIN32_FIND_DATA();
while (pathStack.Count > 0)
{
dirName = pathStack.Pop();
if (Path.GetPathRoot(dirName) == dirName)
{
realPath = dirName;
}
else
{
IntPtr findHandle = FindFirstFile(dirName, ref data);
realPath =
Path.Combine(realPath, data.cFileName);
FindClose(findHandle);
}
}
if (isFile)
{
IntPtr findHandle = FindFirstFile(fullPath, ref data);
realPath =
Path.Combine(realPath, data.cFileName);
FindClose(findHandle);
}

return realPath;
}
}
July 08

Impersonation Utility class

Below is a class I use when I need to do particular actions using impersionation. You create an instance of the class, attach an event handler to the ExecuteImpersonatedAction event and then call the Impersonate function passing the domain username and password for the user to impersonate. This will then do the impersonation raise the event to run your handler, then undo the impersonation.
Its not rocket science but it does stop you having to reinvent this wheel all the time.
 
Let me know what you think.
 
/// <summary>
/// Manages the execution of client code in the context of an impersonated user.
/// </summary>
public class ImpersonatedAction : IDisposable
{
[
DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[
DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
 
private static IntPtr tokenHandle = IntPtr.Zero;
private static WindowsImpersonationContext impersonatedUser;
/// <summary>
/// Raises an event that can execute code in the impersonated user's context.
/// </summary>
public event EventHandler<EventArgs> ExecuteImpersonatedAction;
/// <summary>
/// Creates a new instance of the <see cref="ImpersonatedAction"/> class,
/// </summary>
public ImpersonatedAction()
{
}

/// <summary>
/// Impersonates a specified user account and raises the <see cref="ExecuteImpersonatedAction"/>
/// event for client actions running unde the impersonated context.
/// </summary>
/// <param name="domain">The impersonating user's account domain.</param>
/// <param name="userName">The impersonating user's account name.</param>
/// <param name="password">The impersonating user's account password.</param>
/// <remarks></remarks>
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void Impersonate(string domain, string userName, SecureString password)
{
try
{
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_BATCH = 4;
const int LOGON32_LOGON_SERVICE = 5;
const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
tokenHandle =
IntPtr.Zero;
// Get password
IntPtr ptr = Marshal.SecureStringToBSTR(password);
string pw = Marshal.PtrToStringUni(ptr);
Marshal.ZeroFreeBSTR(ptr);
// Logon impersonation user
bool returnValue = LogonUser(
userName,
domain,
pw,
LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
if (!returnValue)
{
int ret = Marshal.GetLastWin32Error();
Trace.WriteLine(String.Format("LogonUser call failed with error code {0}.", ret));
throw new Win32Exception(ret);
}
// Create impersonated context
impersonatedUser = WindowsIdentity.Impersonate(tokenHandle);
// Execute client action
this.OnExecuteImpersonatedAction();
}
finally
{
// Undo impersonation
if (impersonatedUser != null)
{
impersonatedUser.Undo();
}
impersonatedUser =
null;
// Release pointer
if (tokenHandle != IntPtr.Zero)
{
CloseHandle(tokenHandle);
}
tokenHandle =
IntPtr.Zero;
}
}
/// <summary>
/// Raises the <see cref="ExecuteImpersonatedAction"/> event.
/// </summary>
protected virtual void OnExecuteImpersonatedAction()
{
if (ExecuteImpersonatedAction != null)
{
this.ExecuteImpersonatedAction(this, EventArgs.Empty);
}
}
#region IDisposable Members

// Track whether Dispose has been called
private bool disposed = false;
/// <summary>
/// Releases all resources used by the <see cref="ImpersonatedAction"/>.
/// </summary>
public void Dispose()
{
this.Dispose(true);
// Remove this object from the Finalization queue to prevent second execution of finalization code
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes the instance's managed and unmanaged resources.
/// </summary>
/// <param name="disposing">Set true to indicate that the method has been called directly
/// or indirectly by a user's code.
/// Set false to indicate that the method has been called by the runtime from inside the
/// finalizer</param>
protected virtual void Dispose(bool disposing)
{
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
// Check to see if Dispose has already been called.
if (!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources
if (impersonatedUser != null)
{
impersonatedUser.Undo();
}
}
// Dispose unmanaged resources
if (tokenHandle != IntPtr.Zero)
{
CloseHandle(tokenHandle);
}
}
disposed =
true;
}
/// <summary>
/// The class destructor.
/// </summary>
~ImpersonatedAction()
{
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
this.Dispose(false);
}
#endregion
}
July 05

Refactor! Pro

Hey,
So I have recently been trying to geek up do to the fact that my current role which I have been in for 21 months so far has actually de-skilled me. So I thought I would go through all the dotnetrocks episodes I had been missing out on and then thought I would have a look through all the dnrtv's to SEE how to do a lot of the things talked about on dotnetrocks.
I saw one of the dnrtv sessions with Mark Miller talking about CodeRush and Refactor! Pro and thought I'd give it a watch. I used to use these tools a few years ago and kinda remembered how handy and fast the refactoring was and how easy it made things. Watching the dnrtv episode brought it all back and actually showed me how much better it had got since then too.
 
I would advise anybody who refactors to have a serious look at this dnrtv episode (http://www.dnrtv.com/default.aspx?showNum=107) and check out Refactor! Pro and CodeRush. These are seriously handing tools and come with a free component (from the same developers) called DXCore which enables a lot of new integration with visual studio.
The tools are from DevExpress and are pretty cheap really.
 
Check them out and let me know what you think.

Nerd Test

I just took the Nerd Test over at nerdtests.com. I saw this mentioned on someone elses blog and remember hearing about it a while ago so thought I would give it a go. Turns out I'm a Cool Nerd King.
 
NerdTests.com says I'm a Cool Nerd King.  What are you?  Click here!
 
June 30

Moving to .NET 3.0 and onwards

I have been starting the last couple of weeks to think about upgrading myself to .NET 3.0 and then on to 3.5. I have been working in the same place for about 20 months now and have been responsibly for the implementation of all the projects workflow foundation (WF) components.

I know WF is officially part of .NET 3 so it may seem like I may already be a .NET 3 developer. The problem is, the workflows we have been doing have been pretty basic. There have been some interesting things with regard to services such as an MSMQ receiver service. The workflows themselves however have been basic and I haven't yet done any suspend and resume type functionality in the workflows, which I personally think is pretty important.

So my goal for the next 2 months (which is probably the amount of time till I leave this role and have to find myself a new role in what is currently a competitive market), is to become and expect .NET 3 developer. I have work coming up on Workflows in the next 2 months which seem quite a good fit for sleeping workflows and also for WCF communication to be the driver to wake these workflows up.

So over this period of 2 months, I am going to learn WF and WCF and I am going to do this through a lot of web research and reading of MSDN, blogs and other sources of help. I am also during this period going to attempt to document the process of learning, and recording the good sources of information I found on this blog.

So if you are looking to learn .NET 3.0 soon and don't know where to start, or are learning it and have good sources of information on getting started, please let me know via this blog and hopefully we can all help each other out.

 

Ciaran

Computer Science Education: Where Are the Software Engineers of Tomorrow?

Saw this post on the web today and thought is definately asked a good set of questions. I very much agree with the author and believe Computer Science students should definately learn more that just Java or .NET when studying for their degree. When I left Uni, I could code C++, Java, Visual Basic, Pascal and C# and I personally think I was far more prepared for the real world then my friends because I was able to code soutions to problems myself rather than having to find a package to provide the answers.
Have a read yourself and let me know what you think.
 
 
 
Ciaran
May 20

.NET Number format strings

I have seen a number of posts in the newsgroups and on other forums of people asking about the formatting strings in .NET which in my opinion is always hard to find in the help. I stumbled across a great blog entry from John Sheehan today who has made a PDF which explains them for numbers and dates.
 
Well done that man!
 
November 16

Ambiguous match found

I have had this exception a couple of times before and keep forgetting what the problem is and dedicating the best part of a morning figuring out what the problem is.
I had this issue today in a team development I was working on. Its a web application and when the new version was promoted to the UAT environment, it had and issue loading a particular page. The stack trace is below:
System.Reflection.AmbiguousMatchException: Ambiguous match found.
at System.RuntimeType.GetField(String name, BindingFlags bindingAttr)
at System.Web.UI.Util.GetNonPrivateFieldType(Type classType, String fieldName) at System.Web.Compilation.BaseTemplateCodeDomTreeGenerator.BuildFieldDeclaration(ControlBuilder builder)
at System.Web.Compilation.BaseTemplateCodeDomTreeGenerator.BuildSourceDataTreeFromBuilder(ControlBuilder builder, Boolean fInTemplate, Boolean topLevelControlInTemplate, PropertyEntry pse)
at System.Web.Compilation.BaseTemplateCodeDomTreeGenerator.BuildSourceDataTreeFromBuilder(ControlBuilder builder, Boolean fInTemplate, Boolean topLevelControlInTemplate, PropertyEntry pse)
at System.Web.Compilation.BaseTemplateCodeDomTreeGenerator.BuildSourceDataTreeFromBuilder(ControlBuilder builder, Boolean fInTemplate, Boolean topLevelControlInTemplate, PropertyEntry pse)
at System.Web.Compilation.TemplateControlCodeDomTreeGenerator.BuildMiscClassMembers()
at System.Web.Compilation.BaseCodeDomTreeGenerator.BuildSourceDataTree()
at System.Web.Compilation.BaseTemplateBuildProvider.GenerateCode(AssemblyBuilder assemblyBuilder)
at System.Web.Compilation.AssemblyBuilder.AddBuildProvider(BuildProvider buildProvider)
 
The are a few pages on the internet whic give some basic explanation of the reasons behind this exception and the main one mentioned in the pages i have found if that people have had overloaded indexers on web controls. This is obviously a real cause for this issue but is not the only one.
The issue I keep having on team developements is caused by people deviating from our naming convention. The issue is caused by a type, normally a user control, having two (or more) public members with the same name (when considered case insensitive). This is an issue when the control/page is loaded as the loader uses reflection to find the public memebrs of the type. It does this with case insensitive options and can get errors if two things clash.
An Example of this is that we had an event on the control called something like DoTheBusiness. There was also a button on the control called doTheBusiness. This wasnt an issue in our C# app and caused no issues when running the webapplication through the visual studio web server. However, when loaded into an IIS environment it causes the issue shown in the stack trace.
It can be hard to track this down two as  the control you are loading the loading through LoadControl() or the page you are accessing might not have this issue. It could reference a control which has this issue or references one which does and so on.
Our naming conventions in our web applications and all the ones I have worked on is to use hungarian notation for the controls on the pages. this would prevent this issue as the button would(should)  not ever clash with public field on the page.
 
I hope this post helps people that experience this issue. Let me know if it helps you.
 
 
July 20

A strong business case for WPF?

I had up till recently been thinking that WPF was just going to be most usefull for imitating the consumer 'oooooooohhh' factor with fancy Mac type graphics on a PC. I hadnt come up with a good reason to learn it to integrate it into a business application. As with most clever things about graphics, Bob Powell has a good point to make on his blog in a post with the same title from Feb 10th.
His basic point is that when databinding to rapidly changing data sources from stock quotes to transaction/sales data  in real time, the drawing part of the application is taking up a large percentage of the processing time. Using WPF, all this can be done on the graphics card and the processor can be released to do some real work.
 
Good Point, Well Made Bob
 
 

Return

I have returned to my blog after a long time away. I have been quite busy with a couple of independent projects in recent months but i slowly emerging from the other end and looking forward to be able to look at the new technology and online content that has come about in the last few months.
I have been catching up on all my DotNetRocks episodes that I have missed which is becoming harder as they have now moved up to two a week. Plus Richard Campbell, esteemed co-host of DNR has setup his own spin off which seems to be more targetted towards infrastructure guru's rather than .NET developers but although I havent actually got round to listening to it yet, I have downloaded it to my Windows Mobile phone and its on the playlist.
 
One of the reasons for my return to blogging is that while visiting the Mondays site to get the latest episode of the worlds greatest not technical podcast, the site was down. So I emailed info@pwop.com to let them know. I got a response today from Carl Franklin who rates pretty highly in the scale I posted about in one of the first entries on my blog. I took the opportunity to reply to him letting him know I appreciated the response, congratulating him on the greatness of Mondays and the like and not only did he respond, he did it really fast and gave me a real human like answer.
I am very impressed with today and it therefore re-affirmed my determination to get involved in the community and take part.
So in short, I am going to make a determined effort to make this blog a useful source of information for developers.
 
March 23

Slow webform designer switches

I have worked on a few web site projects that suffer from slow designer load times when moving from markup to design views in the web application. These applications have often suffered from bad architecture in the web site where not enough of the code seperated out inton another assembly. The reason these thingas go hand in hand is because in order to load the web form designer, visual studio has to compile the app_code directory first. This therefore means that a large app code directory will slow down the desginer load due to the time taken for compilation. Now, the reason visual studio likes classes to go in the app code folder is for seperation of logic from presentation which is the target of most good architects. I personally think howvever that in most projects, the most part of this app_code folder could be put into a different assembly from the web site. To a lot of people this gives the impression of a different layer and to the most part this code can be viewed that way. Web services, image choosers, utility methods validation objects etc shpuld all live outside the presentation logic in a web site. So, the answer to slow load times on your webform designer is to make sure your app code folder is a simple set of presenttion classes and all other logic is moved out to a proper dll, reducing compilation and therefore load times

Messing about with VirtualPaths

I know a lot of coders who love the System.IO.Path class. For those that don't know about it, the class has lots of handy functions for dealing with paths from combining them to getting folder or file names from them. All these coders used to hate it when it came to web programming or any work with urls where they were unable to use the path class as thery had to deal with web addresses or "virtual paths".

The good news is that .Net 2 has the System.Web.VirtualPathUtility class which aims to be just and useful to web site developers as the Path class is to winforms and service developers. It has handy functions for getting relative paths from one virtual path to another or making them app relative etc.

Definitely worthing checking out if you are wrtiting code to handle re-directs or resource urls etc.

Apple advertising

I have been walking past posters of the new apple advertising campain which has two guys, ones a mac and ones an apple. The pc guy is dowdy dressed while the apple guys is a bit more spruced. In each poster they are holding little signs at there chest like one for example, the pc guy is holding one saying, " I can be a bit trikcy to setup" and the mac guy is holding one saying "I work straight out of the box". Everytime I see one of these posters I think to myself that's not right, new pcs are easy to setup, they come with good software, especially vista, they can be for play as well as work. In fact I reckon there are far more pc games in the world then mac based games and vista is pretty good at managing photos and videos and personal stuff.

The genius in this advertising isn't just that the people walking around this world who may have used and old pc but has probably never seen a mac are going to start believing this. They probably won't know about Vista yet and when thinking to themselves "What should I get for browsing the web?" they are going to think mac. That's just advertisng, the genius is that although these claims are outdated and inaccurate, there is no body to challenge them. The PC market is not like macs, macs are apple and pc's are anyone. There is no one company to stand up and say something about the claims as no one owns the brand 'PC'.

Although I don't like the adverts, I have to admit, its clever.

Center align on windows forms

I have been to a number of companys and seen a number of times, forms layouts that contain a centre aligned header, the sort of which, you would find on a web page. Eveytime I see this I come across a Form_Resize event handler which recalculates the location evrytime the form changes size. The code has often been complicated by the fact that people have things stuck to the side of their window.

A little known fact it seems is that this effect can be achieved without code in .NET 2.0 with the use of anchors. Or more importantly the non use of them. By default controls are anchored to the top left of the form which means when the form size is changed, their distance from the top left side of the for remains constant. If you change the control anchor to bottom left, then the control will keep the same distance from the bottom and left sides of the form when the form if resized. The clever trick with this is when you centre a control on the form horizontally, vertically or both, turning off the anchor in a direction will keep the control centred in that direction when resizing. This can be usefull and saves a lot of code if you need it often so my advice is checkout control anchors and the toolbar buttons for positioning before writing code like that again.

February 27

Millahseconds

 I heard some very bad news the other day. Coding and comedy genius Mark Miller has decided to stop producing Millahseconds.

For all of you who are total unaware of what this is. Here is the official description:

Millahseconds is a weekly voyage into the manic mind of Mark Miller of Mondays fame, a manic paranoid schizophrenic software developing sex-addict (and part-time ditch digger for the county).
Millahseconds is a comedy podcast designed for men, but hot chicks can listen in too.
Be advised: Millahseconds is *not* for government agents, feminist Nazis, or prosecuting attorneys in any current or future litigation.
Mark likes to spend his spare time thwarting the imminent alien invasion, keeping the monkey menace at bay, and trying oh-so desperately to get laid. Not necessarily in that order.

MillahSeconds are brief rants of comedy genius from Mr Miller who happens to be a top level architect for DevExpress who make a fantastic plug-in for VS.NET called CodeRush. You may have heard Mark on .NET Rocks! before talking about discoverability and things or, if you know what good for you, on Mondays which is a comedy show produced by the same team behind .NET Rocks.

I think the developer community and in fact the community at large should show Mr Miller he is loved and wanted and should download his show in hugh number to convince him to carry on. I also think everyone would benefit from tuning into Mondays too. Which is made a lot easier by the fact that the entire back catalogue is available to download and stream.

Anyway, support Mr Miller in MillahSeconds and in his fight against the Monkey Menace.

All hail, Millllllllllaaaaaaaaaaaaaaaaaaaaaaaaahhhhhhhhhhhhhhhhhhhhhhh.

February 16

ASP.NET AJAX and Beyond

Well ASP.NET Ajax is out and has been for a little while now. I have been using it in apps off and on since about March last year. I have to say, Update Panels are the simplest way I have seen to get AJAX going on whatever application you want. They are soooo easy to plug in and get working its insane. The rest of the framework is also powerful and used in conjunction with other controls, especially on Intranet applications makes some really cool things possible.
Going forward there is also XBAP which although isnt exactly a web based technology ( I think its a windows based technology delivered over the web, like ClickOnce smart clients) it does, for windows users, look like a really super powerful web application and will make intranet development a very powerful concept when its really here and in use. It effectivly allows you to deploy a WPF XAML application to the client in a browser window.
Also in the future for web applications is WPF/E. This is a cross platform/browser (via plugins) technology that allows web developers to make things that look real clever like flash, but using .NET technology, making it easier to localise and integrate into large schale business and ecommerce systems. This is a real cool technology that I am definately going to be watch.
 
I think the landscape for web development is going to change a great deal for MS developers over the next few years and while it seems a bit daunting at the moment when you think about all the new things there are to learn, I'm sure it is going to be easy to move from one to the other and benefits that can be gained from a UI point of view seem to be enormous. I think we are on the verge of the web becoming a really useable and simple platform for integration of services web xml and webservices allowing systems to talk, and these new presentation technologies which will allow people to interact with it easily and will enable us as developers to make UI's that people will want to use.
 
Let me know what you guys think about these new tools.
 
February 15

Windows Live Writer

This is my first post through Windows Live Writer. Its a test as much as a demo of the software. It seems like a handy little tool. It has spell checking and basic layout options and of course enables you to edit you blog posts offline. This is handy for me as I spend 3 hours a day on the train and can always think of things to blog when I'm on my laptop coding, but I don't have Internet on the train.

Any, test complete, tool is cool.

 

Wooooooooow!

 

I was just looking for the download link for Live Writer to add it to the above post, when I came across another cool Live Spaces feature : "Blog from your phone". The sales blurb says:

"Blog from your mobile phone. Enable “email publishing” under Settings. Get your unique email address for blogging. Email blog entries from your mobile phone to this address from anywhere in the world where your phone has Internet access."

That is also cool as I have a Windows Mobile 5 phone with full keyboard and things, this will make blogging even easier.

 

Ciaran

Happy New Year

Well its a new year. In fact it has been for a while but I have been very busy this year so far with a development project I have been working on. It has made my spare time suffer a lot which has reduced the amount of time I have been able to spend in the communities. I have some things I am going to post up here soon, little tools to use while developing.
 
Well thats all I have time for now, just a ping to confirm I'm alive.
 
 
December 15

ASP.NET can render in CSS (if you tell it how)

The ASP.NET team have finally released some control adapters for the standard .NET controls to use CSS.
This means we can now use the built in ASP.NET controls for menus and such things with worrying about issues rendering on PDA's or Text Only browsers or for screen readers. I think its a shame this wasnt how the controls were built to begin with but this is better than nothing.
 
I advise all people using ASP.NET, especially for public websites to use these extenders to help make their sites CSS compliant and accessible. There is no good reason not to anymore.
 
I have web access on my phone and I know it annoys me when I go to sites like national rail and have to spend about (150KB of credit) downloading a simple 3 textbox form.  Using good markup can help cure this pain.
 
At least take a look
http://www.asp.net/CSSAdapters - This is the main page
 
http://www.asp.net/CSSAdapters/Menu.aspx - This is the menu example
 
Go forth and be accessible.

Handy Tool: Adding auditing to SQL Server 2005 Db

This isnt mine i'm affraid, its a friends.
A cool tool that goes through through your sql server 2005 database, creates a sister database with audit copies of all your tables and writes triggers to do the auditing.
Big Timesaver.
 
December 14

Generic Enum Parsing and bit changing.

I was very frustrated the other day when I wanted to write a couple of generic functions in C# which take an enum generic parameter and turn flags on or off and check if there on etc. Just to tidy up lots of bitwise checking in my code.
Imagine my dissapointment when it got :
error CS0702: Constraint cannot be special class 'System.Enum'
This was quite iritating as I could seem to find out why. What I did find out though was that C++ for CLR did allow this, so I pulled out VC++ 2005 and had a go at doing what I wanted. I am no great C++ programmer so the thing that turned this from about 2 minutes work to 30 minutes was that I had declared the type and the methods without a public: block so I couldnt seem them in C#.
 
All thats fine now so I have got a class with some generics methods for making enum work simpler. I have kept the C++ for this as there are probably going to be other uses, especially with arrays (which get the same error). Heres the code for a C++ class library targeted to the CLR:
namespace BasicHelpers{

	public ref class EnumHelper  sealed : System::Object
	{
		public:
			generic  where T : System::Enum
			static T Parse(System::String ^valueName)
			{
				return Parse(valueName, false);
			}
	 
			generic  where T : System::Enum
			static T Parse(System::String ^valueName, bool ignoreCase)
			{
				return safe_cast(System::Enum::Parse(T::typeid, valueName, ignoreCase));
			}

			generic	 where T : System::Enum
			static System::Boolean IsFlagged(T value, T flag)
			{
				System::Int32 i1 = safe_cast(value );
				System::Int32 i2 = safe_cast(flag );
				return safe_cast((i1 & i2) == i2);
			}

			generic  where T : System::Enum
			static T Flag(T value, T flag, System::Boolean onOrOff)
			{
				System::Int32 i1 = safe_cast(value );
				System::Int32 i2 = safe_cast(flag );
				System::String ^name = System::Enum::GetName(T::typeid,(onOrOff ? (i1 | i2) : (i1 & ~i2)));
				return Parse(name);
			}
	
	};

};

December 08

Mondays are the best days of the week.

If you hate Mondays, then try Mondays. It is a kind of comedy show from the people that do the (also excellent) DotNetRocks. It is pure humour and the only thing I can't stand about it is that it isn't out evey Monday. For all the newer Mondays fans though, there is the enitre back catalogue online to keep you going.
 
This is the best podcast in the world ever!!!
 

MouseWheel Not Working

I saw in a newsgroup a problem where mousewheel wasnt working on a panel and the issue is because the form isnt passing the event on to its children. I wrote the code below which when pasted into a form. Makes it pass on the event so controls on the form get notified of the MouseWheel event.
bool sendingMessage = false;
  protected override void WndProc(ref Message m)
  {
  
   Point mp = MousePosition;
   if (m.Msg == 522)
   {
    if (sendingMessage)
   {
    m.Result = (IntPtr)0;
    return;
   }
    Debug.Print("Mouse Wheel: lparam = {0},WParam = {1}, Result ={2}", m.LParam, m.WParam, m.Result);
    try{
     sendingMessage = true;
    SendMessage(GetChildAtPoint(PointToClient(mp)).Handle,     m.Msg, m.WParam.ToInt32(), m.LParam.ToString());
    sendingMessage = false;
    }catch(Exception exception){
     exception.ToString();
    }
   m.Result = (IntPtr)0;
   
   }
   base.WndProc(ref m);
  }
  [DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hwnd, [MarshalAs(UnmanagedType.U4)] int Msg, int wParam, [MarshalAsSystem.Runtime.InteropServices.UnmanagedType.LPStr)] string lParam);
  
 
Hope it helps someone
 

Ciaran O'Donnell

Learning WCF: A Hands-on Guide
CLR Via C#: Applied .NET Framework 2.0 Programming