The Life and Times of a Dev

Yes, we're really that weird
posts - 191 , comments - 345 , trackbacks - 106

My Links

News

Twitter












Tag Cloud

Archives

Post Categories

Play

Work

Thursday, December 11, 2014

Virtual Com ports

In the hardware world, much of the communication still happens over RS232 or RS485 serial ports.  Unit testing this can be a challenge.  To help with that, I’ve created a custom SerialPort wrapper, which, among other things, helps with multiple threads trying to hit the serial port at the same time.  When you’re iterating over actors, this is a key bit of functionality that needs to happen.

Because I have this class injected, I can easily substitute a mock to the things that actually do serial communication.  However, how do you unit test the serial component itself?  System.IO.SerialPort doesn’t have an interface, so it is challenging to test.

The solution I’m using is com0com, which is essentially a null modem emulator.

There are other solutions that are also great, but they aren’t free.  In particular, I was impressed by Eltima’s Virtual Serial Port Driver.  I almost bought it, but couldn’t rationalize it just for automated unit tests.

To use com0com, you’ll likely need to download the signed version, unless you have driver signing turned off on your computer.  Once installed, I use a simple batch file to install the desired com ports:

@echo off
cd\
cd "program files (x86)\com0com\"
"setupc.exe" --silent install PortName=COM181,EmuBR=yes,EmuOverrun=yes PortName=COM182,EmuBR=yes,EmuOverrun=yes

There are many more options, but what I needed was pretty simple.  Once this is done, SerialPort connects to the virtual com port just like it’s a real com port and does its thing.

One issue I ran into is that most unit test runners run multiple tests on different threads.  Since COM ports are strictly limited and only one thing can connect at a time, this can be a problem.  To get around, I just made a single massive test for my serial port component.

Posted On Thursday, December 11, 2014 5:36 PM | Comments (0) | Filed Under [ Unit Testing Serial Port ]

Thursday, November 27, 2014

Unit Testing Multi-threaded code

I spent the day today writing unit tests for code I wrote yesterday.  No, I’m not a big fan of TDD. Smile  I am, however, a big fan of high (as close to 100% as practical) code coverage.

The device I’m working on is very multi-threaded.  As a matter of fact, a key principle is DON’T BLOCK!  Because of this, there are quite a few Task’s, lots of awaiting, and several timers that poll on a regular basis.

This makes for code that can be tricky to unit test.  After all, if you’re not blocking, you’re on a different thread than the unit test thread and you need to make the unit test thread wait until the code has run its course.  Here’s a couple of things I’ve found to make this easier.

First, for any timers, like System.Timers.Timer, wrap them in an interface and then inject them with IoC.  Doing this, will let you raise the elapsed event whenever you want.  For example, the system.timers.timer class can easily be wrapped by something like this:

public class Timer : System.Timers.Timer, ITimer
{
    [InjectionConstructor]
    public Timer()
    {
    }

    public Timer(double interval)
        : base(interval)
    {
    }
}

This can then be mocked like this:

Mock timer = new Mock();
timer.Raise(t => t.Elapsed += null, (ElapsedEventArgs)null);

Note that ElapsedEventArgs has no public constructor, so the best you can do is pass in a null, which is far from ideal.

Second, if you’re going to be using Task.Run, you’ll want something that causes those tasks to run immediately.  I’ve wrapped the Task class with the following (Sorry for the bad formatting--I REALLY miss live writer plug-ins . . .):

using System;
using System.Threading;
using System.Threading.Tasks;

