【问题标题】:C# Class Library How To Add Startup Code [duplicate]C#类库如何添加启动代码[重复]
【发布时间】:2014-12-18 13:51:54
【问题描述】:

以下是在服务器上首次调用 DLL 时如何编写 C++ 功能来执行某些操作。在 C# 类库中如何做到这一点?对于 Visual Studio 中的类库项目,属性中的启动是灰色的(禁用),但需要是库,因为我在我的 Web 应用程序中使用它作为参考。并且不知道如何在 C# 中编写等效的代码,因此我可以编写一些代码来在加载或启动 dll 时记录事件。

BOOL WINAPI DllMain(
  HINSTANCE hinstDLL, // handle to DLL module
   DWORD fdwReason, // reason for calling function
   LPVOID lpReserved ) // reserved
{
   // Perform actions based on the reason for calling.
   switch( fdwReason )
   {
     case DLL_PROCESS_ATTACH:
        // Initialize once for each new process.
        // Here is where the module POST should be invoked
        // Return FALSE to fail DLL load in case POST fails
     break;
     case DLL_THREAD_ATTACH:
        // Do thread-specific initialization.
     break;
     case DLL_THREAD_DETACH:
     // Do thread-specific cleanup.
     break;
     case DLL_PROCESS_DETACH:
     // Perform any necessary cleanup.
     break;
     }
     return TRUE; // Successful DLL_PROCESS_ATTACH.
}

【问题讨论】:

  • 因为我在我的 Web 应用程序中使用它作为参考 如果它托管在 IIS 中,请使用该应用程序启动前属性。 dailydotnettips.com/2011/08/27/…
  • “Visual Studio 中的类库项目的属性中的启动是灰色的(禁用),但需要是库,因为我在我的 Web 应用程序中使用它作为参考。” i> -- 你可以像引用类库一样引用其他项目的可执行程序集。

标签: c# c++ multithreading visual-studio startup


【解决方案1】:

我在我的网络应用程序中使用它作为参考

如果它托管在 IIS 中,您可以使用 PreApplicationStartMethodAttribute 在应用程序启动的早期运行代码。

这允许您执行一次性初始化,但可能会在必要之前强制初始化,因为 IIS 将在应用程序启动时运行您的代码,而不是在您第一次使用程序集中的类时运行。

如何在 C# 中编写等效的代码,以便在加载或启动 dll 时编写一些代码来记录事件。

DllMain 有一些非常严格的限制。无论如何,你不能指望能够可靠地从DllMain 记录事件,所以没有先例“我可以在 C++ 中这样做,现在我如何在 C# 中做到这一点”。

【讨论】:

  • 日志记录可以是安全的:“在DllMain 内可以安全地执行以下任务 - 打开、读取和写入文件。”只要您不使用 C# 执行此操作:“您永远不应该在 DllMain 中执行以下任务 - 使用托管代码” - msdn.microsoft.com/en-us/library/windows/desktop/…
【解决方案2】:

C# 中没有这样的结构。 C# 是一种面向对象的语言,因此所有*可执行代码都驻留在类中。 CLR 支持这种初始化,但在 C# 或 VB.NET 中不可用。

ASP.NET 确实支持可以添加到程序集以在启动时执行代码的属性,但它是特定于 ASP.NET 的;例如,当您将程序集加载到 WPF 应用程序时,它不会被执行。

但是,意味着您不需要在 C# 中的库初始化代码。如果您有代码需要在使用程序集中的类之前运行,请使用这些类的静态或实例构造函数进行适当的初始化。

如果您有不适合在构造函数中运行的昂贵代码,我的下一个选择是记录在案的Init 方法,您可以在其中允许用户选择何时运行初始化代码。如果用户选择在启动时不运行(或者不知道,则在需要初始化时运行(构造函数、成员访问等)

*我希望这是一些深奥的例外,但我想不出

【讨论】:

  • 一个例外:当您必须预先缓存值或对象并且操作非常广泛时。如果它可以在启动期间启动,那么当用户触发一个读取该值的操作时......他不会等待。当然你可以在你的 Main() 中放一些初始化代码,但是......最好避免。
  • 全局对象的初始化器存在于类之外。这不是很深奥,是吗?这不正是 C# 使用您在第一段中提到的 CLR 初始化的方式吗?
【解决方案3】:

我不确定这是否是最好的方法,但您可以使用静态构造函数,例如:

public static class Class1
{
    static Class1()
    {
       //this constructor will be called the first time this class is used.
    }
}

请注意,在第一次使用 DLL 的任何静态成员之前不会调用此构造函数,这就是为什么这可能不是最佳方法的原因。但是,您当然可以在实例构造函数中处理任何基于实例的初始化。

【讨论】:

  • 它会在第一个静态成员被访问时调用,而不是在加载 DLL 时调用。如果您在 2 小时后访问 Class1……它将在 2 小时后被调用。如果您永远不会调用任何成员,则根本不会调用它。 DLL 加载时调用 DllMain...
  • @AdrianoRepetti -- 引用的程序集根据需要加载,而不是在应用程序首次启动时加载。因此,如果第一次需要它是在使用静态成员时——无论是马上还是两个小时后——那么就是静态构造函数运行的时候。但是您确实指出了一件事:它只会在引用静态成员时运行。
  • 除非显式加载,但无论如何我们都不知道更多关于 OP 场景的信息,我的核心思想只是:[在 C# 中] 加载 DLL 时你没有任何内容,调用者应该触发你的代码以某种方式。
猜你喜欢
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多