#include #include #include #include "include.h" #include //回调函数,在C#版本的DLL中,我们需要实现IVisitor接口,并将其引用传给Computer。 //由于没有办法在C++里实现C#接口,考虑到IVisitor接口只包含函数,因此我提供了IVisitor的默认实现, //其实现为调用以下四个回调函数,它们的指针会被转换为C#委托供IVisitor的C#实现调用。 //注意!!哪怕提供空实现也要提供,要不然就不保证不出问题了。 void VisitComputerCallBack(IComputer& computer, Visitor* visitor) { computer.Traverse(visitor); } void VisitHardwareCallBack(Hardware& hardware, Visitor* visitor) { hardware.Update(); std::vector subHardwares = hardware.getSubHardware(); for (int i = 0; i < subHardwares.size(); i++) { subHardwares[i].Accept(visitor); } } void VisitSensorCallBack(Sensor& sensor, Visitor* visitor) { } void VisitParameterCallBack(Parameter& parameter, Visitor* visitor) { } void destroy(const Napi::CallbackInfo& info){ computer->Close(); computer=nullptr; CoUninitialize(); } // 使用智能指针管理资源 std::shared_ptr computer; std::shared_ptr visitor; // 封装 COM 初始化/卸载 struct ComInitializer { HRESULT hr; ComInitializer() { hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); } ~ComInitializer() { if (SUCCEEDED(hr)) { CoUninitialize(); } } }; void log(std::string log) { std::ofstream logfile; logfile.open("native_module.log", std::ios::app); logfile << log << std::endl; logfile.close(); } // 安全的初始化函数 Napi::Object init(Napi::Env env, Napi::Object exports) { log("Com initing"); ComInitializer comInit; // RAII 管理 COM 生命周期 // 检查 COM 初始化结果 if (FAILED(comInit.hr)) { log("Com init fail"); _com_error err(comInit.hr); Napi::Error::New(env, err.ErrorMessage()).ThrowAsJavaScriptException(); return exports; } log("Com inited"); computer = std::make_shared(); computer->setCpuEnabled(true); computer->setGpuEnabled(true); computer.setGpuEnabled(true); computer.setMotherboardEnabled(true); computer.setStorageEnabled(true); computer.setBatteryEnabled(true); computer.setControllerEnabled(true); computer.setMemoryEnabled(true); computer.setNetworkEnabled(true); computer.setPsuEnabled(true); computer->Open(); log("Computer inited"); visitor = std::make_shared(); visitor->setVisitComputerCallBack(VisitComputerCallBack); visitor->setVisitHardwareCallBack(VisitHardwareCallBack); visitor->setVisitParameterCallBack(VisitParameterCallBack); visitor->setVisitSensorCallBack(VisitSensorCallBack); visitor->commit(); computer->Accept(visitor.get()); // 传递原始指针 log("Visitor inited"); // 导出函数 exports.Set(Napi::String::New(env,"cpu_name"), Napi::Function::New(env, cpu_name)); exports.Set(Napi::String::New(env,"cpu_load"), Napi::Function::New(env, cpu_load)); exports.Set(Napi::String::New(env,"cpu_power"), Napi::Function::New(env, cpu_power)); exports.Set(Napi::String::New(env,"cpu_speed"), Napi::Function::New(env, cpu_speed)); exports.Set(Napi::String::New(env,"cpu_temperature"), Napi::Function::New(env, cpu_temperature)); exports.Set(Napi::String::New(env,"cpu_voltage"), Napi::Function::New(env, cpu_voltage)); exports.Set(Napi::String::New(env,"current_gpu_status"), Napi::Function::New(env, current_gpu_status)); exports.Set(Napi::String::New(env,"mem_clock"), Napi::Function::New(env, mem_clock)); exports.Set(Napi::String::New(env,"mem_free_size"), Napi::Function::New(env, mem_free_size)); exports.Set(Napi::String::New(env,"mem_used_size"), Napi::Function::New(env, mem_used_size)); exports.Set(Napi::String::New(env,"mem_name"), Napi::Function::New(env, mem_name)); exports.Set(Napi::String::New(env,"mem_size"), Napi::Function::New(env, mem_size)); exports.Set(Napi::String::New(env,"vmem_free_size"), Napi::Function::New(env, vmem_free_size)); exports.Set(Napi::String::New(env,"vmem_used_size"), Napi::Function::New(env, vmem_used_size)); exports.Set(Napi::String::New(env,"current_disk_used"), Napi::Function::New(env, current_disk_used)); exports.Set(Napi::String::New(env,"disk_name"), Napi::Function::New(env, disk_name)); exports.Set(Napi::String::New(env,"monitor_info"), Napi::Function::New(env, monitor_info)); exports.Set(Napi::String::New(env,"destroy"), Napi::Function::New(env, destroy)); log("Export inited"); return exports; } NODE_API_MODULE(hardware_monitor, init)