HOWTO: Create C++ Wrapper library for .NET

This tutorial step by step instructions to expose .lib files or access native functions from a managed application using a wrapper dll.

Create the C/C++ wrapper DLL:

  1. Create a Win32 project in Visual Studio 2010 and name it DemoLib.
  2. Select DLL in application type
  3. Check Export symbols in additional options.
  4. In DemoLib.h: modify #define, add the function fnDemoLibAdd(int a, int b) and remove all the other declarations.
    #define DEMOLIB_API extern "C" __declspec(dllexport)
    
    DEMOLIB_API int fnDemoLibAdd(int a, int b);
    
  5. In DemoLib.cpp, add the following definition:
    DEMOLIB_API int fnDemoLibAdd(int a, int b)
    {
        return (a+b);
    }
    
  6. To specify include directories:
    Right-click on the Demolib project and select Configuration Properties, C/C++ and then General. In Additional Include Directories: Click edit and add the directory
  7. To include *.lib files:
    Right-click on the Demolib project and select Configuration Properties, Linker and then Input. In Additional Dependencies: Click edit and add the library(*.lib) file
  8. To change the output directory:
    Right-click on the Demolib project and select Configuration Properties and then General. In Output Directory: Click edit and specify the directory preferably with macros
  9. Build the project, the DemoLib.dll will be in the  default output directory: Debug/Release or in the directory specified above.
Use the Wrapper DLL:
  1. Create a .NET 4 Visual C# project in Visual Studio 2010
  2. Add DemoLib.dll ceated above to the project and select the “Copy to Output Directory” as “Copy if newer”
  3. Add the function definitions using DllImport
    [DllImport("DemoLib.dll")]
    public static extern int fnDemoLibAdd(int a, int b)
    
  4. Function  fnDemoLibAdd() can be called from within c# now.
Note: Add the following to application’s app.config to prevent pInvokeStackImbalance error.

<configuration>
   <runtime>
      <NetFx40_PInvokeStackResilience enabled="1"/>
   </runtime>
</configuration>

References: Calling a C++ lib from C#

HOWTO: Get HardDisk Temperature with .NET

Hard disk temperature can be obtained using WMI calls in .NET. The temperature can be retrieved from the Vendor Specific array, in the MSStorageDriver_ATAPISmartData class. This array stores the information for each Vendor differently. So we have to search for the temperature attribute(194 or Hex C2) in the array and retrieve the temperature value.

This following code works on most models with S.M.A.R.T capabilities including Samsung, Seagate, IBM (Hitachi), Fujitsu (not all models), Maxtor, WD (Western Digital) (not all models).

C#

//S.M.A.R.T.  Temperature attritube
const byte TEMPERATURE_ATTRIBUTE = 194;
public List GetDriveTemp()
{
	List retval = new List();
	try
	{
		ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData");
                //loop through all the hard disks
		foreach (ManagementObject queryObj in searcher.Get())
		{
			byte[] arrVendorSpecific = (byte[])queryObj.GetPropertyValue("VendorSpecific");
			//Find the temperature attribute
                        int tempIndex = Array.IndexOf(arrVendorSpecific, TEMPERATURE_ATTRIBUTE);
			retval.Add(arrVendorSpecific[tempIndex + 5]);
		}
	}
	catch (ManagementException err)
	{
		Console.WriteLine("An error occurred while querying for WMI data: " + err.Message);
	}
	return retval;
}

VB .NET

'S.M.A.R.T.  Temperature attritube
Const TEMPERATURE_ATTRIBUTE As Byte = 194
Public Function GetDriveTemp() As List
	Dim retval As New List()
	Try
		Dim searcher As New ManagementObjectSearcher("root\WMI", "SELECT * FROM MSStorageDriver_ATAPISmartData")
		'loop through all the hard disks
		For Each queryObj As ManagementObject In searcher.[Get]()
			Dim arrVendorSpecific As Byte() = DirectCast(queryObj.GetPropertyValue("VendorSpecific"), Byte())
			'Find the temperature attribute
			Dim tempIndex As Integer = Array.IndexOf(arrVendorSpecific, TEMPERATURE_ATTRIBUTE)
			retval.Add(arrVendorSpecific(tempIndex + 5))
		Next
	Catch err As ManagementException
		Console.WriteLine("An error occurred while querying for WMI data: " + err.Message)
	End Try
	Return retval
End Function

References: Temperature – Attribute information

Display GIF Animation in WPF .NET 3.5

Since WPF Image control does not allow GIF animation to be displayed, it has to be manually animated using a timer.  We can use either System.Timers.Timer or System.Windows.Threading.DispatcherTimer.

System.Timers.Timer runs on a different thread then the user interface (UI) thread in an WPF application and to access objects on the UI thread, cross-thread Invoke or BeginInvoke method on the dispacther of the object has to be used.

System.Windows.Threading.DispatcherTimer runs on the same thread as the dispatcher of the object. The following code snippet  shows how to animate an GIF with DispathcerTimer.

System.Windows.Media.Imaging.GifBitmapDecoder decodes a GIF image from a URI or a filestream to BitmapSource frames which is later displayed by the WPF Image Control.

C#


    private int m_imgIndex = 0;
    private DispatcherTimer m_dTimer = null;

    public void Init() {
        // DispatcherTimer setup
        m_dTimer = new DispatcherTimer();
        m_dTimer.Interval = new TimeSpan(0, 0, 2);
        //  Hook up the Tick event for the timer.
        m_dTimer.Tick += new System.EventHandler(this.OnTimerTick);
        // Start the timer
        m_dTimer.Start();
    }

    //  Event Handler
    private void OnTimerTick(object sender, EventArgs e) {
        Uri uri = new Uri("pack://application:,,,/AppName;component/Images/myImage.gif");
        GifBitmapDecoder decoder = new GifBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
        if ((m_imgIndex + lt)) {
            decoder.Frames.Count;
            //  Get the Image frame for the index
            BitmapSource bitmapSource = decoder.Frames(m_imgIndex);
            m_imageContent.Source = bitmapSource;
            m_imgIndex++;
        }
        else {
            // Stop the timer
            m_dTimer.Stop();
        }
    }

