Technical Journal

Programming, software technologies, operating systems, IT

Enum to List

I’ve found this method useful lately so I thought I should add it here where everyone can see it.
It is meant to be used with the .NET Compact Framework. In the full framework this would have been much easier -
without reflection.
What the method does is that it adds the enum’s fields to a generic list of the same type T as the enum.

public static List EnumToList( )
{
Type enumType = typeof( T );

if( enumType.BaseType != typeof( Enum ) )
{
throw new ArgumentException( “Not an enum type!” );
}

List enumFieldList = new List( );

FieldInfo[ ] enumFields = typeof( T ).GetFields( );

foreach( FieldInfo fieldInfo in enumFields )
{
if( !fieldInfo.IsSpecialName )
{
enumFieldList.Add( (T) Enum.Parse( enumType, fieldInfo.Name, false ) );
}
}

return enumFieldList;
}

April 24, 2009 Posted by andocs | Windows CE | , , , , | No Comments Yet

Windows CE Full Screen applications

The first task I had to do when I started developing my first Windows CE application was to make my main program window appear in full screen mode. After some research I came across a small article posted on Code Project. It describes a method of showing a window in full screen mode using standard window management calls which is what I was looking for. I completed the source with proper definitions of system calls and structures. I provide this source code along with a basic test application.

            The usual method of doing this would have been to use SHFullScreen, but I was not able to use this function as my OS Design was not to contain aygshell.dll, the library from which this function was part of.

            I am developing under .NET Compact Framework 2.0.

            First, I had to define some useful enums containing constants of the Windows API. Here are some of them, for the rest please see the attached project as this post would grow unreasonably if I pasted them here.

      [Flags( )]

      internal enum FullScreenFlags : int

      {

            SwHide = 0,

            ShowTaskbar = 0×1,

            HideTaskbar = 0×2,

            ShowSipButton = 0×4,

            HideSipButton = 0×8,

            SwRestore = 9,

            ShowStartIcon = 0×10,

            HideStartIcon = 0×20

 

      }

 

      internal enum Hwnd : int

      {

            HWND_TOP = 0,

            HWND_BOTTOM = 1,

            HWND_TOPMOST = -1,

            HWND_NOTOPMOST = -2

      }

 

            A very useful thing to do is to check www.pinvoke.net and retrieve the values of certain constants that you would make use of in various situations.

            Next, I had to implement a static class that imports my needed functions from coredll.dll. This dll is very useful to get acustomed with because in it you will find system calls that you are very likely to need in your development process under .NET CF. So, here is what you need:

 

      public static class Coredll

      {

            /// <summary>

            /// The function retrieves the handle to the top-level

            /// window whose class name and window name match

            /// the specified strings. This function does not search child windows.

            /// </summary>

            /// <param name=”lpClass”></param>

            /// <param name=”lpWindow”></param>

            /// <returns></returns>

            [DllImport( "coredll.dll", SetLastError = true )]

            public static extern IntPtr FindWindowW( string lpClass, string lpWindow );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            public static extern bool ShowWindow( IntPtr hwnd, int state );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            public static extern bool SetWindowPos( IntPtr hwnd, IntPtr hwndAfter,

                                                                              int xPos, int yPos, int cX, int cY, int wFlage );

 

            [DllImport( "coredll.dll" )]

            public static extern int GetSystemMetrics( int smIndex );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            [return: MarshalAs( UnmanagedType.Bool )]

            public static extern bool SystemParametersInfo( Spi uiAction, uint uiParam, IntPtr pvParam, Spif fWinIni );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            [return: MarshalAs( UnmanagedType.Bool )]

            public static extern bool SystemParametersInfo( Spi uiAction, uint uiParam, String pvParam, Spif fWinIni );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            [return: MarshalAs( UnmanagedType.Bool )]

            public static extern bool SystemParametersInfo( Spi uiAction, uint uiParam, ref AnimationInfo pvParam, Spif fWinIni );

 

            [DllImport( "coredll.dll", EntryPoint = "SystemParametersInfo", SetLastError = true )]

            public static extern bool SystemParametersInfoGet( uint action, uint param, ref uint vparam, uint init );

 

            [DllImport( "coredll.dll", EntryPoint = "SystemParametersInfo", SetLastError = true )]

            public static extern bool SystemParametersInfoSet( uint action, uint param, uint vparam, uint init );

 

            /// <summary>

            /// to find whether you are running on a Smartphone or a Pocket PC

            /// </summary>

            /// <param name=”uiAction”></param>

            /// <param name=”uiParam”></param>

            /// <param name=”pvParam”></param>

            /// <param name=”fWinIni”></param>

            /// <returns></returns>

            [DllImport( "Coredll.dll", EntryPoint = "SystemParametersInfoW", CharSet = CharSet.Unicode )]

            public static extern int SystemParametersInfo4Strings( uint uiAction, uint uiParam, System.Text.StringBuilder pvParam, uint fWinIni );

      }

           

            Now, to put things toghether here are the two methods needed to enter full screen mode and end it:

 

            public static void StartFullScreen( Control control )

            {

                  IntPtr hWndInputPanel = Coredll.FindWindowW( “SipWndClass” , null );

                  IntPtr hWndSipButton = Coredll.FindWindowW( “MS_SIPBUTTON”, null );

                  if( hWndInputPanel != null ) Coredll.ShowWindow( hWndInputPanel, SW_HIDE );

                  IntPtr hWndTaskBar = Coredll.FindWindowW( “HHTaskBar”, null );

 

                  IntPtr hWnd = control.Handle;

 

                  if( hWndTaskBar != null ) Coredll.ShowWindow( hWndTaskBar, (int) Sw.SW_HIDE );

                  if( hWndInputPanel != null ) Coredll.ShowWindow( hWndInputPanel, (int) Sw.SW_HIDE );

                  if( hWndSipButton != null ) Coredll.ShowWindow( hWndSipButton, (int) Sw.SW_HIDE );

 

                  Coredll.SetWindowPos(

                        hWnd, (IntPtr) ( (int)Hwnd.HWND_TOPMOST ), 0, 0,

                        Coredll.GetSystemMetrics( (int) SystemMetric.SM_CXSCREEN ),

                        Coredll.GetSystemMetrics( (int) SystemMetric.SM_CYSCREEN ),

                        (int) Swp.SWP_SHOWWINDOW );

            }

 

            public static void StopFullScreen( Control control )

            {

                  //IntPtr hWndInputPanel = Coredll.FindWindowW( “SipWndClass” , null );

                  IntPtr hWndSipButton = Coredll.FindWindowW( “MS_SIPBUTTON”, null );

                  IntPtr hWndTaskBar = Coredll.FindWindowW( “HHTaskBar”, null );

 

                  IntPtr hWnd = control.Handle;

 

                  Rect rtDesktop = new Rect( );

 

                  if( hWndTaskBar != null )

                  {

                        Coredll.ShowWindow( hWndTaskBar, (int) Sw.SW_SHOW );

                  }

                  //Never forcibly show the input panel

                  //if( hWndSipButton != null )

                  //{

                  //    Coredll.ShowWindow( hWndSipButton, Sw.SW_SHOW );

                  //}

 

                  IntPtr rectPtr = Marshal.AllocHGlobal( Marshal.SizeOf( rtDesktop ) );

 

                  if( Coredll.SystemParametersInfo( Spi.SPI_GETWORKAREA, 0, rectPtr, Spif.None ) ) )

                  {

                        Rect rect = (Rect) Marshal.PtrToStructure( rectPtr, typeof( Rect ) );

 

                        Coredll.SetWindowPos( hWnd, (IntPtr) ( (int) Hwnd.HWND_TOPMOST ), 0, 0, rect.right – rect.left, rect.bottom – rect.top, (int) Swp.SWP_SHOWWINDOW );

                  }

                  Marshal.FreeHGlobal( rectPtr );

            }

 

            The first method, StartFullScreen, hides the SIP( Standard Input Panel ), the SIP button bar and the task bar leaving the entire screen to be filled by the application window. The application window’s size is set to the size of the entire screen in SetWindowPos. It’s that simple!

            When you want to exit full screen mode, you need to show the task bar, get the size of the client work area, specified with Spi.SPI_GETWORKAREA and then calculated the new size of the window( it would appear as a maximized window on your screen ).

