Mar 26, 2009

Have you ever tried to change the default icon used on a VSNET Addin project? (Updated)

That icon is embedded in hexadecimal in the .Addin xml file.

<AboutIconData>000001000200101010000000040028010000260000002020100000000400E80200004E0100002800000010000000200000000100040000000000C0000000000000000000000000000000000000000000000000008000008000000080800080000000800080008080000080808000C0C0C0000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF000000000000000000007FFF8FF8FF8F00007FFF8FF8FF8F000078888888888800007F778778778F00007F778778778F000078888888888800007F778778778F00007F778778778F000078888888888800007F778778778F00007F778778778F000078888888800000007FFF8FF8F7F700007FFF8FF8F770000077777777770000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0010000C0030000C0070000C00F0000280000002000000040000000010004000000000000020000000000000000000010000000100000000000000000008000008000000080800080000000800080008080000080808000C0C0C0000000FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220022B2222B2022B2022B02222B22B022022B22022B2022B2022B22000022B022022B22022B2022B2022B22000022B02222B022022B2022B2022B22222B222B22022B22022B2022B2022B22022B222222022B22022B222B0222B00222B0220222022B000000000000000000000000002222B000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000555555555555555555555555555555555555555555555555555555555555555500000000000000000000000000000000055000055005555500550055055005500550005550550005505500550550550005500555505500055055005505505500055055055055000550550055055055000550550550550005505500550550550005555005505500055055555005505550055500055055000550000000000055000550000550550005500000000550550000000000000000000000000000000000555555555555555555555555555555555555555555555555555555555555555500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF30042201208420F1208420F104842000208420802080861223FFFFFF07FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000FFFFFFFF9E60CC999C4E4C93984E4C93924E4C93924E4C93864E41918E4E7FF39E4E7F93FFFFFFFF0000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF</AboutIconData>


I've found some people discussing ways to do that.
Someone talked about an alternate undocumented tag to put a reference but it didn't work, but another one really offered me the missing and useful information that the blob there in the xml is just the .ico file in hex form.

Problem is that I wanted to make it an automatic thing: edit the .ico file, build the project and voilá! the new icon shows when you select your rebuilt addin in the test VSNET instance "About" dialog.

So first I've coded this small utility program:


using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;

namespace IconHexer
{
class Program
{
static void Main(string[] args)
{
try {
if (args.Length >= 1) {
string icoFile = args[0];
if (File.Exists(icoFile)) {
StringBuilder builder = new StringBuilder();
byte[] data = File.ReadAllBytes(icoFile);
for (int i = 0; i < data.Length; i++)
builder.Append(data[i].ToString("X2"));
string hexedIcon = builder.ToString();
if (args.Length < 2)
Console.WriteLine(hexedIcon);
else
for (int j = 1; j < args.Length; j++) {
string addinFile = args[j];
if (File.Exists(addinFile)) {
string addinBackupFile = addinFile + ".backup";
string xml = File.ReadAllText(addinFile, Encoding.Unicode);
int start = xml.IndexOf("<AboutIconData>");
int end = xml.IndexOf("</AboutIconData>");
if (end > start && start > 0) {
xml = xml.Substring(0, start + "<AboutIconData>".Length)
+ hexedIcon
+ xml.Substring(end);
if (File.Exists(addinBackupFile))
File.Delete(addinBackupFile);
File.Move(addinFile, addinBackupFile);
File.WriteAllText(addinFile, xml, Encoding.Unicode);
Console.WriteLine("File '{0}' updated (backuped at '{1}')", addinFile, addinBackupFile);
}
} else {
ShowError("Addin file '{0}' doesn't exist", addinFile);
}
}
} else {
ShowError("Icon file '{0}' doesn't exist", icoFile);
}
} else {
ShowError("Please use '{0} pathToIcoFile [pathToAddinFile]'", Path.GetFileName(Assembly.GetEntryAssembly().Location));
}
} catch (Exception e) {
ShowError(e.ToString());
}
}

private static void ShowError(string format, params string[] parameters)
{
Console.Error.WriteLine("ERROR: " + format, parameters);
Environment.ExitCode = 1;
}
}
}

After building it as an exe tool in the solution I've tweaked the csproj for the Addin project to specially mark the two addin files:
<ItemGroup>
<Content Include="..\..\..\Addins\NUnitRunnerAddIn - For Testing.AddIn">
<Link>NUnitRunnerAddIn - For Testing.AddIn</Link>
<AddinFile>true</AddinFile>
</Content>
<EmbeddedResource Include="NUnitRunnerAddIn.ico" />
<Content Include="NUnitRunnerAddIn.AddIn">
<AddinFile>true</AddinFile>
</Content>
</ItemGroup>

and use them on a BeforeBuild target:
<Target Name="BeforeBuild">
<Message Importance="high" Text="Updating embedded icon on .Addin files"/>
<Exec
WorkingDirectory="$(ProjectDir)"
Command="&quot;$(SolutionDir)IconHexer\bin\$(ConfigurationName)\IconHexer&quot; &quot;$(ProjectDir)NUnitRunnerAddIn.ico&quot; &quot;%(Content.Identity)&quot;"
Condition="%(Content.AddinFile) == 'true'" />
</Target>

Last step is to put a build dependency on the tool project from the addin project, and edit the icon file (which path is hardcoded on the example above) and build the solution and run the addin and as expected the new icon is there in the VSNET about box as promised.

Hope it helps some other guy having to do that in the future...

Mar 20, 2009

TED Video - Kamal Meattle: How to grow your own fresh air

brings some interesting info about how to continuously renew the stock of this scarce resource "breathable air"

Some more info about Mr. Meattle:
http://www.technologyreview.com/read_article.aspx?id=17442

About the newest building he cites in the video:

Dear lazyweb: can you tell me where do I find the published papers he talks explaining more precisely the plants and proportions needed?

Kamal expands it a bit at:


but any more info is welcome. For instance, some blog I just scanned was talking about one of those plants being bad for cats, I have a dog so I would like to know the reasoning (the pros and cons) on plant selection, on a expanded view.

Well you got the gist of it, comments welcome