none
C# 调用API ReadFile和PeekNamedPipe该如何声明? RRS feed

  • 问题

  • BOOL WINAPI ReadFile(
     __in     HANDLE hFile,
     __out    LPVOID lpBuffer,
     __in     DWORD nNumberOfBytesToRead,
     __out_opt  LPDWORD lpNumberOfBytesRead,
     __inout_opt LPOVERLAPPED lpOverlapped
    );
    BOOL WINAPI PeekNamedPipe(
     __in    HANDLE hNamedPipe,
     __out_opt LPVOID lpBuffer,
     __in    DWORD nBufferSize,
     __out_opt LPDWORD lpBytesRead,
     __out_opt LPDWORD lpTotalBytesAvail,
     __out_opt LPDWORD lpBytesLeftThisMessage
    );
        //Takes in a device path and opens a handle to the device.
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern SafeFileHandle CreateFile(
          string lpFileName,
          uint dwDesiredAccess,
          uint dwShareMode, 
          IntPtr lpSecurityAttributes, 
          uint dwCreationDisposition,
          uint dwFlagsAndAttributes, 
          IntPtr hTemplateFile);
    //Uses a handle (created with CreateFile()), and lets us read USB data from the device.
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool ReadFile(
          SafeFileHandle hFile,
          IntPtr lpBuffer,
          uint nNumberOfBytesToRead,
          ref uint lpNumberOfBytesRead,
          IntPtr lpOverlapped);
        //Copies data from a named or anonymous pipe into a buffer without removing it from the pipe. It also returns information about data in the pipe.
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool PeekNamedPipe(
          SafeFileHandle hFile,
          IntPtr lpBuffer,
          uint nBufferSize,
          ref uint lpBytesRead,
          ref uint lpTotalBytesAvail,
          ref uint lpBytesLeftThisMessage
          );
    SafeFileHandle ReadHandleToUSBDevice = null;
    ReadHandleToUSBDevice = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
    


    在一个后台进程内调用ReadFile读取USB管道数据会因为没有可供读取的数据而发生阻塞。我尝试先调用PeekNamedPipe以检测是否有数据可供读取,可能是因为方法声明是数据类型定义错误,ErrorStatus = (uint)Marsha.l.GetLastWin32Error();总是返回1或者1008。

    请问:是否可以使用PeekNamedPipe检测读取缓冲区大小,或者需要采用其他方法?

    2010年5月21日 0:20

答案

