首页 > 编程语言 >如何让Visual Studio Tools for Unity插件用于调试你自己的Mono嵌入应用程序

如何让Visual Studio Tools for Unity插件用于调试你自己的Mono嵌入应用程序

时间:2024-01-13 16:56:41浏览次数:32  
标签:插件 Mono flag Visual Unity Studio mono 进程

     最近在测试将mono嵌入到C++应用程序中,苦于没有调试器,有时候还是不怎么方便。网上搜了一下,有VS插件MDebug、VSMonoDebugger,实际试用了一下,有点麻烦,而且似乎对Windows+Visual Studio 2022支持不大好。因此想到了,Unity引擎是基于mono的,Visual Studio 2022也内置了针对Unity的调试器,名为:Visual Studio Tools for Unity。我想如果这个插件也能调试我的应用程序就好了。

     打开VS,使用菜单中的“附加到Unity”菜单打开附加对话框。最后发现并不能识别我的mono嵌入应用程序。因此直接调试Visual Studio 2022,查找和研究VS发现Unity进程的方法。经过一系列的调试,发现查找Unity相关进程的代码位于:SyntaxTree.VisualStudio.Unity.Messaging.dll 中,文件路径:

// c:\program files\microsoft visual studio\2022\professional\common7\ide\extensions\microsoft\visual studio tools for unity\SyntaxTree.VisualStudio.Unity.Messaging.dll
// SyntaxTree.VisualStudio.Unity.Messaging, Version=17.8.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

     具体路径可能你跟我不一样。下面这个函数位于:SyntaxTree.VisualStudio.Unity.Messaging.UnityProbe类中。

public static IEnumerable<UnityProcess> GetUnityProcesses(string informationFormat = null, bool localPlayerProcessDetection = false)
{
    Process[] array = SafeProcess.GetProcesses().ToArray<Process>();
    IEnumerable<UnityProcess> enumerable = from p in array
        where p.ProcessProperty((Process _) => _.ProcessName) == "Unity"
        select UnityProbe.UnityProcessFor(p, UnityProcessType.Editor, UnityProbe.GetDebuggerPort(p.Id), informationFormat);
    if (!localPlayerProcessDetection)
    {
        return enumerable;
    }
    IEnumerable<UnityProcess> enumerable2 = from p in array.Where(new Func<Process, bool>(UnityProbe.IsLocalPlayerProcess))
        select UnityProbe.UnityProcessFor(p, UnityProcessType.Player, 0, informationFormat);
    return enumerable.Concat(enumerable2);
}

      我们可以看到,这里使用了两种方法来探查Unity相关进程。其一是直接查找名字叫Unity的进程,其二是探查可能是Unity Player(即Windows PC档)的进程。前者直接查看进程名称,后者通过下面这个函数来判断:

public static bool IsLocalPlayerProcess(Process process)
{
    bool flag;
    try
    {
        if (process.MainWindowHandle == IntPtr.Zero)
        {
            flag = false;
        }
        else
        {
            ProcessModule mainModule = process.MainModule;
            if (mainModule == null)
            {
                flag = false;
            }
            else
            {
                string fileName = mainModule.FileName;
                string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName);
                string directoryName = Path.GetDirectoryName(fileName);
                if (directoryName == null)
                {
                    flag = false;
                }
                else
                {
                    flag = Directory.Exists(Path.Combine(directoryName, fileNameWithoutExtension + "_Data")) && File.Exists(Path.Combine(directoryName, "UnityPlayer.dll"));
                }
            }
        }
    }
    catch (Exception)
    {
        flag = false;
    }
    return flag;
}

      可以看到,只要目标进程目录下有一个 “进程名(无扩展名)” + "_Data"的目录,且该目录下有一个UnityPlayer.dll,即可被视为Unity相关进程。

  因此要将我们自己的进程被该插件识别到,也有两种方法,假如我们的项目叫MyApp。那么其一是让我们生成的进程也叫Unity.exe;其二是在MyApp.exe所在目录下,新增一个MyApp_Data,然后再随便新建一个空白文本文件,把名称(含扩展名)改成"UnityPlayer.dll"即可。

       这样执行后,你就会发现,你的进程出现在了搜索对话框中了。

       当然,如果此时你直接双击连接是无法连接成功的,因为前面的任务只是让你可以被找到,如果要被连接上,还有另外一些额外的要求。让我们看一下下面这个函数:

public static int GetDebuggerPort(int processId)
{
    return 56000 + processId % 1000;
}

    可以看到,调试器假定了目标端口和进程id之间的关联关系,因此在我们初始化mono的时候,也需要考虑到这一点,因此,我们初始化mono调试器的时候,应该这样:

int DebuggerPort = 56000 + GetProcessId() % 1000;

