的P / Invoke在ASP.NET(读/写从DLL文本文件) [英] P/Invoke in ASP.NET (Reading/writing text file from dll)

查看:216
本文介绍了的P / Invoke在ASP.NET(读/写从DLL文本文件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我写和读的文本文件中的 C ++的Win32 程序。这个C ++程序生成一个DLL,我引用这个DLL在我的ASP.NET Web应用程序。

使用P / Invoke,我打电话的方法来读取,并从这个DLL文件写入

该DLL工作正常,当我测试了这一点与P /调用在WPF应用程序。
参考DLL是在这个WPF应用程序,并要求当DLL写入方法斌/调试文件夹中生成相同的文件夹的文本文件。
此外,从同一个文件夹,我可以使用DLL的读取方法读取文本文件。

然而,当我打电话从我的ASP.NET web应用程序的DLL方法中,genearted文件转到其他目录(最有可能是因为该dll被加载别的地方执行),我无法找到这哪里产生文件云(没有任何错误)

到桌面应用程序类似,有一些方式,外商投资企业将在bin文件夹本身写的,这样我可以从bin文件夹本身看?

举例code:

.cpp文件

 的externCD_API INT WRITE1()
{
    MYFILE ofstream的;
    myfile.open(example.txt的);
    MYFILE<< 写这一个档案\\ n;
    myfile.close();
    返回1;
}为externCD_API的char *是Read1()
{
    ifstream的myReadFile;
    myReadFile.open(test.txt的);
    CHAR输出[100];
    如果(myReadFile.is_open())
    {
        而(!myReadFile.eof())
        {
        myReadFile>>输出;
        }
    }
    返回输出;
}

C#.aspx.cs

 函数[DllImport(Testing1.dll,入口点=fnTest,CallingConvention = CallingConvention.Cdecl,字符集= CharSet.Ansi)
        公共静态外部INT WRITE1();
        函数[DllImport(Testing1.dll,入口点=ReadTest,CallingConvention = CallingConvention.Cdecl,字符集= CharSet.Ansi)
        公共静态外部的StringBuilder是Read1();


解决方案

由于您使用相对路径,该文件将是相对的过程中在该点的工作目录上,你打电话到本地code 。这是因为你已经发现了一个相当脆的安排。

我会通过增加一个额外的字符串参数到本机code,指定使用的文件的完整路径解决问题。您可以从管理code,我相信这产生足够容易。

本地code

 的externCD_API INT WriteTest(字符*文件名)
{
    ....
    myfile.open(文件名);
    ....
}

管理code

 函数[DllImport(Testing1.dll,CallingConvention = CallingConvention.Cdecl)
公共静态外部INT WriteTest();


另外要指出的是,你的函数读取数据不正确。它试图返回堆栈分配的缓冲区。您需要在管理code分配一个缓冲区,然后传递到本机code。也许是这样的:

 的externCD_API INT ReadTest(字符*文件名字符*缓冲区,INT LEN)
{
     //读取不超过len个字符以上的文件名,缓冲区
}

和被管理方:

 函数[DllImport(Testing1.dll,CallingConvention = CallingConvention.Cdecl)
公共静态外部INT ReadTest(字符串文件名,StringBuilder的缓冲,INT LEN);
....
StringBuilder的缓冲=新的StringBuilder(100);
INT RETVAL = ReadTest(FullySpecifiedFileName,缓冲,buffer.Capacity);

I have a C++ Win32 program in which I am writing and reading a text file. This C++ program generates a dll and I am referencing this dll in my ASP.NET web application.
Using P/Invoke, I am calling methods to read and write file from this dll.

The dll is working fine when I tested this out with P/invoke in WPF application. The reference dll is in the bin/Debug folder for this WPF app, and the write method in dll when called generates a text file in the same folder. Further, from the same folder, I can use the dll's read method to read the text file.

However, when I call the Dll methods from my ASP.NET web app, the genearted file goes to some other directory (most probably because the dll is loaded somewhere else to execute) and I am not able to locate where this generated file goes (without any error)

Similar to desktop application, is there some way that the fie will be written in bin folder itself, so that I can read from the bin folder itself?

Example code:
.cpp file

extern "C" D_API int Write1()
{
    ofstream myfile;
    myfile.open ("example.txt");
    myfile << "Writing this to a file.\n";
    myfile.close();
    return 1;
}

extern "C" D_API char* Read1()
{
    ifstream myReadFile;
    myReadFile.open("test.txt");
    char output[100];
    if (myReadFile.is_open())
    {
        while (!myReadFile.eof()) 
        {
        myReadFile >> output;       
        }
    }
    return output;
}

C# .aspx.cs

[DllImport("Testing1.dll", EntryPoint = "fnTest", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern int Write1();


        [DllImport("Testing1.dll", EntryPoint = "ReadTest", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern StringBuilder Read1();

解决方案

Since you are using relative paths, the file will be relative to the working directory of the process at the point at which you call into the native code. This is a rather brittle arrangement as you have discovered.

I would solve the problem by adding an extra string parameter to the native code that specifies the full path of the file to use. You can generate this easily enough from your managed code I am sure.

Native code

extern "C" D_API int WriteTest(char *filename)
{
    ....
    myfile.open(filename);
    ....
}

Managed code

[DllImport("Testing1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int WriteTest();


The other point to make is that your function to read data is incorrect. It attempts to return a stack allocated buffer. You need to allocate a buffer in the managed code and then pass that to the native code. Perhaps something like this:

extern "C" D_API int ReadTest(char *filename, char* buffer, int len)
{
     //read no more than len characters from filename into buffer
}

And on the managed side:

[DllImport("Testing1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReadTest(string filename, StringBuilder buffer, int len);
....
StringBuilder buffer = new StringBuilder(100);
int retval = ReadTest(FullySpecifiedFileName, buffer, buffer.Capacity);

这篇关于的P / Invoke在ASP.NET(读/写从DLL文本文件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