[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[特效代码] bat脚本中获取、控制光标位置

各位大佬好,
楼主也是一位计算从业人员,写代码、用脚本也好多年了。脚本也只是简单应用,脚本问题还是会经常来这儿搜索学习。
关于控制光标位置的方法(tab和backspace方法)其实一早就用过,但是win10上不好使,一直没有去研究。
上周工作中又用到了,想着这次一定好好研究研究,然后翻遍了互联网,发现也没有好的方法,不过倒是学习到了很多其他技巧,然后自己应用到光标的获取和控制上,效果还行。
发出来分享给大家,顺便问问还有没有更好法。
另外,这个脚本启动时会打印// 2>nul这一行,大家有没有好的办法优化一下?
  1. // 2>nul & @goto :batch_start
  2. /*
  3. :batch_start
  4. @echo off
  5. setlocal
  6. setlocal ENABLEDELAYEDEXPANSION
  7. rem 必须执行的步骤,初始化c#辅助程序
  8. call :init_cursor_control
  9. rem 下面的代码主要是为了清除屏幕第二行输出的// 2>nul,会有闪烁。如果觉得不好,可以删掉,或者用cls清屏。
  10. rem 但是cls清屏会把屏幕所有都清掉,包括非本脚本输出内容。
  11. call :get_cursor_info Current_X Current_Y Max_X Max_Y
  12. set /a Init_Y=%Current_Y% - 1
  13. call :set_cursor_position 0 %Init_Y%
  14. call :get_back_space BackSpace
  15. set "BlankSpace="
  16. for /l %%a in (1,1,%Max_X%) do set "BlankSpace=!BlankSpace! "
  17. echo %BackSpace%%BlankSpace%
  18. set /a Init_Y=%Current_Y% - 2
  19. call :set_cursor_position 0 %Init_Y%
  20. rem 脚本加在下面位置,其他地方不要动
  21. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  22. echo 按B键退出
  23. call :get_cursor_info Current_X Current_Y Max_X Max_Y
  24. :test_loop
  25. call :set_cursor_position 0 %Current_Y%
  26. echo %date% %time%
  27. choice /t 1 /n /c wb /d w>nul
  28. if %errorlevel%==2 goto :batch_end
  29. goto :test_loop
  30. rem 脚本加在上面位置,其他地方不要动
  31. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  32. rem 脚本最后退出位置,下面的代码不要更改
  33. :batch_end
  34. endlocal
  35. exit /b %errorlevel%
  36. rem 获取backspace回退键
  37. :get_back_space
  38. for /F %%a in ('"prompt $h & for %%b in (1) do rem"')do set "%~1=%%a"
  39. goto :eof
  40. rem 设置光标位置
  41. :set_cursor_position
  42. "%cursor_control_exe_file_path%" setcursorposition %~1 %~2
  43. goto :eof
  44. rem 获取当前窗口光标位置以及窗口尺寸
  45. :get_cursor_info
  46. "%cursor_control_exe_file_path%" getcursorposition
  47. set /p %~1= <"%cursor_control_exe_file_path%.CurrentX"
  48. set /p %~2= <"%cursor_control_exe_file_path%.CurrentY"
  49. set /p %~3= <"%cursor_control_exe_file_path%.MaxX"
  50. set /p %~4= <"%cursor_control_exe_file_path%.MaxY"
  51. goto :eof
  52. rem 初始化c#辅助程序,如果未找到就进行编译
  53. :init_cursor_control
  54. :: find csc.exe
  55. set "csc="
  56. for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do  set "csc=%%#"
  57. if not exist "%csc%" (
  58.    echo no .net framework installed
  59.    exit /b 10
  60. )
  61. set cursor_control_exe_file_path=%tmp%\cursor_control.exe
  62. if not exist "%cursor_control_exe_file_path%" (
  63.    call %csc% /nologo /warn:0 /out:"%cursor_control_exe_file_path%" "%~dpsfnx0" || (
  64.       exit /b %errorlevel%
  65.    )
  66. )
  67. goto :eof
  68. */
  69. using System;
  70. using System.Runtime.InteropServices;
  71. using System.Diagnostics;
  72. using System.IO;
  73. using System.Text;
  74. namespace SetConsoleCursorPosition
  75. {
  76.     class Program
  77.     {
  78.         [DllImport("kernel32.dll", SetLastError = true)]
  79.         static extern IntPtr GetStdHandle(int nStdHandle);
  80.         [DllImport("kernel32.dll", SetLastError = true)]
  81.         internal static extern bool SetConsoleCursorPosition(
  82.             IntPtr hConsoleOutput,
  83.             COORD dwCursorPosition);
  84.         [DllImport("kernel32.dll", SetLastError = true)]
  85.         static extern bool GetConsoleScreenBufferInfo(
  86.             IntPtr hConsoleOutput,
  87.             ref CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo);
  88.         [DllImport("kernel32.dll", SetLastError = true)]
  89.         static extern uint GetLastError();
  90.         public struct COORD
  91.         {
  92.             public short X;
  93.             public short Y;
  94.         };
  95.         public struct SMALL_RECT
  96.         {
  97.             public ushort Left;
  98.             public ushort Top;
  99.             public ushort Right;
  100.             public ushort Bottom;
  101.         };
  102.         public struct CONSOLE_SCREEN_BUFFER_INFO
  103.         {
  104.             public COORD dwSize;
  105.             public COORD dwCursorPosition;
  106.             public ushort wAttributes;
  107.             public SMALL_RECT srWindow;
  108.             public COORD dwMaximumWindowSize;
  109.         };
  110.         const int STD_INPUT_HANDLE = -10;
  111.         const int STD_OUTPUT_HANDLE = -11;
  112.         const int STD_ERROR_HANDLE = -12;
  113.         static void WriteFile(string filepath, int value)
  114.         {
  115.             FileStream fileStream = File.Create(filepath);
  116.             byte[] bytes = new UTF8Encoding(true).GetBytes(Convert.ToString(value));
  117.             fileStream.Write(bytes, 0, bytes.Length);
  118.             fileStream.Close();
  119.         }
  120.         static int Main(string[] args)
  121.         {
  122.             try
  123.             {
  124.                 if (0 == args.Length)
  125.                 {
  126.                     return 87; // ERROR_INVALID_PARAMETER
  127.                 }
  128.                 IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  129.                 if (args[0].ToLower() == "getcursorposition")
  130.                 {
  131.                     CONSOLE_SCREEN_BUFFER_INFO oCONSOLE_SCREEN_BUFFER_INFO = new CONSOLE_SCREEN_BUFFER_INFO();
  132.                     bool bRes = GetConsoleScreenBufferInfo(iStdOut, ref oCONSOLE_SCREEN_BUFFER_INFO);
  133.                     if (!bRes)
  134.                     {
  135.                         uint uiLastErrorCode = GetLastError();
  136.                         return (int)uiLastErrorCode;
  137.                     }
  138.                     string strAppPath = Process.GetCurrentProcess().MainModule.FileName;
  139.                     WriteFile(strAppPath + ".CurrentX", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.X);
  140.                     WriteFile(strAppPath + ".CurrentY", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.Y);
  141.                     WriteFile(strAppPath + ".MaxX", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.X);
  142.                     WriteFile(strAppPath + ".MaxY", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.Y);
  143.                     return 0;
  144.                 }
  145.                 else if (args[0].ToLower() == "setcursorposition")
  146.                 {
  147.                     if (args.Length < 3)
  148.                     {
  149.                         return 87; // ERROR_INVALID_PARAMETER
  150.                     }
  151.                     COORD oCursorPosition;
  152.                     oCursorPosition.X = short.Parse(args[1]);
  153.                     oCursorPosition.Y = short.Parse(args[2]);
  154.                     bool bRes = SetConsoleCursorPosition(iStdOut, oCursorPosition);
  155.                     if (!bRes)
  156.                     {
  157.                         uint uiLastErrorCode = GetLastError();
  158.                         return (int)uiLastErrorCode;
  159.                     }
  160.                     return 0;
  161.                 }
  162.                 return 87; // ERROR_INVALID_PARAMETER
  163.             }
  164.             catch (Exception ex)
  165.             {
  166.                 Console.WriteLine("exception: " + ex.ToString());
  167.                 return 87; // ERROR_INVALID_PARAMETER
  168.             }
  169.         }
  170.     }
  171. }
复制代码

优化了下,用findstr\for\more从脚本里查找c#辅助代码,生成新的c#源代码文件,原脚本开头就是标准的bat脚本了,就不会出现// 2>nul这个啦:
  1. :batch_start
  2. @echo off
  3. setlocal
  4. setlocal ENABLEDELAYEDEXPANSION
  5. rem 必须执行的步骤,初始化c#辅助程序
  6. call :init_cursor_control
  7. rem 脚本加在下面位置,其他地方不要动
  8. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  9. echo 按B键退出
  10. call :get_cursor_info Current_X Current_Y Max_X Max_Y
  11. :test_loop
  12. call :set_cursor_position 0 %Current_Y%
  13. echo %date% %time%
  14. choice /t 1 /n /c wb /d w>nul
  15. if %errorlevel%==2 goto :batch_end
  16. goto :test_loop
  17. rem 脚本加在上面位置,其他地方不要动
  18. :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  19. rem 脚本最后退出位置,下面的代码不要更改
  20. :batch_end
  21. endlocal
  22. exit /b %errorlevel%
  23. rem 获取backspace回退键
  24. :get_back_space
  25. for /F %%a in ('"prompt $h & for %%b in (1) do rem"')do set "%~1=%%a"
  26. goto :eof
  27. rem 设置光标位置
  28. :set_cursor_position
  29. "%cursor_control_exe_file_path%" setcursorposition %~1 %~2
  30. goto :eof
  31. rem 获取当前窗口光标位置以及窗口尺寸
  32. :get_cursor_info
  33. "%cursor_control_exe_file_path%" getcursorposition
  34. set /p %~1= <"%cursor_control_exe_file_path%.CurrentX"
  35. set /p %~2= <"%cursor_control_exe_file_path%.CurrentY"
  36. set /p %~3= <"%cursor_control_exe_file_path%.MaxX"
  37. set /p %~4= <"%cursor_control_exe_file_path%.MaxY"
  38. goto :eof
  39. rem 初始化c#辅助程序,如果未找到就进行编译
  40. :init_cursor_control
  41. :: find csc.exe
  42. set "csc="
  43. for /r "%SystemRoot%\Microsoft.NET\Framework\" %%# in ("*csc.exe") do  set "csc=%%#"
  44. if not exist "%csc%" (
  45.    echo no .net framework installed
  46.    exit /b 10
  47. )
  48. set cursor_control_exe_file_path=%tmp%\cursor_control.exe
  49. if not exist "%cursor_control_exe_file_path%" (
  50.    call :gen_helper_csharp_source
  51.    call %csc% /nologo /warn:0 /out:"%cursor_control_exe_file_path%" "%cursor_control_exe_file_path%.cs" || (
  52.       exit /b %errorlevel%
  53.    )
  54. )
  55. goto :eof
  56. :gen_helper_csharp_source
  57. for /f "tokens=1,2 delims=: " %%n in ('findstr /N /C:"helper_csharp_start" "%~dpsfnx0"') do (
  58.    ::echo %%n "%%o"
  59.    if "%%o"=="helper_csharp_start" (
  60.       set /a helper_csharp_start_line=%%n+1
  61.   ::echo helper_csharp_start_line=!helper_csharp_start_line!
  62.   more +!helper_csharp_start_line! "%~dpsfnx0" > "%cursor_control_exe_file_path%.cs"
  63.   goto :eof
  64.    )
  65. )
  66. goto :eof
  67. rem c#辅助程序开始位置
  68. :helper_csharp_start  
  69. using System;
  70. using System.Runtime.InteropServices;
  71. using System.Diagnostics;
  72. using System.IO;
  73. using System.Text;
  74. namespace SetConsoleCursorPosition
  75. {
  76.     class Program
  77.     {
  78.         [DllImport("kernel32.dll", SetLastError = true)]
  79.         static extern IntPtr GetStdHandle(int nStdHandle);
  80.         [DllImport("kernel32.dll", SetLastError = true)]
  81.         internal static extern bool SetConsoleCursorPosition(
  82.             IntPtr hConsoleOutput,
  83.             COORD dwCursorPosition);
  84.         [DllImport("kernel32.dll", SetLastError = true)]
  85.         static extern bool GetConsoleScreenBufferInfo(
  86.             IntPtr hConsoleOutput,
  87.             ref CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo);
  88.         [DllImport("kernel32.dll", SetLastError = true)]
  89.         static extern uint GetLastError();
  90.         public struct COORD
  91.         {
  92.             public short X;
  93.             public short Y;
  94.         };
  95.         public struct SMALL_RECT
  96.         {
  97.             public ushort Left;
  98.             public ushort Top;
  99.             public ushort Right;
  100.             public ushort Bottom;
  101.         };
  102.         public struct CONSOLE_SCREEN_BUFFER_INFO
  103.         {
  104.             public COORD dwSize;
  105.             public COORD dwCursorPosition;
  106.             public ushort wAttributes;
  107.             public SMALL_RECT srWindow;
  108.             public COORD dwMaximumWindowSize;
  109.         };
  110.         const int STD_INPUT_HANDLE = -10;
  111.         const int STD_OUTPUT_HANDLE = -11;
  112.         const int STD_ERROR_HANDLE = -12;
  113.         static void WriteFile(string filepath, int value)
  114.         {
  115.             FileStream fileStream = File.Create(filepath);
  116.             byte[] bytes = new UTF8Encoding(true).GetBytes(Convert.ToString(value));
  117.             fileStream.Write(bytes, 0, bytes.Length);
  118.             fileStream.Close();
  119.         }
  120.         static int Main(string[] args)
  121.         {
  122.             try
  123.             {
  124.                 if (0 == args.Length)
  125.                 {
  126.                     return 87; // ERROR_INVALID_PARAMETER
  127.                 }
  128.                 IntPtr iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  129.                 if (args[0].ToLower() == "getcursorposition")
  130.                 {
  131.                     CONSOLE_SCREEN_BUFFER_INFO oCONSOLE_SCREEN_BUFFER_INFO = new CONSOLE_SCREEN_BUFFER_INFO();
  132.                     bool bRes = GetConsoleScreenBufferInfo(iStdOut, ref oCONSOLE_SCREEN_BUFFER_INFO);
  133.                     if (!bRes)
  134.                     {
  135.                         uint uiLastErrorCode = GetLastError();
  136.                         return (int)uiLastErrorCode;
  137.                     }
  138.                     string strAppPath = Process.GetCurrentProcess().MainModule.FileName;
  139.                     WriteFile(strAppPath + ".CurrentX", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.X);
  140.                     WriteFile(strAppPath + ".CurrentY", oCONSOLE_SCREEN_BUFFER_INFO.dwCursorPosition.Y);
  141.                     WriteFile(strAppPath + ".MaxX", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.X);
  142.                     WriteFile(strAppPath + ".MaxY", oCONSOLE_SCREEN_BUFFER_INFO.dwMaximumWindowSize.Y);
  143.                     return 0;
  144.                 }
  145.                 else if (args[0].ToLower() == "setcursorposition")
  146.                 {
  147.                     if (args.Length < 3)
  148.                     {
  149.                         return 87; // ERROR_INVALID_PARAMETER
  150.                     }
  151.                     COORD oCursorPosition;
  152.                     oCursorPosition.X = short.Parse(args[1]);
  153.                     oCursorPosition.Y = short.Parse(args[2]);
  154.                     bool bRes = SetConsoleCursorPosition(iStdOut, oCursorPosition);
  155.                     if (!bRes)
  156.                     {
  157.                         uint uiLastErrorCode = GetLastError();
  158.                         return (int)uiLastErrorCode;
  159.                     }
  160.                     return 0;
  161.                 }
  162.                 return 87; // ERROR_INVALID_PARAMETER
  163.             }
  164.             catch (Exception ex)
  165.             {
  166.                 Console.WriteLine("exception: " + ex.ToString());
  167.                 return 87; // ERROR_INVALID_PARAMETER
  168.             }
  169.         }
  170.     }
  171. }
复制代码

TOP

返回列表