You can download a sample project form 4shared: Source code here.

April 12, 2009 Posted by andocs | Windows CE | , , , , , , | 4 Comments

C++ UNREFERENCED_PARAMETER

I am currently developing a driver for one of our custom made devices under Windows CE and I came across this macro -

UNREFERENCED_PARAMETER in one of the driver examples I took as reference for developing my own. The definition itself does not say much:

#define  UNREFERENCED_PARAMETER(P) (P)

All it does is to layout the parameter or expression it has been passed. After some browsing on the internet I’ve found this post by Paul DiLascia:

http://msdn.microsoft.com/en-us/magazine/cc163805.aspx which I think greatly explains what is meant by compiling with Warning Level 4 – it made me a believer anyway.

Indeed, an unreferenced parameter would cause an error when compiling using level 4 and this is where UNREFERENCED_PARAMETER comes in handy.

For instance you have a function like this:

void foo( int arg1, float arg2 )

{

     UNREFERENCED_PARAMETER( arg1 );

}

Since you won’t be using arg1 and also you will compile with level 4, you just fool the compiler by passing arg1 as parameter to a macro that just adds the line:

arg1;

to your code. And since it is not used the compiler does not generate code for it and no efficiency or space is lost.

I will not repeat here stuff written in that post, just thought I’d mention it as a great post on C++ I’ve found.