public class BackgroundTask : Task
{

public BackgroundTask(Action action)

: base(action)

{

}

public BackgroundTask(Action action, CancellationToken cancellationToken)

: base(action, cancellationToken)

{

}

public BackgroundTask(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)

: base(action, cancellationToken, creationOptions)

{

}

public BackgroundTask(Action action, TaskCreationOptions creationOptions)

: base(action, creationOptions)

{

}

public BackgroundTask(Action action, object state)

: base(action, state)

{

}

public BackgroundTask(Action action, object state, CancellationToken cancellationToken)

: base(action, state, cancellationToken)

{

}

public BackgroundTask(Action action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)

: base(action, state, cancellationToken, creationOptions)

{

}

public BackgroundTask(Action action, object state, TaskCreationOptions creationOptions)

: base(action, state, creationOptions)

{

}

public static bool RunTasksSynchronously { get; set; }

public static new Task Run(Action action)

{

if (RunTasksSynchronously)

{

Task task = new Task(action);

task.RunSynchronously();

return task;

}

return Task.Run(action);

}

public static new Task Run(Func function)

{

if (RunTasksSynchronously)

{

Task task = new Task(() => function.Invoke());

task.RunSynchronously();

return task;

}

return Task.Run(function);

}

public static new Task Run(Action action, CancellationToken cancellationToken)

{

if (RunTasksSynchronously)

{

Task task = new Task(action);

task.RunSynchronously();

return task;

}

return Task.Run(action, cancellationToken);

}

public static new Task Run(Func function, CancellationToken cancellationToken)

{

if (RunTasksSynchronously)

{

Task task = new Task(() => function.Invoke());

task.RunSynchronously();

return task;

}

return Task.Run(function, cancellationToken);

}

public static new Task Run(Func function)

{

if (RunTasksSynchronously)

{

Task task = new Task(function);

task.RunSynchronously();

return task;

}

return Task.Run(function);

}

public static new Task Run(Func> function, CancellationToken cancellationToken)

{

if (RunTasksSynchronously)

{

Task task = function.Invoke();

return task;

}

return Task.Run(function, cancellationToken);

}

public static new Task Run(Func function, CancellationToken cancellationToken)

{

if (RunTasksSynchronously)

{

Task task = new Task(function);

task.RunSynchronously();

return task;

}

return Task.Run(function, cancellationToken);

}

}

Note that setting RunTasksSynchronously in a non-testing environment will probably do bad things, but in testing makes all of your tasks run synchronously, which makes unit testing MUCH easier.

Now if only there were an easy way to write unit tests for race conditions!

Posted On Thursday, November 27, 2014 12:29 AM | Comments (1) | Filed Under [ Unit Testing ]

Thursday, November 20, 2014

Testing EntityFramework with Moq

Let’s face it, EntityFramework is a pain to mock.  With few interfaces, testing things that use it can be a real pain.  Here’s a few things I’ve found to make it easier:

  1. Make sure that you have an interface for your DbContext object so that it can easily be mocked.  If you’re doing Database First, be aware that EF 7 will eliminate EDMX support, so welcome to the code first era (I hear you . . .).
  2. Rather than using your Dependency Injector to directly inject an instance of your IDbContext, create a context provider instead.  This will make testing easier since you can easily mock the provider.  Something like IMyContext context = IContextProvider.GetContext(); where IContextProvider is injected.  You can also easily set things like lazy loading and dynamic proxy generation, both of which are useless for anything that doesn’t have direct access to the database.
  3. Make sure you’re using IDbSet instead of DbSet

With all of that in place, you can do some really fun stuff.  Here’s a method that I use to setup a DbSet that is backed by a List, and is attached to the context:

protected Mock> SetupDbSet(IList dataSource, Mock context) where T : class
{
    Mock> set = new Mock>();

    set.As>().Setup(drs => drs.Provider).Returns(dataSource.AsQueryable().Provider);
    set.As>().Setup(drs => drs.Expression).Returns(dataSource.AsQueryable().Expression);
    set.As>().Setup(drs => drs.ElementType).Returns(dataSource.AsQueryable().ElementType);
    set.As>().Setup(drs => drs.GetEnumerator()).Returns(dataSource.AsQueryable().GetEnumerator());

    set.Setup(s => s.Add(It.IsAny())).Callback(dataSource.Add);
    set.Setup(s => s.Remove(It.IsAny())).Callback((i) => dataSource.Remove(i));

    Type type = typeof(IDbSet);
    Type contextType = typeof(IMyDbContext);
    var parameter = System.Linq.Expressions.Expression.Parameter(contextType);
    PropertyInfo info = contextType.GetProperties().First(pi => pi.PropertyType == type);
    var body = System.Linq.Expressions.Expression.Property(parameter, info);
    dynamic func = System.Linq.Expressions.Expression.Lambda(body, parameter);

    context.SetupProperty>(func, set.Object);

    return set;
}

