PInvoke of WriteFile from C#

PInvoke of WriteFile from C#

Post by Gnanavel » Wed, 28 May 2003 22:20:22



Hi All,

I have a FileAccessor utiltiy class with which, I am trying to use Win32
calls to create a file and write some binary data inot the file.

In the FileAccessor class I have

 [DllImport("kernel32", SetLastError=true)]
        static extern unsafe int CreateFile(
            string filename,
            uint desiredAccess,
            uint shareMode,
            uint attributes,
            uint creationDisposition,
            uint flagsAndAttributes,
            uint templateFile);

 [DllImport("kernel32", SetLastError=true)]
        static extern unsafe int WriteFile(
            int hFile, void* lpBuffer,
            int nBytesToWrite, out int nBytesWritten, int overlapped);

The way, I am creating the file is
int handle = CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, 0,
CREATE_ALWAYS, 0, 0);

...

and I am tring to put some binary data into the file like ....
fixed (byte* bytePointer = buffer) {
int error = WriteFile(handle, (void *)(bytePointer + offset), length, out
actual, 0);
if(error == 0 || error == -1){
int errorCode = Marshal.GetLastWin32Error();
// I am repetedly getting always the error ERROR_INVALID_USER_BUFFER  only
some times I do not get the error

Quote:}

Let me know what the problem is. Should we have to take care of anything
explicit for C#/.Net environment ?

Regards
Gnan

 
 
 

PInvoke of WriteFile from C#

Post by Bill Pries » Thu, 29 May 2003 00:54:37


Hello Gnan,

IMHO, you should not have to use any Win32 API calls for File IO. The
System.IO namespace handles everything natively in the .NET environment and,
although sometimes cryptic, is overly packed with every method that you need
to open a file, write binary data to it, and close it again. You should have
a look at it and see if you can modify your code to use the System.IO
namespace.

For your FileAccessor class:

using System.IO;

static bool CreateFile(string FileName, int Buffer, byte[] Data)
{
   BinaryWriter oWriter = new BinaryWriter(File.Create(FileName,
Buffer),System.Text.Encoding.UTF8);
    oWriter.Write(Data);
    oWriter.Close();

Quote:}

HTH,
Bill P.


Quote:> Hi All,

> I have a FileAccessor utiltiy class with which, I am trying to use Win32
> calls to create a file and write some binary data inot the file.

> In the FileAccessor class I have

>  [DllImport("kernel32", SetLastError=true)]
>         static extern unsafe int CreateFile(
>             string filename,
>             uint desiredAccess,
>             uint shareMode,
>             uint attributes,
>             uint creationDisposition,
>             uint flagsAndAttributes,
>             uint templateFile);

>  [DllImport("kernel32", SetLastError=true)]
>         static extern unsafe int WriteFile(
>             int hFile, void* lpBuffer,
>             int nBytesToWrite, out int nBytesWritten, int overlapped);

> The way, I am creating the file is
> int handle = CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, 0,
> CREATE_ALWAYS, 0, 0);

> ...