April 7, 2009 Posted by andocs | Programming | , | No Comments Yet

Install an application for all users

In this article I present techniques based on Visual Studio 2005 Deployment, C#, Windows Registry. 

I have recently encountered one of those errors you should expect but you don’t. I have an application for which I have created an installer project, under Visual Studio 2005. The application works fine after installation for the administrative role user that installed it, but when switching to a less priviledge user on the same computer the install/ repair program starts for that user prompting for the installation kit path. As an aditional detail, the setup kit creates the application registry keys it requires under HKEY_CURRENT_USER key. And this is the flaw…

When creating registry entries for an application that might be used by more than one user, each of which having different access rights on the computer, we should place the registry key under the “user/ machine hive” node in the Registry view of the deployment project. This way we ensure that the keys get into the right place when the application is first installed. According to Microsoft’s definition, the keys placed under user/ machine hive will be placed either under HKEY_CURRENT_USER when the application is insalled only for one user and under HKEY_LOCAL_MACHINE when the application is intalled for all users. Here is a screenshot :

 Visual Studio Registry View

The problem with keys under HKEY_LOCAL_MACHINE is that they are read only for restricted users, for example user belonging only to the “Users” group. It is though required to assign special permissions for those keys a user not only to read but also modify. The reason I needed this was to save some user settings in the registry, so when a less privileged user saves the settings, he/ she must also have proper permisions.

To solve my problem I’ve created a custom installer class implemented an event handler for the Commited event. In this handler, write access permissions are given to users belonging to the “Users” group.

I give bellow the implementation of my event handler.

// Event handler for ‘Committed’ event.

private void CustomInstaller_Committed( object sender, InstallEventArgs e ){

RegistryKey hkCustom = null;RegistryKey hkTester = null;

// depending on the installation options, we will search for the application’s registry keys :

// 1. – if installation is performed just for the current user, the keys will be under HKEY_CURRENT_USER

// 2. – else if the installation is performed for all users, the keys will be under HKEY_LOCAL_MACHINE

hkCustom = Registry.CurrentUser.OpenSubKey( “Software” ).OpenSubKey( “CustomInstallerTester” );if( hkCustom != null ){

hkTester = hkCustom.OpenSubKey( “Tester99″, RegistryKeyPermissionCheck.ReadWriteSubTree /*required*/ );}

if( hkTester == null ){

hkCustom = Registry.LocalMachine.OpenSubKey( “Software” ).OpenSubKey( “CustomInstallerTester” );

}

if( hkCustom != null ){

if( hkTester == null ){

hkTester = hkCustom.OpenSubKey( “Tester99″, RegistryKeyPermissionCheck.ReadWriteSubTree /*required*/ );}}

 

if( hkTester != null ){

System.Security.AccessControl.RegistrySecurity regSec = new System.Security.AccessControl.RegistrySecurity( );// grant write permissions to the users group :

regSec.AddAccessRule( new RegistryAccessRule( “users”,

RegistryRights.ReadKey | RegistryRights.WriteKey | RegistryRights.Delete,

InheritanceFlags.ContainerInherit,PropagationFlags.None,

AccessControlType.Allow) );hkTester.SetAccessControl( regSec );}

 

if( hkTester != null ) { hkTester.Close( ); }

if( hkCustom != null ) { hkCustom.Close( ); }

 

}

 

 

February 19, 2008 Posted by andocs | Programming, Windows | | 5 Comments

Canceling the Load Form event in .NET

I was trying to find a way not to load a form when some error condition occured.

Briefly, the whole cancel logic should be placed in the constructor of the form and an exception should be thrown whenever canceling is necessary. The Show or ShowDialog methods must be included in the same try-catch block as the constructor.

Thus, when the exception is thrown, no form is displayed. There is no reliable way of canceling the Load event from within the Load event handler : if you call Close( ), you get an exception of the type : “Cannot acces a disposed object” on the Show or ShowDialog form methods.

See the following discussion also :

http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=1286.

July 20, 2007 Posted by andocs | Programming, Windows | | No Comments Yet

Ubuntu .ICEAuthority problem

Recently I’ve rebooted my VMWare Ubuntu machine and after the login sequence I’ve received an error whose log I give bellow.

