ASP.NET中的P/Invoke(从dll读取/写入文本文件)

问题描述:

我有一个C++ Win32程序,我在其中编写和阅读文本文件。这个C++程序生成一个DLL,我在我的ASP.NET Web应用程序中引用这个DLL。
使用P/Invoke,我调用读取和写入该dll文件的方法。ASP.NET中的P/Invoke(从dll读取/写入文本文件)

当我用WPF应用程序中的P/invoke测试了这个DLL时,dll工作正常。 参考dll位于此WPF应用程序的bin/Debug文件夹中,并且在调用dll时,写入方法在同一文件夹中生成文本文件。 此外,from the same folder,我可以使用dll的读取方法来读取文本文件。

但是,当我从我的ASP.NET Web应用程序调用Dll方法时,生成的文件会转到其他目录(很可能是因为dll被加载到其他地方执行),我无法找到这个位置生成的文件去(没有任何错误)

与桌面应用程序类似,是否有某种方式,fie将被写入bin文件夹本身,以便我可以从bin文件夹本身读取?

示例代码:
cpp文件

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(); 

由于使用相对路径,该文件将是相对于工作您调用本机代码时所在进程的目录。这是你发现的一个相当脆弱的安排。

我会通过向指定要使用的文件的完整路径的本机代码添加额外的字符串参数来解决问题。我确信您可以从托管代码中轻松生成此代码。

本地代码

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

托管代码

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

另一点要提出的是,你的函数读取数据不正确。它试图返回一个堆栈分配的缓冲区。您需要在托管代码中分配一个缓冲区,然后将其传递给本机代码。也许是这样的:

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

而且在管理方面:

[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); 
+0

..和使用默认的工作目录也可以有权限的问题 - 例如,你可以结束一个IIS进程无法写入的目录。 – MiMo 2012-04-25 11:10:11

+0

@MMo的确如此,但事实并非你想要的文件是真正的杀手。 – 2012-04-25 11:14:09

+0

当然 - 我只是增加了一个理由,为什么最好避免使用当前工作目录。 – MiMo 2012-04-25 11:17:23