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')
 
原文地址:https://www.cnblogs.com/kamimxr/p/12572058.html