std::string argument = std::string("--debugger-agent=transport=dt_socket,embedding=1,server=y,suspend=n,address=127.0.0.1:") + ToStlString(DebuggerPort);

const char* options[] = 
{
   argument.c_str()
};

mono_jit_parse_options(sizeof(options)/sizeof(options[0]), (char**)options);
mono_debug_init(MONO_DEBUG_FORMAT_MONO);

    这样你就可以白嫖Visual Studio Tools for Unity,用于调试你自己的mono嵌入程序了。

 

标签:插件,Mono,flag,Visual,Unity,Studio,mono,进程
From: https://www.cnblogs.com/bodong/p/17962564

相关文章

  • Chrome 浏览器插件 V3 版本 Manifest.json 文件中 Action 的类型(Types)、方法(Methods)和
    一、类型(Types)一、OpenPopupOptions1.属性windowId:number可选打开操作弹出式窗口的窗口ID。如果未指定,则默认为当前活动窗口。二、TabDetails1.属性tabId:number可选要查询其状态的标签页ID。如果未指定标签页,则返回非标签页专属状态。三、UserSettin......
  • 小程序开发:在插件市场寻找步骤条组件并二开
    想实现一个可滚动的步骤条用来显示自己的随笔作为一名全栈工程师,要是全部都自己写,那太废时间了,首先去uniapp的插件市场逛逛看有没有符合需要的组件先:第一个: 看着符合自己的要求了,该有的有了,但是感觉左边的色调太单调了,故pass。第二个: 这个看起来颜色就比较丰富一些了,右边......
  • 小程序开发:将改造后的步骤条插件移植到自己的小程序
    删减了很多原组件代码和用不上的一些组件之后就可以正式移植到自己的小程序了。对比下移植前小程序包大小和移植后小程序包大小:移植前: 移植后: 所有文章类的页面单独分了分包,不占用主包大小,因为主包最多2m,单个分包也不能超过2m。步骤条代码经过删减后,仅16.3k。且移植后效果......
  • Unity 获取当前系统时间并在UI界面中显示
    在Unity3D中获取当前系统时间,并在UITEXT中显示 代码:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem;usingTMPro;usingUnityEngine.UI;usingUnityEngine.SceneManagement;publicclassTIME_show:MonoBehaviou......
  • 无涯教程-JUnit - Eclipse插件
    要使用eclipse设置JUnit,请遵循以下步骤。步骤1-下载JUnit包根据系统上的操作系统下载JUnitjar。OSJar名称Windowsjunit4.10.jarLinuxjunit4.10.jarMacjunit4.10.jar假设您已将上面的JAR文件复制到文件夹C:\>JUnit。步骤2-设定Eclipse环境打开eclipse→......
  • idea 热部署插件 JRebel
    前言:热部署:是在不关闭或重启服务的情况下,更新Java类文件或配置文件,实现修改内容生效;通过热部署,可提高开发效率,节省程序打包重启的时间;同时,可实现生产环境中需要不停机或重启的服务的升级。 随着代码量增加,也需要不断改动,我们需要重新Run或者DeBug。开发效率......
  • [Maven] 02 - POM模型与常见插件
    POM模型1依赖关系Maven一个核心的特性就是依赖管理。当我们处理多模块的项目(包含成百上千个模块或者子项目),模块间的依赖关系就变得非常复杂,管理也变得很困难。针对此种情形,Maven提供了一种高度控制的方法。通俗理解:依赖谁就是将谁的jar包添加到本项目中。可以依赖中央仓......
  • idea安装插件后报错打不开怎么办,两步教会你
    解决方法:老版本的插件路径:C:\Users\用户名\.IntelliJIdea20xx.X\config\plugins找到这个路径下:C:\Users\用户名\.IntelliJIdea20xx.X\config\plugins 删除 刚才安装的插件就可以了,如果你忘记了你安装插件的名称,那么可以根据安装时间来进行筛选新版本的插件路径:2020以上的版本的......
  • dremio jdbc 插件时间增量处理的一些问题
    dremio支持一些增量数据处理能力,同时可以选择增量字段,目前dremio是提供了一些实现,比如反射数据基于iceberg对于增量可以是不同的数据源(jdbc的,文件系统的,iceberg的),日常大家可能选择基于时间戳的(尤其业务系统是基于时间标识的append类型的)对于时间类型(timestamp),不同数据库......
  • Unity3D 性能杀手Overdraw详解
    前言Unity3D是一款强大的游戏开发引擎,但在使用过程中,我们需要注意一些可能会影响游戏性能的因素。其中之一就是Overdraw(过度绘制),它可以成为性能杀手。本文将详细解释Overdraw的概念、原因以及如何通过代码实现来减少Overdraw对游戏性能的影响。对惹,这里有一个游戏开发交流小组,希......