Xaml color scheme generator

I’ve made a xaml color scheme generator that works with http://colorschemedesigner.com/

It generates a resource dictionary and xaml demo source. In the color scheme generator site, just export to xaml, and save to a file. In the generator, browse for that file, and click convert.

Download it here

24. December 2009 15:04 by Rick | Comments (2) | Permalink

Windows 7 Multi-touch Panning with ScrollViewer in WPF 3.5 Part Duex

In my last post I described a class that wraps the ScrollViewer control to enable multi-touch panning in it.

Well, it’s not exactly the right way to do it. You should be receiving the pan messages in the Window, then finding the scroll viewer where the window was touched using a Hit Test, and scroll that ScrollViewer.

 

Code Snippet
  1.         private void Page2_Loaded(object sender, RoutedEventArgs e)
  2.         {
  3.             // Get our items for the itemscontrols
  4.             this.GetItems();
  5.  
  6.             // Check for multi-touch capabilities
  7.             if (Windows7.Multitouch.Handler.DigitizerCapabilities.IsMultiTouchReady)
  8.             {
  9.                 // Enable stylus events
  10.                 Windows7.Multitouch.WPF.Factory.EnableStylusEvents(this);
  11.                 // Add the gesture handler
  12.                 this.GestureHandler = Windows7.Multitouch.WPF.Factory.CreateGestureHandler(Window.GetWindow(this));
  13.                 // Attach the handler to the method
  14.                 this.GestureHandler.Pan += new EventHandler<Windows7.Multitouch.GestureEventArgs>(this.GestureHandler_Pan);
  15.             }
  16.         }
  17.  
  18.  
  19.         private void GestureHandler_Pan(object sender, Windows7.Multitouch.GestureEventArgs e)
  20.         {
  21.             this.panTranslation = e.PanTranslation;
  22.  
  23.             PointHitTestParameters hitTestParameters = new PointHitTestParameters(Windows7.Multitouch.WPF.PointUtil.ToDrawingPointF(e.Center));
  24.             VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(this.HitTestResult), hitTestParameters);
  25.         }
  26.  
  27.         public HitTestResultBehavior HitTestResult(HitTestResult rawresult)
  28.         {
  29.             ScrollViewer sv = null;
  30.             try
  31.             {
  32.                 sv = (ScrollViewer)rawresult.VisualHit;
  33.             }
  34.             catch
  35.             {
  36.             }
  37.  
  38.             // If we have a reference to the scrollviewer, then we scroll
  39.             if (sv != null)
  40.             {
  41.                 // Make the Scroller scroll
  42.                 sv.ScrollToVerticalOffset(sv.VerticalOffset - this.panTranslation.Height);
  43.  
  44.                 // Stop trying to find more controls in the visual tree
  45.                 return HitTestResultBehavior.Stop;
  46.  
  47.             }
  48.             else
  49.             {
  50.                 // Continue trying to find more controls in the visual tree
  51.                 return HitTestResultBehavior.Continue;
  52.             }
  53.  
  54.         }

When you are tracking multi-touch in a specific control, the touchs register at the window level, so even if you are not touching in the ScrollViewer, it still will pan it.

So the code was moved to the window , and uses the standard <ScrollViewer>.

Download the example project in C# and VB.NET

13. November 2009 01:23 by Rick | Comments (2) | Permalink

Windows 7 Multi-touch Panning with ScrollViewer in WPF 3.5

UPDATE: You should be using the Window to receive events. See my updated post for details.

Yes, it can be done easily, including inertia. It does require the Windows 7 Multitouch .NET Interop Sample Library

First, create a class that inherits from scrollviewer.

Code Snippet
  1. Public Class MultiTouchScollViewer
  2.     Inherits ScrollViewer
  3.  
  4. End Class

Then you add references to Windows7.Multitouch.dll and Windows7.Multitouch.Wpf.dll.

Then modify the MultiTouchScrollViewer like so:

Code Snippet
  1. Imports System.Windows
  2. Imports System.Windows.Controls
  3.  
  4. Public Class MultiTouchScrollViewer
  5.     Inherits ScrollViewer
  6.  
  7.     Private GestureHandler As Windows7.Multitouch.GestureHandler
  8.  
  9.     Public Sub New()
  10.         AddHandler MyBase.Loaded, New RoutedEventHandler(AddressOf Me.MultiTouchScollViewer_Loaded)
  11.         Me.GestureHandler = Nothing
  12.     End Sub
  13.  
  14.     Private Sub MultiTouchScollViewer_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs)
  15.         If Windows7.Multitouch.TouchHandler.DigitizerCapabilities.IsMultiTouchReady Then
  16.             GestureHandler = Windows7.Multitouch.WPF.Factory.CreateGestureHandler(System.Windows.Window.GetWindow(Me))
  17.             AddHandler GestureHandler.Pan, AddressOf Me.GestureHandler_Pan
  18.         End If
  19.     End Sub
  20.  
  21.     Private Sub GestureHandler_Pan(ByVal sender As Object, ByVal e As Windows7.Multitouch.GestureEventArgs)
  22.         Dim s As System.Drawing.Size = e.PanTranslation
  23.  
  24.         Me.ScrollToVerticalOffset(Me.VerticalOffset - s.Height)
  25.     End Sub
  26.  
  27. End Class

