Monday, March 12, 2012
Here is the link to my current blog:
http://robertbunn.blogspot.com/
Tuesday, February 21, 2012
I was working with some sample code which unfortunately was in Visual Basic. After working on translating the Visual Basic to a language that doesn't suck (anything else is better) for about 20 minutes I started to try to think of ways to increase the rate I translated the VB code to C#. My first thought was to write a Haiku about it. Here it goes:
I hate Visual Basic
The Bubonic Plague
is much more preferable
After writing this I realized that writing Haikus is like writing Visual Basic, both are a waste of time. ;)
Monday, November 09, 2009
I have two projects one is production code (called Main), the other is a unit test project to test the real production code (called Main.Test). Both Main and Main.Test are signed with a strong name key. To expose the internal stuff to the Main.Test project we have to add an item at the bottom of the AssemblyInfo.cs class (in Main, not Main.Test) which looks similar to this:
(Note: Names and Public Keys have been changed to protect the innocent, and semi-innocent)
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Main.Test, PublicKey=1028000004800030940000100602000000240000525341310004
0000010001001312297cb7c20cfb40f4efef6e5e96dcf84fa46db61b43b2bf65cf
49d547d6a5f14ef07f54d6313b39b10ae631e158748b39e2ab4c816b0753f2a
432160dddf06a1a7170d7ab6e4df081784da7a08b37a3a8a47b722ed6cf6c1c
f6896bc709f805a8087a758156171b7deb74a2ded23ce55688f9b2a67bfeedf1
081496da76f4")]
Now you may be thinking to yourself: "That's great bob, but how in the hell did you get this value for the public key in the first place?"
Good question! Here is the answer:
1. Open a visual studio command prompt and enter this command:
(This is using Visual Studio 2008)
C:\Program Files\Microsoft Visual Studio 9.0\VC>sn -p "[RestOfPath]\Main.Test\MainProjectStrongNameKey.snk" "[RestOfPath]\Main.Test\MainProjectStrongNameKey.publickey"
2. You should then get a message that says "Public key written blah blah blah".
3. Now in the same command window, enter this command:
C:\Program Files\Microsoft Visual Studio 9.0\VC>sn -tp "[RestOfPath]\Main.Test\MainProjectStrongNameKey.publickey"
Now the command line should spit out the long public key, which you can then use like I did above. Now you can test your internal members in the Main project from the Main.Test project
Happy testing!
Thursday, October 22, 2009
Today I got the following error when working with the Linq to Sql dbml file:
"System.InvalidOperationException: Incorrect AutoSync specification for member 'xxxxx'."
The problem involved the primary key "NationId" in the following image:
When you right-click on NationId and select properties, you see this in the Properties window:
The problem is that the auto-sync property should be "OnInsert" instead of "Always". However, I have not figured out how to make "OnInsert" the default when the view/table is dropped on the designer. If anyone knows the answer to this please leave a comment, because as it stands now I will have to change this property every time I rebuild my dbml file.
Sunday, May 10, 2009
The ScatterViewItem is a very useful way to get the “surface feel” into your apps very quickly. However it is likely you will want to customize how your ScatterViewItem looks and reacts to user input. The following steps will help you customize it to your hearts content. This procedure could be applied generally to any other control as well.
1. Create a WPF application in Visual Studio, add a ScatterView and ScatterViewItem. Save the project.
2. Open project in Expression Blend.
3. Under Objects and Timeline, right click on the ScatterViewItem control, select Edit Control Parts (Template) -> Edit a Copy…
4. Give it a new name like ‘ScatterViewItem_Customized’ and click OK.
5. Save the project and return to VS. VS will prompt you to reload changed files.
6. Now you will have the entire default control template to modify to your hearts content.
When I first started learning Surface I quickly realized how to turn a WPF app into a surface app. Basically, I did a search and replace for each control in the WPF app that has a matching control in Surface such as Button and TextBox. By doing simple replacements I was able to get a surface app up and running quickly. However, I recently learned a way to really extend this method.
All you need to do is edit the control template for the particular WPF control (that doesn’t have a surface twin) and in the template convert all instances of Button into s:SurfaceButton, all instances of Slider into s:SurfaceSlider, and the Thumb into s:SurfaceThumb, etc.. Just make sure you change both the controls themselves, as well as the control styles (for instance, if the first control in the template is a <Button> and it has a <Button.Style>, so change this to <s:SurfaceButton> and <s:SurfaceButton.Style>).
See my previous blog post for a way to get at the entire default control template for editing.
I tried my first attempt at running an application in user mode yesterday and learned a couple of things. You can find both of these things in the documentation, but who actually reads the docs? If you want to test out an application in user mode, but don’t feel like going through creating and copying the xml file to the proper folder, there is a way around this. I copied the exe file into the “T” users Documents folder (anywhere else would work to). Then I clicked on the “Enter User Mode” shortcut which you have on an administrator account. Once you have been switched over to user mode then hit “Ctrl-Shift-Esc.” At this point you will see the task manager, which will allow you to browse to and start the exe you saved earlier. Simply hit Ctrl-Alt-Del to get back to Admin mode. If you try to switch to user mode and you get an error message that says something like “object is in an incorrect state” (or something like that, I can’t remember it exactly). You probably changed your table user account password. To fix this problem you need to use SurfUser.exe. Change the directory in your command line to the folder containing the surfuser.exe executable and run the surfuser regen command. The surfuser app will regenerate and register that new password with the system for the default table user account. You can change the default password for the table user account, but you must use the surfuser app to do this. The docs will tell you how to go about this.
P.S. Don’t forget to make sure the bios on your surface unit is updated to the latest version which at the time of this writing is 0206. See “BIOS updates for a microsoft surface unit” in the SDK docs for further details.
Last week I needed to completely reset my surface unit back to factory settings due to erratic behavior (mostly in VS 2008). I followed the docs on the process Microsoft released in their SDK, but I had a couple of hiccups I thought I would share with you.
1. When you restart your surface you will want to hit your delete key once a second when the bios screen appears. Then when that screen changes you will want to hit F8. For some reason I had difficulty timing these key strokes.
2. you will need to switch from the X: drive to the C: drive to run the recovery.cmd command. Believe it or not, I tried cd C:\ to switch drives. I haven’t needed to switch drives in a long time in a command window. The proper way to switch drives is to type in just C:\ without the cd part. How embarrassing.
3. I know some threads on the Surface forum suggest that you might need a “secret” password to do this (maybe I misread them), however I found out from Josh (Surface guy at Microsoft who really knows his stuff) that this password is only needed for more advanced bios stuff. He didn’t detail what that was exactly, but restoring my surface unit wasn’t one of them.
Other than these hiccups the restore went quite smooth and relatively quickly if you follow the docs Microsoft provides.
I have found myself converting WPF apps to Surface apps quite often lately. Most of the necessary changes are fairly obvious, but I encountered one lately I thought I would share with you. In WPF apps there is functionality to capture the mouse cursor, but in Surface we have no mouse. So we need to perform the analogous catch of a finger (or whatever else you like) contact. Below is the first method I needed to change in a recent project:
private void OnMouseDown(object sender, MouseButtonEventArgs args)
{
UIElement source = sender as UIElement;
Point p = args.GetPosition(source);
if (a boolean)
{
this.CaptureMouse();
}
else
return;
}
By the way, “this” is a ContentControl. Notice the this.CaptureMouse() line? Clearly this needs to change for surface. There is no this.CaptureFinger() on a SurfaceContentControl (that would be way too easy). So I modified the above code to the following:
private void SurfaceContentControl_ContactDown(object sender, ContactEventArgs e)
{
UIElement source = sender as UIElement;
Point p = e.GetPosition(source);
if (a boolean)
{
e.Contact.Capture(this);
}
else
return;
}
So in this case I switched:
this.CaptureMouse();
for this:
e.Contact.Capture(this);
That was easy enough. Let’s try another.
private void OnMouseMove(object sender, MouseEventArgs args)
{
UIElement source = sender as UIElement;
Point p = args.GetPosition(source);
if (!(sender as UIElement).IsMouseCaptured)
{
//Do some stuff
}
}
Which I changed to:
private void SurfaceContentControl_ContactChanged(object sender, ContactEventArgs e)
{
UIElement source = sender as UIElement;
Point p = e.GetPosition(source);
if ((sender as UIElement) != e.Contact.Captured)
{
//Do some stuff
}
}
So in this case I changed:
if (!(sender as UIElement).IsMouseCaptured)
into this:
if ((sender as UIElement) != e.Contact.Captured)
We’re on a roll here, let’s do another:
private void OnMouseUp(object sender, MouseButtonEventArgs args)
{
if (this.IsMouseCaptured)
{
UIElement source = sender as UIElement;
Point p = args.GetPosition(source);
if (a boolean)
//Do something
this.ReleaseMouseCapture();
}
}
Turns into this:
private void SurfaceContentControl_ContactUp(object sender, ContactEventArgs e)
{
if (this.IsAnyContactCaptured)
{
UIElement source = sender as UIElement;
Point p = e.GetPosition(source);
if (a boolean)
//Do something
this.ReleaseAllContactCaptures();
}
}
Now you know how to change mouse capture logic in old WPF apps into new finger capture logic. Please feel free to comment if you know how I could improve this.
After months of development I finally got around to packaging up my app for deployment in user mode on the Surface. I did run into a couple of minor hurdles at first which I will share with you, and tell you how I got around them. First of all, check out the documentation on the Microsoft Surface community site and the SDK. In your root app directory you will see a file like myapp.xml which is generated by visual studio for you.
The following code example shows the default XML file.
<?xml version="1.0" encoding="utf-8" ?>
<ss:ApplicationInfo
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ss="http://schemas.microsoft.com/Surface/2007/ApplicationMetadata">
<Application>
<Title>SurfaceApplication</Title>
<Description>SurfaceApplication</Description>
<ExecutableFile>SurfaceApplication.exe</ExecutableFile>
<Arguments></Arguments>
<IconImageFile>Resources\icon.png</IconImageFile>
<Preview>
<PreviewImageFile>Resources\iconPreview.png</PreviewImageFile>
</Preview>
</Application>
</ss:ApplicationInfo>
Notice in the <ExecutableFile> element, how it has “SurfaceApplication.exe” as the value?
It should really look like this:
%ProgramFiles%\Microsoft Surface\SurfaceApplication\SurfaceApplication.exe
The urls in your other elements like the previewIcon should follow the same format. Hopefully, this helps some people out.