起因:公司有两条不同网线,其中有一条连接公司自己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?还是太年轻了。如果知道原因或者解决方案,请不吝赐教。