> and I am tring to put some binary data into the file like ....
> fixed (byte* bytePointer = buffer) {
> int error = WriteFile(handle, (void *)(bytePointer + offset), length, out
> actual, 0);
> if(error == 0 || error == -1){
> int errorCode = Marshal.GetLastWin32Error();
> // I am repetedly getting always the error ERROR_INVALID_USER_BUFFER  only
> some times I do not get the error
> }

> Let me know what the problem is. Should we have to take care of anything
> explicit for C#/.Net environment ?

> Regards
> Gnan


 
 
 

PInvoke of WriteFile from C#

Post by Brian Grunkemeyer [MS » Sat, 07 Jun 2003 08:56:10


Just to reiterate, please try to learn & use classes from our existing IO
namespace if possible.  While I wasn't able to find the reason why your code
wasn't working after looking at this for about a minute, I did see at least
two 64 bit portability problems and two subtle lurking security bugs I fixed
in FileStream in V1 or V1.1.  Plus, this code will not be reliable in future
versions of the CLR.  If you can use FileStream, please do so.  Using
P/Invoke to duplicate parts of the Framework is just asking for future pain.
I know the docs weren't great, but in V1.1 they should be better with many
more samples.

FYI - the best way to write a byte[] to a file is like this:

using(FileStream fs = File.Create(fileName)) {
    fs.Write(buffer, 0, buffer.Length);

Quote:}

Note the C# using statement here automatically calls Dispose for you in a
try/finally block, closing the file handle even if Write failed.  In a
future version, we may add a method like WriteAll(String fileName, byte[]
bytes) on File to make this easier to approach.

--
Brian Grunkemeyer
MS CLR Base Class Library team

This posting is provided "AS IS" with no warranties, and confers no rights.


> Hello Gnan,

> IMHO, you should not have to use any Win32 API calls for File IO. The
> System.IO namespace handles everything natively in the .NET environment
and,
> although sometimes cryptic, is overly packed with every method that you
need
> to open a file, write binary data to it, and close it again. You should
have
> a look at it and see if you can modify your code to use the System.IO
> namespace.

> For your FileAccessor class:

> using System.IO;

> static bool CreateFile(string FileName, int Buffer, byte[] Data)
> {
>    BinaryWriter oWriter = new BinaryWriter(File.Create(FileName,
> Buffer),System.Text.Encoding.UTF8);
>     oWriter.Write(Data);
>     oWriter.Close();
> }

> HTH,
> Bill P.



> > Hi All,

> > I have a FileAccessor utiltiy class with which, I am trying to use Win32
> > calls to create a file and write some binary data inot the file.

> > In the FileAccessor class I have

> >  [DllImport("kernel32", SetLastError=true)]
> >         static extern unsafe int CreateFile(
> >             string filename,
> >             uint desiredAccess,
> >             uint shareMode,
> >             uint attributes,
> >             uint creationDisposition,
> >             uint flagsAndAttributes,
> >             uint templateFile);

> >  [DllImport("kernel32", SetLastError=true)]
> >         static extern unsafe int WriteFile(
> >             int hFile, void* lpBuffer,
> >             int nBytesToWrite, out int nBytesWritten, int overlapped);

> > The way, I am creating the file is
> > int handle = CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_WRITE, 0,
> > CREATE_ALWAYS, 0, 0);

> > ...

> > and I am tring to put some binary data into the file like ....
> > fixed (byte* bytePointer = buffer) {
> > int error = WriteFile(handle, (void *)(bytePointer + offset), length,
out
> > actual, 0);
> > if(error == 0 || error == -1){
> > int errorCode = Marshal.GetLastWin32Error();
> > // I am repetedly getting always the error ERROR_INVALID_USER_BUFFER
only
> > some times I do not get the error
> > }

> > Let me know what the problem is. Should we have to take care of anything
> > explicit for C#/.Net environment ?

> > Regards
> > Gnan

 
 
 

PInvoke of WriteFile from C#

Post by David Brown » Sun, 08 Jun 2003 08:00:25




Quote:> Just to reiterate, please try to learn & use classes from our existing IO
> namespace if possible.  While I wasn't able to find the reason why your
code
> wasn't working after looking at this for about a minute, I did see at
least
> two 64 bit portability problems and two subtle lurking security bugs I
fixed
> in FileStream in V1 or V1.1.  Plus, this code will not be reliable in
future
> versions of the CLR.  If you can use FileStream, please do so.  Using
> P/Invoke to duplicate parts of the Framework is just asking for future
pain.
> I know the docs weren't great, but in V1.1 they should be better with many
> more samples.

> FYI - the best way to write a byte[] to a file is like this:

> using(FileStream fs = File.Create(fileName)) {
>     fs.Write(buffer, 0, buffer.Length);
> }

> Note the C# using statement here automatically calls Dispose for you in a
> try/finally block, closing the file handle even if Write failed.  In a
> future version, we may add a method like WriteAll(String fileName, byte[]
> bytes) on File to make this easier to approach.

> --
> Brian Grunkemeyer
> MS CLR Base Class Library team

I have implemented an ExtendedFileStream subclass of FileStream to get
access to alternate file streams and temporary files using
FILE_FLAG_TEMPORARY, FILE_FLAG_DELETE_ON_CLOSE.

ExtendedFileStream's constructor uses CreateFile though PInvoke, and passes
the handle to the IntPtr constructor for FileStream.

It seems to work for Named Pipes too, and I was thinking of using it for COM
ports as well.

Is this a good approach, or should I avoid the FileStream for accessing the
other OS objects which use file handles?

David

 
 
 

1. PInvoke for MSMQ and PInvoke for Callbacks

We are trying to write PInvoke wrappers for MSMQ - but how
do we handle the structures MQQUEUEPROPS, MQMSGPROPS,
MQMGMTPROPS and in particular the aPropVar array of
MQPROPVARIANT - can you convert a union to a managaged
type?

Also does CF support Delegates in PInvoke for callback
functions. The documentation says .Net does - but Managed
to Unmanaged types for SDE says delegates not supported.

Thanks in advance for any help

2. What work followed from Homunculus (1963)?

3. How to call this SQL function using PInvoke in C#?

4. Prob: DOS app with serial comms under Win95

5. PINVOKE..C#-evc++, .lifetime of classes on C++ side

6. Immediate Need for SAP BPC (Microsoft Version) Lead Consultant -- NJ

7. SDE Pocket PC Comm Port Sample in VB and C# using pInvoke

8. BasCompress freeware

9. PInvoke Problem - How to convert that to c#?

10. How do you debug a C++ DLL you are pinvoking from a C# app?

11. PInvoke question (C#)

12. SDE Pocket PC Comm Port Sample in VB and C# using pInvoke

13. PINVOKE, C# DllImport and C memcpy