Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取应用程序域中启动的进程的程序集名称_C#_Appdomain - Fatal编程技术网

C# 获取应用程序域中启动的进程的程序集名称

C# 获取应用程序域中启动的进程的程序集名称,c#,appdomain,C#,Appdomain,我有一个创建应用程序域并启动它的服务: this._appDomain = AppDomain.CreateDomain(this._appName, AppDomain.CurrentDomain.Evidence, appDomainSetup); this._startStopControllerToRun = (IStartStop)this._appDomain.CreateInstanceFromAndUnwrap(assemblyName, this._fullyQualified

我有一个创建应用程序域并启动它的服务:

this._appDomain = AppDomain.CreateDomain(this._appName, AppDomain.CurrentDomain.Evidence, appDomainSetup);
this._startStopControllerToRun = (IStartStop)this._appDomain.CreateInstanceFromAndUnwrap(assemblyName, this._fullyQualifiedClassName);
this._startStopControllerToRun.Start();
这已经运行了很长一段时间了。问题是在该应用程序域中启动的控制器调用框架日志类时。记录器获取条目程序集名称,并将其作为源记录在事件日志中。以下是记录器获取源(调用方)名称的方式:

在添加
if
检查之前,记录器将记录源的“未知”。经过一些研究,我在
if
块中添加了这种尝试。现在,记录器将“mscorlib”记录为源(条目程序集名称)

以下是概述: 主机->控制器(在应用程序域内运行)

如何获取域中运行的程序集(具有控制器)的名称

注意:我也尝试过(如下),但它给出了日志类所在的框架的名称(而不是应用程序域中运行控制器的程序集的名称):


这也许是你想做什么的一种方法。我在这里演示的是通过
SetData
GetData
方法向创建的
AppDomain
传递和接收元数据,所以不管我如何创建实际的远程类型

using System;
using System.Reflection;

namespace ConsoleApplication13
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain appDomain = AppDomain.CreateDomain("foo");

            appDomain.SetData(FooUtility.SourceKey, FooUtility.SourceValue);

            IFoo foo = (IFoo)appDomain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, typeof(Foo).FullName);

            foo.DoSomething();
        }
    }

    public static class FooUtility
    {
        public const string SourceKey = "Source";
        public const string SourceValue = "Foo Host";
    }

    public interface IFoo
    {
        void DoSomething();
    }

    public class Foo : MarshalByRefObject, IFoo
    {
        public void DoSomething()
        {
            string source = AppDomain.CurrentDomain.GetData(FooUtility.SourceKey) as string;

            if (String.IsNullOrWhiteSpace(source))
                source = "some default";

            Console.WriteLine(source);
        }
    }
}
哪些产出:

Foo主机
按任意键继续

因此,在您的情况下,您可以将任何源元数据传递到AppDomain:

this._appDomain = AppDomain.CreateDomain(this._appName, AppDomain.CurrentDomain.Evidence, appDomainSetup);

this._appDomain.SetData("Source", "MyController");

this._startStopControllerToRun = (IStartStop)this._appDomain.CreateInstanceFromAndUnwrap(assemblyName, this._fullyQualifiedClassName);
this._startStopControllerToRun.Start();
并在
GetSource
方法中检查其存在性

private static string GetSource()
{
    try
    {
        string source = AppDomain.CurrentDomain.GetData("Source") as string;

        if (!String.IsNullOrWhiteSpace(source))
            return source;

        var assembly = Assembly.GetEntryAssembly();

        // GetEntryAssembly() can return null when called in the context of a unit test project.
        // That can also happen when called from an app hosted in IIS, or even a windows service.
        if (assembly == null)
        {
            // From http://stackoverflow.com/a/14165787/279516:
            assembly = new StackTrace().GetFrames().Last().GetMethod().Module.Assembly;
        }

        return assembly.GetName().Name;
    }
    catch
    {
        return "Unknown";
    }
}
更新备选方案

您还可以声明一个公共接口方法,用于在目标域中的静态位置上设置源