With that method, all you need to do is the following:

IList myEntities = new List();

// add entities

this.SetupDbSet(myEntities, mydbContextMock):

 

With those two lines of code, you’ll have mocked data in your context wherever it’s needed and be able to easily get to the changes made to the dbset.

Enjoy!

Posted On Thursday, November 20, 2014 4:06 PM | Comments (0) |

Working with Hardware

I’m working on a hardware project that involves software controlling motors, grippers and the like.  I can’t go into details on the project, but it’s quite a bit of fun.

I’ve learned a really important design principle for hardware interaction.  I’m sure some of you that have more hardware experience than I do will simply say, “duh”, but I had to learn the hard way.

In version one, I made good objects for all of the components and then tied them together into a single device.  They had base classes and such, good OO techniques.

It ended up being a pain in the kiester!  Who would have thought!

A far better pattern to follow is the Actor pattern.  Basically, you have a central state manager (ActorManager) that is responsible for giving each Actor (i.e. software addressable component) a chance to do its thing.

Each actor has access to a central state repository, and is responsible for writing it’s state to that repository as well.  If it cares about another component, it looks in state for the information it needs, otherwise it does its thing and moves on.

As an example, suppose you have three axis on a gantry (X, Y, Z), and these axis have to move in such a way that they don’t collide in their container.

With a top down approach, like the first revision, the device has to talk to x, y, and z and do a bunch of work to determine if they’re in a state where they can move, if they’re going to do something bad, etc.

With the actor pattern, if X needs to know if Z is in a good position, it looks in state for Z’s position.  If z isn’t in a good position, it does nothing, or if it’s in a good position, it moves.  Simple.  Y on the other hand, doesn’t care where Z or X are, so it can just move and does so.  Z is the same.  Simple.

Objects are still involved, they’re just much more loosely coupled.

Posted On Thursday, November 20, 2014 12:44 PM | Comments (0) |

Wednesday, November 7, 2012

Remote Desktop Connection Manager

For years, I’ve been using the “Remote Desktops” mmc plugin to manage servers in our infrastructure.  I’ve upgraded to Windows 8 and Remote Desktops is nowhere to be found!  I search and searched and came across a forum listing saying “Why don’t you just use Remove Desktop Connection Manager?”

I downloaded it and started using it and its WAY better than Remote Desktops!  I’m glad they took it out and I discovered this tool.  I wish I had discovered this two years ago!

Technorati Tags:

Posted On Wednesday, November 7, 2012 9:16 AM | Comments (2) |

Tuesday, October 23, 2012

Directory Synchronization

We’re using federated security with Office 365 and everything was running swimmingly and then I started getting the following error when trying to synchronize security information:

“An unknown error occurred with the Microsoft Online Services Sign-in Assistant. Contact Technical Support.”

Great.  Very descriptive.  In the event viewer, you get a bit more detail:

GetAuthState() failed with -2147186688 state. HResult:0. Contact Technical Support.  (0x80048831)

If you do some searching, you’ll find that there are a couple of MSDN articles about this error.  In KB2502710 you’re told to reinstall sign in assistant.  This one requires a reboot.  In KB2517393 you’re told to make sure that your proxy settings are working correctly.  I’m not using a proxy and everything was set up right.

Rather frustrating and I couldn’t figure out what was going on.  What finally keyed me in was the error number being presented.  Rather than 80048800, which is listed in the second article, I was getting 80048831.  I did a quick search and found something that was seemingly unrelated here.  Could it really be so simple as the password having expired for my synchronization user?

Turns out, it was that simple.  Once the password was reset and reentered, everything worked great again.

Since this isn’t a user that humans use, I also don’t want the password to expire.  You can find the instructions for that (use Set-MsolUser –UserPrincipalName <user ID> –PasswordNeverExpires $true) here.

Technorati Tags:

Posted On Tuesday, October 23, 2012 10:12 AM | Comments (2) |

Thursday, September 27, 2012

On iOS 6

“Introducing Windows ME, reimagined as iOS6 and by Apple!”

Remember, it just works, and when it doesn’t, you’re holding it wrong.

Posted On Thursday, September 27, 2012 10:56 AM | Comments (0) |

Thursday, August 16, 2012

