找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 72459|回复: 33

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

[复制链接]
发表于 2024-6-8 15:41:02 | 显示全部楼层 |阅读模式
本帖最后由 dreamer 于 2024-6-10 08:42 编辑

問題描述:下方批次檔是將Office 零售轉大量授權的工具,由於要自動化所以製作一個呼叫他的批次檔
  1. Call "%~pd0C2R-R2V-AIO.cmd"
  2. Echo %_msg%&Rem C2R-R2V-AIO檔的變數
复制代码
在C2R-R2V-AIO的1481行是離開批次的處理段落,有試著在1487行前加上
  1. endlocal&Set _msg=%_msg%
复制代码
但卻沒有效果,這個問題困擾了我一週,最終還是沒有找到答案,目前推測可能是過多的exit /b 跟 goto 所以造成非預期的現象,但還是想了解真正的原因而不是推測,希望有高手能給出更合理的分析,謝謝。
這個問題目前暫時用doskey+findstr解決(思路是將結果放到doskey後再用findstr判斷結果是否為finished=Finished),由於代碼過長貼不下源代碼如下
來源:https://github.com/abbodi1406/C2R-R2V-AIO
发表于 2024-6-8 17:17:48 | 显示全部楼层
脚本太复杂,没看明白意思,大概理了下退出的代码
第1是 104行之前 多个 goto :e_  后退出,这之前没有定义msg。可以忽略。
第2是 104行之后 第117行,if 语句两个call 其中定义了msg,并在141行退出。故可以试试在141行之前添加一行
  1. endlocal & set _msg=%msg%
复制代码
发表于 2024-6-8 18:17:27 | 显示全部楼层

未见源代码,但若在复合语块,如 for...do() 或 if...() 中用 endlocal&set _msg=%_msg% 这类 ‘续命’ 的玩法,会被 ‘预处理’ 提前毙掉的...
发表于 2024-6-8 19:37:58 | 显示全部楼层
本帖最后由 newswan 于 2024-6-8 20:14 编辑
  1. Call "%~pd0C2R-R2V-AIO.cmd" _msg
  2. Echo %_msg%&Rem C2R-R2V-AIO檔的變數
复制代码

  1. :E_Exit
  2. endlocal&Set %1=%msg%
复制代码
 楼主| 发表于 2024-6-9 06:06:27 | 显示全部楼层
回复 2# 77七
感謝指點,追蹤了下141行
  1. endlocal&set _msg=%msg%
复制代码
它似乎只會有空值
 楼主| 发表于 2024-6-9 06:07:14 | 显示全部楼层
回复 3# aloha20200628
感謝指點,這個是我沒吸收到的,謝謝。
 楼主| 发表于 2024-6-9 06:19:42 | 显示全部楼层
回复 4# newswan

感謝回覆,感覺他會是空值,實作也是空值.
发表于 2024-6-9 08:40:55 | 显示全部楼层
用 for 获取输出

  1. pushd "%~dp0"

  2. for /f "usebackq tokens=1,* delims= " %%a in (` C2R-R2V-AIO.cmd `) do (
  3.         if "%%a" == "msg" (set _msg_=%%b)
  4. )

  5. popd
复制代码
原文件 1481
  1. :E_Exit
  2. echo msg %msg%
复制代码
发表于 2024-6-9 11:44:51 | 显示全部楼层
本帖最后由 77七 于 2024-6-9 13:09 编辑

回复 5# dreamer


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


1482行左右添加行
  1. :E_Exit
  2. >>"%~dp0#.txt" echo,%msg%
  3. if %_Debug% EQU 1 goto :eof
  4. echo.
  5. echo Press any key to exit.
复制代码


