Monday, March 22, 2010

Windows Phone 7 Application Bar Templates

I created templates for the Application Bar images for myself and I'm sharing them in case they would be useful to anyone else. Here are the PSD and PNGs:
The PSD is broken up into layers so you can easily hide the template to save off your icon. Just stay within the white square on either template (inner 26x26) and you should be good to go.

http://cid-27c22899419e6236.skydrive.live.com/self.aspx/.Public/AppBarIconTemplate.png
http://cid-27c22899419e6236.skydrive.live.com/self.aspx/.Public/AppBarIconTemplate.psd

Boxee Launcher

Started another new Codeplex project: http://boxeelauncher.codeplex.com/

This is the sibling of Hulu Launcher. Boxee Launcher is a simple Windows Media Center add-in that attempts to launch Boxee and manage the windows as seamlessly as possible.

Monday, March 15, 2010

Hulu Launcher

Started a new Codeplex project: http://hululauncher.codeplex.com/
Hulu Launcher is a simple Windows Media Center add-in that attempts to launch Hulu Desktop and manage the windows as seamlessly as possible.

Check it out if you're into that sort of thing.

Friday, March 5, 2010

How to Create and Modify ClickOnce Manifests

Working with ClickOnce manifests can be a pain, especially if you need to integrate that work into your build process. There are several tools you can work with and potentially automate.
  1. mage.exe - This is the backing process behind mage.ui. In my opinion, mage.exe is the next step up from the "Publish" tab in Visual Studio -- it works, but only for basic cases. Comes with the .NET SDK.
  2. mt.exe - This is a great little tool that can validate, sign, and update the hashes in your manifests. It can also merge manifests and dump manifests from executables, as well as extract COM information to generate your own Reg-Free COM information (better than the Visual Studio build process does, actually -- most of our Reg-Free COM manifests are manually built with mt.exe).
  3. Microsoft.Build.Tasks.Deployment.ManifestUtilities - This namespace is a god-send, although it doesn't work with VSTO deployment manifests (in fact, it will probably mangle them). I believe the Visual Studio build process uses these classes internally, but I'm not sure. You can use this to modify application and deployment manifests in just about any way imaginable. To get access to this, add a reference to the Microsoft.Build.Tasks assembly. 

    To read a manifest using this, start at ManifestReader.ReadManifest(path) and work from there.
    To sign your manifests (or other files) from code, take a look at SecurityUtilities.SignFile(certThumbprint, timestampUrl, path)

Saturday, February 27, 2010

{x:Static} Replacement in Silverlight


So, there's no {x:Static} in Silverlight. That kind of sucks. I wrote this value converter to try to get around that. Unlike {x:Static}, you should put the whole path in the Source and avoid using the Binding.Path property. The converter should parse everything as needed. The code below doesn't support indexers of any kind, but it wouldn't be too hard to add.

You can use it in your XAML like this:
<local:BlockContainer Blocks="{Binding Source=Cubus.Game.CubusGame.Current.CurrentPlayer.Blocks, Converter={StaticResource static}}"/>

Here's the class. My apologies for the formatting.
 
public class StaticConverter : IValueConverter
{
#region IValueConverter Members

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value is string))
{
throw new ArgumentException("Value must be of type string.");
}

try
{
string staticValue = (string)value;

// First we need to find the type
string typeName = null;
Type type = null;
int periodIndex = 0;
int lastPeriodIndex = staticValue.LastIndexOf(".");

while (type == null && periodIndex < lastPeriodIndex)
{
periodIndex = staticValue.IndexOf(".", periodIndex + 1);
typeName = staticValue.Substring(0, periodIndex);

// This bizarre block of code is how you enumerate through
// loaded assemblies in Silverlight. Normally you'd use
// AppDomain.Current.GetAssemblies() or something like that.
foreach (AssemblyPart ap in Deployment.Current.Parts)
{
System.Windows.Resources.StreamResourceInfo sri = Application.GetResourceStream(new Uri(ap.Source, UriKind.Relative));
System.Reflection.Assembly assembly = new AssemblyPart().Load(sri.Stream);
type = assembly.GetType(typeName);

if (type != null)
{
break;
}
}
}

if (type == null)
{
throw new NullReferenceException(string.Format("No type was found matching the name {0}.", typeName));
}

// Now let's find the value.
// After the type name, the first part of the path
// should be a static member. After that, the rest
// should be instance members.

object workingValue = null;
Type workingType = type;
string[] path = staticValue.Substring(periodIndex + 1, staticValue.Length - (periodIndex + 1))
.Split(new string[] { "." }, StringSplitOptions.None);

for (int i = 0; i < path.Length; i++)
{
BindingFlags flags;
if (i == 0)
{
flags = (BindingFlags.Static | BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.Public);
}
else
{
flags = (BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.Public);
}

PropertyInfo propInfo = workingType.GetProperty(path[i], flags);
if (propInfo != null)
{
workingValue = propInfo.GetValue(workingValue, null);
}
else
{
FieldInfo fieldInfo = workingType.GetField(path[i], flags);
if (fieldInfo != null)
{
workingValue = fieldInfo.GetValue(workingValue);
}
else
{
throw new NullReferenceException(string.Format("No properties or fields were found matching the name {0}.", path[i]));
}
}

workingType = workingValue.GetType();
}

return workingValue;
}
catch
{
if (DesignerProperties.GetIsInDesignMode(new UserControl()))
{
return DependencyProperty.UnsetValue;
}
else
{
throw;
}
}
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}

#endregion
}

Things in WPF that I wish were in Silverlight

  • {x:Static}
  • MultiBinding
  • Custom markup extensions
  • PropertyMetadata overrides
  • Adorners
  • Faster hit-testing
  • The Mouse class, being able to check mouse state without setting flags all over the place.

Reg-Free COM in VSTO Applications, Part 2

A simple test did have us using the Activation Context API to load a COM object in Word, however we never could get it working with a more advanced solution, such as ActiveX controls. The results of the basic test show that this should be possible, but for now this is on the back-burner. Someone with a very advanced knowledge of manifests and SxS should be able to get this set up.

From a high-level view, there are two things you need to do:
  1. P/Invoke the Activation Context API, and use it to load the manifest that your reg-free COM information is in (usually it's Native.[assemblyname].manifest) during the startup of your VSTO add-in.
  2. The VSTO build process will not include your Native.[assemblyname].manifest in the Application Manifest, so you'll have to add it yourself. Since I wrote it at work I can't share our method, but we ended up creating a command-line tool that runs as a post-build step and manually adds the file reference using XmlDocument, and re-hashes and re-signs everything.