如题
先上懒人下载链接
从unity2017开始发布程序,日志就不在程序同级目录了。这使得发布之后找日志、查bug比较麻烦。当然可以发布时选择dev模式调试,在屏幕上查看,但不方便。
先看一下一般找到打开log日志需要多少步骤:
一般打开streamingAsset文件夹需要的步骤
本帖主要解决的问题:
1.exe同级目录一键打开log日志
2.exe同级目录一键打开streamingAssets配置目录
3.streamingAssets目录一键返回exe根目录
4.自动创建exe快捷方式至电脑桌面
实现原理
命令行……批处理……bat
当然也有直接在C#代码里用Shell命令实现的,我是觉得还得拖进来dll太麻烦,不如直接用计算机自带的bat命令!!!
上代码
//=====================================================
// - FileName: #AutoCreateShortCut#.cs
// - Created: #Guido Kuo#
// - CreateTime: #2020/4/22#
// - Email: #kuoguido@gmail.com#
// - Description: #通过命令行方式创建相关快捷方式,以解决需要多次打开相关文件夹查找程序运行日志、配置文件、桌面快捷方式等#
// - (C) Copyright 2020 - 2099,Inc.
// - All Rights Reserved.
//======================================================
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
public class AutoCreateShortCut : MonoBehaviour
{
#region 定义变量
/// <summary>
/// 程序根目录路径
/// </summary>
private string _rootPath;
/// <summary>
/// 协程等待文件创建的间隔时间
/// </summary>
private const float IntervalTime = 1.5f;
private bool _isStartDestroy;
private bool _pathHasChinese;
private int _recordInt;//1代表有中文字符就提示 2代表忽略永不提示且不执行本脚本
private const string RecordIntKey = "RecordIntKey";
#endregion
void Awake()
{
if (PlayerPrefs.HasKey(RecordIntKey))
{
_recordInt = PlayerPrefs.GetInt(RecordIntKey);
}
if (_recordInt == 2)
{
Destroy(GetComponent<AutoCreateShortCut>());
return;
}
_rootPath = Directory.GetParent(Application.dataPath).FullName + "\\";
InitCreateLogLnk();
InitCreateStreamingAssetsLnk();
InitCreateReturnLnk();
#if !UNITY_EDITOR && PLATFORM_STANDALONE_WIN
InitCreateCurrentExeToDesktop();
#endif
}
#region 初始化创建
/// <summary>
/// 创建程序桌面快捷方式
/// </summary>
void InitCreateCurrentExeToDesktop()
{
string exeShortCutName = Application.productName + ".lnk";
string exeShortCutPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\";
string exeShortCutBatPath = Application.dataPath + "/CreateExeInk.bat";
string exeFilePath = _rootPath + Application.productName + ".exe";
string exeShortCutContent = /*"%1 mshta vbscript:CreateObject(\"Shell.Application\").ShellExecute(\"cmd.exe\",\"/c %~s0 ::\",\"\",\"runas\",1)(window.close)&&exit\n" +*/
"mshta VBScript:Execute(\"Set a=CreateObject(\"\"WScript.Shell\"\"):Set b=a.CreateShortcut(\"\"" +
exeShortCutPath + exeShortCutName + "\"\"):" + "b.TargetPath=\"\"" + exeFilePath +
"\"\":b.WorkingDirectory=\"\"%~dp0\"\":b.Save:close\")";
JudgmentFile(exeShortCutBatPath, exeShortCutContent, exeShortCutPath, exeShortCutName);
}
/// <summary>
/// 创建日志快捷方式
/// </summary>
void InitCreateLogLnk()
{
string logShortCutName = "Log.Lnk";
string logShortCutBatPath = Application.dataPath + "/CreateLogLnk.bat";
StringBuilder sb = new StringBuilder();
string debugFilePath = sb.Append(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)).Append("Low\\").Append(Application.companyName).Append("\\").Append(Application.productName).Append("\\output_log.txt").ToString();
if (!File.Exists(debugFilePath))
File.Create(debugFilePath);
//如果创建不成功就取消下面的注释 注释为管理员身份运行批处理
string createLogShortCutContent = /*"%1 mshta vbscript:CreateObject(\"Shell.Application\").ShellExecute(\"cmd.exe\",\"/c %~s0 ::\",\"\",\"runas\",1)(window.close)&&exit\n" +*/
"mshta VBScript:Execute(\"Set a=CreateObject(\"\"WScript.Shell\"\"):Set b=a.CreateShortcut(\"\"" +
_rootPath + logShortCutName + "\"\"):" + "b.TargetPath=\"\"" + debugFilePath +
"\"\":b.WorkingDirectory=\"\"%~dp0\"\":b.Save:close\")";
JudgmentFile(logShortCutBatPath, createLogShortCutContent, _rootPath, logShortCutName);
}
/// <summary>
/// 创建外部加载文件夹快捷方式
/// </summary>
void InitCreateStreamingAssetsLnk()
{
if (!Directory.Exists(Application.streamingAssetsPath))//创建StreamingAssets文件夹
Directory.CreateDirectory(Application.streamingAssetsPath);
if (Directory.Exists(Application.streamingAssetsPath))
{
string streamingAssetsShortCutName = "StreamingAssets.url";
string streamingAssetsShortCutBatPath = Application.dataPath + "/CreateStreamingAssetLnk.bat";
//如果创建不成功就取消下面的注释 注释为管理员身份运行批处理
string createStreamingAssetsShortCutContent = /*"%1 mshta vbscript:CreateObject(\"Shell.Application\").ShellExecute(\"cmd.exe\",\"/c %~s0 ::\",\"\",\"runas\",1)(window.close)&&exit\n" +*/
"echo [InternetShortcut] > \"" + _rootPath + streamingAssetsShortCutName + "\"\n" + "echo URL=file:///" + Application.streamingAssetsPath + " >> \"" + _rootPath + streamingAssetsShortCutName + "\"";
JudgmentFile(streamingAssetsShortCutBatPath, createStreamingAssetsShortCutContent, _rootPath, streamingAssetsShortCutName);
}
}
/// <summary>
/// 创建返回程序根目录快捷方式
/// </summary>
void InitCreateReturnLnk()
{
if (!Directory.Exists(Application.streamingAssetsPath))//创建StreamingAssets文件夹
Directory.CreateDirectory(Application.streamingAssetsPath);
if (Directory.Exists(Application.streamingAssetsPath))
{
string returnShortCutName = "A_ReturnRootFolder.url";
string returnShortCutBatPath = Application.dataPath + "/CreateReturnLnk.bat";
//如果创建不成功就取消下面的注释 注释为管理员身份运行批处理
string returnShortCutContent = /*"%1 mshta vbscript:CreateObject(\"Shell.Application\").ShellExecute(\"cmd.exe\",\"/c %~s0 ::\",\"\",\"runas\",1)(window.close)&&exit\n" +*/
"echo [InternetShortcut] > \"" + (Application.streamingAssetsPath + "/" + returnShortCutName).Replace("/", "\\") + "\"\n" + "echo URL=file:///" + _rootPath.Replace("\\", "/") + " >> \"" + (Application.streamingAssetsPath + "/" + returnShortCutName).Replace("/", "\\") + "\"";
JudgmentFile(returnShortCutBatPath, returnShortCutContent, Application.streamingAssetsPath + "/", returnShortCutName);
}
}
#endregion
/// <summary>
/// 判断文件
/// </summary>
/// <param name="batPath">bat批处理路径</param>
/// <param name="shortCutContent">bat批处理内容</param>
/// <param name="shortCutPath">快捷方式路径</param>
/// <param name="shortCutName">快捷方式名称</param>
void JudgmentFile(string batPath, string shortCutContent, string shortCutPath, string shortCutName)
{
if (File.Exists(batPath))
{
if (JudgmentContent(batPath, shortCutContent))
{
if (File.Exists(shortCutPath + shortCutName))
return;
else
StartCoroutine(CreateShortCutLnk(batPath, shortCutContent, shortCutPath, shortCutName));
}
else
{
File.Delete(batPath);
File.Delete(shortCutPath + shortCutName);
StartCoroutine(CreateShortCutLnk(batPath, shortCutContent, shortCutPath, shortCutName));
}
}
else
StartCoroutine(CreateShortCutLnk(batPath, shortCutContent, shortCutPath, shortCutName));
}
/// <summary>
/// 判断bat批处理内容是否相同
/// </summary>
/// <param name="batPath">bat批处理路径</param>
/// <param name="compareContent">对比的内容</param>
/// <returns></returns>
bool JudgmentContent(string batPath, string compareContent)
{
return File.ReadAllText(batPath) == compareContent;
}
/// <summary>
/// 判断字符串中是否包含中文
/// </summary>
/// <param name="str">需要判断的字符串</param>
/// <returns>判断结果</returns>
bool HasChinese(string str)
{
return Regex.IsMatch(str, @"[\u4e00-\u9fa5]");
}
#region 创建的协程
/// <summary>
/// 创建快捷方式
/// </summary>
/// <param name="batPath">bat批处理路径</param>
/// <param name="shortCutContent">bat批处理内容</param>
/// <param name="shortCutPath">快捷方式路径</param>
/// <param name="shortCutName">快捷方式名称</param>
/// <returns></returns>
IEnumerator CreateShortCutLnk(string batPath, string shortCutContent, string shortCutPath, string shortCutName)
{
if (HasChinese(shortCutContent))
{
_pathHasChinese = true;
}
else
{
if (!File.Exists(batPath))
{
File.Create(batPath);
yield return new WaitForSeconds(IntervalTime);
#if UNITY_EDITOR
AssetDatabase.Refresh();
#endif
File.WriteAllText(batPath, shortCutContent, Encoding.Default);
yield return new WaitForSeconds(IntervalTime);
#if UNITY_EDITOR
AssetDatabase.Refresh();
#endif
Application.OpenURL(batPath);
}
else
{
if (!File.Exists(shortCutPath + shortCutName))
{
Application.OpenURL(batPath);
}
}
}
}
IEnumerator WaitToDestroy()
{
yield return new WaitForSeconds(IntervalTime * 5);
Destroy(GetComponent<AutoCreateShortCut>());
}
#endregion
void OnGUI()
{
//if (Input.GetKeyDown(KeyCode.C))
//{
// PlayerPrefs.DeleteAll();
//}
if (_pathHasChinese)
{
GUI.BeginGroup(new Rect((float)Screen.width / 2 - 200, (float)Screen.height / 2 - 200, 400, 400));
GUI.Box(new Rect(0, 0, 400, 400), "");
GUIStyle gs = new GUIStyle();
gs.alignment = TextAnchor.MiddleCenter;
gs.fontSize = 25;
gs.normal.textColor = Color.red;
string content = "路径中有中文,请检查文件路径!";
GUI.Label(new Rect(0, 0, 400, 50), content, gs);
gs.fontSize = 23;
gs.normal.textColor = Color.white;
GUI.Box(new Rect(140, 100, 120, 50), "");
content = "退出检查";
if (GUI.Button(new Rect(140, 100, 120, 50), content, gs))
{
Application.Quit();
#if !UNITY_EDITOR
Process.GetCurrentProcess().Kill();
#endif
}
GUI.Box(new Rect(140, 200, 120, 50), "");
content = "忽略本次";
if (GUI.Button(new Rect(140, 200, 120, 50), content, gs))
{
Destroy(GetComponent<AutoCreateShortCut>());
}
gs.normal.textColor = Color.green;
GUI.Box(new Rect(140, 300, 120, 50), "");
content = "永久忽略";
if (GUI.Button(new Rect(140, 300, 120, 50), content, gs))
{
PlayerPrefs.SetInt(RecordIntKey, 2);
Destroy(GetComponent<AutoCreateShortCut>());
}
GUI.EndGroup();
if (_isStartDestroy)
{
StopCoroutine("WaitToDestroy");
_isStartDestroy = false;
}
}
else
{
if (!_isStartDestroy)
{
StartCoroutine("WaitToDestroy");
_isStartDestroy = true;
}
}
}
}