PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Возможно ли использование библиотек .net в PureBasic?


Возможно ли использование библиотек .net в PureBasic?

Сообщений 1 страница 6 из 6

1

Здравствуйте.
Для одного из проектов возникла необходимость отслеживать температуру процессора.
Поиски в Google привели к осознанию того, что проблема довольно сложная, а готовых некоммерческих решений практически нет.
Одно из таких решений -  Open Hardware Monitor. А точнее входящая в его состав OpenHardwareMonitorLib.dll, но проблема заключается в том, что это библиотека классов для .NET Framework 2.0.
Можно ли как-то прикрутить ее к программе, написанной на PureBasic?
Догадываюсь, что нельзя, но возможно существуют какие-нибудь «костыли».
Вот примеры использования данной библиотеки на C# и VB.NET.

Отредактировано katod (05.03.2020 13:44:18)

0

2

Теоретически это возможно. https://www.purebasic.fr/english/viewto … mp;t=48578

0

3

Как я понял, они используют библиотеку DispHelper или COMatePLUS, чтобы работать с библиотекой .NET средствами COM.
Поиски в интернете по данной теме привели к следующим выводам: во-первых, .NET библиотека должна быть скомпилирована с атрибутом COMVISIBLE в значении True; во-вторых, такую библиотеку нужно вручную регистрировать в системе при помощи утилиты RegAsm из состава .NET Framework.

Утилита RegAsm не смогла зарегистрировать актуальную версию OpenHardwareMonitorLib.dll скачанную с сайта автора, но мне удалось найти исправленную версию здесь.

Тестовая программа выглядит так:

Код:
XIncludeFile "COMatePLUS\COMatePLUS.pbi"

Global computer.COMateObject

