If I manually edit %appdata%\Notepad++\shortcuts.xml
and manually add a find replace macro (See MACRO below), then close shortcuts.xml and then restart Notepad++, the macro is available to run from the Macro Menu button:
I wrote a program that programmatically edits shortcuts.xml and inserts the very same macro. Notepad++ is not up when I run my program. I know my program is working based on diffing copies of manually modified and programmatically modified shortcuts.xml files. However, when I restart Notepad++ after running my program, the Macro button is "dead", i.e., all macros, although present in shortcuts.xml, disappear from the Macro button.
Is Notepad++ somehow sensitive to its shortcuts.xml file being programmatically manipulated?
MACRO Screenshot (text version follows)
Text Version
<Macro name="Redactor" Ctrl="no" Alt="no" Shift="no" Key="0">
<Action type="0" message="2422" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2325" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="(?:[0-9]{1,3}\.){3}[0-9]{1,3}" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1602" wParam="0" lParam="0" sParam="IP-Placeholder" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1609" sParam="" />
<Action type="0" message="2422" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2325" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1602" wParam="0" lParam="0" sParam="email-placeholder" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1609" sParam="" />
</Macro>
It's working now.
My original (non-working) code did this:
// shortcuts.xml is encoded UTF-8, no BOMs
string shortCutsXmlFilepath = Path.Combine($"{System.Environment.GetEnvironmentVariable("APPDATA")}\\NotePad++", "shortcuts.xml");
XDocument shortCutsXmlDocument = XDocument.Load(shortCutsXmlFilepath);
// manipulate xDocument elements .......
shortCutsXmlDocument.Save(shortCutsXmlFilepath);
The result was that shortcuts.xml had UTF-8 byte order marks (BOM) inserted (EF BB BF
) at the beginning of the file. When I next executed Notepad++ and it read shortcuts.xml, it silently failed to read shortcuts.xml and so no macros were displayed under the Macro menu button.
The Fix
The fix is to read shortcuts.xml using a StreamReader
and write it using a StreamWriter
. I explicitly asserted the 'no BOM' option in both so that there's no chance of the saved version of shortcuts.xml having the BOMs inserted (the 'no BOM' option is the default).
Note: To enable BOM, use new UTF8Encoding(true)
instead.
XDocument shortCutsXmlDocument = LoadNotepadPpShortcutsXmlDocument();
// manipulate xDocument elements .......
SaveNotepadPpShortcutsXmlDocument(shortCutsXmlDocument);
//
//
//
private static XDocument LoadNotepadPpShortcutsXmlDocument()
{
string shortCutsXmlFilepath = Path.Combine($"{System.Environment.GetEnvironmentVariable("APPDATA")}\\NotePad++", "shortcuts.xml");
if (File.Exists(shortCutsXmlFilepath) == false)
{
MessageBox.Show($"Can't find '{shortCutsXmlFilepath}'");
Application.Exit();
}
XDocument xDocument = new XDocument();
using (StreamReader stream = new StreamReader(path: shortCutsXmlFilepath, new UTF8Encoding(false)))
{
xDocument = XDocument.Load(stream);
}
return (xDocument);
}
private static XDocument SaveNotepadPpShortcutsXmlDocument(XDocument document)
{
string shortCutsXmlFilepath = Path.Combine($"{System.Environment.GetEnvironmentVariable("APPDATA")}\\NotePad++", "shortcuts.xml");
//todo Verify that Path.Combine($"{System.Environment.GetEnvironmentVariable("APPDATA")}", "\\NotePad++") exists before writing shortcuts.xml
using (StreamWriter stream = new StreamWriter(shortCutsXmlFilepath, append: false, new UTF8Encoding(false)))
{
document.Save(stream);
}
return (document);
}