Well That Was Fun (The wrong way to migrate mailboxes in Office 365)

NOTE:  BY FOLLOWING THE STEPS HERE YOU WILL PERMENENTLY AND IRREVOCABLY DELETE USERS AND THEIR DATA!!!  MAKE SURE YOU HAVE BACKUPS (PST’S)!

Ugh.

First, I want everyone know know that this was a self-inflicted problem.  I thought I knew what I was doing, but really didn’t know.  I do wish that there were warnings letting you know you were about to ruin your life, but there isn’t, so this is an easy mistake to make.

Our company is moving to office 365 from Exchange 2010.  We want to keep a local on premise version for various reasons, so we’ve set up a hybrid exchange configuration.  We tested it by moving a couple of mailboxes over and everything appeared to be working great.

However, the person helping me quit his job at the company we were outsourcing our IT stuff to.  I thought I knew what he had done, but didn’t.

Here’s our configuration:

  1. Exchange 2010
  2. Office 365
  3. Federated Security for Single Sign On
  4. Active Directory Synchronization

The big mistake that I made was when we were ready to move mailboxes to the cloud, I used the Email Migration tool in the Office 365 Tenant Portal.  If you have a HYBRID exchange configuration with with active directory synchronization, DO NOT USE THE E-MAIL MIGRATION image BUTTON!!! You’ll be hosed if you do.  Instead, use the Remote Move Request feature of EMC or powershell.

Note that the pain will be somewhat mitigated if you leave your MX records pointing at your on premise server, since all mail will continue to be delivered to your on premise server.  However, if you moved it, like I did, you have more work.

Here’s some of the symptoms that you did the wrong thing:

  1. Archive folders (personal archives) don’t appear to have migrated.
  2. Users can log into both portal.microsoftonline.com and access outlook AND your on premises OWA site, and both still work.
  3. Autodiscover sends people, seemingly at random, to your on premise server and to the office 365 servers.
  4. You have mailboxes for users on both your on premise servers and in office 365.

As soon as you realize what you’ve done, you’ll want to crawl under a rock and die.  There is NO easy solution.  After many hours on the phone with Microsoft Tech Support, here are the steps you need to take to recover:

  1. Ensure that you have Rollup 3 for service pack 2 installed on your on premises internet facing hybrid server.
  2. If you’ve moved your MX record, MOVE IT BACK! Smile  Seriously, you’ll have to send it back to your on premise server.
  3. If you moved your MX record, you’ll need to export all new mail that is in office 365 into PST’s.  THIS IS REALLY IMPORTANT!  YOU’RE ABOUT TO PERMENENTLY DELETE DATA! 
    1. To do this, grant a NON-FEDERATED user (and admin user) full access to the mailboxes.  You can do this using EMC’s Manage Full Access permission, or by using a powershell script to do the same.  You’ll need to create the user in office 365.
    2. Set up an outlook profile (I set up an entire VM) and connect it to the user in step one.
    3. Wait forever for the mail to synchronize down to the outlook profile (you probably want to avoid Cached Exchange Mode).  If you’ve got lots of mail, you’re going to have to do this in groups.
    4. Using outlook, export the new mail to a pst (file, open, import, export to file, outlook pst, select the top level mailbox, put a filter in, change the filename to the name of the mailbox, no password, export . . . and yes, that was from memory . . .)
      1. I’d name the file after the user whose mailbox you’re exporting
    5. After PST creation, create a new profile (control panel, Mail, Show Profiles) for an on premise user THAT DOES NOT HAVE A 365 MAILBOX.  Again, you’ll probably need to create the user.
    6. Import the PST’s into the appropriate location in outlook (File, import, import from a file, outlook data file (.pst), select the pst file to import, select the appropriate mailbox from the dropdown list).
    7. Wait forever for mail to sync (you’ll probably want to avoid Cached Exchange Mode).
    8. You’re done.  Wasn’t that fun?
  4. Next, deactivate active directory synchronization in the Office 365 portal and then wait for up to 72 hours for it to complete.  Yup, 72 hours . . . sucks to be you right now.  (It actually took about 7 hours.  I’m not sure if MS made it happen faster because I was already in the tech support queue or not)
  5. Once deactivation is complete, delete the offending users and mailboxes.  You may need to use the Remove-Mailbox powershell command in remote powershell to get rid of the offending mailboxes. (See the additional details below)
  6. Once the users are gone, turn Active Directory synchronization back on and synchronize.
    1. This may take up to 24 hours.
  7. Move the mailboxes the RIGHT way using EMC and Remote Move requests.

