起因:公司有两条不同网线,其中有一条连接公司自己svn服务器,另外一条通过使用外网ip登录svn,但是外网ip不时在变换,于是有个想法:用工具向web服务器发送ip,另一端请求web获取ip。恰好公司也有一个web大佬,于是就准备开搞了。(说到这里,不禁感到自己还是太年轻了,这是后话)
发送IP主要功能:开机启动,获取外网IP,Web发送IP,隐藏于后台右下角显示icon。
接受IP主要功能:web请求IP,SNV命令(Relocate ,commit,update)
发送IP 代码:
using UnityEngine;
using System.Collections;
using Microsoft.Win32;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Runtime.InteropServices;
using WinForms = System.Windows.Forms;
using MsgBoxBase = System.Windows.Forms.MessageBox;
using System.Threading;
using System;
using LitJson;
/// <summary>
/// 开机启动,最小化窗口,
/// </summary>
public class OpenPC : MonoBehaviour
{
public string ip = "";
private string SendKey = "ip";
private string URL = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private bool allowQuit= true;
public InputField input;
public bool IsSettingStartOpen
{
get
{
return PlayerPrefs.HasKey("IP");
}
set
{
PlayerPrefs.SetFloat("IP", 0);
}
}
public void Awake()
{
//判断是否设置开机启动
if (IsSettingStartOpen)
{
return;
}
else
{
RegisterStartOpen();
}
//发送IP
StartCoroutine(SendIP());
}
void Start()
{
HideTaskBar();
}
public IEnumerator SendIP()
{
yield return StartCoroutine(StartGetIp());
Debug.Log(ip);
WWWForm tForm = new WWWForm();
tForm.AddField(SendKey, ip);
StartCoroutine(PostUrl(URL, tForm));
}
private IEnumerator StartGetIp()
{
WWW w = new WWW(@"http://icanhazip.com/");
yield return w;
ip = w.text;
input.text = ip;
}
private IEnumerator PostUrl(string url, WWWForm form)
{
if (string.IsNullOrEmpty(ip))
{
yield break;
}
UnityWebRequest www = UnityWebRequest.Post(url, form);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
MsgBoxBase.Show("上传IP异常,请检查", "IP Send Error", WinForms.MessageBoxButtons.OK, WinForms.MessageBoxIcon.Warning);
Debug.LogError(www.error);
yield return www.error;
}
else
{
if (www.responseCode == 200)
{
JsonData data = JsonMapper.ToObject(www.downloadHandler.text);
var code = data["code"].ToString();
if (code == "0")
{
}
else
{
MsgBoxBase.Show("上传IP异常,请检查", "IP Send Error", WinForms.MessageBoxButtons.OK, WinForms.MessageBoxIcon.Warning);
}
}
}
yield return new WaitForSeconds(10f);
if (allowQuit)
{
Application.Quit();
}
}
public void RegisterStartOpen()
{
try
{
string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (rgkRun == null)
{
rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
}
rgkRun.SetValue("dhstest", path);
}
catch
{
Debug.Log(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
}
finally
{
regeditkey();
}
}
public void CancelStartOpen()
{
//MessageBox.Show("取消开机自启动,需要修改注册表", "提示");
try
{
string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
true);
if (rgkRun == null)
{
rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
}
rgkRun.DeleteValue("dhstest", false);
}
catch
{
Debug.Log("error OnBtn2Click");
}
finally
{
regeditkey();
}
}
private void regeditkey()
{
Debug.Log("regeditkey");
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
}
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
private const int SW_HIDE = 0; //hied task bar
private const int SW_RESTORE = 9;//show task bar
private static System.Windows.Forms.NotifyIcon _notifyIcon = new System.Windows.Forms.NotifyIcon();
private static int _width = 100, _height = 100;
private IntPtr window;
public void HideTaskBar()//最小化到托盘
{
input.gameObject.SetActive(false);
try
{
window = GetForegroundWindow();
ShowWindow(window, SW_HIDE);
_notifyIcon.BalloonTipText = "AIScanner1.1.0";//托盘气泡显示内容
_notifyIcon.Text = "AIScanner";//鼠标悬浮时显示的内容
_notifyIcon.Visible = true;//托盘按钮是否可见
_notifyIcon.Icon = CustomTrayIcon(Application.streamingAssetsPath + "/icon.png", _width, _height);//托盘图标
_notifyIcon.ShowBalloonTip(2000);//托盘气泡显示时间
_notifyIcon.MouseClick += notifyIcon_MouseClick;//双击托盘图标响应事件
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
private static System.Drawing.Icon CustomTrayIcon(string iconPath, int width, int height)
{
System.Drawing.Bitmap bt = new System.Drawing.Bitmap(iconPath);
System.Drawing.Bitmap fitSizeBt = new System.Drawing.Bitmap(bt, width, height);
return System.Drawing.Icon.FromHandle(fitSizeBt.GetHicon());
}
private void notifyIcon_MouseClick(object sender, System.Windows.Forms.MouseEventArgs e)//点击托盘图标
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
_notifyIcon.MouseDoubleClick -= notifyIcon_MouseClick;
_notifyIcon.Visible = false;
ShowWindow(window, SW_RESTORE);
}
}
private void OnDestroy()
{
_notifyIcon.MouseDoubleClick -= notifyIcon_MouseClick;
}
}
然后是接受IP,
接受IP代码 :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using LitJson;
using Microsoft.Win32;
using WinForms = System.Windows.Forms;
using MsgBoxBase = System.Windows.Forms.MessageBox;
using System.IO;
public class SVNSet : MonoBehaviour {
//获取ip
public InputField input;
//svn项目根目录即 .svn文件所在目录
public string SVNProjectPath = "";
//svn项目根地址
public string SVNIP = "";
private string IP = "";
public string EXE = "TortoiseProc.exe";
private string URL = "https://xxxxxxxxxxxxx";
public Text ProjectFilePath;
TextEditor te;
public void Awake()
{
//先查找是否有.svn的文件
bool ifFind = false;
SVNProjectPath = System.Environment.CurrentDirectory;
var dirctory = new DirectoryInfo(SVNProjectPath);
//同级目录下 (直接解压到.svn同级目录下情况)
if (!ifFind)
{
foreach (var item in dirctory.GetFileSystemInfos())
{
if (item.Name == ".svn")
{
ifFind = true;
break;
}
}
}
//上一级目录下 (生成新文件夹方式解压到.svn同级目录下情况)
if (!ifFind)
{
foreach (var item in dirctory.Parent.GetFileSystemInfos())
{
if (item.Name == ".svn")
{
SVNProjectPath = dirctory.Parent.FullName;
ifFind = true;
break;
}
}
}
if (!ifFind)
{
MsgBoxBase.Show("工具exe或工具的文件夹未放到.svn目录下,svn功能已失效", "Error", WinForms.MessageBoxButtons.OK, WinForms.MessageBoxIcon.Warning);
}
ProjectFilePath.text = SVNProjectPath;
GetIP();
//IP = GetSVNIP(IP);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Q))
{
SVNRelocate();
}
else if (Input.GetKeyDown(KeyCode.W))
{
SVNRelocate_bug();
}
else if (Input.GetKeyDown(KeyCode.E))
{
SVNCommit();
}
else if (Input.GetKeyDown(KeyCode.R))
{
SVNUpdate();
}
}
void GetIP()
{
StartCoroutine(PostUrl(URL));
}
private IEnumerator PostUrl(string url)
{
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.LogError(www.error);
yield return www.error;
}
else
{
if (www.responseCode == 200)
{
JsonData data = JsonMapper.ToObject(www.downloadHandler.text);
IP = GetSVNIP(data["ip"].ToString());
input.text = IP;
}
}
}
public void SVNRelocate()
{
//relocate 有bug 替换ip时会将原ip也替换成目标ip, 然后提示错误
//目前解决方案就是先粘贴后再点击
CopyString(IP);
ProcessCommand(EXE, "/command:relocate /path:" + SVNProjectPath);
}
public void Paste()
{
te.Paste();
Debug.LogError("paste");
}
public void SVNRelocate_bug()
{
ProcessCommand(EXE, "/command:relocate /path:" + IP);
}
public void SVNCommit()
{
List<string> pathList = new List<string>();
string basePath = SVNProjectPath + "/Assets";
pathList.Add(basePath);
pathList.Add(SVNProjectPath + "/ProjectSettings");
string commitPath = string.Join("*", pathList.ToArray());
ProcessCommand(EXE, "/command:commit /path:" + commitPath);
}
public void SVNUpdate()
{
ProcessCommand(EXE, "/command:update /path:" + SVNProjectPath);
}
void CopyString(string str)
{
te = new TextEditor();
te.text = str;
te.SelectAll();
te.Copy();
}
public string GetSVNIP(string ip)
{
//ip最后一位字符隐藏?导致换行
ip = ip.Remove(ip.Length - 1, 1);
var str = "svn://" + ip + ":1234";
return str;
}
public static void ProcessCommand(string command, string argument)
{
System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(command);
info.Arguments = argument;
info.CreateNoWindow = true;
info.ErrorDialog = true;
info.UseShellExecute = true;
if (info.UseShellExecute)
{
info.RedirectStandardOutput = false;
info.RedirectStandardError = false;
info.RedirectStandardInput = false;
}
else
{
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.StandardOutputEncoding = System.Text.UTF8Encoding.UTF8;
info.StandardErrorEncoding = System.Text.UTF8Encoding.UTF8;
}
System.Diagnostics.Process process = System.Diagnostics.Process.Start(info);
if (!info.UseShellExecute)
{
Debug.Log(process.StandardOutput);
Debug.Log(process.StandardError);
}
process.WaitForExit();
process.Close();
}
public void RegisterStartOpen()
{
try
{
string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
if (rgkRun == null)
{
rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
}
rgkRun.SetValue("dhstest", path);
}
catch
{
Debug.Log(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
}
finally
{
regeditkey();
}
}
public void CancelStartOpen()
{
//MessageBox.Show("取消开机自启动,需要修改注册表", "提示");
try
{
string path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
true);
if (rgkRun == null)
{
rgkRun = Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
}
rgkRun.DeleteValue("dhstest", false);
}
catch
{
Debug.Log("error OnBtn2Click");
}
finally
{
regeditkey();
}
}
private void regeditkey()
{
Debug.Log("regeditkey");
RegistryKey rgkRun = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
}
}
注意:Registry.LocalMachine.CreateSubKey 因为不是管理员打开可能会报权限的错,LocalMachine修改成CurrentUser即可。
后话:unity 放在后台,尝试过用thread等方案甚至空场景(放在后台后把所有gameobject删除了),cpu在任务管理器的占用始终超过50%,这,个个问题比较严重,但是就是不知道是什么导致的,推测可能是unity自己主线程有循环没有使用sleep?还是太年轻了。如果知道原因或者解决方案,请不吝赐教。