【问题标题】:C# Mono/.NET differential CAD software retrievementC# Mono/.NET 差分 CAD 软件检索
【发布时间】:2012-01-22 02:40:02
【问题描述】:

好的,我会尽力而为,但我认为我的英语在涉及复杂的主题/短语时仍然太糟糕了。

我必须构建一个类(目前它不是静态的)来检索有关外部应用程序(客户 PC 上可用的软件)的信息。

Linux 类很容易编写代码,但现在我必须在 Windows 上实现它。

基本上,我在从我的应用程序的 x86 版本读取 x64 注册表时遇到了一些困难:您只能通过使用 [DllImport("advapi32.dll")] 来做到这一点。

从一开始我就知道软件退役很大程度上取决于目标操作系统,所以我创建了 4 个类:

public abstract ExternalApplications 定义了一些基本方法,由ExternalApplicationsWinExternalApplicationsMacExternalApplicationsUnix 派生而来。

在我的应用程序中,我创建了一个 ExternalApplications 实例并通过切换操作系统类型来分配它:

ExternalApplications ex = null;

switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT:
   goto default;
case PlatformID.MacOSX:
   _ex = new ExternalApplicationsMac(); break;
case PlatformID.Unix:
   _ex = new ExternalApplicationsUnix(); break;
default:
   _ex = new ExternalApplicationsWin(); break;
}

这样,方法调用将自动分派到正确的 ExternalApplicationsXXX 类型。

现在通过介绍[DllImport("advapi32.dll")],我有义务:

  • 更改类结构(为静态外部)
  • 它可能会在 Unix/Mac OS X 编译(使用 DllNotFoundException)

有几种选择: (1) 我可以为 Linux、Mac 和 Windows 创建 3 个具有相同目标程序集名称的并行项目 (.cproj)。这些项目将包含相同的类和方法,因此我可以在我的应用程序中毫无问题地引用它。

这个选项很糟糕,它缺乏自动化:一切都是手动完成的。

(2) 我可以使用 C# 指令来完成预防性的“DllImport”代码排除

#if !MONO
...
#endif

我确信还有许多其他方法,例如 DLLMAP 和其他方法。 我认为更有经验的程序员会告诉我什么是最优雅/最可靠的解决方案。

编辑 1:

我刚刚发现可以从 x86 应用程序读取 x64 注册表配置单元,但仅限于 .NET 4.0 及更高版本(根据我的来源,仍需要测试)。

string registryBranchPath = "SOFTWARE\MySoft";
RegistryKey regKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
regKey = regKey.OpenSubKey(registryBranchPath);

这仅解决了我的问题的一部分,另一部分(关于在 Windows 特定的非静态类中使用 DllImport 的可能性)仍有待确认/测试。

【问题讨论】:

  • 个人而言,如果我在进行单独的构建,我将有一个类(或者可能具有相同名称的克隆),其代码由编译时常量指定
  • 我有点困惑。问题似乎与注册表有关,它甚至在 OSX/Linux 上都不可用。为什么不尽可能使用适用于所有平台的“设置”策略?
  • 在我的应用程序中,我必须检测 CAD 引擎安装。在 linux 上我可以读取“which bricscad”命令的输出,而在 Windows 中我必须读取注册表项。

标签: c# winapi mono registry 32bit-64bit


【解决方案1】:
  1. 你的类不需要是static,只有导入的外部方法被标记为这样。此外,导入的方法应该标记为private,因为除了导入类之外,什么都不能直接调用它。

  2. 您不需要任何花哨的编译技巧/代码拆分,DllImport 在实际调用之前不会被检查。

来自MSDN documentation for DllImport的例子:

using System;
using System.Runtime.InteropServices;

class Example
{
    // Use DllImport to import the Win32 MessageBox function.
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int MessageBox(IntPtr hWnd, String text, 
      String caption, uint type);

    public void MessageBox()
    {
        // Call the MessageBox function using platform invoke.
        MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);
    }
}

【讨论】:

  • 1 - 请为我提供第一点的示例或链接? 2 - 这是一件很棒的事情!我不知道 Invoke 是在运行时完成的,我认为编译器会在编译期间以某种方式测试/探测所有这些库。
  • 好的,现在我明白了。谢谢,即使我最初的问题与 x64 注册表读取有关,您的解决方案对其他人和我来说都更有趣。
【解决方案2】:

所以对我来说最终的解决方案看起来像这个简化的 sn-p:

public static class UsageClass
{
    private static ExternalApplications _extApps;

    public static void Initialize()
    {
        _extApps = null;

        switch (Environment.OSVersion.Platform)
        {
            case PlatformID.Win32NT:
                goto default;
            case PlatformID.MacOSX:
                _extApps = new ExternalApplicationsMac(); break;
            case PlatformID.Unix:
                _extApps = new ExternalApplicationsUnix(); break;
            default:
                _extApps = new ExternalApplicationsWin(); break;
        }
    }

    internal abstract class ExternalApplications
    {
        public abstract string[] DoSomething();
    }

    internal class ExternalApplicationsWin : ExternalApplications
    {
        public abstract void DoSomething()
        {
            // Windows code
            RegistryKey regKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                (Environment.Is64BitOperatingSystem) ? RegistryView.Registry64 : RegistryView.Registry32).OpenSubKey("SOFTWARE\MySoft");
            ...

        }
    }

    internal class ExternalApplicationsUnix : ExternalApplications
    {
        public abstract void DoSomething()
        {
            // Unix code
        }
    }

    internal class ExternalApplicationsMac : ExternalApplications
    {
        public abstract void DoSomething()
        {
            // Mac code
        }
    }
} 

【讨论】:

    猜你喜欢
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 2016-11-17
    • 2019-06-22
    • 2020-04-22
    • 2013-04-02
    相关资源
    最近更新 更多