If OpenWindow(0, 0, 0, 300, 200, "COMate .NET", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  computer = COMate_CreateObject("OpenHardwareMonitor.Hardware.Computer")
  If computer
    Debug #S_OK
    Debug computer\Invoke("Open()")
    Debug computer\SetProperty("CPUEnabled = #True")
    Debug computer\GetStringProperty("Hardware(0)\Name")

    Repeat
    Until WaitWindowEvent() = #PB_Event_CloseWindow

    Debug computer\Invoke("Close()")
    Debug computer\Release()
  EndIf
EndIf

End

Явных ошибок не выдает, но не возвращает имя компонента системы через GetStringProperty.
Насколько я понял, свойство Hardware является массивом объектов типа Hardware.
Проблема усугубляется тем, что я мало что понимаю в COM и .NET.

Поправка: Похоже, недостаточно просто добавить атрибут COMVISIBLE, для классов, содержащихся в библиотеке. Нужно добавлять также интерфейсы для классов с описанием экспортируемых методов и свойств. Моих познаний в C# будет явно недостаточно, плюс нет времени и желания копаться в чужом коде.

Отредактировано katod (14.03.2020 00:53:47)

0

4

Тем не менее, мне удалось решить поставленную задачу немного другим способом, выкладываю его ниже, может быть мой опыт будет кому-то полезен.

Вместо того чтобы переписывать исходники чужой библиотеки, нужно просто написать свою библиотеку-обертку для нее.

Этот код для PascalABC.NET демонстрирует пример реализации данного подхода.

Код:
library OhmlWrapper;

{$reference 'OpenHardwareMonitorLib.dll'}

uses
  System.Runtime.InteropServices, OpenHardwareMonitor.Hardware;

type
  [Guid('AFB4EA0D-85DD-4407-BDD4-A602F0CF2A81')]
  [InterfaceType(COMInterfaceType.InterfaceIsDual)]
  [ComVisible(True)]
  IProcessor = interface
    [DispId(1)]
    procedure Open();
    [DispId(2)]
    procedure Close();
    [DispId(3)]
    function Name(): String;
    [DispId(4)]
    function Temperature(): Single;
  end;
  
  [Guid('B3BD284F-BC3D-4EE1-9A42-2BA6C9E7FC99')]
  [ClassInterface(ClassInterfaceType.None)]
  [ProgId('OhmlWrapper.Processor')]
  [ComVisible(True)]
  TProcessor = class(IProcessor)
    private Computer: OpenHardwareMonitor.Hardware.Computer = nil;
    
    public procedure Open();
    begin
      if Computer = nil then
      begin
        Computer := new OpenHardwareMonitor.Hardware.Computer;
        
        Computer.Open;
        Computer.CPUEnabled := True;
      end
    end;
    
    public procedure Close();
    begin
      if Computer <> nil then
      begin
        Computer.Close;
        
        Computer := nil;
      end;
    end;
    
    public function Name(): String;
    begin
      Result := 'Error';
      
      if Computer <> nil then
      begin
        for var i := 0 to Computer.Hardware.Count - 1 do
          if Computer.Hardware[i].HardwareType = HardwareType.CPU then
          begin
            Result := Computer.Hardware[i].Name;
            
            Break;
          end;
      end;
    end;
    
    public function Temperature(): Single;
    begin
      Result := 3.14;
      
      if Computer <> nil then
      begin
        for var i := 0 to Computer.Hardware.Count - 1 do
          if Computer.Hardware[i].HardwareType = HardwareType.CPU then
          begin
            Computer.Hardware[i].Update;
            
            for var j := 0 to Computer.Hardware[i].Sensors.Count - 1 do
              if Computer.Hardware[i].Sensors[j].SensorType = SensorType.Temperature then
              begin
                Result := Computer.Hardware[i].Sensors[j].Value.Value;
                
                Break;
              end;
            
            Break;
          end;
      end;
    end;
  end;

begin
end.

Данный пример извлекает только имя процессора и его температуру, но ничего не мешает нарастить функциональность до всей доступной для актуальной версии OpenHardwareMonitorLib.dll.

Выбор PascalABC.NET обусловлен только личными предпочтениями, на самом деле подойдет любой .NET ориентированный язык программирования, конечно с соответствующими правками кода.

На этапах компиляции и выполнения библиотека OpenHardwareMonitorLib.dll должна находиться в одном каталоге с библиотекой-оберткой.

Ссылки:
Актуальная версия OpenHardwareMonitor.
Немного теории COM Interop.
Примеры реализации здесь, здесь и здесь.

Отредактировано katod (14.03.2020 16:46:59)

0

5

Итак, теперь у нас есть библиотека-обертка OhmlWrapper.dll, осталось зарегистрировать ее в системе при помощи утилиты RegAsm.exe.

Самый простой способ – это создать пакетный файл, содержащий необходимые команды.

Для регистрации:

Код:
rem C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe OhmlWrapper.dll /unregister
rem C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe OhmlWrapper.dll /codebase
rem C:\Windows\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe OhmlWrapper.dll /unregister
rem C:\Windows\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe OhmlWrapper.dll /codebase

C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe OhmlWrapper.dll /unregister
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe OhmlWrapper.dll /codebase
rem C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe OhmlWrapper.dll /unregister
rem C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe OhmlWrapper.dll /codebase

pause

Для отмены регистрации:

Код:
rem C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe OhmlWrapper.dll /unregister
rem C:\Windows\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe OhmlWrapper.dll /unregister

C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe OhmlWrapper.dll /unregister
rem C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe OhmlWrapper.dll /unregister

pause

Путь к RegAsm.exe может отличаться в зависимости от расположения системного каталога и версии .NET Framework.

Важно соблюдать разрядность и версию .NET Framework и регистрируемой библиотеки, кроме того, запускать пакетный файл придется от имени администратора.

Подробнее про утилиту RegAsm.

Отредактировано katod (14.03.2020 18:00:45)

0

6

Наконец, вишенка на торте, программа демонстрирующая результат наших действий.

Код:
XIncludeFile "COMatePLUS\COMatePLUS.pbi"

Global Processor.COMateObject

Processor = COMate_CreateObject("OhmlWrapper.Processor")
If Processor
  If OpenWindow(0, 0, 0, 400, 80, "OhmlWrapperTest", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    If LoadFont(0, "Arial", 10)
      SetGadgetFont(#PB_Default, FontID(0))
    EndIf
    
    TextGadget(0, 10, 10, 380, 25, "CPU Name: ")
    TextGadget(1, 10, 45, 380, 25, "CPU Temperature: ")
    
    AddWindowTimer(0, 0, 1000)
    
    Processor\Invoke("Open()")
    
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_Timer
          If EventTimer() = 0
            SetGadgetText(0, "CPU Name: " + Processor\GetStringProperty("Name()"))
            SetGadgetText(1, "CPU Temperature: " + StrF(Processor\GetRealProperty("Temperature()"), 2) + " °C")
          EndIf
        Case #PB_Event_Gadget
        Case #PB_Event_CloseWindow
          Break
      EndSelect
    ForEver
    
    Processor\Invoke("Close()")
  EndIf
  Processor\Release()
EndIf

End

Думаю, код в пояснениях не нуждается, актуальную версию COMatePLUS можно скачать здесь.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Возможно ли использование библиотек .net в PureBasic?