英文:
Why does schtasks not recognize XML syntax?
问题
<?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>
英文:
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>
答案1
得分: 1
我认为此MSDN页面可以提供有价值的信息来解决您的问题。
正如您也指出的,该帖子表明问题与您的XML文件的编码有关(请参阅最新答案):
尽管任务计划程序将任务文件导出为UTF-16编码,但除非它是UTF-8,否则它将拒绝读取它。使用诸如TextPad或Notepad++之类的文本编辑器将XML另存为UTF-8编码文件,任务计划程序将正确地导入它(即使主XML标记显示encoding="UTF-16")。
在您的代码中,您正在指示UTF-16
作为期望的输出编码。在我的macOS机器上,使用该配置Transformer
将生成一个UTF-16大端序的文件。
如上述帖子中所述,此编码似乎不受支持:
是的,这些编码与schtasks导入xml文件配合使用(编码方式与
Notepad
中命名的方式相同):Unicode Ansi可以使用,而Unicode大端序和UTF-8则不行。
不幸的是,这个最后的答案没有提供太多帮助。请参阅此帖子。
然而,您可以尝试修改您的程序以输出UTF-8
。
要做到这一点,显然,您只需要在您的代码中更改这一行:
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
不幸的是,这也可能会有些棘手。
如果这是您的情况,您可以尝试类似于以下的操作:
String taskName = "taskname";
File f = new File("C:\\Users\\Cardinal System\\Desktop\\TaskScheduler.exe");
File f2 = new File("C:\\Users\\Cardinal System\\Desktop\\input.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(f2); // f2是XML文件
Node n = document.getElementsByTagName("Command").item(0);
// f是此任务将执行的目标可执行文件
n.setTextContent("\"" + f.getAbsolutePath() + "\"");
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
File fout = new File("/Users/jccampanero/Desktop/output.xml");
Writer out = null;
try {
out = new OutputStreamWriter(new FileOutputStream(fout), Charset.forName("UTF-8"));
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
Source input = new DOMSource(document);
Result output = new StreamResult(out);
transformer.transform(input, output);
out.flush();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "schtasks", "/Create", "/TN", taskName, "/XML",
"\"" + fout.getAbsolutePath() + "\"");
Process p = builder.start();
如果这也不起作用,您可以尝试使用不同的编码,例如您机器上的默认编码,或者为您的document
尝试不同的序列化方法:
Writer writer = new FileWriter("C:\\Users\\Cardinal System\\Desktop\\output.xml");
XMLSerializer xml = new XMLSerializer(writer, null);
xml.serialize(document);
请注意,这段代码使用了FileWriter
,而FileWriter
将会将默认字符编码应用于您的XML。有关更多信息,请参阅此Stack Overflow问题。
因此,我最好的猜测是,无论如何都会通过应用您机器的默认编码来解决问题。
英文:
I think this MSDN page can provide valuable information to solve your problem.
As you also indicated, that post suggests that the problem is related to the encoding of your XML file (see the latest answers):
> Even though the Task Scheduler exports a task file as UTF-16 encoded, it refuses to read it unless it's UTF-8. Use a text editor like TextPad or Notepad++ to save the XML as a UTF-8 encoded file, and the Task Scheduler will correctly import it (even if the main XML tag shows encoding="UTF-16").
In your code, you are indicating UTF-16
as the desired output encoding. In my machine, with macOS, with that configuration the Transformer
will generate a file in UTF-16 Big Endian.
As stated in the post mentioned above, this encoding appears to be unsupported:
> Yes, these encodings work with schtasks import xml files (encodings as Notepad
names them): Unicode Ansi, and these do not: Unicode big endian, UTF-8
Unfortunately, this last answer doesn't provide much help. See this post.
Nevertheless, you can try and modify your program to output UTF-8
.
To do that, apparently, you would just need to change this line in your code:
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
Unfortunately, again, it could also be tricky.
If that is your case, you can try something like:
String taskName = "taskname";
File f = new File("C:\\Users\\Cardinal System\\Desktop\\TaskScheduler.exe");
File f2 = new File("C:\\Users\\Cardinal System\\Desktop\\input.xml");
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-8");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
File fout = new File("/Users/jccampanero/Desktop/output.xml");
Writer out = null;
try {
out = new OutputStreamWriter(new FileOutputStream(fout), Charset.forName("UTF-8"));
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
Source input = new DOMSource(document);
Result output = new StreamResult(out);
transformer.transform(input, output);
out.flush();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "schtasks", "/Create", "/TN", taskName, "/XML",
"\"" + fout.getAbsolutePath() + "\"");
Process p = builder.start();
If it doesn't work either, you can try a different encoding, like the default on your machine, or a different serialization approach for your document
:
Writer writer = new FileWriter("C:\\Users\\Cardinal System\\Desktop\\output.xml");
XMLSerializer xml = new XMLSerializer(writer, null);
xml.serialize(document);
Please, be aware that under the hood this code snippet uses FileWriter
which in turn will apply the default character encoding to your XML. Please, see this stack overflow question for more information.
So my best guest is that probably applying your machine's default encoding one way or another will do the trick.
答案2
得分: 1
我曾经遇到类似的问题,并发现SCHTASKS
只尊重它认为是“正确的”编码:ANSI和UTF16小尾。无论xmllint
说什么都无关紧要。
无论您在encoding=<your encoding>
中放入什么,都不会使SCHTASKS
接受UTF8(带或不带BOM)、UTF-16大尾或任何其他编码,除了它的两种首选编码。
两种解决方法:
- 如果只有ANSI字符,请删除编码属性(然后使用记事本将其保存为ANSI)
- 将其保存为UTF-16 LE,并将编码设置为“UTF-16”。
英文:
I had a similar issue, and found that SCHTASKS
does not respect any encoding apart from what it deems are the "right ones": ANSI and UTF16 Little Endian. It does not matter if xmllint
says it's OK.
It does not matter what you put into encoding=<your encoding>
, nothing will make SCHTASKS
accept UTF8 with or without BOM, UTF-16 Big Endian or anything else than its two preferred encodings.
Two fixes:
- remove the encoding attribute if you only have ANSI characters (and just save it as ANSI using Notepad)
- save it as UTF-16 LE and set the encoding to "UTF-16".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论