简体   繁体   English

NetFileEnum返回ERROR_MORE_DATA

[英]NetFileEnum returns ERROR_MORE_DATA

Attempting to retrieve a large list of open files from a file server returns the ERROR_MORE_DATA value (Error number 234), but works fine when dealing with only a small list of files (seems to return around 84 entries). 尝试从文件服务器中检索打开的文件的较大列表将返回ERROR_MORE_DATA值(错误号234),但在仅处理少量文件列表时就可以正常工作(似乎可以返回约84个条目)。 This code is based upon the example at: http://pinvoke.net/default.aspx/netapi32/NetFileEnum.html 此代码基于以下示例: http : //pinvoke.net/default.aspx/netapi32/NetFileEnum.html

Most examples I have found don't really touch on how to handle a large number of files. 我发现的大多数示例并没有真正涉及如何处理大量文件。 From my understanding, this has something to do with the resume_handle, however I'm not sure what needs to be done. 据我了解,这与resume_handle有关,但是我不确定需要做什么。 Do I need to somehow call this method in a loop? 我是否需要以某种方式在循环中调用此方法?

Code is as follows: 代码如下:

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;
        }
    }
}

In my limited experience a very large number of results can be larger than the max buffer. 以我有限的经验,非常多的结果可能会比最大缓冲区大。 In this case a more data response is given and instructs us to call again with the provided resume handle. 在这种情况下,会给出更多的数据响应,并指示我们使用提供的恢复句柄再次调用。 In your example, the resume handle will not be changed because the DllImport signature doesn't define it as an out parameter. 在您的示例中,恢复句柄将不会更改,因为DllImport签名未将其定义为out参数。 Using the resume handle result from the first call (passing in zero means first call) allows you to receive the next batch. 使用第一个调用的恢复句柄结果(传递零表示第一个调用)可以接收下一批。 Loop until you receive a success response or some other error. 循环播放,直到收到成功响应或其他错误。

Be sure to fix the issue where the NetFileEnum signature is defined. 确保解决了定义NetFileEnum签名的问题。 The resume handle is not defined with an out so cannot be changed by the called function. 简历句柄未使用out定义,因此被调用的函数无法更改。

Try the following DLL Import signature instead: 请尝试以下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
);

You should be able to re-call NetFileEnum with the resulting resume handle multiple times when you get a more data response. 当您获得更多数据响应时,您应该能够多次调用NetFileEnum及其结果的恢复句柄。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM