NetFileEnum returns ERROR_MORE_DATA
NetFileEnum returns ERROR_MORE_DATA
正在尝试从文件服务器 return 中检索大量打开文件 ERROR_MORE_DATA 值(错误编号 234),但在仅处理少量文件时工作正常(似乎 return 大约 84 个条目)。此代码基于以下示例:http://pinvoke.net/default.aspx/netapi32/NetFileEnum.html
我发现的大多数示例并没有真正涉及如何处理大量文件。据我了解,这与 resume_handle 有关,但我不确定需要做什么。我是否需要以某种方式在循环中调用此方法?
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace OpenFiles
{
class Program
{
public static string computername = "computername";
static void Main(string[] args)
{
List<string> theFileList = NativeMethods.GetFiles(computername);
foreach (string file in theFileList)
{
Console.WriteLine(file);
}
}
}
static class NativeMethods
{
[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileEnum(
string servername,
string basepath,
string username,
int level,
ref IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
IntPtr resume_handle
);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct FILE_INFO_3
{
public int fi3_id;
public int fi3_permission;
public int fi3_num_locks;
[MarshalAs(UnmanagedType.LPWStr)]
public string fi3_pathname;
[MarshalAs(UnmanagedType.LPWStr)]
public string fi3_username;
}
[DllImport("Netapi32.dll", SetLastError = true)]
static extern int NetApiBufferFree(IntPtr Buffer);
public static List<string> GetFiles(string Computername)
{
const int MAX_PREFERRED_LENGTH = -1;
int dwReadEntries;
int dwTotalEntries;
IntPtr pBuffer = IntPtr.Zero;
FILE_INFO_3 pCurrent = new FILE_INFO_3();
List<string> fileList = new List<string>();
int dwStatus = NetFileEnum(Computername, null, null, 3, ref pBuffer, MAX_PREFERRED_LENGTH, out dwReadEntries, out dwTotalEntries, IntPtr.Zero);
if (dwStatus == 0)
{
for (int dwIndex = 0; dwIndex < dwReadEntries; dwIndex++)
{
IntPtr iPtr = new IntPtr(pBuffer.ToInt32() + (dwIndex * Marshal.SizeOf(pCurrent)));
pCurrent = (FILE_INFO_3)Marshal.PtrToStructure(iPtr, typeof(FILE_INFO_3));
string fileInfo = pCurrent.fi3_id + "," +
pCurrent.fi3_num_locks + "," +
pCurrent.fi3_pathname + "," +
pCurrent.fi3_permission + "," +
pCurrent.fi3_username;
fileList.Add(fileInfo);
}
NetApiBufferFree(pBuffer);
}
else
{
Console.WriteLine("error: " + dwStatus);
}
return fileList;
}
}
}
根据我有限的经验,大量结果可能会大于最大缓冲区。在这种情况下,会给出更多数据响应,并指示我们使用提供的恢复句柄再次调用。在您的示例中,恢复句柄不会更改,因为 DllImport 签名未将其定义为输出参数。使用第一次调用的恢复句柄结果(传入零表示第一次调用)允许您接收下一批。循环直到收到成功响应或其他错误。
务必解决定义 NetFileEnum 签名的问题。
恢复句柄没有用 out 定义,因此不能被调用的函数更改。
改为尝试以下 DLL 导入签名:
[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileEnum(
string servername,
string basepath,
string username,
int level,
ref IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
out IntPtr resume_handle
);
当您获得更多数据响应时,您应该能够使用生成的恢复句柄多次重新调用 NetFileEnum。
正在尝试从文件服务器 return 中检索大量打开文件 ERROR_MORE_DATA 值(错误编号 234),但在仅处理少量文件时工作正常(似乎 return 大约 84 个条目)。此代码基于以下示例:http://pinvoke.net/default.aspx/netapi32/NetFileEnum.html
我发现的大多数示例并没有真正涉及如何处理大量文件。据我了解,这与 resume_handle 有关,但我不确定需要做什么。我是否需要以某种方式在循环中调用此方法?
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace OpenFiles
{
class Program
{
public static string computername = "computername";
static void Main(string[] args)
{
List<string> theFileList = NativeMethods.GetFiles(computername);
foreach (string file in theFileList)
{
Console.WriteLine(file);
}
}
}
static class NativeMethods
{
[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileEnum(
string servername,
string basepath,
string username,
int level,
ref IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
IntPtr resume_handle
);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
struct FILE_INFO_3
{
public int fi3_id;
public int fi3_permission;
public int fi3_num_locks;
[MarshalAs(UnmanagedType.LPWStr)]
public string fi3_pathname;
[MarshalAs(UnmanagedType.LPWStr)]
public string fi3_username;
}
[DllImport("Netapi32.dll", SetLastError = true)]
static extern int NetApiBufferFree(IntPtr Buffer);
public static List<string> GetFiles(string Computername)
{
const int MAX_PREFERRED_LENGTH = -1;
int dwReadEntries;
int dwTotalEntries;
IntPtr pBuffer = IntPtr.Zero;
FILE_INFO_3 pCurrent = new FILE_INFO_3();
List<string> fileList = new List<string>();
int dwStatus = NetFileEnum(Computername, null, null, 3, ref pBuffer, MAX_PREFERRED_LENGTH, out dwReadEntries, out dwTotalEntries, IntPtr.Zero);
if (dwStatus == 0)
{
for (int dwIndex = 0; dwIndex < dwReadEntries; dwIndex++)
{
IntPtr iPtr = new IntPtr(pBuffer.ToInt32() + (dwIndex * Marshal.SizeOf(pCurrent)));
pCurrent = (FILE_INFO_3)Marshal.PtrToStructure(iPtr, typeof(FILE_INFO_3));
string fileInfo = pCurrent.fi3_id + "," +
pCurrent.fi3_num_locks + "," +
pCurrent.fi3_pathname + "," +
pCurrent.fi3_permission + "," +
pCurrent.fi3_username;
fileList.Add(fileInfo);
}
NetApiBufferFree(pBuffer);
}
else
{
Console.WriteLine("error: " + dwStatus);
}
return fileList;
}
}
}
根据我有限的经验,大量结果可能会大于最大缓冲区。在这种情况下,会给出更多数据响应,并指示我们使用提供的恢复句柄再次调用。在您的示例中,恢复句柄不会更改,因为 DllImport 签名未将其定义为输出参数。使用第一次调用的恢复句柄结果(传入零表示第一次调用)允许您接收下一批。循环直到收到成功响应或其他错误。
务必解决定义 NetFileEnum 签名的问题。 恢复句柄没有用 out 定义,因此不能被调用的函数更改。
改为尝试以下 DLL 导入签名:
[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileEnum(
string servername,
string basepath,
string username,
int level,
ref IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
out IntPtr resume_handle
);
当您获得更多数据响应时,您应该能够使用生成的恢复句柄多次重新调用 NetFileEnum。