全部回复

  • 我发现可以使用new FileStream(WriteHandleToUSBDevice, FileAccess.Read)来读取数据,然则,还是不允许检测是否可读取,不允许设定超时。
    2010年5月21日 6:23
  • 你好 关于这几个方法的使用你可以参考msdn 上有详细的例子 http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

    http://msdn.microsoft.com/en-us/library/microsoft.win32.safehandles.safefilehandle.aspx (例子)

     关于Win32 错误代码 参考 http://blog.sina.com.cn/s/blog_55dbebb00100fegb.html

    1 0x0001 错误的函数。  


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~
    • 已标记为答案 Jo Sader 2010年5月29日 2:42
    2010年5月21日 9:21
    版主
  • 你好 关于这几个方法的使用你可以参考msdn 上有详细的例子 http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

    http://msdn.microsoft.com/en-us/library/microsoft.win32.safehandles.safefilehandle.aspx (例子)

     


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~


    先生/女士,我对你的回复感到失望。

    如此无意义的回复来自于版主让我感到惊诧,我宁愿没有人回复。

    2010年5月21日 9:27
  • 后台进程?你的前台和后台是同一个用户么?默认只有管理员和管道的所有者有权访问管道。在Windows Vista或之后的Windows版本,即使是用同一个用户身份,低IL的程序默认也不能访问高IL程度创建的管道。

    你可以在创建的时候就指定让其他用户可以访问。在.Net里面,对应的类是System.IO.Pipes.PipeSecurity。如果你需要更多信息,可以在Windows SDK中搜索Named Pipe Security and Access Rights



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2010年5月21日 23:03
    版主
  • 你好 关于这几个方法的使用你可以参考msdn 上有详细的例子 http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

    http://msdn.microsoft.com/en-us/library/microsoft.win32.safehandles.safefilehandle.aspx (例子)

     


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~


    先生/女士,我对你的回复感到失望。

    如此无意义的回复来自于版主让我感到惊诧,我宁愿没有人回复。


    你好 对于API这些访问我不是很熟悉,所以我看到你的主题很久都没有回复自己是否要花时间帮你查找资料的时候我很犹豫,不过我花了很长的时间在MSDN上帮你搜索这些相关的例子,如果你怀疑是方法定义错了,可以在那上面看到。对于我的回复让你失望请谅解。

    对于我本人知识的缺陷深表遗憾,请见谅,不是每个版主什么都懂,我相信每个人都是这样,我仅是希望能够给你提高一些有用的信息,至少让你感觉得到有人在关注你。

    同时这是.NET一般性问题讨论区,我想你的问题不是主要涉及.NET了,更多的是如何在一门语言中调用其它语言的API,所以发送在VS分类下面的C#版块可能更好。


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~
    2010年5月23日 2:07
    版主
  • 你好 关于这几个方法的使用你可以参考msdn 上有详细的例子 http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx

    http://msdn.microsoft.com/en-us/library/microsoft.win32.safehandles.safefilehandle.aspx (例子)

     


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~


    先生/女士,我对你的回复感到失望。

    如此无意义的回复来自于版主让我感到惊诧,我宁愿没有人回复。


    你好 对于API这些访问我不是很熟悉,所以我看到你的主题很久都没有回复自己是否要花时间帮你查找资料的时候我很犹豫,不过我花了很长的时间在MSDN上帮你搜索这些相关的例子,如果你怀疑是方法定义错了,可以在那上面看到。对于我的回复让你失望请谅解。

    对于我本人知识的缺陷深表遗憾,请见谅,不是每个版主什么都懂,我相信每个人都是这样,我仅是希望能够给你提高一些有用的信息,至少让你感觉得到有人在关注你。

    同时这是.NET一般性问题讨论区,我想你的问题不是主要涉及.NET了,更多的是如何在一门语言中调用其它语言的API,所以发送在VS分类下面的C#版块可能更好。


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~


    先生,

      如果我的措词让你感到不快,我道歉。

      由您的回复可以知道,您对于此问题确实无法解答,能够热心的帮忙寻找答案是好的,但当您完全无法确认找到的东西是否有助于解决问题时,请不要黏贴,帮忙拉关注度请使用明确表达的意思。虽然我技术不行,发帖求教前还是做了功课的,大部分表面资料都有看过了,可惜至今无解。

       发在这个板块仅仅是因为我上一个发在C#版块里的问题,被移动过来了。

    2010年5月26日 14:29
  • 移动你的帖子的原因是你的问题的解决不依赖于你所在论坛的主题。比如这个问题需要的是API方面的知识而不是语言方面的知识。如果你在英文论坛发表的话有比较专门的论坛讨论API,这里没有比较专门的论坛,所以只能移动到一个通用的论坛了。

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2010年5月26日 15:25
    版主
  • 你好,其实我想强调的是 我给你的信息其实是有用的,虽然我并没有学过C++,这一两天才开始学,按照我给你的链接的地址,我将你的需求写成了代码,最终成功的运行了,下面是完整的代码,希望对你有帮助:

    需要说明的是 返回error为0代表所有方法都成功的执行了。

    输出:

    Read Succeed.
    Win32 Error Code:0
    total bytes of this file:2103760
    read bytes of this file:2103344
    left bytes of this file:0

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    using System.IO;

    namespace ConsoleApplicationTest
    {
        public class FileHandleApiTest
        {
            public const short FILE_ATTRIBUTE_NORMAL = 0x80;
            public const short INVALID_HANDLE_VALUE = -1;
            public const uint GENERIC_READ = 0x80000000;
            public const uint GENERIC_WRITE = 0x40000000;
            public const uint CREATE_NEW = 1;
            public const uint CREATE_ALWAYS = 2;
            public const uint OPEN_EXISTING = 3;

            /// <summary>
            /// Create or open file,stream,and so on...
            /// </summary>
            /// <param name="lpFileName">The name of the object to be created or opened.</param>
            /// <param name="dwDesiredAccess"></param>
            /// <param name="dwShareMode"></param>
            /// <param name="lpSecurityAttributes"></param>
            /// <param name="dwCreationDisposition"></param>
            /// <param name="dwFlagsAndAttributes"></param>
            /// <param name="hTemplateFile"></param>
            /// <returns></returns>
            [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
              uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
              uint dwFlagsAndAttributes, IntPtr hTemplateFile);


            //[DllImport("kernel32.dll", EntryPoint = "PeekNamedPipe", SetLastError = true)]
            //static extern bool PeekNamedPipe(IntPtr hNamedPipe, IntPtr lpBuffer, uint nBufferSize, ref uint lpBytesRead, ref uint lpTotalBytesAvail, ref uint lpBytesLeftThisMessage);
            [DllImport("kernel32.dll")]
            static extern bool PeekNamedPipe(IntPtr hNamedPipe, IntPtr lpBuffer,
               uint nBufferSize, IntPtr lpBytesRead, IntPtr lpTotalBytesAvail,
               IntPtr lpBytesLeftThisMessage);

            uint errorStatus;
            public void Test()
            {

                //my USB H,there is a plain text file apitest.txt in it, and the content of it is "this is a test string"
                string lpFileName = "\\\\.\\H:\\apitest.txt";
                IntPtr readHandle = CreateFile(lpFileName, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

                if (readHandle != IntPtr.Zero)
                {
                    Console.WriteLine("Read Succeed.");
                    PeekNamedPipeTest(readHandle);
                }
                else
                {
                    errorStatus = (uint)Marshal.GetLastWin32Error();
                    Console.WriteLine("Win32 Error Code:{0}", errorStatus);
                }

               

            }

            /// <summary>
            /// Test PeekNamedPipe function
            /// </summary>
            /// <param name="handle"></param>
            void PeekNamedPipeTest(IntPtr handle)
            {
                //uint bytesRead = 0;
                //uint bytesToRead = 100;
                //uint bytesTotal = 0;
                //uint bytesLeftThisMessage = 0;

                //byte[] lpBuffer = new byte[bytesToRead];
                uint bytesToRead = 1000;
                IntPtr lpBuffer = Marshal.AllocHGlobal((int)bytesToRead);
                IntPtr bytesRead = Marshal.AllocHGlobal(sizeof(uint));
                IntPtr bytesTotal = Marshal.AllocHGlobal(sizeof(uint));
                IntPtr bytesLeftThisMessage = Marshal.AllocHGlobal(sizeof(uint));

                bool succeed = PeekNamedPipe(handle, lpBuffer, bytesToRead, bytesRead, bytesTotal, bytesLeftThisMessage);

               
                if (succeed)
                {
                    Console.WriteLine("Read string succeed.");
                }
                else
                {
                    errorStatus = (uint)Marshal.GetLastWin32Error();
                    //will get 0,it means all operations finished successfully.
                    Console.WriteLine("Win32 Error Code:{0}", errorStatus);
                }
                //display info
                Console.WriteLine("total bytes of this file:{0}", Marshal.ReadInt32(bytesTotal));
                Console.WriteLine("read bytes of this file:{0}", Marshal.ReadInt32(bytesRead));
                Console.WriteLine("left bytes of this file:{0}", Marshal.ReadInt32(bytesLeftThisMessage));

                Marshal.FreeHGlobal(lpBuffer);
                Marshal.FreeHGlobal(bytesRead);
                Marshal.FreeHGlobal(bytesTotal);
                Marshal.FreeHGlobal(bytesLeftThisMessage);
            }

        }
    }


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~
    2010年5月27日 3:31
    版主
  • 你好,其实我想强调的是 我给你的信息其实是有用的,虽然我并没有学过C++,这一两天才开始学,按照我给你的链接的地址,我将你的需求写成了代码,最终成功的运行了,下面是完整的代码,希望对你有帮助:

    需要说明的是 返回error为0代表所有方法都成功的执行了。

    输出:

    Read Succeed.
    Win32 Error Code:0
    total bytes of this file:2103760
    read bytes of this file:2103344
    left bytes of this file:0

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    using System.IO;

    namespace ConsoleApplicationTest
    {
        public class FileHandleApiTest
        {
            public const short FILE_ATTRIBUTE_NORMAL = 0x80;
            public const short INVALID_HANDLE_VALUE = -1;
            public const uint GENERIC_READ = 0x80000000;
            public const uint GENERIC_WRITE = 0x40000000;
            public const uint CREATE_NEW = 1;
            public const uint CREATE_ALWAYS = 2;
            public const uint OPEN_EXISTING = 3;

            /// <summary>
            /// Create or open file,stream,and so on...
            /// </summary>
            /// <param name="lpFileName">The name of the object to be created or opened.</param>
            /// <param name="dwDesiredAccess"></param>
            /// <param name="dwShareMode"></param>
            /// <param name="lpSecurityAttributes"></param>
            /// <param name="dwCreationDisposition"></param>
            /// <param name="dwFlagsAndAttributes"></param>
            /// <param name="hTemplateFile"></param>
            /// <returns></returns>
            [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
              uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
              uint dwFlagsAndAttributes, IntPtr hTemplateFile);


            //[DllImport("kernel32.dll", EntryPoint = "PeekNamedPipe", SetLastError = true)]
            //static extern bool PeekNamedPipe(IntPtr hNamedPipe, IntPtr lpBuffer, uint nBufferSize, ref uint lpBytesRead, ref uint lpTotalBytesAvail, ref uint lpBytesLeftThisMessage);
            [DllImport("kernel32.dll")]
            static extern bool PeekNamedPipe(IntPtr hNamedPipe, IntPtr lpBuffer,
               uint nBufferSize, IntPtr lpBytesRead, IntPtr lpTotalBytesAvail,
               IntPtr lpBytesLeftThisMessage);

            uint errorStatus;
            public void Test()
            {

                //my USB H,there is a plain text file apitest.txt in it, and the content of it is "this is a test string"
                string lpFileName = "\\\\.\\H:\\apitest.txt";
                IntPtr readHandle = CreateFile(lpFileName, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

                if (readHandle != IntPtr.Zero)
                {
                    Console.WriteLine("Read Succeed.");
                    PeekNamedPipeTest(readHandle);
                }
                else
                {
                    errorStatus = (uint)Marshal.GetLastWin32Error();
                    Console.WriteLine("Win32 Error Code:{0}", errorStatus);
                }

               

            }

            /// <summary>
            /// Test PeekNamedPipe function
            /// </summary>
            /// <param name="handle"></param>
            void PeekNamedPipeTest(IntPtr handle)
            {
                //uint bytesRead = 0;
                //uint bytesToRead = 100;
                //uint bytesTotal = 0;
                //uint bytesLeftThisMessage = 0;

                //byte[] lpBuffer = new byte[bytesToRead];
                uint bytesToRead = 1000;
                IntPtr lpBuffer = Marshal.AllocHGlobal((int)bytesToRead);
                IntPtr bytesRead = Marshal.AllocHGlobal(sizeof(uint));
                IntPtr bytesTotal = Marshal.AllocHGlobal(sizeof(uint));
                IntPtr bytesLeftThisMessage = Marshal.AllocHGlobal(sizeof(uint));

                bool succeed = PeekNamedPipe(handle, lpBuffer, bytesToRead, bytesRead, bytesTotal, bytesLeftThisMessage);

               
                if (succeed)
                {
                    Console.WriteLine("Read string succeed.");
                }
                else
                {
                    errorStatus = (uint)Marshal.GetLastWin32Error();
                    //will get 0,it means all operations finished successfully.
                    Console.WriteLine("Win32 Error Code:{0}", errorStatus);
                }
                //display info
                Console.WriteLine("total bytes of this file:{0}", Marshal.ReadInt32(bytesTotal));
                Console.WriteLine("read bytes of this file:{0}", Marshal.ReadInt32(bytesRead));
                Console.WriteLine("left bytes of this file:{0}", Marshal.ReadInt32(bytesLeftThisMessage));

                Marshal.FreeHGlobal(lpBuffer);
                Marshal.FreeHGlobal(bytesRead);
                Marshal.FreeHGlobal(bytesTotal);
                Marshal.FreeHGlobal(bytesLeftThisMessage);
            }

        }
    }


    I see you~http://hi.baidu.com/1987raymondMy Blog~~~

     

    感谢您的热心支持。
    我是在读取USB管道数据,在我的开发环境里这与读取文件不同,网络上的资料显示确实不同,我没有找到检测USB缓冲区是否有数据的方法。

    2010年5月27日 6:12
  • 的确没有标准的方法,USB设备对文件读写函数的处理是在驱动程序里面,每个驱动都可以有和其他驱动不同的行为。

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2010年5月27日 17:04
    版主