marți, 11 septembrie 2012

Fast Facts - BinaryReader

This post is about the BinaryReader class and the ReadBytes method return value.

public virtual byte[] ReadBytes( int count )


This method returns an array of count bytes or the number of bytes left to the end of the underlying stream, whichever is less.
When there are no more bytes to read, calling ReadBytes return an empty array of bytes, not a null value. This is useful to know when verifying the outcome of a read operation.
To prove this, there is a quick C# method that you can load in LINQPad:



public static void Main()
{
    const int arrayLength = 20;

    // Create random data to write to the stream. 
    byte[] dataArray = new byte[arrayLength];
    new Random().NextBytes(dataArray);

    BinaryWriter binWriter = new BinaryWriter(new MemoryStream());

    // Write the data to the stream.
    Console.WriteLine("Writing the data.");
    binWriter.Write(dataArray);

    // Create the reader using the stream from the writer.
    BinaryReader binReader = 
        new BinaryReader(binWriter.BaseStream);

    // Set Position to the beginning of the stream.
    binReader.BaseStream.Position = 0;

    // Read and verify the data. 
    byte[] verifyArray = null;
    for( int i = 0; i < 6; i++ )
    {
        // ReadBytes returns an empty array when there are no more bytes to read.
        verifyArray = binReader.ReadBytes(sizeof(uint));
        Console.WriteLine( (verifyArray!=null) ? "Length = " + verifyArray.Length : "Array is null" );
        verifyArray = null;
    }    
}

Running this program will display:

Writing the data.
Length = 4
Length = 4
Length = 4
Length = 4
Length = 4
Length = 0


vineri, 31 august 2012

DllImport default path

When using DllImport for interop in C#, the default path of the library that you want to import is dictated by the operating system. The search order used by Windows OS depends on whether SafeDllSearchMode is enabled or disabled. When the safe mode is enabled, the current directory is placed lower in the search order. See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx for complete information on Dinamyc-Link Library Search Order.

Beside the implicit search order described below, one can use the .dll full path with the DllImport attribute.

The search order when safe mode is enabled is:

1.The directory from which the application loaded.

2.The system directory. Use the GetSystemDirectory function to get the path of this directory.

3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.

4.The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.

5.The current directory.

6.The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

And when the safe mode is disabled:

1.The directory from which the application loaded.

2.The current directory.

3.The system directory. Use the GetSystemDirectory function to get the path of this directory.

4. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.

5.The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.

6.The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

I have successfully used the directory from which the application is loaded, but it will be interesting to give a try to the other modes. Probably the most efficient is the use the first option most of the time for better performance, just because it's the first place the OS looks for the .dll. Knowing where the OS will look for the .dll is essential and a point to remember.

duminică, 19 februarie 2012

TIOBE index

TIOBE Software measures programming languages indexes with respect to their popularity among developers. The latest rankings are available here.

This month Java is the leader and has been maintaining its position since February last year, closely followed by C, which also maintains its position. The next three positions are held by C#, C++ and Objective-C. This is an interesting ranking and specially, it is good to know where the demand is going when starting to learn a new programming language. Compared to last year, C#, which I favor over Java simply because I spend most of my time developing for the Windows platform, jumped three positions and it now holds 3rd place, even though at significant distance from positions 1 and 2 (about 8 percent). I do not expect C# to be #1 any time soon, specially since it is not (natively) portable to Unix-like systems, and of course C is a natural leader, even though complex, no serious developer should lack knowledge of C.

Regarding the leader, Java, I remember I liked it a low while in college and after that and I still develop some pieces of code using it and I think it is all right, but when it comes to Windows desktop programming and developing software that has a user interface, I don't see it as a rival for C# right now. Well, this is a kind of debate that would not end if put on a forum or discussion group and of course, everyone would be right, since the best programming language is the one that you have used the most and feel most confortable using, no doubt about it. Enjoy coding!

marți, 14 februarie 2012

Add Command Prompt Shortcut to Windows Explorer Context Menu