/etc/gdm/PreSession/Default: Registering your session with wtmp and utmp
/etc/gdm/PreSession/Default: running: /usr/bin/X11/sessreg -a -w /var/log/wtmp -u /var/run/utmp -x “/var/lib/gdm/:20.Xservers” -h “” -l “:20″ “wes”
/etc/gdm/Xsession: Beginning session setup…
_IceTransTransNoListen: unable to find transport: tcp
_IceTransmkdir: ERROR: euid != 0,directory /dev/X will not be created.
_IceTransmkdir: ERROR: Cannot create /dev/X
_IceTransPTSOpenServer: mkdir(/dev/X) failed, errno = 13
_IceTransOpen: transport open failed for pts/ubuntu:
_IceTransMakeAllCOTSServerListeners: failed to open listener for pts
_IceTransISCOpenServer: Protocol is not supported by a ISC connection
_IceTransOpen: transport open failed for isc/ubuntu:
_IceTransMakeAllCOTSServerListeners: failed to open listener for isc
_IceTransSCOOpenServer: Protocol is not supported by a SCO connection
_IceTransOpen: transport open failed for sco/ubuntu:
_IceTransMakeAllCOTSServerListeners: failed to open listener for sco

** (gnome-session:23826): WARNING **: Unable to lock ICE authority file:

The solution I’ve found on a forum( http://www.linuxquestions.org/questions/showthread.php?s=ef11204ac2b7cacdd6cfc0b651512838&t=403160&page=3 ).  To save you the trouble of digging for it in the posts, I’ll just mention what I did to make Gnome start :

Open the failsafe terminal and edit the file /etc/gdm/Xsession. Add the following lines right under the PROGNAME = Xsession line :

ICEAUTHORITY=”tmp/ICEauthority-${root}”
export ICEAUTHORITY

This worked fine for me since Gnome is now normally started.

June 5, 2007 Posted by andocs | Linux | | No Comments Yet

Set PATH environment variable

This post may look shorter than it’s title. In order to set the PATH environment variable to include your custom path you should type the following on the command line :

> PATH=$PATH:/your_dir

That should do the trick.

June 2, 2007 Posted by andocs | Linux | | No Comments Yet

Create an ODBC connection from VS2005 setup

I am developing an application in the medical field with an Sql Server database ( let’s name it “MyDB” ) . Recently some of our clients have been asking for a way to easily export the data from our database in order to be used into some other analysis oriented tool.

That would have been easily achieved through an ODBC connection in the created into the Control Panel. I looked up for an easy way to create the ODBC connection through the Visual Studio 2005 Setup project. It turned out to be as easy as that. All you have to do is create registry entries for your ODBC connection. In my case, I’ve created a new System DSN and afterwards just copied the registry entries into my own setup project, I erased the DSN I’ve manually created and then I’ve executed the setup kit to test whether it works or not. Everything went just fine …

Let me give an example for a connection that requires an SqlServer driver.

In the Setup Project, open the registry view and browse to the key HKEY_LOCAL_MACHINE\Software. Under this key you will have to create the ODBC.INI key. Then, under this key, you will create a key with your database name, in our case that would be MyDB. Here is how an export from the registry editor would look like, for the database name key :

[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI]

[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\MyDB]
“Description”=”My database”
“Default”=”"
“StatsLog_On”=”Yes”
“Driver”=”C:\\Windows\\system32\\SQLSRV32.dll”
“Trusted_Connection”=”Yes”
“Server”=”(local)”
“LastUser”=”"
“Database”=”MyDB”.

You can easily copy these entries into your setup project under the database name ( “MyDB” ) key I’ve mentioned before.

Now, you must get back to the upper level ODBC.INI key and under it, create the key :”ODBC Data Sources”. You will then set the key : “MyDB” with the string value “SqlServer”. Here’s how the export looks like :

[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources]
“MyDB”=”SQL Server”

So, now you have created, into your setup project, the registry entries you need in order to automatically create an ODBC connection upon application setup. If you want to test this, erase ODBC entry from your ODBC administrator tool in Control Panel, build up your kit, and when the setup finishes, check the registry editor again and view the entries right where they were before. Now, check the ODBC administrator tool and notice the ODBC entry.

On the other hand, when you need to uninstall the application, there is no need for you to do anything special as the uninstall process will remove the registry entries for you.

Please note that the example I’ve given works with an Sql Server database. For other types, you have to repeat the same procedure, because the registry keys will not be the same as in this case, for, let’s say, a Microsoft Access database.

May 12, 2007 Posted by andocs | Programming, Windows | | 1 Comment