VB .NET

Private m_imgIndex As Integer = 0
Private m_dTimer As DispatcherTimer = Nothing
' Initialization
Public Sub Init()
    'DispatcherTimer setup
    m_dTimer = New DispatcherTimer()
    m_dTimer.Interval = New TimeSpan(0, 0, 2)
    ' Hook up the Tick event for the timer.
    AddHandler m_dTimer.Tick, AddressOf OnTimerTick
    'Start the timer
    m_dTimer.Start()
End Sub

' Event Handler
Private Sub OnTimerTick(ByVal sender As Object, ByVal e As EventArgs)
    Dim uri As New Uri("pack://application:,,,/AppName;component/Images/myImage.gif")
    Dim decoder As New GifBitmapDecoder(uri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default)
    If m_imgIndex &lt; decoder.Frames.Count Then
        ' Get the Image frame for the index
        Dim bitmapSource As BitmapSource = decoder.Frames(m_imgIndex)
        m_imageContent.Source = bitmapSource
        m_imgIndex += 1
    Else
       'Stop the timer
       m_dTimer.Stop()
    End If
End Sub

HOWTO: Tweet SVN Comments from Windows

I’m assuming you have a SVN server running and the repositories setup properly if not check out Visual SVN server.

  1. The required svn server version is 1.6.3
  2. Install Python 2.5 or 2.6
  3. Install Python SVN bindings for the installed Python version (2.5 or 2.6)
  4. Download twitvn.py script
  5. Create a folder C:\twitvn
  6. Copy the script to the folder C:\twitvn
  7. Create the file svn_repo_path/hooks/post-commit.bat
  8. Copy the following to that file changing the username and password of your twitter account at the end of the file
  9. @ECHO OFF
    
    :: POST-COMMIT HOOK
    ::
    :: The post-commit hook is invoked after a commit.  Subversion runs
    :: this hook by invoking a program (script, executable, binary, etc.)
    :: named 'post-commit' (for which this file is a template) with the
    :: following ordered arguments:
    ::
    ::   [1] REPOS-PATH   (the path to this repository)
    ::   [2] REV          (the number of the revision just committed)
    ::
    :: The default working directory for the invocation is undefined, so
    :: the program should set one explicitly if it cares.
    ::
    :: Because the commit has already completed and cannot be undone,
    :: the exit code of the hook program is ignored.  The hook program
    :: can use the 'svnlook' utility to help it examine the
    :: newly-committed tree.
    ::
    :: On a Unix system, the normal procedure is to have 'post-commit'
    :: invoke other programs to do the real work, though it may do the
    :: work itself too.
    ::
    :: Note that 'post-commit' must be executable by the user(s) who will
    :: invoke it (typically the user httpd runs as), and that user must
    :: have filesystem-level permission to access the repository.
    ::
    :: On a Windows system, you should name the hook program
    :: 'post-commit.bat' or 'post-commit.exe',
    :: but the basic idea is the same.
    ::
    :: The hook program typically does not inherit the environment of
    :: its parent process.  For example, a common problem is for the
    :: PATH environment variable to not be set to its usual value, so
    :: that subprograms fail to launch unless invoked via absolute path.
    :: If you're having unexpected problems with a hook program, the
    :: culprit may be unusual (or missing) environment variables.
    ::
    :: Here is an example hook script, for a Unix /bin/sh interpreter.
    :: For more examples and pre-written hooks, see those in
    :: the Subversion repository at
    :: http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
    :: http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
    
    SET PYTHON_PATH=C:\Python25
    
    Set PATH=%PYTHON_PATH%;%PATH%
    
    SET REPOS=%1
    
    SET REV=%2
    
    Python C:\twitvn\twitvn.py -u username -p password -f "%REPOS%" -r "%REV%"
    
  10. Start Commiting

HOWTO: AVR-GCC on Ubuntu 8.10

These are the  steps that I used to install AVR-GCC on Ubuntu 8.10. Using checkinstall will install the files as .deb so it could be easily managed by the package manager.
Note: Ensure that you have the multiverse and universe repositories enabled.
  1. Install build-essentials, checkinstall, avr-libc, binutils-avr, bison, flex, byacc
    sudo apt-get install build-essential checkinstall avr-libc binutils-avr bison flex byacc
  2. Download gcc-core-4.2.2
  3. Edit /etc/checkinstallrc and change TRANSLATE=0
    # Are we going to use filesystem translation?TRANSLATE=0
  4. build and install gcc-core-4.2.2
    tar -vxf gcc-core-4.2.2.tar.bz2
    cd gcc-4.2.2
    mkdir avr-gcc# cd avr-gcc
    ../configure --target=avr --program-prefix="avr-" --enable-languages=c --disable-libssp
    make
    sudo checkinstall
    
  5. Ensure that the 3rd option version is a number
  6. Remove the empty lib directory
    sudo rm -r /usr/local/avr/lib
  7. Make symbolic links to where binutils and libc are installed
    sudo ln -s /usr/avr/bin /usr/local/avr/bin
    sudo ln -s /usr/avr/lib /usr/local/avr/lib
    sudo ln -s /usr/avr/include /usr/local/avr/include
  8. Test it and let me know

References : http://www.nanork.org/wiki/linux-install