I’m at Step 4 right now.  If anything else exciting comes up, I’ll update this post.  I couldn’t find many posts on this “fun” so I thought I’d create one.  I guess others are just more experienced than I am. Smile

 

UPDATE:

So step 5 needs way more detail.  After several more hours on the phone with Microsoft Support, we ended up doing the following to get rid of the bad mailboxes:

Did I mention that by following these steps you’re going to lose data if you don’t have it backed up?

  1. Remove the mailboxes using whatever means you desire (powershell, whatever, doesn’t really matter), which will also delete the users from the system
    1. At this point, you can still recover the users.  If you turn on ADSynch, the users will recover and be re-associated with the deleted mailboxes, which leaves you back where you started.
  2. Using remote powershell for microsoft online, get a list of all online users using the get-msolUser | fl DisplayName, ObjectId command
  3. One by one, delete the users from office 365 using Remove-MSOLUser –ObjectId {Guid from step 2}
    1. If you don’t want to permanently delete your users, you’ll need to get to the operations level at Microsoft.  Yeah, not much you can do about it.
  4. Once the users are deleted that have the duplicate mailboxes, flush the recycle bin using the following command:  Get-MsolUser –ReturnDeletedUsers | Remove-MsolUser –RemoveFromRecycleBin –force
  5. Once this is done, re-enable active directory synchronization, synchronize and your done.  Easy, no?

UPDATE:

This link might be helpful.  It talks about how to delete a user even with ADSynch turned on.

 

BIG Props to FP from Microsoft Support.  Without him I’d have been sunk!

Technorati Tags:

Posted On Thursday, August 16, 2012 8:54 AM | Comments (1) |

Wednesday, July 11, 2012

Reading Credit Card Data from a MagTek Card Swipe Device

Sometimes as developers we’re spoiled by third parties that do a lot of the heavy lifting for us.  However, sometimes we’re NOT spoiled and we have to get our hands dirty.

Today, I spent much of the day getting my hands dirty.  I’m working on a project that uses a MagTek credit card swiper and all MagTek provides you in terms of dlls is a c++ dll and an ActiveX dll.  What fun is that?  I wanted to avoid com interop (no, I don’t have a good reason) and write a C# class that handled talking with their C++ dlls directly.

This ended up being a good lesson in P/Invoke and how to deal with unsafe (I’m guessing strcat) code in a dll that I don’t control.

1207 lines of code (and comments) later, I have the final result completed.  I’m not going to post the entire post, since it would be WAY to long, but here are the key bits:

Here’s the dll imports you’ll need:

/// <summary>
///   Clears the data buffer
/// </summary>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAClearBuffer();

/// <summary>
///   Opens the MTUSCRA Device
/// </summary>
/// <returns> A uint that is an <see cref="ErrorValuesEnum" /> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRACloseDevice();

/// <summary>Gets the card data from the reader.</summary>
/// <param name="cardData">The card data structure for holding the card information. </param>
/// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRAGetCardData(ref MTMSRDATA cardData);

//// This has been removed because it requires unsafe code.
/////// <summary>Gets the card data delimited by the provided string.</summary>
/////// <param name="data">The string result that will be sent back. </param>
/////// <param name="delimiter">The delimiter for the string </param>
/////// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
////[DllImport("MTUSCRA.dll")]
////private static extern unsafe uint MTUSCRAGetCardDataStr(byte* data, string delimiter);

/// <summary>Opens the MTUSCRA Device</summary>
/// <param name="deviceName">The name of the device to open </param>
/// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRAOpenDevice(string deviceName);

/// <summary>Opens the MTUSCRA Device</summary>
/// <param name="command">The command to send </param>
/// <param name="commandLength">The length of the command sent. </param>
/// <param name="result">The result of the command </param>
/// <param name="resultLength">The length of the result. </param>
/// <returns>A uint that is an <see cref="ErrorValuesEnum"/> </returns>
[DllImport("MTUSCRA.dll")]
private static extern uint MTUSCRASendCommand(string command, uint commandLength, ref string result, ref uint resultLength);