Download the VB.NET code here

Download the C# code here

NOTE: It does require hit testing if using multiple scrollviewers in the same window.

9. November 2009 05:04 by Rick | Comments (2) | Permalink

Binary hacking an executable part duex

A couple of the tools I use for binary hacking:

One of the problems with binary hacking a .net executable is references. Say you have an executable and a .dll file that is referenced by the executable. If you modify the .dll and resign it with a new public key token, the executable’s reference will be broken.

You are welcome to download the following code and binaries to "crack" along with me.

Crack Me Test files

In the zip file above, I have the following files:

crack01

In the Common Library class library code, is the following:

Code Snippet
  1.     Public Shared Function IsLicensed() As Boolean
  2.         Dim retval As Boolean = False
  3.         retval = False
  4.         Return retval
  5.     End Function

<rant>This is BAD for you to protect your executables this way. There are even professional .NET component designers who use methods like this. All you have to do is change the false to a true and it is cracked. Please, you are selling these components to developers, some who know how to crack, and most know how to use reflector at least. Duh!</rant>

Open up ILDASM by typing ILDASM at the visual studio command prompt. Once you open the CommonLibrary.dll Go to the view menu, and choose “show bytes”. Navigate to the method you wish to crack, in this case the CommonLibrary.LicenseProtector.IsLicensed() function and double-click on it. crack02 This brings up the IL code for it, but more importantly, by turning on the “show bytes” it allows you to find this method in the binary file.

Now go ahead and open the CommonLibrary.dll in UltraEdit or any other binary editor. We are going to change the false to a true.

According to the picture above on the right, we are looking for the following hex code 16 0B 16 0B 07 2A. Your code may vary. Once we find it, and are sure we are in the right place by searching again for it, we can now edit it. Change the 16s to 17s. This makes the false to a true.crack03

This is how it looks after. 17 0B 17 0B 07 2A.

Now that we’ve cracked it, we have to re-sign it with a public key. Run the following, which creates a crack.snk key file.

sn.exe -k crack.snk

Then we can run the SNReplace. The code for that is at the top of the article, create a console app and paste that code there.

snreplace.exe commonlibrary.dll crack.snk

crack04crack05

Now, open the CrackMeTest.exe in reflector and the commonlibrary.dll in reflector. When you click on the CrackMeTest.exe in reflector, you will see the public key token, which is 82db601ed5cd3521 (On my machine). Since you re-signed the commonlibrary.dll you will see a different public key token. If you navigate in Reflector to the method CommonLibrary.LicenseProtector.IsLicensed() you will see it returns true.

crack06

Great, but now we have to fix the reference between the exe and dll. Write down the public key tokens for both. Now we run the resigner on the executable.

snreplace.exe CrackMeTest.exe crack.snk

This will change the public key of the executable to the same as the dll file. Plus it will help us, since we won’t have duplicates for the public key since we re-signed our exe.

Open the exe in UltraEdit. We are looking for the old key, which in this case is 82 DB 60 1E D5 CD 35 21 (May be different on your machine). When we find it, we just swap that out with the new key, and then we re-sign the executable again. Voila, the reference to the .dll has changed to the new key.

kick it on DotNetKicks.com

11. July 2009 22:58 by Rick | Comments (2) | Permalink

Changing the URL for TFS 2008

I’ve seen many sites for changing the URL in TFS, but they usually refer to TFS 2005. Here’s my way of changing it on TFS 2008.

Step 1. Run the command TFSAdminUtil ActivateAT tfs.mycompany.com

Step 2. Start RegEdit and Navigate to the following key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TeamFoundation\ReportServer\80\Sites

and change the two string values BaseReportsUrl and ReportsService.

Navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TeamFoundation\Servers and edit the server string value.

Step 3. Go to C:\Program Files\Microsoft Visual Studio 2008 Team System Web Access\Web and edit the web.config under <tfServers>