使用以下脚本调用
  1. @echo off
  2. cd /d "%~dp0"
  3. rem 把两个脚本放在同一目录下。或者自行修改两个脚本的 #.txt 路径
  4. del "%~dp0#.txt" 2>nul
  5. start "" "%~dp0C2R-R2V-AIO.cmd"
  6. :loop
  7. if not exist "%~dp0#.txt" (
  8.         timeout 1
  9.         goto :loop
  10. )
  11. set _msg=
  12. for /f "useback delims=" %%a in ("%~dp0#.txt") do (
  13.         set _msg=%%a
  14. )
  15. if defined _msg (
  16.         echo %_msg%
  17. ) else (
  18.         echo 原脚本未定义msg
  19. )
  20. del "%~dp0#.txt" 2>nul
  21. pause
复制代码



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

我是这样认为的,不知道对不对
 楼主| 发表于 2024-6-9 13:30:02 | 显示全部楼层
回复 8# newswan
又學到一招了!真心感謝,這個方式可以取得C2R-R2V-AIO所有的輸出文字.感覺在這個基礎上,可以將所有需要的函數用Echo輸出而不用考慮setlocal造成的問題,太棒了!
 楼主| 发表于 2024-6-9 13:42:34 | 显示全部楼层
回复 9# 77七
之前有測試寫入文件確實可行,想說寫入文件那干脆寫入到doskey 裡會不會更好一些.我的作法是在C2R-R2V-AIO 的:E_Exit後加上
  1. If "%msg%" EQU "Finished" Doskey Finished=%msg%
复制代码
然後在用findstr找出符合的字串,因為Finished是唯一條件,找到就成立找不到就失敗,所以用以下內容去判斷
  1. Doskey /macros|findstr /B /E /C:"finished=Finished">Nul&&Echo 完成
复制代码
发表于 2024-6-9 13:53:51 | 显示全部楼层
回复 11# dreamer


  
  1. start %SystemRoot%\Sysnative\cmd.exe /c ""!_cmdf!" -wow "
复制代码
这行代码作用不是打开一个新窗口?打开的新窗口,call 已经获取不到其变量了吧
发表于 2024-6-9 14:33:30 | 显示全部楼层
本帖最后由 77七 于 2024-6-9 14:51 编辑

回复 11# dreamer


   可以试着用以下脚本调用
脚本已经修改,刚才逻辑不对
  1. @echo off
  2. if exist "%SystemRoot%\Sysnative\cmd.exe" (
  3.         call %SystemRoot%\Sysnative\cmd.exe /c "%~dp0C2R-R2V-AIO.cmd"
  4. ) else (
  5.         if exist "%SystemRoot%\SysArm32\cmd.exe" (
  6.                 if /i %PROCESSOR_ARCHITECTURE%==AMD64 (
  7.                         call %SystemRoot%\SysArm32\cmd.exe /c "%~dp0C2R-R2V-AIO.cmd"
  8.                 ) else call "%~dp0C2R-R2V-AIO.cmd"
  9.         ) else call "%~dp0C2R-R2V-AIO.cmd"
  10. )
  11. pause
复制代码



删除原脚本第25-43行,注意脚本中的路径,然后按照2楼方法。试试能不能取得msg值。(当然,2楼已经说明,msg存在空值可能)
本人认知、能力有限,可以试一下。
 楼主| 发表于 2024-6-9 15:19:29 | 显示全部楼层
回复 12# 77七
33行有定義,它再次呼叫自身,所以應該還是可以取到值.
  1. set "_cmdf=%~f0"
复制代码
发表于 2024-6-9 15:43:49 | 显示全部楼层
回复 14# dreamer


   
无论他执行哪个脚本,只要打开了新窗口,新窗口可以继承原窗口的变量,而不能回传。
可以简单写个脚本验证
  1. @echo off

  2. if "%~1" equ "" (
  3.         title 旧
  4.         set a=a
  5.         start "" "%~f0" xx
  6. ) else (
  7.         title 新
  8.         set b=b
  9. )
  10. echo %a%
  11. echo %b%
  12. pause
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-18 01:43 , Processed in 0.019044 second(s), 7 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表