/// <summary>
/// Raised when the card state data changes.
/// </summary>
/// <param name="callBack">The call back for card data state changing.</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRACardDataStateChangedNotify(CardDataStateChangedCallBack callBack);

/// <summary>
/// Raised when the device state changes
/// </summary>
/// <param name="callBack">The call back for card data state changing.</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRADeviceStateChangedNotify(DeviceStateChangedCallBack callBack);

/// <summary>
/// Gets the current device state.
/// </summary>
/// <param name="deviceState">The device state</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAGetDeviceState(ref uint deviceState);

/// <summary>
/// Gets the current data state.
/// </summary>
/// <param name="dataState">The data state</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAGetCardDataState(ref uint dataState);

/// <summary>
/// Gets the cproduct id of the card reader.
/// </summary>
/// <param name="productId">The product id</param>
[DllImport("MTUSCRA.dll")]
private static extern void MTUSCRAGetPID(ref uint productId);

You’ll need a couple of delegates as well:

/// <summary>
///   A delegate for handling the card data state callback.
/// </summary>
/// <param name="dataState"> The data state </param>
private delegate void CardDataStateChangedCallBack(uint dataState);

/// <summary>
///   A delegate for handling the device state callback.
/// </summary>
/// <param name="deviceState"> The device state </param>
private delegate void DeviceStateChangedCallBack(uint deviceState);

And then you’ll want to wire those up like so:

 

this.CardDataStateChanged = new CardDataStateChangedCallBack(this.OnCardDataStateChanged);
this.DeviceStateChanged = new DeviceStateChangedCallBack(this.OnDeviceStateChanged);

MTUSCRACardDataStateChangedNotify(this.CardDataStateChanged);
MTUSCRADeviceStateChangedNotify(this.DeviceStateChanged);

And finally, you’ll want the Struct that you’ll need to use to get the card data:

[StructLayout(LayoutKind.Sequential)]
public struct MTMSRDATA
{
    /// <summary>The default data size for tracks.</summary>
    private const int DEF_MSR_DATA_LEN = 256;

    /// <summary>The card data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN * 3)]
    public string m_szCardData;

    /// <summary>masked card data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN * 3)]
    public string m_szCardDataMasked;

    /// <summary>Track 1 Data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack1Data;

    /// <summary>Track 2 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack2Data;

    /// <summary>Track 3 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack3Data;

    /// <summary>Masked track 1 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack1DataMasked;

    /// <summary>masked track 2 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack2DataMasked;

    /// <summary>masked track 3 data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szTrack3DataMasked;

    /// <summary>MagnePrint data.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szMagnePrintData;

    /// <summary>Card encode type.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szCardEncodeType;

    /// <summary>MagnePrint Status.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szMagnePrintStatus;

    /// <summary>DUKPT Session ID.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szDUKPTSessionID;

    /// <summary>Device Serial Number.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szDeviceSerialNumber;

    /// <summary>DUKPT Key Serial Number.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szDUKPTKSN;

    /// <summary>First Name from Track 1.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szFirstName;

    /// <summary>Last Name from Track 1.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szLastName;

    /// <summary>PAN from Track 2.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szPAN;

    /// <summary>The Expiration Month.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szMonth;

    /// <summary>The Expiration Year.</summary>
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = DEF_MSR_DATA_LEN)]
    public string m_szYear;

    /// <summary>Reader product ID.</summary>
    public uint m_dwReaderID;

    /// <summary>MagnePrint length.</summary>
    public uint m_dwMagnePrintLength;

    /// <summary>MagnePrint Status.</summary>
    public uint m_dwMagnePrintStatus;

    /// <summary>Track 1 data length.</summary>
    public uint m_dwTrack1Length;

    /// <summary>Track 2 length.</summary>
    public uint m_dwTrack2Length;

    /// <summary>Track 3 length.</summary>
    public uint m_dwTrack3Length;

    /// <summary>Track 1 length masked.</summary>
    public uint m_dwTrack1LengthMasked;

    /// <summary>Track 2 length masked.</summary>
    public uint m_dwTrack2LengthMasked;

    /// <summary>Track 3 length masked.</summary>
    public uint m_dwTrack3LengthMasked;

    /// <summary>Card encode type.</summary>
    public uint m_dwCardEncodeType;

    /// <summary>Track 1 decode status.</summary>
    public uint m_dwTrack1DcdStatus;

    /// <summary>Track 2 decode status.</summary>
    public uint m_dwTrack2DcdStatus;

    /// <summary>The m_dw track 3 dcd status.</summary>
    public uint m_dwTrack3DcdStatus;

    /// <summary>Card swipe status.</summary>
    public uint m_dwCardSwipeStatus;
}