Step 4. Go to C:\Program Files\Microsoft Visual Studio 2008 Team Foundation Server\TFSServerScheduler and edit the TFSServerScheduler.exe.config, and edit the key TFSNameUrl

Step 5. Go to Start > All Programs > Administrative Tools > SharePoint 3.0 Central Administration. Navigate to Operations > Alternate Access Mappings (under Global Configuration). Add two mappings for Internal URLs

http://tfs.mycompany.com Zone: Intranet

http://tfs.mycompany.com:17012 Zone: Intranet

You need to do this so the document node in Team Explorer will map to the proper URL, and for the portal and project creation to work properly.

You should do a IISRESET or reboot.

kick it on DotNetKicks.com
28. May 2009 07:33 by Rick | Comments (2) | Permalink

MEF helper class for VB.NET

This is a class I created to help me with MEF. It might be useful to somebody.

It is a singleton with IDisposable to create a shared object for your application’s lifetime.

It also features lambda queries for finding metadata as well.

#Region "Compiler Options"
Option Strict Off
Option Explicit On
Option Compare Binary
#End Region
#Region "Library Imports"
Imports System.ComponentModel.Composition
Imports System.ComponentModel.Composition.Hosting
#End Region
' Template version 1.2.0.2. Code developed for framework v2.0.50727.3074
' This code is copyright (c) 2009 ActiveAsp Software. All rights reserved.
''' <summary>
''' Managed Extensibility Framework Helper Class
''' </summary>
''' <remarks>
''' Singleton object
''' -- Change Log --------------------------------------------------------
''' 4/5/2009 11:55:06 PM by Rick - Initial Creation
''' 
''' </remarks>
Public NotInheritable Class MefHelper
    Implements IDisposable
#Region "Constructor / Deconstructor"
    ''' <summary>
    ''' The starting point for this class
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub New()
        ' Enter Shared Class Creation Code Here
        Dim sPathInitial As String = System.IO.Path.GetDirectoryName(GetType(MefHelper).Assembly.Location)
        _ExtensionsPath = System.IO.Path.Combine(sPathInitial, "Extensions")
    End Sub
#Region " IDisposable Support "
    Private disposedValue As Boolean = False        ' To detect redundant calls
    ' IDisposable
    Protected Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                _Container.Dispose()
                _Container = Nothing
            End If
        End If
        Me.disposedValue = True
    End Sub
    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region
#End Region
#Region "Public"
#Region "Public Property Declarations"
    Private _Container As CompositionContainer = Nothing
    Public ReadOnly Property Container() As CompositionContainer
        Get
            Return _Container
        End Get
    End Property
    Private _ExtensionsPath As String = ""
    Public Property ExtensionsPath() As String
        Get
            Return _ExtensionsPath
        End Get
        Set(ByVal value As String)
            If Not _ExtensionsPath = value Then
                _ExtensionsPath = value
            End If
        End Set
    End Property
#End Region
#Region "Public Shared Property Declarations"
    ' Properties
    Public Shared ReadOnly Property Instance() As MefHelper
        Get
            If (MefHelper._instance Is Nothing) Then
                SyncLock MefHelper.syncRoot
                    If (MefHelper._instance Is Nothing) Then
                        MefHelper._instance = New MefHelper
                    End If
                End SyncLock
            End If
            Return MefHelper._instance
        End Get
    End Property
    ' Fields
    Private Shared _instance As MefHelper 'ModReq(IsVolatile)
    Private Shared syncRoot As Object = New Object
#End Region
#Region "Public Methods"
    Public Sub Compose()
        Dim Catalog As New AggregateCatalog()
        ' Add This assembly's catalog parts
        Catalog.Catalogs.Add(New AssemblyCatalog(GetType(MefHelper).Assembly))
        ' Directory of catalog parts
        If System.IO.Directory.Exists(_ExtensionsPath) Then
            Catalog.Catalogs.Add(New DirectoryCatalog(_ExtensionsPath))
        End If
        _Container = New CompositionContainer(Catalog)
    End Sub
    Public Function GetExportByContractType(Of T)() As Export(Of T)
        Dim RetVal As Export(Of T) = Nothing
        Try
            RetVal = _Container.GetExport(Of T)()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByContractType(Of T, U)() As Export(Of T, U)
        Dim RetVal As Export(Of T, U) = Nothing
        Try
            RetVal = _Container.GetExport(Of T, U)()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByContractType(Of T)() As Generic.List(Of Export(Of T))
        Dim RetVal As Generic.List(Of Export(Of T)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByContractType(Of T, U)() As Generic.List(Of Export(Of T, U))
        Dim RetVal As Generic.List(Of Export(Of T, U)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByContractName(Of T)(ByVal name As String) As Export(Of T)
        Dim RetVal As Export(Of T) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).Where(Function(p) String.Compare(p.Definition.ContractName, name, True) = 0).Single()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByContractName(Of T, U)(ByVal name As String) As Export(Of T, U)
        Dim RetVal As Export(Of T, U) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).Where(Function(p) String.Compare(p.Definition.ContractName, name, True) = 0).Single()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByContractName(Of T)(ByVal name As String, ByVal value As String) As Generic.List(Of Export(Of T))
        Dim RetVal As Generic.List(Of Export(Of T)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).Where(Function(p) String.Compare(p.Definition.ContractName, name, True) = 0).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByContractName(Of T, U)(ByVal name As String, ByVal value As String) As Generic.List(Of Export(Of T, U))
        Dim RetVal As Generic.List(Of Export(Of T, U)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).Where(Function(p) String.Compare(p.Definition.ContractName, name, True) = 0).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByMetadata(Of T)(ByVal name As String) As Export(Of T)
        Dim RetVal As Export(Of T) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).Where(Function(p) p.Metadata.ContainsKey(name) = True).Single()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByMetadata(Of T)(ByVal name As String, ByVal value As String) As Export(Of T)
        Dim RetVal As Export(Of T) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).Where(Function(p) String.Compare(p.Metadata(name).ToString(), value, True) = 0).Single()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByMetadata(Of T, U)(ByVal name As String, ByVal value As String) As Export(Of T, U)
        Dim RetVal As Export(Of T, U) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).Where(Function(p) String.Compare(p.Metadata(name).ToString(), value, True) = 0).Single()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportByMetadata(Of T, U)(ByVal name As String) As Export(Of T, U)
        Dim RetVal As Export(Of T, U) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).Where(Function(p) p.Metadata.ContainsKey(name) = True).Single()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByMetadata(Of T)(ByVal name As String, ByVal value As String) As Generic.List(Of Export(Of T))
        Dim RetVal As Generic.List(Of Export(Of T)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).Where(Function(p) String.Compare(p.Metadata(name).ToString(), value, True) = 0).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByMetadata(Of T)(ByVal name As String) As Generic.List(Of Export(Of T))
        Dim RetVal As Generic.List(Of Export(Of T)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T).Where(Function(p) p.Metadata.ContainsKey(name) = True).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByMetadata(Of T, U)(ByVal name As String, ByVal value As String) As Generic.List(Of Export(Of T, U))
        Dim RetVal As Generic.List(Of Export(Of T, U)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).Where(Function(p) String.Compare(p.Metadata(name).ToString(), value, True) = 0).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
    Public Function GetExportsByMetadata(Of T, U)(ByVal name As String) As Generic.List(Of Export(Of T, U))
        Dim RetVal As Generic.List(Of Export(Of T, U)) = Nothing
        Try
            RetVal = _Container.GetExports(Of T, U).Where(Function(p) p.Metadata.ContainsKey(name) = True).ToList()
        Catch ex As Exception
        End Try
        Return RetVal
    End Function
#End Region
#End Region
End Class

Download the code

5. April 2009 23:02 by Rick | Comments (2) | Permalink

Using MEF and querying the catalog container with VB.NET

I am using the Managed Extensibility Framework preview 4 in VB.NET, and I have to say, that it rocks!

The project I am writing is a UI container that has “add-ins” that process files and such. I am working with another programmer to develop other add-ins for the app as well.

To query for specific metadata, we first have to create an interface and a custom attribute.

Public Interface IMefMetadataView
    ReadOnly Property Name() As String
End Interface
<MetadataAttribute()> _
Public Class MefMetadata
    Inherits Attribute
    Public Sub New()
    End Sub
    Public Sub New(ByVal name As String)
        _Name = name
    End Sub
    Private _Name As String = ""
    Public ReadOnly Property Name() As String
        Get
            Return _Name
        End Get
    End Property
End Class

This attribute allows you to specify a name of the add-in. Then we create an interface for our add-in.

    Public Interface IAddin
    End Interface

Then we can create an add-in or two.

	<Export(GetType(IAddin))> _
	<AddinMetadata("Add-in one")> _
	Public Class Addin1
	    Implements IAddin
	
	End Class
	
	<Export(GetType(IAddin))> _
	<AddinMetadata("Add-in two")> _
	Public Class Addin2
	    Implements IAddin
	
	End Class

Now, in our host user interface, we create a catalog and a container. Specifically we are creating an AggregateCatalog (a catalog of catalogs if you will) and then creating a catalog for just our assembly, then we are adding it into the container.

    Dim Container as CompositionContainer
    Dim Catalog As New AggregateCatalog()
    Dim AssemCatalog As New AssemblyCatalog(GetType(Module1).Assembly)
    Catalog.Catalogs.Add(AssemCatalog)
    Container = New CompositionContainer(Catalog)

Querying:

Get a list of addins:

    Dim Addins As Generic.List(Of Export(Of IAddin, IMefMetadataView)) = _
        Container.GetExports(Of IAddin, IMefMetadataView).ToList()

Query for a specific add-in with a name in the metadata using a lambda function:

Dim x As Export(Of IAddin, IMefMetadataView) = Addins.Where(Function(p) String.Compare(p.Metadata("Name").ToString(), "Add-in one", True) = 0).Single()

Or

Dim x As Export(Of IAddin, IMefMetadataView) = Addins.Where(Function(p) String.Compare(p.MetadataView.Name, "Add-in one", True) = 0).Single()

The box directly above allows us to query strongly typed metadata, thanks to the IMefMetadataView Interface and the MefMetadata class.

kick it on DotNetKicks.com
5. April 2009 21:15 by Rick | Comments (549) | Permalink

Cracking .NETZ executables

.NETZ is a free open source tool that compresses and packs the Microsoft .NET Framework executable (EXE, DLL) files in order to make them smaller. Smaller executables consume less disk space and load faster because of fewer disk accesses.

Today we are going to show you how to extract assemblies from them, so we can crack them!

First, we use reflector to save the resources to a folder. Right-click on the zip.dll and choose Save As… Then do the same for the guid resource.

Saving resource from reflector

Then, in reflector, we find the unzip method. It’s in the namespace netz.NetzStarter.Unzip(data() as byte)

So we copy that code to the clipboard, and fire up Visual Studio and make a new console app.

Paste the unzip code to the module, and add namespaces at the top:

Imports System.IO
Imports ICSharpCode.SharpZipLib.Zip.Compression.Streams

Then we add the following code to the Main() sub.

Sub Main()
    Dim folder As String = "C:\Cracked\Files"
    ' This is the name of the resource we took from
    ' reflector.
    Dim bFile As String = _
    	System.IO.Path.Combine(folder, "A6C24BF5-3690-4982-887E-11E1B159B249")
    Dim b() As Byte = My.Computer.FileSystem.ReadAllBytes(bFile)

    ' Attach a .exe to the end of the string
    bFile += ".exe"
    ' write the bytes to the file.
    Using ms As MemoryStream = UnZip(b)
        Dim outBytes() As Byte = ms.GetBuffer
        My.Computer.FileSystem.WriteAllBytes(bFile, outBytes, False)
    End Using
End Sub

And run it. It should make an executable file in the same folder… Happy cracking!



kick it on DotNetKicks.com
6. March 2009 11:11 by Rick | Comments (2) | Permalink

When good code goes bad…

In my post about refactoring code, I wrote on how you can tell how good a programmer is by looking at his code. That got me to thinking: Some stuff that seems simple, is sometimes hard to remember.

For instance, if you want a class to only have shared methods, you should mark it as not inheritable and set the constructor to private.

Public NotInheritable Class SomeClass Private Sub New() End Sub Public Shared Function SomeMethod() as boolean End Function End Class
The code in C# is like so:
public sealed class SomeClass { private SomeClass() { } public static bool SomeMethod() { } }
Sometimes I get lazy and forget to mark it not inheritable, but lately I’ve been using code analysis, and trying to make my code be more like the .net framework libraries and use best practices.


kick it on DotNetKicks.com
14. January 2009 19:20 by Rick | Comments (0) | Permalink

The “cloud” buzzword

The “cloud” seems to be the buzzword of the moment. Loosely defined as software as a service running off the internet.

For some reason, this is rather grating to me. I don’t know why! Reminds me of when XML first gained traction as a buzzword before people knew what it was. They (the media and blogs) made it out to seem if XML was the be-all, end-all technology. It would not only save the world, but cook you a sandwich at lunchtime if you programmed it right.

I guess they got tired of the web 2.0 buzzword.



kick it on DotNetKicks.com
14. January 2009 18:32 by Rick | Comments (0) | Permalink

About Rick

Rick lives in North Las Vegas. He loves his wife, kids, dog, motorcycle, music and programming. There ain't nothing else. Oh yeah, mountain dew!



Programming interests are geared towards multimedia. Platforms are asp.net, windows forms, and WPF.

Calendar

<<  March 2010  >>
MoTuWeThFrSaSu
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar

RecentComments

Comment RSS