事情的起因是个人打了爱之巢,之后不久刷到了Kinito Pet的实况,对Meta游戏开玩家的盒这种行为感到十分有趣,故而预研了下如何开盒,方便日后独游使用。理论上是Windows环境的C#方案,但因为仅使用Windows环境下的Unity进行测试,所以也可能存在其他引擎环境不适用的情况

直接获取

  部分信息可以直接获取,省时省力

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//获取操作系统信息
print(Environment.UserName); //当前用户的用户名
print(Environment.MachineName); //计算机的名称
print(Environment.OSVersion); //系统版本

//通过进程名匹配一些常见软件(包括修改器)
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
print(process.ProcessName);//进程名称
print(process.StartTime);//启动时间
print((DateTime.Now - process.StartTime).TotalSeconds);//运行时间(单位Sec)
}

//调用摄像头
WebCamDevice[] devices = WebCamTexture.devices;
if (devices.Length > 0)//电脑有摄像头
{
WebCamTexture webCamTexture = new WebCamTexture(devices[0].name);//单独创建窗口显示的话需要其他插件支持
webCamTexture.Play();//简易方案的话建议创建RawImage并赋予其纹理
}

创建进程

  有些信息则需要创建进程,在命令行中获取。下面我先来由一个简单的进程创建进行介绍

1
2
3
4
5
6
7
8
9
10
11
string GetCmdInfo(string command)
{
Process process = new();
process.StartInfo.FileName = "cmd.exe";//必须项,随便写个文件名
process.StartInfo.Arguments = "/c " + command;//必须项,执行的命令
process.StartInfo.CreateNoWindow = true;//不创建窗口
process.StartInfo.UseShellExecute = false;//不套壳交互
process.StartInfo.RedirectStandardOutput = true;//重定向输出
process.Start();
return process.StandardOutput.ReadToEnd();
}

  然后我们就可以利用进程执行命令行来实现各种拓展功能(如获取硬件信息等,目前获取硬件信息最主流的方案是引入System.Management调ManagementObjectSearcher进行遍历,但Unity引入需要一些额外操作,此处先采用wmic指令进行获取)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//调用打印机
Process printProcess = new Process();
printProcess.StartInfo.FileName = "cmd.exe";
printProcess.StartInfo.Arguments = $"/p \"{filePath}\"";
printProcess.StartInfo.CreateNoWindow = true; printProcess.Start();

//获取硬件信息
print(GetCmdInfo("wmic cpu get name"));//CPU信息
print(GetCmdInfo("wmic diskdrive get model"));//硬盘信息
print(GetCmdInfo("wmic memorychip get capacity"));//内存信息(单位KB)
print(GetCmdInfo("wmic path win32_videocontroller get name"));//显卡信息

//以下需要管理员权限且会被杀毒软件拦截
GetCmdComd("wmmic process call create shutdown.exe");//关机
GetCmdComd("wmmic process where pic='114514' call terminate");//按进程块号杀进程
GetCmdComd("wmmic process where name='qq.exe' call terminate");//按进程名称杀进程
GetCmdComd(@"wmic process call create 'C:\\QQ.exe'");//按进程路径开进程

模拟键鼠

  接着就是获取并模拟键盘鼠标的相关操作了,到这一步就逃不开给Unity的C#加点料了。个人推荐NuGet for Unity,安装Input Simulator。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//模拟键盘
InputSimulator sim = new();
sim.Keyboard.TextEntry(command[i]);

//模拟鼠标
[DllImport("user32.dll")]
public static extern bool SetCursorPos(int x, int y);
[DllImport("user32.dll")]
public static extern bool GetCursorPos(out Vector2Int point);

void Start()
{
GetCursorPos(out Vector2Int point);//单位为像素,左上角为(0, 0)
SetCursorPos(Screen.width / 2, Screen.height / 2);
}

写在最后

  大概就先这样吧,兴趣来了后经各方求证记录下了这些C#对系统的调用权作Meta游戏预研。欢迎补充,接下来就是各位发挥创意的时候了,例如忽然把玩家摄像头打开,告诉玩家我看见你了;在威胁玩家时调用打印机打一份死亡通告;在玩家不肯告诉角色真实地址时直接打开命令行ipconfig后停几秒说我已经知道了……当然也希望各位在制作Meta游戏时注意开盒的不要过火…….

1
2
3
4
5
6
7
8
9
10
11
//抛砖引玉个打开ipconfig的交互
command = “ipconfig\r”; Process process = new(); process.StartInfo.FileName = "cmd.exe";
process.StartInfo.CreateNoWindow = false; process.StartInfo.UseShellExecute = true;
process.Start(); process.WaitForExit(1000);//等待窗口完成
for (int i = 0; i < command.Length; i++)
{
process.WaitForExit(200);
sim.Keyboard.TextEntry(command[i]);//逐字输入
}
process.WaitForExit(2000);
process.Kill();//意满离