0

向 Windows 批处理脚本向导请求一些魔法......:D

出于比赛目的,我的团队成员使用BoincTasks在完成 99% 时自动暂停 Boinc 工作单元,因此他们可以在开始日期后恢复它们,从而在短时间内发送大量结果。不幸的是,BoincTasks 可以自动挂起任务,但不能自动恢复它们。所以:如果用户不能在某个日期/时间留在计算机前手动恢复任务,最好有一个 Windows 批处理脚本能够完成这项工作,由 Windows 调度程序触发。

Boinc 使用(假).XML 文件来跟踪他管理的任何任务。通常,您会在此处找到它:C:\ProgramData\BOINC\client_state.xml

这是其中有趣的部分(完整文件为 368k):

<active_task>
   <project_master_url>http://asteroidsathome.net/boinc/</project_master_url>
   <result_name>ps_170405_input_161867_8_1</result_name>
   <active_task_state>1</active_task_state>
   ...
</active_task>

每个任务都有一个“active_task”标签。暂停的任务将“active_task_state”子标签设置为“0”。

Boinc 有一个命令行可执行文件,可以恢复单个任务,假设您知道一些参数。这是一个例子:

boinccmd --task [project_master_url] [result_name] resume

所以,我想编写一个批处理脚本,能够从选定的“project_master_url”恢复挂起的任务。这是理想的场景:我想从“asteroidsathome”Boinc 项目中恢复所有任务(参见上面代码中的 url)。

  1. 打开并解析 "C:\ProgramData\BOINC\client_state.xml" ;
  2. "project_master_url"=="the project url"找到所有具有AND的“active_task”分支"active_task_state"==0
  3. 对于每个任务,执行命令行,如上所述。

我很习惯 Linux .sh 和 PHP 脚本,但我只是不明白如何在 Windows 批处理中获得相同的结果。我已经找到了如何使用以下方法解析 XML:从批处理中解析 xml ......但是“过滤/将提取的数据扔到命令行”过程仍然是一个谜 :(

一些咒语可以施展吗?感谢:D

4

1 回答 1

0

好的。我设法做到了......它有效:) 我很确定有很大的改进空间。随意提出一个更好的方法来做到这一点

@echo off
setlocal enableextensions EnableDelayedExpansion

rem Settings
rem ==============================================================
rem Defines the url of the project we want the tasks to be resumed
set ResumeProjectUrl=https://wuprop.boinc-af.org/
rem ==============================================================
rem Defines the path to the client_state.xml Boinc file
set ClientStateFile=%ProgramData%\BOINC\client_state.xml
rem Defines the path to the boinccmd.exe
set BoincCmdFile=%ProgramFiles%\BOINC\boinccmd.exe

rem This is real content, extracted from client_state.xml
rem (useful to have a quick reference)
rem    <project_master_url>https://wuprop.boinc-af.org/</project_master_url>
rem    <result_name>data_collect_v4_1490525102_609550_0</result_name>
rem    <active_task_state>1</active_task_state>

rem Find the lines that contains a specific string... "project_master_url" seems OK (1st line in the above example)
for /f "delims=:" %%I in ('findstr.exe /I /L /N /C:"project_master_url" "%ClientStateFile%" 2^>nul') do (

    rem assign variables :
    rem a is the first line number, containing <project_master_url>value</project_master_url>
    rem b is the next line number, containing <result_name>value</result_name>
    rem c is the next line number, containing <active_task_state>value</active_task_state>
    set /a a=%%I
    set /a b=a+1
    set /a c=a+2

    rem As we want to resume only a specific project WUs, let's evaluate the url first
    rem read first line (a)
    for /f "tokens=1* delims=]" %%A in ('^<"%ClientStateFile%" FIND /N /V "" ^| FINDSTR /B /C:"[!a!]"') do (

        rem extract project_master_url value (between <tag></tag>)
        rem %%a is opening tag, %%b is the value, %%c is closing tag
        for /f  "tokens=2-4delims=<>" %%a in ("%%B") do (

            rem Let's compare the project_master_url value and the desired url (in Settings)
            if "%ResumeProjectUrl%"=="%%b" (

                rem If values are the same let's find if <active_task_state> is 0 (suspended)
                rem Read third line (c)
                for /f "tokens=1* delims=]" %%A in ('^<"%ClientStateFile%" FIND /N /V "" ^| FINDSTR /B /C:"[!c!]"') do (

                    rem extract active_task value (between <tag></tag>)
                    rem %%a is opening tag, %%b is the value, %%c is closing tag
                    for /f  "tokens=2-4delims=<>" %%a in ("%%B") do (

                        rem Value is 0 (suspended)
                        if "%%b"=="0" (

                            rem Read second line (b)
                            for /f "tokens=1* delims=]" %%A in ('^<"%ClientStateFile%" FIND /N /V "" ^| FINDSTR /B /C:"[!b!]"') do (

                                rem extract result_name value (between <tag></tag>)
                                rem %%a is opening tag, %%b is the value, %%c is closing tag
                                for /f  "tokens=2-4delims=<>" %%a in ("%%B") do (

                                    rem let's call the boinccmd executable to resume the task
                                    start "Resuming" /B "%BoincCmdFile%" --task %ResumeProjectUrl% %%b resume
                                )
                            )
                        )
rem                     if "%%b" NEQ "0" (
rem                         echo "Good project, but the task is active"
rem                     )
                    )
                )
            )
rem         if "%ResumeProjectUrl%" NEQ "%%b" (
rem             echo "Other project"
rem         )
        )
    )

    rem clear variables
    set a=
    set b=
    set c=

)
endlocal
于 2017-04-22T09:24:13.283 回答