using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
#if UNITY_STANDALONE_WIN
enum DumpCommandType
{
enumDump_Begin = 0,
enumDump_BackgroundExecutionFlag = enumDump_Begin, // 后台上传宕机信息(不显示DumpReport界面)
enumDump_ForceUpload, // Dump是否强制上报(忽略玩家在DumpReport界面上的选择)
enumDump_LogDirectory, // 设置log文件路径
enumDump_CollectFile, // 设置需收集的文件名
enumDump_LogDirectory_UTF8, // 设置log文件路径(传入参数为UTF8,Unity/UE 使用此参数)
enumDump_CollectFile_UTF8, // 设置需收集的文件名(传入参数为UTF8,Unity/UE 使用此参数)
enumDump_SetURL, // 设置上传url (internal_cn|internal_us|external|test) => (国内|海外|外部项目|内部测试)
enumDump_SetBeta, // 设置 beta
enumDump_SetUserIdentifier, // 设置 UserIdentifier
enumDump_SetUserIdentifier_UTF8,
enumDump_AddExtraData, // 添加额外数据
enumDump_AddExtraData_UTF8, // 添加额外数据(传入参数为UTF8,Unity/UE 使用此参数)
enumDump_leaveBreadcrumbType, // 设置面包屑传入字符串的格式
enumDump_GM_TEST, // GM测试指令
enumDump_Count
}
public class DumpForPC : MonoBehaviour
{
private static IntPtr StringToCharPtr(string s)
{
return Marshal.StringToHGlobalUni(s);
}
private static string YourAppVersion = "NA";
[DllImport("Crasheye64")]
private static extern bool InitDumperCrasheye(string appkey, string version, string channId);
[DllImport("Crasheye64")]
private static extern void UnInitDumper();
[DllImport("Crasheye64")]
private static extern bool SetConfig(int nDumpCommandType, IntPtr pArg);
public static void SetForceUpload(bool isForceUpload)
{
IntPtr pBool = Marshal.AllocHGlobal(1);
Marshal.WriteByte(pBool, Convert.ToByte(isForceUpload));
SetConfig((int)DumpCommandType.enumDump_ForceUpload, pBool);
Marshal.FreeHGlobal(pBool);
}
[DllImport("Crasheye64")]
private static extern bool SetConfig(int nDumpCommandType, IntPtr[] pArg);
[DllImport("Crasheye64")]
public static extern bool SendScriptException(string errorTitle, string stackTrace, string language);
public static bool SetBackgroundUpload(bool isBackgroundUpload)
{
IntPtr pBool = Marshal.AllocHGlobal(1);
Marshal.WriteByte(pBool, Convert.ToByte(isBackgroundUpload));
bool result = SetConfig((int)DumpCommandType.enumDump_BackgroundExecutionFlag, pBool);
Marshal.FreeHGlobal(pBool);
return result;
}
public delegate void FnOnCrashCallback(bool bCaptureSucceed, IntPtr cpszCrashReportFile);
[DllImport("Crasheye64")]
public static extern bool SetOnMiniDumpCreateCallBack(FnOnCrashCallback pCallback);
[DllImport("Crasheye64", CharSet = CharSet.Unicode)]
public static extern bool PushLogTrace([MarshalAs(UnmanagedType.LPStr)] string cpszMessage);
[DllImport("Crasheye64", CharSet = CharSet.Unicode)]
public static extern bool leaveBreadcrumb([MarshalAs(UnmanagedType.LPStr)] string cpszMessage);
//AddExtraData专用参数
private static IntPtr[] extraData = new IntPtr[2];
///
/// Windows的初始化
///
/// 平台申请的当前应用
/// 应用的渠道号
public static void Init(string appKeyForPC,string channIdForPC)
{
try
{
bool res = InitDumperCrasheye(appKeyForPC, YourAppVersion, channIdForPC);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 反初始化 CrasheyeSdk
/// 在程序正常退出时调用
///
public static void UnInit()
{
try
{
UnInitDumper();
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 设置上报路径.
/// internal_cn => 国内自研项目
/// internal_us => 海外自研项目
/// external => 外部项目
/// 若不设置, 默认是 external
/// 若要设置, 建议在 Init 之前调用.
///
/// internal_cn/internal_us/external 三选一
public static void SetURL(string url)
{
if (String.IsNullOrEmpty(url))
{
Debug.LogError("set url is null or empty!");
return;
}
var szLogDir = url.Replace("/", "\\");
IntPtr pLogDir = Marshal.StringToHGlobalAnsi(szLogDir);
SetConfig((int)DumpCommandType.enumDump_SetURL, pLogDir);
Marshal.FreeHGlobal(pLogDir);
}
///
/// 标记当前版本为调试版本.
/// 若要设置, 建议在 Init 之前调用.
///
public static void SetBeta()
{
try
{
IntPtr pLogDir = default;
SetConfig((int)DumpCommandType.enumDump_SetBeta, pLogDir);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 设置用户id.
///
/// 项目内部的用户id
public static void SetUserIdentifier(string userIdentifier)
{
if (string.IsNullOrEmpty(userIdentifier))
{
Debug.LogError("user identifier is null or empty!");
return;
}
try
{
var szUserIdentifier = userIdentifier.Replace("/", "\\");
IntPtr pUserIdentifier = Marshal.StringToHGlobalAnsi(szUserIdentifier);
SetConfig((int)DumpCommandType.enumDump_SetUserIdentifier, pUserIdentifier);
Marshal.FreeHGlobal(pUserIdentifier);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 设置用户id.
///
/// 项目内部的用户id
public static void SetUserIdentifier_UTF8(string userIdentifier)
{
if (string.IsNullOrEmpty(userIdentifier))
{
Debug.LogError("user identifier is null or empty!");
return;
}
try
{
var szUserIdentifier = userIdentifier.Replace("/", "\\");
IntPtr pUserIdentifier = Marshal.StringToHGlobalAnsi(szUserIdentifier);
SetConfig((int)DumpCommandType.enumDump_SetUserIdentifier_UTF8, pUserIdentifier);
Marshal.FreeHGlobal(pUserIdentifier);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 添加自定义数据,额外上报信息.
/// 以键值对的形式添加额外信息, 添加的信息会被包含着崩溃报告中随报告一同上报.
///
/// Key
/// Value
public static void AddExtraData(string szKey,string szValue)
{
if (string.IsNullOrEmpty(szKey) || string.IsNullOrEmpty(szValue))
{
Debug.LogError("AddExtraData szKey or szVanlue is null");
return;
}
try
{
extraData[0] = Marshal.StringToHGlobalAnsi(szKey);
extraData[1] = Marshal.StringToHGlobalAnsi(szValue);
SetConfig((int)DumpCommandType.enumDump_AddExtraData, extraData);
Marshal.FreeHGlobal(extraData[0]);
Marshal.FreeHGlobal(extraData[1]);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 添加自定义数据,额外上报信息.
/// 以键值对的形式添加额外信息, 添加的信息会被包含着崩溃报告中随报告一同上报.
///
/// Key
/// Value
public static void AddExtraDataUTF8(string szKey, string szValue)
{
if (string.IsNullOrEmpty(szKey) || string.IsNullOrEmpty(szValue))
{
Debug.LogError("AddExtraData szKey or szVanlue is null");
return;
}
try
{
extraData[0] = Marshal.StringToHGlobalAnsi(szKey);
extraData[1] = Marshal.StringToHGlobalAnsi(szValue);
SetConfig((int)DumpCommandType.enumDump_AddExtraData_UTF8, extraData);
Marshal.FreeHGlobal(extraData[0]);
Marshal.FreeHGlobal(extraData[1]);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 添加额外上报日志(文件).
/// 添加的文件会被包含着崩溃报告中随报告一同上报.
///
/// 需要额外收集的文件
public static void AddCustomLog(string collectFile)
{
if (string.IsNullOrEmpty(collectFile))
{
Debug.LogError("AddCustomLog collectFile is null or empty");
return;
}
try
{
var szCollectFile = collectFile.Replace("/", "\\");
Debug.Log(szCollectFile);
IntPtr pCollectFile = Marshal.StringToHGlobalAnsi(szCollectFile);
SetConfig((int)DumpCommandType.enumDump_CollectFile_UTF8, pCollectFile);
Marshal.FreeHGlobal(pCollectFile);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 添加额外上报日志(目录).
/// 添加的目录会被包含着崩溃报告中随报告一同上报.
///
/// 需要额外收集的文件目录
public static void AddCustomLogDirectory(string CollectLogDirectory)
{
if (string.IsNullOrEmpty(CollectLogDirectory))
{
Debug.LogError("AddCustomLog CollectLogDirectory is null or empty");
return;
}
try
{
var szCollectLogDirectory = CollectLogDirectory.Replace("/", "\\");
Debug.Log(szCollectLogDirectory);
IntPtr pCollectLogDirectory = Marshal.StringToHGlobalAnsi(szCollectLogDirectory);
SetConfig((int)DumpCommandType.enumDump_LogDirectory_UTF8, pCollectLogDirectory);
Marshal.FreeHGlobal(pCollectLogDirectory);
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
///
/// 设置版本号信息
///
///
public static void SetAppVersion(string yourAppVersion)
{
if (yourAppVersion == null)
{
return;
}
YourAppVersion = yourAppVersion;
}
public static void SetBreadCrumbType(Int32 breadCrumbType)
{
IntPtr bCT = Marshal.AllocHGlobal(sizeof(Int32));
Marshal.WriteInt32(bCT, breadCrumbType);
SetConfig((int)DumpCommandType.enumDump_leaveBreadcrumbType, bCT);
Marshal.FreeHGlobal(bCT);
}
public static void OnHandleUnresolvedException(object sender, UnhandledExceptionEventArgs args)
{
Debug.Log(args.ExceptionObject.GetType());
if (args != null && args.ExceptionObject != null && typeof(Exception).IsInstanceOfType(args.ExceptionObject))
{
Debug.Log("OnHandleUnresolvedException Ture");
Exception ex = (Exception)args.ExceptionObject;
Debug.Log("C# error Source:" + ex.StackTrace);
Debug.Log("C# error StackTrace:" + ex.StackTrace);
LibSendScriptException(ex.Source, ex.StackTrace);
}
else
{
Debug.Log("OnHandleUnresolvedException False");
}
}
public static void LibSendScriptException(string error, string stack)
{
Debug.Log("LibSendScriptException");
bool res = SendScriptException(error, stack, "C#");
Debug.Log(res);
}
public static void OnHandleLogCallback(string logString, string stackTrace, LogType type)
{
Debug.Log("OnHandleLogCallback: type: " + type + "logString: " + logString);
if (LogType.Assert == type || LogType.Exception == type)
{
LibSendScriptException(logString, stackTrace);
}
}
}
#endif