I am trying to import a scheduled task XML into the Windows Task Scheduler by executing schtasks from Java. Before my program runs the schtasks command, it inserts a file path in the <Command>
element. The task scheduler command works before I edit the XML, but not afterwards. It keeps giving me the same error:
ERROR: The task XML is malformed.
(1,2)::ERROR: incorrect document syntax
Interestingly enough, taskschd.msc
imports my task with no trouble. It's only schtasks that is giving me trouble. If I manually enter the file path using the taskschd.msc and then export it, it perfectly matches the XML my program outputs, but schtasks accepts it. This makes me believe that it has something to do with the file encoding. That being said, I encode the file with the same UTF-16 format that taskschd.msc produces, so I also suspect it may have something to do with the way the javax.xml
library processes documents. I poked around the internet for some answers, but the only results I could find were for flawed powershell scripts and actually malformed XML documents. So what exactly is causing this problem and how can I fix it?
This is how my program is editing the XML document and executing schtasks:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(f2); // f2 is the XML file
Node n = document.getElementsByTagName("Command").item(0);
// f is the target executable that this task will execute
n.setTextContent("\"" + f.getAbsolutePath() + "\"");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-16");
Result output = new StreamResult(f2);
Source input = new DOMSource(document);
transformer.transform(input, output);
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "schtasks", "/Create", "/TN", taskName, "/XML",
"\"" + f2.getAbsolutePath() + "\"");
Process p = builder.start();
And here is the final XML file that is passed to schtasks:
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task" version="1.2">
<RegistrationInfo>
<Date>2020-09-11T16:33:30</Date>
<Author>CardinalSystem</Author>
<URI>\LOTHStartupScheduler</URI>
</RegistrationInfo>
<Triggers>
<LogonTrigger>
<StartBoundary>2020-09-11T16:33:00</StartBoundary>
<Enabled>true</Enabled>
</LogonTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<GroupId>S-1-5-32-545</GroupId>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>"C:\Users\Cardinal System\Desktop\TaskScheduler.exe"</Command>
<Arguments>-startup 1</Arguments>
</Exec>
</Actions>
</Task>