【问题标题】:GDI+ Window preventing ShutdownGDI+ 窗口防止关机
【发布时间】:2014-07-01 13:01:27
【问题描述】:

我正在使用 C# 和 .NET Framework 2.0 为 Server 2003 进行开发

只要程序运行,我就无法关闭我的机器。什么都没有发生,但是当 alt+tabbing 时,我可以看到一个名为“GDI+ Window”的窗口。只要我关闭我的程序,我就可以正常关闭计算机。

但是,在我的其他计算机(Windows XP Professional、Windows 8、Windows 8.1)上却没有。

程序从数据库中提取数据并将它们发送到互联网,所以我有一个线程在后台运行。会不会有问题?

主类中的代码如下:

public partial class Form1 : Form
{
    bool run = true;
    //AutoStart autoS = new AutoStart();
    int interval;
    //LogFileBuilder lfboom = new LogFileBuilder(true);*/

    public Form1()
    {
        InitializeComponent();
        /*OpenOnce();
        //autoS.EintragHinzufügen();
        WriteMe();
        LogFileBuilder lfb = new LogFileBuilder();
        lfb.writeLine("Programm gestartet");
        new Thread(Durchführung).Start();*/
    }
}

当然,表单中还有其他方法和事件处理程序,但它们不相关,因为在重现此问题时不会调用它们。如您所见,我已经注释掉了除 InitializeComponents() 之外的整个代码,但问题仍然存在。

复制步骤:
1.打开程序
2. 关闭服务器
3.除了alt+tab列表中新增的“GDI+窗口”,没有任何反应,无法打开

【问题讨论】:

  • 我建议重新考虑是否需要为在后台运行并从数据库中提取信息并将其发送到 Internet 的程序显示 UI。如果不创建任何类型的 UI,则不会初始化 GDI+,也不会创建此窗口。
  • 我考虑过UI,但它很重要,因为我必须经常更改一些数据,这样更方便,并且可以结构化显示信息。我从您的链接中插入了示例代码,但我得到了一个 TypeLoadException。附加信息:无法加载程序集“MyProject,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”中的类型“MyProject.Form1”,因为方法“SetForegroundWindow”没有实现(无 RVA) . (由我免费翻译)
  • 如果 UI 仅用于配置,我会将 UI 从正常模式中分离出来。也许使用命令行参数,例如/config。这将导致 UI 出现,否则正常运行应用程序将不会显示 UI。即使没有可用的桌面,它也可以在后台运行。
  • 但是我不是必须再次关闭 UI 才能关闭 PC 吗?这对我来说实际上是一个非常大的问题,因为它将安装在多台计算机上,有些人不会考虑在关闭 PC 之前关闭程序,所以它必须 100% 稳定。

标签: c# gdi+ windows-server-2003


【解决方案1】:

正如Cody Gray 所指出的,当 GDI+ 子系统初始化并保持前台窗口时,存在已知条件。 KB article 943453 中提供的解决方案是在主窗体加载后显式设置前台窗口,如下所示:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    //using System.Runtime.InteropServices;
    // tell the runtime to use the user32.dll for implementation of the next method
    [DllImport("user32.dll")]
    // what is returned by this method
    [return: MarshalAs(UnmanagedType.Bool)]
    // the methed to call in User32
    // upper/lower case is important
    static extern bool SetForegroundWindow(IntPtr hWnd);

    private void Form1_Load(object sender, EventArgs e)
    {
        SetForegroundWindow(this.Handle);
    }
} 

在您声称您尝试过但遇到类型加载异常的 cmets 中:

System.TypeLoadException 未处理 消息:mscorlib.dll 中发生了“System.TypeLoadException”类型的未处理异常
附加信息:无法从程序集“App, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”加载类型“App.Form1”,因为方法“SetForegroundWindow”没有实现(无 RVA)。

这是因为SetForegroundwindow没有应用[Dllimport]属性。我可以通过用[Dllimport] 注释该行来重现该异常。没有它,您的代码将编译,但因为方法 SetForegroundWindow 将没有任何实现,运行时拒绝加载您的类型,因此出现异常。

在技术意义上,RVA 代表相对虚拟地址,它是模块基地址的偏移量。查找项目 RVA 并将其添加到基地址将返回项目(方法、数据等)开始指针。如果因为没有要执行的内容而没有要查找的内容,则无法安全地执行该模块。有关更多背景信息,请参阅https://msdn.microsoft.com/en-us/library/ms809762.aspx

所以总结一下,调用时的代码如下

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

将执行this unmanaged method in the WinAPI

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2020-06-26
    相关资源
    最近更新 更多