• c++ 脚本初级介绍


    జ్ఞ ా رً ॣ

    脚本是什么应该就不用多说了吧,想必想写脚本的人一定知道什么是脚本;

    众所周知,c++不是写脚本的最佳选择;但我最熟悉c++,所以一直在用它写脚本,偶尔用html5写写github的网页,js什么的就靠其他大神的成就啦~。

    接下来介绍c++的基本用法;

     一、鼠标的控制:

       正如小数有double,整数有int,鼠标也有自己的定义:POINT;

    POINT p;  //我们定义了一个名字叫做p的鼠标;

      那么靠这个p可以做什么呢?

      1.有时候为了控制鼠标,我们需要知道屏幕某个点的坐标:

      p是封装的,也就是说可以调用p.x和p.y,即:

    cout<<p.x<<" "<<p.y<<endl; //输出的便是鼠标在屏幕上的坐标;

      但是,定义p之后直接调用p.x和p.y是不行的,因为你没有给p赋值。因此调用:

    GetCursorPos(&P); //坐标便是目前鼠标的位置,以屏幕的左上角为(0,0)的平面直角坐标系,右下角便是你屏幕的分辨率最大值;大小写要注意,一定不能写错;

       有人测试后会发现,我仅仅是读到了一瞬间的鼠标位置,难道每测一次都要运行一次吗?

      算法的基础去哪了?while大循环啊!

    #include <bits/stdc++.h>
    #include <windows.h>
    #define inc(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    int main()
    {
      POINT P;
      while(1){
        GetCursorPos(&P);
        printf("%d %d ",P.x,P.y);
      }
    }

        请注意,脚本处处是坑,prinf(" ")的用法是接下来输出的内容从这一行开始输出,可以覆盖原来的内容;如果没被覆盖完全那么没被覆盖的部分就仍然保持原来的内容;

      也就是说:printf("%d %d ",P.x,P.y);是不行的,只能printf("%d %d        ",P.x,P.y);

      为什么呢?如果原来的坐标是(123,1024); 即输出:123 1024;

      假如你移动你的指针到(21,35);那么是输出21 35吗?不是,输出的是21  35024;原因参考 的用法,自己体会吧;

      2.我们需要把鼠标移到某个位置,并单击或双击

      首先你需要先知道屏幕的分辨率最大是什么:

    int x=GetSystemMetrics(SM_CXSCREEN);
    int y=GetSystemMetrics(SM_CYSCREEN);

        现在(x,y)就是右下角的坐标;

      与GetCursorPos相对的,SetCursorPos(x,y)是将鼠标移到屏幕上坐标是(x,y)的位置上。如:SetCursorPos(264,119);

      模拟鼠标的点击:

    mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0); //模拟按下鼠标左键 
    mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);  //模拟抬起鼠标左键 

       但要注意,按下抬起两次中间要给电脑运行提供一个时间,这时需要用到:Sleep()函数;如Sleep(2234)就是程序暂停2234毫秒;  

       因此写出函数:

    void click(){ //模拟了鼠标的单击
        mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
        Sleep(100);
        mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);
    } 

      那么双击呢?想必可以自己写出来了吧;就是调用两次click();

    二、键盘的控制

       仅仅依靠鼠标无法写出好的脚本,因此键盘的控制也不能少;

      1.监测键盘的按键

      比如说你写了这样一个脚本,用来恶搞同学: 

    
    
    int x=GetSystemMetrics(SM_CXSCREEN);
    int y=GetSystemMetrics(SM_CYSCREEN);
    while(1){
      SetCursorPos(rand()%x,rand()%y);
      Sleep(200);
    }

     显然的,恶搞结束后就算是你想停止该程序运行也只能使用键盘win+r运行cmd,通过tasklist和taskkill /pid来结束进程;

      那么有没有更好的办法呢?

      有!就像侠盗猎车手GTA的秘籍差不多,按下指定的按键组合后停止该程序;

    #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)

      上面这句话就是把写起来贼为困难的话变成人话,这个函数的返回值是一个bool值,如果按下了VK_NONAME键,返回1,否则返回0;

      因此可以将恶搞的程序修改一下:

    int x=GetSystemMetrics(SM_CXSCREEN);
    int y=GetSystemMetrics(SM_CYSCREEN);
    while(1){
      SetCursorPos(rand()%x,rand()%y);
      Sleep(200);
       if(KEY_DOWN(‘M')&&KEY_DOWN('X')&&KEY_DOWN('R')){
              return 0;      
       } 
    }

      这样你只需要像真正的大佬一样,随意的按下几个键子,就终止了这个看似恶魔般的程序;

      2.模拟键盘的按键

      先来看一下这两个函数:

    keybd_event(ascii,0,0,0);
    keybd_event(ascii,0,KEYEVENTF_KEYUP,0); 

      第一个参数:虚拟键码(键盘键码对照表一会给出);
      第二个参数:硬件扫描码,一般设置为0即可;
      第三个参数:函数操作的一个标志位,如果值为KEYEVENTF_EXTENDEDKEY则该键被按下,也可设置为0即可,如果值为KEYEVENTF_KEYUP则该按键被抬起;
      第四个参数:定义与击键相关的附加的32位值,一般设置为0即可。

      其中要格外注意,ascii并不是传统的ASCII码,

     

       

       因此可以写出模拟按下按键的函数:

    void press(int asi){
        keybd_event(asi,0,0,0);
        keybd_event(asi,0,KEYEVENTF_KEYUP,0);
        Sleep(100);
    }

    三、获取系统信息优化脚本

      很多时候,为了得到某些数据,我们需要从电脑中读取或运行某些东西,所以需要更多的脚本技巧;

      1.获取系统目前的时间

    time_t nowTime = time(NULL);
    struct tm *t = localtime(&nowTime);
    printf("
    %d-%02d-%02d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

      time_t 是一种类型,它定义的是时间类型nowTime;

      结构体指tm针指向的是nowTime的地址;

       tm结构体的原型:

    struct tm {
       int tm_sec;         /* 秒,范围从 0 到 59                */
       int tm_min;         /* 分,范围从 0 到 59                */
       int tm_hour;        /* 小时,范围从 0 到 23                */
       int tm_mday;        /* 一月中的第几天,范围从 1 到 31                    */
       int tm_mon;         /* 月份,范围从 0 到 11                */
       int tm_year;        /* 自 1900 起的年数                */
       int tm_wday;        /* 一周中的第几天,范围从 0 到 6                */
       int tm_yday;        /* 一年中的第几天,范围从 0 到 365                    */
       int tm_isdst;       /* 夏令时                        */    
    };

        localtime(&nowTime);把从1900-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间;

        %02d指的就是如果位数不够就补0补到2位;

        如数字是0,那么输出00;

      2.设置程序的正版激活信息

      众所周知,每台电脑乃至每个主板、硬盘都有唯一的编号,我们在激活时使用这些编号作为hash值,并生成针对于此hash值下的激活代码。(比如说用后缀自动机或者回文自动机算法来得到一个10MB的序列)这样就算其他终端得到这台终端的激活码也无法使用软件。

      我们可以用三种语句来获得唯一号:

    wmic BaseBoard get Manufacturer
    
    wmic BaseBoard get Product
    
    wmic diskdrive get SerialNumber //硬盘唯一号

      我通常选用第三句获取硬盘信息; 

         请注意,这三句话并不是c++的语言,而是cmd中的语法;

      在c++中,对于调用的cmd语法,我们可以使用system(".........");这样的语句。比如说system("ping baidu.com -l 1024 -t"); 或者system("wmic diskdrive get SerialNumber");

      对于cmd中的语法,下面或许会有一些专项介绍;

      但是,仅仅运行system("wmic diskdrive get SerialNumber");仅仅会在控制台上得到结果,无法让程序得到有效输入,怎么办呢?

      解决办法之一:将这句话运行时重定向输出内容到一个文件比如tmp.out,然后程序再重定向输入到tmp.out中;

      解决方法之二:重定向输入到控制台,读取控制台显示的内容;

    void GetOnlykey(){ //第二种解决问题的办法
        FILE *popen(const char *command,const char *type);
        FILE *file;    
        strcat(ptr, "wmic diskdrive get SerialNumber");      
        if((file=_popen(ptr, "r"))!=NULL)
        {
               while(fgets(tmpp,1024,file)!=NULL){ 
                  memcpy(tmp,cmd,1024);
               memcpy(cmd,tmpp,1024);   //只需要最后一行的字符串
            }
            _pclose(file);
        }
        inc(i,1,(int)strlen(tmp)) onlykey=(onlykey*10%p+tmp[i])%p; 
    }

      在这里稍微扩展一下,freopen("tmp.in","r",stdin);将输入流定义到tmp.in文件里,而freopen("con","r",stdin);将输入流定义到控制台了;

      获得hash之后作为种子,srand("hash值")就好了;

      3.设定该程序后台运行;

      要做到这种效果,我们需要用到除了c++之外的语言。即:.vbs文件

      我们新建一个文档,键入以下内容,并把扩展名更改为.vbs;

    Set us=WScript.CreateObject("WScript.shell")
    us.Run "solve.exe" ,0

      其中“us”是一个名称,可以随意设定; "solve.exe"是要后台运行程序的名称;这两个地方可以根据需要进行修改;

      假设这个.vbs文件叫background.vbs。那么如何在c++的程序中调用它呢?

      使用cmd中start的语法,调用语句:system("start background.vbs");就可以了。但要注意,vbs文件和该c++程序需要在一个文件夹内,否则应该使用cmd的start扩展语法;(具体的在cmd语法介绍里);

     四、cmd——命令提示符语法简介

      之前便说过,在c++中调用cmd的语法需要用到system(".......");语句,而要调用system(" "),我们需要包含<windows.h>库,也就是#include <windows.h>

      1.cd语法:

      cd命令是”change directory”中单词的首字母缩写,其英文释义是改变目录,所以该命令的功能是从当前目录切换到指定目录。

      其中目录的路径可分为绝对路径和相对路径。若目录名称省略,则切换至使用者的用户目录(也就是刚登录时所在的目录、home目录)。

      用法:cd [选项] [目录名]

      cd / 切换到用户根目录
      cd ../.. 返回上两级目录;
      cd .. 表示切换到上一级目录。
      cd !$  把上个命令的参数作为cd参数使用。

      2.dir语法:

       /S    显示指定目录和所有子目录中的文件。

        dir /?  显示目录中的文件和子目录列表。

      dir /d      只显示当前目录下的文件名称

      dir /od     按文件修改时间排序,递增;

      dir /o-d    按文件修改时间排序,递减

      dir /od/tc   按文件创建时间排序,递增  

      dir /o-d/tc  按文件创建时间排序,递减

      dir /on 按文件名排序对应,递增

      dir /o-n 按文件名排序对应,递减

      dir /oe 按扩展名排序对应,递增

      dir /o-e 按文件名排序对应,递减

      dir /s /b >a.txt  打印文件夹下的所有文件

      3.title语法:

      title ......   其中“......”便是程序的标题;

      4.start语法:

      利用好start语法可以干很多事情呦,比如说运行电脑中某个位置的程序,或者打开某个网页;

      比如打开baidu.com: system("start https://www.baidu.com");

      比如运行位于C:UsersAdministratorDesktop上的1.exe,那么我们system("start C:\Users\Administrator\Desktop\1.exe");

      注意,单斜杠要变成双斜杠,否则系统会认为这是个乱糟糟的转义序列;

      5.下载http文件

      win10中有个powershell可以实现此功能

      powershell的两种打开方式:直接在开始菜单里找或者在cmd中输入start powershell回车就可以启动

      打开powershell后输入:

    $client = new-object System.Net.WebClient
    $client.DownloadFile('#1', '#2')

      其中#1填写下载地址,#2填写本地保存位置,例如:

    $client = new-object System.Net.WebClient 
    $client.DownloadFile('http://static.duoshuo.com/embed.js','d:embed.js')
     
  • 相关阅读:
    杭电1312--Red and Black(Dfs)
    杭电1102--Constructing Roads(简单并查集)
    杭电1969--Pie(二分法)
    最小生成树:HDU1863-畅通工程
    并查集:HDU1213-How Many Tables(并查集最简单的应用)
    并查集:HDU5326-Work(并查集比较简单灵活的运用)
    最小生成树:POJ1251-Jungle Roads(最小生成树的模板)
    图论:HDU2544-最短路(最全、最经典的最短路入门及小结)
    动态规划、记忆化搜索:HDU1978-How many ways
    记忆化搜索:POJ1088-滑雪(经典的记忆化搜索)
  • 原文地址:https://www.cnblogs.com/kamimxr/p/12572058.html
Copyright © 2020-2023  润新知