Hopefully, this will help you get started and will save you some time.  I know it would have saved me quite a bit!

Good luck!

Technorati Tags: ,,

Posted On Wednesday, July 11, 2012 5:25 PM | Comments (5) |

Monday, July 2, 2012

Easy Scaling in XAML (WPF)

Ran into a problem that needed solving that was kind of fun.  I’m not a XAML guru, and I’m sure there are better solutions, but I thought I’d share mine.

The problem was this:  Our designer had, appropriately, designed the system for a 1920 x 1080 screen resolution.  This is for a full screen, touch screen device (think Kiosk), which has that resolution, but we also wanted to demo the device on a tablet (currently using the AWESOME Samsung tablet given out at Microsoft Build).  When you’d run it on that tablet, things were ugly because it was at a lower resolution than the target device.

Enter scaling.  I did some research and found out that I probably just need to monkey with the LayoutTransform of some grid somewhere.  This project is using MVVM and has a navigation container that we built that lives on a single root view.  User controls are then loaded into that view as navigation occurs.

In the parent grid of the root view, I added the following XAML:

        <Grid.LayoutTransform>
            <ScaleTransform ScaleX="{Binding ScaleWidth}" ScaleY="{Binding ScaleHeight}" />
        </Grid.LayoutTransform>

And then in the root View Model, I added the following code:

/// <summary>
/// The required design width
/// </summary>
private const double RequiredWidth = 1920;

/// <summary>
/// The required design height
/// </summary>
private const double RequiredHeight = 1080;
/// <summary>Gets the ActualHeight</summary>
public double ActualHeight
{
    get
    {
        return this.View.ActualHeight;
    }
}

/// <summary>Gets the ActualWidth</summary>
public double ActualWidth
{
    get
    {
        return this.View.ActualWidth;
    }
}

/// <summary>
/// Gets the scale for the height.
/// </summary>
public double ScaleHeight
{
    get
    {
        return this.ActualHeight / RequiredHeight;
    }
}

/// <summary>
/// Gets the scale for the width.
/// </summary>
public double ScaleWidth
{
    get
    {
        return this.ActualWidth / RequiredWidth;
    }
}

Note that View.ActualWidth and View.ActualHeight are just pointing directly at FrameworkElement.ActualWidth and FrameworkElement.ActualHeight.

That’s it.  Just calculate the ratio and bind the scale transform to it.

Hopefully you’ll find this useful.

Update (7-2-2012):

Note that I tried a ViewBox before, but it didn’t work because of the navigation.  Basically, we needed the following structure in the grid:

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1920"/>
                        <ColumnDefinition Width="1920"/>
                        <ColumnDefinition Width="1920"/>
                    </Grid.ColumnDefinitions>

The first column is the Last Screen.  The second column is the Currently displayed screen, and the last column is the “Next” screen.  When moving next, the “next” screen is loaded into the last column, then the animation is fired to slide in the screen, and then the current panel has the current view replaced and is refocused without animation.  Navigating back is similar in flow.

The total screen space isn’t consumed by the navigation grid.

When using a ViewBox, the entire 5760 pixels are compressed into the available screen space.  A picture would make this more clear, but I can’t show that without revealing stuff you shouldn’t know. Smile

Basically, I needed a single column of the grid to be scaled, not the entire grid, which is what my solution does, where the viewbox attempts to scale everything.

Make sense?

Technorati Tags: ,

Posted On Monday, July 2, 2012 4:29 PM | Comments (3) |

Powered by: