我试图在我的rust可执行文件中使用Network Monitor 3.4的功能:为了做到这一点,我在以下地方添加了以下文件:
target\debug\deps
中的NmApi.lib
target\debug
中的NMAPI.dll
然后我根据应用内文档创建了一些绑定,如下所示:
// NMAPI module
use crate::shared::types::*;
#[link(name="NmApi")]
extern "system" {
pub fn NmCreateCaptureFile(pFileName: LPCWSTR, ulSize: ULONG, ulFlags: ULONG, phCaptureFile: PHANDLE, pulReturnSize: PULONG) -> ULONG;
pub fn NmOpenCaptureEngine(pCaptureEngine: PHANDLE) -> ULONG;
pub fn NmConfigAdapter(hCaptureEngine: HANDLE, ulIndex: ULONG, CallbackFunction: NM_FRAME_CALLBACK,
pCallerContext: LPVOID, CaptureCallbackExitMode: NmCaptureCallbackExitMode) -> ULONG;
pub fn NmStopCapture(pCaptureEngine: HANDLE, adapterInedx: ULONG);
pub fn NmCloseHandle(objectHandle: HANDLE);
pub fn NmAddFrame(hCaptureFile: HANDLE, hFrame: HANDLE) -> ULONG;
pub fn NmStartCapture(hCaptureEngine: HANDLE, ulAdapterIndex: ULONG, CaptureMode: NmAdapterCaptureMode) -> ULONG;
}
// types module
pub type DWORD = u32;
pub type CHAR = u8;
pub type LONG = i32;
pub type ULONG = u32;
pub type PULONG = *mut ULONG;
pub type VOID = c_void;
pub type LPVOID = *mut VOID;
pub type LPCWSTR = *mut u16;
pub type HANDLE = *mut c_void;
pub type PHANDLE = *mut HANDLE;
#[derive(PartialEq)]
#[repr(u32)]
pub enum BOOL {
TRUE = 1,
FALSE = 0,
}
impl BOOL {
const TRUE_LITERAL: &'static str = "true";
const FALSE_LITERAL: &'static str = "false";
}
impl Debug for BOOL {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct(&format!("BOOL {}",if *self == Self::TRUE {Self::TRUE_LITERAL} else {Self::FALSE_LITERAL}))
.finish()
}
}
pub type NM_FRAME_CALLBACK = Option<unsafe extern "system" fn ( _: HANDLE, _: ULONG, _: LPVOID, _: HANDLE)>;
#[repr(u32)]
pub enum NmCaptureCallbackExitMode {
DiscardRemainFrames = 1,
ReturnRemainFrames = 2,
}
#[repr(u32)]
pub enum NmAdapterCaptureMode {
NmLocalOnly = 0,
NmPromiscuous = 1,
}
之后,我尝试复制下面的例子(来自应用内文档)
#include "Stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "objbase.h"
#include "ntddndis.h"
#include "NMApi.h"
void __stdcall
MyFrameIndication(HANDLE hCapEng, ULONG ulAdaptIdx, PVOID pContext, HANDLE hRawFrame)
{
HANDLE capFile = (HANDLE)pContext;
NmAddFrame(capFile, hRawFrame);
}
int __cdecl wmain(int argc, WCHAR* argv[])
{
ULONG ret;
ULONG adapterIndex = 0;
if(2 == argc)
adapterIndex = _wtol(argv[1]);
// Open a capture file for saving frames.
HANDLE myCapFile;
ULONG CapSize;
ret = NmCreateCaptureFile(L"20sec.cap", 20000000, NmCaptureFileWrapAround, &myCapFile, &CapSize);
if(ret != ERROR_SUCCESS)
{
wprintf(L"Error opening capture file, 0x%Xn", ret);
return ret;
}
// Open the capture engine.
HANDLE myCaptureEngine;
ret = NmOpenCaptureEngine(&myCaptureEngine);
if(ret != ERROR_SUCCESS)
{
wprintf(L"Error opening capture engine, 0x%Xn", ret);
NmCloseHandle(myCapFile);
return ret;
}
//Configure the adapter.
ret = NmConfigAdapter(myCaptureEngine, adapterIndex, MyFrameIndication, myCapFile);
if(ret != ERROR_SUCCESS)
{
wprintf(L"Error configuration adapter, 0x%Xn", ret);
NmCloseHandle(myCaptureEngine);
NmCloseHandle(myCapFile);
return ret;
}
//Start capturing frames.
wprintf(L"Capturing for 20 secondsn");
NmStartCapture(myCaptureEngine, adapterIndex, NmLocalOnly);
Sleep(20000);
wprintf(L"Stopping capturen");
NmStopCapture(myCaptureEngine, adapterIndex);
NmCloseHandle(myCaptureEngine);
NmCloseHandle(myCapFile);
return 0;
}
的实现:
pub unsafe extern "system" fn _MyFrameIndication(hCaptureEngine: HANDLE, adapterIndex: ULONG, pContext: LPVOID, hRawFrame: HANDLE) {
let hCapFile: HANDLE = pContext as HANDLE;
let ret = unsafe { NmAddFrame(hCapFile, hRawFrame) };
println!("capturing frame: got code {}",ret);
}
pub const MyFrameIndication: NM_FRAME_CALLBACK = Some(_MyFrameIndication);
fn main () {
let mut myCapFile: HANDLE = unsafe { zeroed() };
let mut CapSize: ULONG = unsafe { zeroed() };
let mut pname: Vec<u16> = OsStr::new("20sec.cap").encode_wide().chain(once(0)).collect();
unsafe {
println!("opening capture file: code is {}",NmCreateCaptureFile(pname.as_mut_ptr(),
2000, 0,
&mut myCapFile as PHANDLE,
&mut CapSize));
};
let mut myCaptureEngine: HANDLE = unsafe { zeroed() };
let ret = unsafe { NmOpenCaptureEngine(&mut myCaptureEngine) };
println!("acquiring capture engine: code is {}", ret);
let ret = unsafe { NmConfigAdapter(myCaptureEngine,
0, MyFrameIndication,
myCapFile,
NmCaptureCallbackExitMode::DiscardRemainFrames) };
println!("configuring adapter: code is {}", ret);
let ret = unsafe {NmStartCapture(myCaptureEngine, 0, NmAdapterCaptureMode::NmLocalOnly)};
println!("starting capture: code is {}",ret);
let before = SystemTime::now();
while (SystemTime::now().duration_since(before).unwrap().as_secs() < 25) {
}
println!("stopping capture");
unsafe {
NmStopCapture(myCaptureEngine, 0)
};
println!("releasing handles");
unsafe {
NmCloseHandle(myCaptureEngine);
NmCloseHandle(myCapFile);
}
}
之后,我构建了二进制文件,没有任何错误,并启动了它:控制台窗口出现,所有代码的输出为0,即ERROR_SUCCESS
的值,这意味着函数被正确调用。
但是在工作目录中没有任何文件出现。此外,回调函数中没有打印任何内容。
有谁能帮我一下吗?我用了一段时间,甚至不知道如何调试它。注:我试着把。lib和。dll文件放在生成的exe的cwd中,也没有改变任何东西。
更新:
我尝试创建新项目,并在.cargo子目录中包含以下配置文件:
[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
rustc-link-lib = {name="NmApi"}
rustc-link-search = {path="C:\Users\grass\Desktop\codes\Rust\cpp_xport\res"}
中的目标是我的默认值。可惜没有改变什么
所以经过一段时间的思考和rust discord社区的一些帮助后,我弄清楚了,希望它能为其他人节省时间。问题是,由于网络接口0是一个以太网接口,所以它不是活动的,并且filename参数实际上应该是一个路径。因此,将文件名转换为绝对路径并使用我的Wi-Fi接口的索引(基本上在ipconfig all的输出中从零开始计数)导致生成捕获文件。