是否有一种干净的方法来访问作为启动 WPF 应用程序的 AppDomain.ExecuteAssembly 调用的一部分传递的命令行参数?
我正在一个单独的应用程序域中启动一个 WPF 应用程序,并将参数传递给该应用程序,如下所示:
AppDomain moduleDomain = AppDomain.CreateDomain("Friendly Name");
moduleDomain.ExecuteAssembly(path, new[] { "arg1", "arg2" });
Run Code Online (Sandbox Code Playgroud)
有一种解决方法可以访问这些参数,因为Environment.GetCommandLineArgs()和StartupEventArgs都返回原始应用程序的命令行参数,而不是使用ExecuteAssembly() 启动的命令行参数。
我想访问传递给 WPF 应用程序的参数,而无需手动定义 Main 方法,最好使用 StartupEventArgs。有办法这样做吗?
在单独的进程中启动 WPF 应用程序是可行的,但会降低性能并使调试变得复杂。
有一个由三个可执行文件组成的应用程序.其中之一 - 调度程序,运行其他可执行文件.调度程序在完成时从可执行文件接收代码.也就是说,只有调度程序始终在运行,其他可执行文件会卸载并再次加载.该应用程序在服务点运行并全天候工作.在第一次启动时,应用程序运行得很快.在一天结束时,应用程序运行速度非常慢.这种行为可能是什么原因?
什么导致最终方法被调用?
这个问题的2个回答(共4个)是:
The CLR is unloading an AppDomain 当AppDomain卸载时,CLR认为AppDomain中没有任何内容是根,并且执行由所有代组成的垃圾收集.
The CLR is shutting down 当进程正常终止时,CLR会关闭(例如,通过任务管理器进行外部关闭).
我假设The CLR is unloading an AppDomain是关闭程序(例如控制台[exe])(按程序的关闭/正常结束)
怎么样The CLR is shutting down?继续上面的[Exe]程序类比:
拜托,我能解释一下吗?
我有一个用C#编写的MMC管理单元.似乎MMC为每个托管管理单元创建了一个单独的AppDomain.它还有一个默认的AppDomain,用于托管系统dll,如mscorlib.dll,Microsoft.ManagementConsole.dll等.
我的管理单元有一个本机C++ DLL,它可以创建可以通过Interop调用托管代码的本机线程.问题是当本机线程访问我的托管代码时,它尝试在默认的AppDomain中执行它,而不是我的管理单元.
有没有办法强制本机线程"切换"到管理单元的AppDomain?我无法重写本机dll.我唯一能做的就是在C++/CLI中实现一些这个dll会调用的C++接口.
最小,完整和可验证的示例如下.要编译它,请在Visual Studio中选择C++/CLR控制台应用程序项目类型.
#include <Windows.h>
#include <msclr/gcroot.h>
using namespace System;
#pragma unmanaged
class IService
{
public:
virtual void Operate() = 0;
};
DWORD __stdcall MyNativeThread(LPVOID arg)
{
IService* service = (IService*)arg;
service->Operate();
return 0;
}
void StartNativeThread(IService* service)
{
CloseHandle(CreateThread(NULL, 0, &MyNativeThread, service, 0, NULL));
}
#pragma managed
public ref class ServiceManagedImpl
{
public:
void Operate()
{
System::Console::WriteLine("ServiceManagedImpl::Operate: Domain: {0}", System::AppDomain::CurrentDomain->Id);
}
};
class ServiceImpl : public IService
{
public:
ServiceImpl(ServiceManagedImpl^ managedImpl)
{
m_managedImpl = managedImpl;
} …Run Code Online (Sandbox Code Playgroud) 我正在为外部应用程序开发一个模块,它是一个加载的 dll。
但是,为了进行开发,您必须重新启动应用程序才能查看代码的结果。
我们已经构建了一段从 startassembly 动态加载 dll 的代码:
开始组装
var dllfile = findHighestAssembly(); // this works but omitted for clarity
Assembly asm = Assembly.LoadFrom(dllFile);
Type type = asm.GetType("Test.Program");
MethodInfo methodInfo = type.GetMethod("Run");
object[] parametersArray = new object[] { };
var result = methodInfo.Invoke(methodInfo, parametersArray);
Run Code Online (Sandbox Code Playgroud)
实际上,我们有一个包含静态启动程序集和动态调用的测试程序集的解决方案,这允许我们在运行时交换程序集。
问题 这段代码每次都会加载一个新的dll,并在程序集名称的末尾搜索最高版本。例如,将加载 test02.dll 而不是 test01.dll,因为应用程序会同时锁定 startassemly.dll 和 test01.dll。现在我们必须一直编辑属性 > 程序集名称。
我想在主应用程序仍在运行时构建一个新的 dll。但是现在我收到消息
该进程无法访问文件 test.dll,因为它正被另一个进程使用
我已经读到您可以使用AppDomains卸载 .dll但问题是我不知道如何正确卸载 AppDomain 以及在哪里执行此操作。
目标是每次重新打开窗口时都必须重新加载新的 test.dll(通过从主应用程序单击按钮)。
假设我有一个名为"MyService"的Windows服务和一个名为"MyEXE"的可执行文件,位于我网络上的几台计算机上.
是否有可能(在"MyService"中)在不同/相同的计算机上启动"MyEXE"的几个实例,让它执行某项任务并将"true/false"结果返回到"MyService"中的回调方法?
像这样的东西
class MyService : ServiceBase
{
delegate void UpdateCallBack(int id, bool updated)
void CheckForUpdates()
{
bool updatesExist = someService.GetCurrentVersion() != currentVersion;
if(updatesExist)
{
UpdatePC("C:\Program Files\MyApp.exe", 1, UpdateComplete);
UpdatePC("\\somepc\Program Files\MyApp.exe", 1, UpdateComplete);
UpdatePC("\\mypc\Program Files\MyApp.exe", 1, UpdateComplete);
}
}
void UpdatePC(string filePath, int id, UpdateCallBack callback)
{
//This is where I am kind of lost
SomeEXERunner runner = new SomeEXERunner();
runner.Run(filePath,"-u",id,callback);
}
void UpdateComplete(int id, bool updated)
{
//do something
if(!updated)
EmailService.NotifyAdmin("PC Not updated", id);
}
}
Run Code Online (Sandbox Code Playgroud)
也许我的整个架构都错了!
我试图在新的AppDomain中托管文本模板类代理.
我有一些旧的脚本代码,它们执行类似的操作,包含以下代码:
_ScriptAppDomain = AppDomain.CreateDomain(scriptDomainFriendlyName);
_ScriptProxy = (IScriptEngineProxy)_ScriptAppDomain.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName,
"LVK.Scripting.ScriptEngineProxy");
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用我的新课程时,请使用以下内容
_TemplateDomain = AppDomain.CreateDomain(templateDomainFriendlyName);
_TemplateProxy = (ITemplateProxy)_TemplateDomain.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName,
"TextTemplate.TemplateProxy");
Run Code Online (Sandbox Code Playgroud)
我只是得到"FileNotFoundException",其中包含以下详细信息:
无法加载文件或程序集'TextTemplate,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = bb70a2e62a722ace'或其依赖项之一.该系统找不到指定的文件.
我错过了什么?
基本上,我在TextTemplate命名空间(和程序集)中有一个Template类,它试图将TemplateProxy类(从MarshalByRefObject降序)加载到新的appdomain中,但看起来我的主程序集没有加载到这个域中.
如果我使用较旧的代码,但是没有使用这个新代码,这是有效的,但我无法发现差异.
这里有一些更多的细节:
如果需要的话,我不反对处理AssemblyResolve事件.我发现我的旧代码工作很奇怪,但事实并非如此.
我有一个不是线程安全的C库- 可能永远不会.我用PInvoke从C#调用它,这很好用.
现在必须从C#程序调用C库,这个程序肯定是多线程的.我可以在C#中通过从单独的AppDomains调用每个C代码实例来管理它,除了看起来效果不佳.我仍然在C库中遇到很多跨线程问题.
AppDomains是否会将C代码混乱(全局等等)彼此隔离或不隔离?如果没有,会是什么?
这是通过C#3e(Microsoft)出现在书籍CLR中的代码 但是它在运行时给出了错误
未处理TypeLoadException无法从程序集"CLRviaCSharp,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null"加载类型"MarshalByRefType".
除了方法'Main'之外,所有代码都是上面提到的书.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;
using System.Runtime.Remoting;
namespace CLRviaCSharp
{
class Program
{
static void Main(string[] args)
{
Marshalling();
}
private static void Marshalling()
{
// Get a reference to the AppDomain that that calling thread is executing in
AppDomain adCallingThreadDomain = Thread.GetDomain();
// Every AppDomain is assigned a friendly string name (helpful for debugging)
// Get this AppDomain’s …Run Code Online (Sandbox Code Playgroud) 我正在使用反射来扫描文件夹中的所有程序集,以实现实现特定接口并从特定基类派生的类型。代码如下:
foreach (string file in Directory.GetFiles(folder, "*.dll"))
{
Assembly assembly = Assembly.LoadFile(file);
Type foundType = (from type in assembly.GetTypes()
where type.GetInterfaces().Contains(typeof(TInterface))
&& type.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`')
select type).FirstOrDefault();
if (foundType == default(Type)) { continue; }
// Register our type so we don't need to use reflection on subsequent requests.
DependencyContainer.Register(typeof(TInterface), foundType);
return CreateInstance<TInterface>(foundType);
}
Run Code Online (Sandbox Code Playgroud)
在代码审查期间,针对这段代码提出了两个问题。首先,一旦找到匹配的类型,我们将无法缩短循环;如果发现多个匹配类型,则需要遍历每个文件并引发异常。那把我带到这里真正的问题...
代码审查者想知道是否有更好的方法来加载每个文件。出于性能原因,我们想知道是否可以遍历应用程序域中已加载的文件,而不是调用Assembly.LoadFile(file)每个文件。我们认为,为什么要加载每个已加载的文件?这是一个有效的问题吗?这种加载文件的方式与将文件加载到应用程序域中的方式相同吗?什么是遍历每个文件的有效方法,这样我们就不会浪费处理时间?
注意:Assembly.LoadFile()的文档不是很有帮助:
在指定路径上加载程序集文件的内容。
我不确定这是否等同于将文件加载到应用程序域中的方式,还是完全不同的情况。