using System;
using System.Reflection;

namespace ConsoleApplication13
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain appDomain = AppDomain.CreateDomain("foo");

            IFoo foo = (IFoo)appDomain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, typeof(Foo).FullName);

            foo.SetSource("Foo Host");

            foo.DoSomething();
        }
    }

    public interface IFoo
    {
        void DoSomething();
        void SetSource(string source);
    }

    public class Foo : MarshalByRefObject, IFoo
    {
        public void DoSomething()
        {
            string source = Foo.Source;

            if (String.IsNullOrWhiteSpace(source))
                source = "some default";

            Console.WriteLine(source);
        }

        public static string Source{get; private set;}

        public void SetSource(string source)
        {
            Foo.Source = source;
        }
    }
}

我遇到了这样一种情况:在.net代码的某个地方,它依赖于Assembly.GetEntryAssembly()。它将获取返回的程序集并检查它是否具有程序集级属性。如果代码位于应用程序域中,则会失败

长话短说,我必须解决这个问题。解决方案是丑陋的,我讨厌我需要这样做,但它工作

如果您阅读此处的文档-

它包含以下部分:

返回值

类型:System.Reflection.Assembly

在默认应用程序域中作为进程可执行文件的程序集,或 AppDomain.ExecuteAssembly执行的第一个可执行文件。可以 从非托管代码调用时返回null

为了解决这个问题,我在exe中添加了一些代码,如果将“/initializingappdomain”作为参数传递,该代码将使进程退出

这里有一些代码来做这件事

// 1. Create your new app domain...
var newDomain = AppDomain.CreateDomain(...);
            
// 2. call domain.ExecuteAssembly, passing in this process and the "/initializingappdomain" argument which will cause the process to exit right away
newDomain.ExecuteAssembly(GetProcessName(), new[] { "/initializingappdomain" });

private static string GetProcessName()
{
   return System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName.Replace(".vshost", ""));
}

// 3. Use your app domain as you see fit, Assembly.GetEntryAssembly will now return this hosting .net exe.

同样,这远非理想。如果您可以避免这种情况,则有更好的解决方案,但如果您发现自己的代码不依赖Assembly.GetEntryAssembly(),这将使您在紧要关头得以生存。

避免寻找后门来获取代码提供的琐碎而准确的信息。添加一个属性。那么基本上是向log方法传递一个字符串吗<代码>Logger.Log(“MyApp”,消息)当日志记录在业务逻辑层中完成并且可以从多个使用者调用时,这种方法不起作用。消费者知道他们的名字,但是每个人都必须将这些信息传递到逻辑方法中。我不想像这样到处传递信息,我真的想把它放在一个地方。
using System;
using System.Reflection;

namespace ConsoleApplication13
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain appDomain = AppDomain.CreateDomain("foo");

            IFoo foo = (IFoo)appDomain.CreateInstanceFromAndUnwrap(Assembly.GetEntryAssembly().Location, typeof(Foo).FullName);

            foo.SetSource("Foo Host");

            foo.DoSomething();
        }
    }

    public interface IFoo
    {
        void DoSomething();
        void SetSource(string source);
    }

    public class Foo : MarshalByRefObject, IFoo
    {
        public void DoSomething()
        {
            string source = Foo.Source;

            if (String.IsNullOrWhiteSpace(source))
                source = "some default";

            Console.WriteLine(source);
        }

        public static string Source{get; private set;}

        public void SetSource(string source)
        {
            Foo.Source = source;
        }
    }
}
// 1. Create your new app domain...
var newDomain = AppDomain.CreateDomain(...);
            
// 2. call domain.ExecuteAssembly, passing in this process and the "/initializingappdomain" argument which will cause the process to exit right away
newDomain.ExecuteAssembly(GetProcessName(), new[] { "/initializingappdomain" });

private static string GetProcessName()
{
   return System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName.Replace(".vshost", ""));
}

// 3. Use your app domain as you see fit, Assembly.GetEntryAssembly will now return this hosting .net exe.