返回列表 发帖

[系统相关] [己解決]批处理命令 call 無法傳值?

本帖最后由 dreamer 于 2024-6-10 08:42 编辑

問題描述:下方批次檔是將Office 零售轉大量授權的工具,由於要自動化所以製作一個呼叫他的批次檔
Call "%~pd0C2R-R2V-AIO.cmd"
Echo %_msg%&Rem C2R-R2V-AIO檔的變數COPY
在C2R-R2V-AIO的1481行是離開批次的處理段落,有試著在1487行前加上
endlocal&Set _msg=%_msg%COPY
但卻沒有效果,這個問題困擾了我一週,最終還是沒有找到答案,目前推測可能是過多的exit /b 跟 goto 所以造成非預期的現象,但還是想了解真正的原因而不是推測,希望有高手能給出更合理的分析,謝謝。
這個問題目前暫時用doskey+findstr解決(思路是將結果放到doskey後再用findstr判斷結果是否為finished=Finished),由於代碼過長貼不下源代碼如下
來源:https://github.com/abbodi1406/C2R-R2V-AIO

脚本太复杂,没看明白意思,大概理了下退出的代码
第1是 104行之前 多个 goto :e_  后退出,这之前没有定义msg。可以忽略。
第2是 104行之后 第117行,if 语句两个call 其中定义了msg,并在141行退出。故可以试试在141行之前添加一行
endlocal & set _msg=%msg%COPY
bat小白,请多指教!谢谢!

TOP


未见源代码,但若在复合语块,如 for...do() 或 if...() 中用 endlocal&set _msg=%_msg% 这类 ‘续命’ 的玩法,会被 ‘预处理’ 提前毙掉的...

TOP

本帖最后由 newswan 于 2024-6-8 20:14 编辑
Call "%~pd0C2R-R2V-AIO.cmd" _msg
Echo %_msg%&Rem C2R-R2V-AIO檔的變數COPY
:E_Exit
endlocal&Set %1=%msg%COPY

TOP

回复 2# 77七
感謝指點,追蹤了下141行
endlocal&set _msg=%msg%COPY
它似乎只會有空值

TOP

回复 3# aloha20200628
感謝指點,這個是我沒吸收到的,謝謝。

TOP

回复 4# newswan

感謝回覆,感覺他會是空值,實作也是空值.

TOP

用 for 获取输出
pushd "%~dp0"
for /f "usebackq tokens=1,* delims= " %%a in (` C2R-R2V-AIO.cmd `) do (
if "%%a" == "msg" (set _msg_=%%b)
)
popdCOPY
原文件 1481
:E_Exit
echo msg %msg%COPY

TOP

本帖最后由 77七 于 2024-6-9 13:09 编辑

回复 5# dreamer


  方法1将msg结果重定向到文本
140行左右添加行
@echo off
>>"%~dp0#.txt" echo,%msg%
@exit /bCOPY


1482行左右添加行
:E_Exit
>>"%~dp0#.txt" echo,%msg%
if %_Debug% EQU 1 goto :eof
echo.
echo Press any key to exit.COPY


使用以下脚本调用
@echo off
cd /d "%~dp0"
rem 把两个脚本放在同一目录下。或者自行修改两个脚本的 #.txt 路径
del "%~dp0#.txt" 2>nul
start "" "%~dp0C2R-R2V-AIO.cmd"
:loop
if not exist "%~dp0#.txt" (
timeout 1
goto :loop
)
set _msg=
for /f "useback delims=" %%a in ("%~dp0#.txt") do (
set _msg=%%a
)
if defined _msg (
echo %_msg%
) else (
echo 原脚本未定义msg
)
del "%~dp0#.txt" 2>nul
pauseCOPY



方法2
可能需要将原脚本 36,41行两个start cmd.exe 及相关部分移植到调用脚本中,这样可以直接 call 调用,有点复杂

我是这样认为的,不知道对不对
bat小白,请多指教!谢谢!

TOP

回复 8# newswan
又學到一招了!真心感謝,這個方式可以取得C2R-R2V-AIO所有的輸出文字.感覺在這個基礎上,可以將所有需要的函數用Echo輸出而不用考慮setlocal造成的問題,太棒了!

TOP

回复 9# 77七
之前有測試寫入文件確實可行,想說寫入文件那干脆寫入到doskey 裡會不會更好一些.我的作法是在C2R-R2V-AIO 的:E_Exit後加上
If "%msg%" EQU "Finished" Doskey Finished=%msg%COPY
然後在用findstr找出符合的字串,因為Finished是唯一條件,找到就成立找不到就失敗,所以用以下內容去判斷
Doskey /macros|findstr /B /E /C:"finished=Finished">Nul&&Echo 完成COPY

TOP

回复 11# dreamer


  
start %SystemRoot%\Sysnative\cmd.exe /c ""!_cmdf!" -wow "COPY
这行代码作用不是打开一个新窗口?打开的新窗口,call 已经获取不到其变量了吧
bat小白,请多指教!谢谢!

TOP

本帖最后由 77七 于 2024-6-9 14:51 编辑

回复 11# dreamer


   可以试着用以下脚本调用
脚本已经修改,刚才逻辑不对
@echo off
if exist "%SystemRoot%\Sysnative\cmd.exe" (
call %SystemRoot%\Sysnative\cmd.exe /c "%~dp0C2R-R2V-AIO.cmd"
) else (
if exist "%SystemRoot%\SysArm32\cmd.exe" (
if /i %PROCESSOR_ARCHITECTURE%==AMD64 (
call %SystemRoot%\SysArm32\cmd.exe /c "%~dp0C2R-R2V-AIO.cmd"
) else call "%~dp0C2R-R2V-AIO.cmd"
) else call "%~dp0C2R-R2V-AIO.cmd"
)
pauseCOPY



删除原脚本第25-43行,注意脚本中的路径,然后按照2楼方法。试试能不能取得msg值。(当然,2楼已经说明,msg存在空值可能)
本人认知、能力有限,可以试一下。
bat小白,请多指教!谢谢!

TOP

回复 12# 77七
33行有定義,它再次呼叫自身,所以應該還是可以取到值.
set "_cmdf=%~f0"COPY

TOP

回复 14# dreamer


   
无论他执行哪个脚本,只要打开了新窗口,新窗口可以继承原窗口的变量,而不能回传。
可以简单写个脚本验证
@echo off
if "%~1" equ "" (
title
set a=a
start "" "%~f0" xx
) else (
title
set b=b
)
echo %a%
echo %b%
pauseCOPY
bat小白,请多指教!谢谢!

TOP

返回列表