How do I disable an add-in in Word?
Word has a disabled add-ins function (Help | About | Disabled Items).
How do I add an add-in to the disabled list without having to crash the add-in and wait for the error to come up?
Solution 1:
I was trying to figure out the binary format of the values in the DisabledItems key myself and your post here got me on the right track. I however think the format is a bit different from how you see it, at least in Office 2010.
As far as I can tell the format is like this:
-
The first four bytes are a 32-bit integer. It usually seems to have the value 1. I'm not sure what purpose it has.
-
The next four bytes are a 32-bit integer that tells us the length of the dll path in bytes, including the terminating character (null or 0x0000).
-
The next four bytes are a 32-bit integer that tells us the length of the friendly name in bytes, including the terminating character (null or 0x0000).
-
The next sequence of bytes is a null-terminated big-endian unicode string containing the path to the add-in dll. For some reason this path always seems to contain only lowercase characters.
-
The next sequence of bytes is a null-terminated big-endian unicode string containing the friendly name of the add-in.
I've been able to successfully hard-disable an add-in using the following C# code:
string path = "<full path to add-in dll>".ToLower();
string friendlyName = "<add-in friendly name>";
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(1); // type of disabled item : 1 => Add in / 2 => Document / 3 => Task pane
writer.Write((path.Length * 2) + 2); // Path length, 2 bytes per character
writer.Write((friendlyName.Length * 2) + 2); // Friendly name length
writer.Write(Encoding.Unicode.GetBytes(path)); // Path
writer.Write(Convert.ToInt16(0)); // null terminator
writer.Write(Encoding.Unicode.GetBytes(friendlyName)); // Friendly name
writer.Write(Convert.ToInt16(0)); // null terminator
writer.Close();
// Version numbers: 11.0 = Office 2003, 12.0 = Office 2007, 14.0 = Office 2010
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\14.0\Word\Resiliency\DisabledItems", true);
key.SetValue("63CB962", stream.ToArray(), RegistryValueKind.Binary);
key.Close();
A similar approach can be used to decode the dll path of an existing value like so:
// Let 'bytes' be a byte array containing the binary registry value
BinaryReader binaryReader = new BinaryReader(new MemoryStream(bytes));
binaryReader.ReadInt32(); // Read the first four bytes and ignore
int pathLength = binaryReader.ReadInt32(); // The next four bytes are the length of the path
binaryReader.Close();
if (bytes.Length >= 12 + pathLength)
{
string path = Encoding.Unicode.GetString(bytes, 12, pathLength - 2);
}
Solution 2:
Answering my own question.
It's in the registry, under HKCU\Software\Microsoft\Office[version]>\Word\Resiliency\DisabledItems (where [version] is 10.0 for XP, 11.0 for 2003 and 12.0 for 2007).
The keys are Binary keys with names of six (random, as far as I can tell) hex characters.
The value is: 01,00,00,00,x,00,00,00,y,[path],00,00,[name],00,00,00 x is the number of bytes in the path (including the two terminator bytes) and y is the number of bytes in the name (which a "friendly name"). x+y should be the total number of bytes minus ten. x and y are both in hex. I assume that they are actually DWORDs, but I've only ever needed the LSB.
The path is encoded in UCS-2, little-endian, so to give an example, "c:\" is 00,63,00,3a,00,5c
Yes, the binary encoding seems to be the awesomely brilliant encoding of "Take a null terminated ASCII string, translate to Unicode, then take the bytes of that and null-terminate the result"
Note that x and y are counts of bytes, not characters; there are 2 bytes per character in UCS-2.
If you want to block a template (ie a .dot rather than a .dll) then put 00 for y and skip the name element, and the termination (so it ends with three null bytes, not five).
Solution 3:
Note that Eirikur's code works only if the Resiliency\DisabledItems subkey is in place. It looks like Word will add/remove this entire subkey when it disables/enables. So, if you get an exception running the code, you probably need to add the subkey first.
(My post here should probably get moderated, it belongs as a comment but I don't have enough points! Bad start)