I always seem to be needing a command prompt and right clicking on a directory and opening a command prompt with the path already set to that directory is very handy. The contents of this post may also be found on various sites on the internet and I am only writing it here specially for me to remember it in the future, when I reinstall Windows :). I have found this post which goes through a seemingly exhaustive process of describing all methods to add the shortcut to the command prompt in the context menu: http://www.petri.co.il/add_command_prompt_here_shortcut_to_windows_explorer.htm. I personally prefer manually creating a key in the Windows registry, under [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell]. To make it easier, I have exported the keys and all you need to do is create a new file, say with Notepad and assign it a .reg extension (not .reg.txt ) and copy the following lines in the new file and double-click it.
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command Prompt] @="Command Prompt" [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\Command Prompt\command] @="cmd.exe /k pushd %1"
Otherwise, open the registry editor and browse to [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell]. Expand this key and create a new key named Command Prompt. Under the newly created Command Prompt create a new key and name it command. Double click the Default entry under command and assign it the value:
cmd.exe /k pushd %1
And that will do the trick. Hopefully, next time I'll remember...

joi, 19 ianuarie 2012

Could not load file or assembly or one of its dependencies.

The full error text is in fact:

Could not load file or assembly 'xxx.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format
and may occur when using Visual Studio 2005 on 64-bit platforms. A common cause of this error is when using third party tools that require the license compiler (lc.exe). On 64 bit systems, the license compiler will run as a 64-bit application by default and if the third party libraries are not compatible with 64-bit platforms, the aforementioned error is generated. One solution to fix this, even though in this case you will be limited to compiling your whole application in x86 mode, is to add the following code in the pre-build and post-build event sections of the project's Build Events section. The statements must be on a single line.

Pre-Build:

if exist %WINDIR%\Microsoft.NET\Framework64\v2.0.50727\ %WINDIR%\Microsoft.NET\Framework64\v2.0.50727\ldr64.exe setwow
Post-Build:
if exist %WINDIR%\Microsoft.NET\Framework64\v2.0.50727\ %WINDIR%\Microsoft.NET\Framework64\v2.0.50727\ldr64.exe set64
For more information on the license compiler, see this post on MSDN: http://msdn.microsoft.com/en-us/library/ha0k3c9f.aspx. I must say I have tried other solutions, as explained in other blogs or forums on-line, which advise to change the target platform to x86 or Any CPU, but those did not work for me.

marți, 3 ianuarie 2012

Show Control in Visual Studio 2005 Toolbox

After creating a custom control with Visual Studio 2005 you may want to have it available in the Toolbox to easily drag and drop it on your own forms. There is an option in Visual Studio 2005 that enables or disables the adding the of the custom control in the Toolbox. To make sure that your control will show up in the Toolbox, verify that under Tools->Options->Windows Forms Designer, the AutoToolboxPopulate option is set to true.

luni, 2 ianuarie 2012

The path is not of a legal form.

In Visual Studio 2005 I got this error when trying to open a form in design mode. This was not a programming error because I was able to properly compile and run my code. After looking at the projects in my solution (luckily, just two simple projects) I have found that one of the projects had a dead reference - a reference with an exclamation mark. I removed that reference and I am now again able to open my form in design mode. I believe a better formulation of the error message would be very helpful in this case.
I post the error stack below, for reference:

The path is not of a legal form.
at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
at System.IO.Path.NormalizePath(String path, Boolean fullCheck)
at System.IO.Path.GetFullPathInternal(String path)
at System.Reflection.AssemblyName.GetAssemblyName(String assemblyFile)
Microsoft.VisualStudio.Design.VSTypeResolutionService.AddProjectDependencies(Project project)
Microsoft.VisualStudio.Design.VSTypeResolutionService.AssemblyEntry.get_Assembly()
Microsoft.VisualStudio.Design.VSTypeResolutionService.AssemblyEntry.Search(String fullName, String typeName, Boolean ignoreTypeCase, Assembly& assembly, String description) at
Microsoft.VisualStudio.Design.VSTypeResolutionService.SearchProjectEntries(AssemblyName assemblyName, String typeName, Boolean ignoreTypeCase, Assembly& assembly) at
Microsoft.VisualStudio.Design.VSTypeResolutionService.SearchEntries(AssemblyName assemblyName, String typeName, Boolean ignoreCase, Assembly& assembly, ReferenceType refType) at
Microsoft.VisualStudio.Design.VSTypeResolutionService.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, ReferenceType refType) at
Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError, Boolean ignoreCase) at
Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError) at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.GetType(ITypeResolutionService trs, String name, Dictionary`2 names) at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.FillStatementTable(IDesignerSerializationManager manager, IDictionary table, Dictionary`2 names, CodeStatementCollection statements, String className) at
System.ComponentModel.Design.Serialization.TypeCodeDomSerializer.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration) at
System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager) at
Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager) at
Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)