C# 非托管函数调用,可能的数据丢失,Ascii 与。 Unicode、中文文件夹名称

发布于 2024-12-05 09:47:34 字数 4366 浏览 1 评论 0原文

所以事情是这样的,我正在工作一个调用旧版 C++ dll 的 C# 应用程序,该应用程序依次循环遍历一个目录,拉回某些目录的名称,即具有 .lib 的目录,我有一个包含以下 3 个文件夹的目录:Default.Lib、中文文本帧的文件.lib、我们的.lib。

正如你所看到的,我们有一些中文文件夹名称,一个字符串是由 C++ 代码在内存中构建的,如下所示,它使用 strcat 在内存中构建它。但是,当控制权返回到 C# 代码时,部分数据似乎丢失了,只剩下前两个文件夹。 Default.Lib,中文文本帧的文件.lib,带有我们的.lib的东西在翻译中丢失了,我将非常感谢任何人可能有的见解。谢谢。

C# 代码片段

 lock (padLock)
            {
                ConnectSign(service);

                int size = MaxFileListSize * 100;
                byte[] mem = new byte[size];
                string finalList;
                int used = size;
                int fileCount = 0;
                string library = "*";
                string extension = "*";
                V7_FILE_LIST_TYPE type = V7_FILE_LIST_TYPE.LibraryList;

                fixed (byte* listbytes = mem)
                {
                    int error = NativeMethods.GetFileDirInfo(sign, type, fileServer, library, extension, &fileCount, listbytes, &used);
                    if (error != 0)
                        throw new V7ResponseException(error, sign, service, "GetFileDirInfo");
                }

                finalList = Encoding.Default.GetString(mem, 0, (int)used);

                string[] libraryArray = finalList.Split(new char[] { '\n', '\0' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < libraryArray.Length; i++)
                {
                    int index = libraryArray[i].LastIndexOf(".lib", StringComparison.OrdinalIgnoreCase);
                    if (index > 0)
                        libraryArray[i] = libraryArray[i].Substring(0, index);
                    //libraryArray[i] = libraryArray[i].Trim().ToLower(CultureInfo.CurrentCulture).Replace(".lib", string.Empty);
                }

                return libraryArray;
            }

[DllImport("V7SSRpc.dll", CharSet = CharSet.Ansi, EntryPoint = "V7ssGetFileDirInfo", BestFitMapping = false, ThrowOnUnmappableChar = true)]
            public static extern int GetFileDirInfo(string sign, V7_FILE_LIST_TYPE type, string fileServer, string library, string extension, int* fileCount, byte* files, int* bytesUsed);

在此处输入图像描述 ******************************C++ DLL 代码-------------------- --------------------

   //--------------------------------------------------------------------
    // RETURN :
    //
    // PARAMS : eListType
    //              szServer
    //              szLib
    //              szExt
    //              *pdwFileCnt
    //              *pbyFileBuf
    //              *pdwFileBufSize
    //
    // REMARKS:
    //
    BOOL CVSign::apiGetFileDirInfo(V7_FILE_LIST_TYPE eListType, LPCSTR szServer, LPCSTR szLib, LPCSTR szExt, 
                                             DWORD *pdwFileCnt, char *pbyFileBuf, DWORD *pdwFileBufSize) const
    {
        BOOL bReturn=TRUE;
        CString sServer(szServer);
        CString sLib(szLib);
        CString sExt(szExt);
        CString sFileInfo, sTemp;
        CStringArray asFiles;
        CFileStatus status;
        CV7Files V7Files;
        DWORD dwBufUsed=0;

    // SOME OTHER LOGIC (not posted)

        USES_CONVERSION;

        //CoInitialize(NULL);
        //AVIFileInit();

        CString sFilePath;
        CV7SequenceFile V7Seq;

        CV7FileInfo fileInfo;

        // go through list of files and build the buffer with file names and other info
        for (nFile=0; nFile<nFiles; nFile++)
        {
            // MORE OBSCURED LOGIC

            sFileInfo += _T("\n");

            // add file info to buffer
            int nLen = sFileInfo.GetLength();
            if (dwBufUsed+nLen<*pdwFileBufSize)
            {
                strcat(pbyFileBuf, T2CA(sFileInfo)); //<--- THIS IS THE IMPORTANT PART
                int nTemp = sFileInfo.GetLength();
                dwBufUsed += nTemp;
            }
            else
            {
                *pdwFileBufSize = 0;

                AVIFileExit();
                CoUninitialize();

                return FALSE;
            }
        }   // end for files

        //AVIFileExit();
        //CoUninitialize();

        *pdwFileBufSize = dwBufUsed;

        return bReturn;
    } // end apiGetFileDirInfo()

在此处输入图像描述

So here is the deal, Im working a C# application that calls into a legacy C++ dll, which in turns loops through a directory pulling back the names of certain directories, i.e directories that have .lib, I have a directory with the following 3 folders: Default.Lib,中文文本帧的文件.lib,我们的.lib.

As you can see we have some chinese folder names, a string is built in memory by the c++ code as you can see below, it use strcat to build it in memory. however when control is returned back to the c# code, it appears part of that data is lost and the only two folders left are the first two. Default.Lib,中文文本帧的文件.lib, something with 我们的.lib gets lost in translation, I would greatly appreciate any insights anyone may have. thanks.

C# code snippet

 lock (padLock)
            {
                ConnectSign(service);

                int size = MaxFileListSize * 100;
                byte[] mem = new byte[size];
                string finalList;
                int used = size;
                int fileCount = 0;
                string library = "*";
                string extension = "*";
                V7_FILE_LIST_TYPE type = V7_FILE_LIST_TYPE.LibraryList;

                fixed (byte* listbytes = mem)
                {
                    int error = NativeMethods.GetFileDirInfo(sign, type, fileServer, library, extension, &fileCount, listbytes, &used);
                    if (error != 0)
                        throw new V7ResponseException(error, sign, service, "GetFileDirInfo");
                }

                finalList = Encoding.Default.GetString(mem, 0, (int)used);

                string[] libraryArray = finalList.Split(new char[] { '\n', '\0' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < libraryArray.Length; i++)
                {
                    int index = libraryArray[i].LastIndexOf(".lib", StringComparison.OrdinalIgnoreCase);
                    if (index > 0)
                        libraryArray[i] = libraryArray[i].Substring(0, index);
                    //libraryArray[i] = libraryArray[i].Trim().ToLower(CultureInfo.CurrentCulture).Replace(".lib", string.Empty);
                }

                return libraryArray;
            }

[DllImport("V7SSRpc.dll", CharSet = CharSet.Ansi, EntryPoint = "V7ssGetFileDirInfo", BestFitMapping = false, ThrowOnUnmappableChar = true)]
            public static extern int GetFileDirInfo(string sign, V7_FILE_LIST_TYPE type, string fileServer, string library, string extension, int* fileCount, byte* files, int* bytesUsed);

enter image description here
*****************************C++ DLL code--------------------------------------

   //--------------------------------------------------------------------
    // RETURN :
    //
    // PARAMS : eListType
    //              szServer
    //              szLib
    //              szExt
    //              *pdwFileCnt
    //              *pbyFileBuf
    //              *pdwFileBufSize
    //
    // REMARKS:
    //
    BOOL CVSign::apiGetFileDirInfo(V7_FILE_LIST_TYPE eListType, LPCSTR szServer, LPCSTR szLib, LPCSTR szExt, 
                                             DWORD *pdwFileCnt, char *pbyFileBuf, DWORD *pdwFileBufSize) const
    {
        BOOL bReturn=TRUE;
        CString sServer(szServer);
        CString sLib(szLib);
        CString sExt(szExt);
        CString sFileInfo, sTemp;
        CStringArray asFiles;
        CFileStatus status;
        CV7Files V7Files;
        DWORD dwBufUsed=0;

    // SOME OTHER LOGIC (not posted)

        USES_CONVERSION;

        //CoInitialize(NULL);
        //AVIFileInit();

        CString sFilePath;
        CV7SequenceFile V7Seq;

        CV7FileInfo fileInfo;

        // go through list of files and build the buffer with file names and other info
        for (nFile=0; nFile<nFiles; nFile++)
        {
            // MORE OBSCURED LOGIC

            sFileInfo += _T("\n");

            // add file info to buffer
            int nLen = sFileInfo.GetLength();
            if (dwBufUsed+nLen<*pdwFileBufSize)
            {
                strcat(pbyFileBuf, T2CA(sFileInfo)); //<--- THIS IS THE IMPORTANT PART
                int nTemp = sFileInfo.GetLength();
                dwBufUsed += nTemp;
            }
            else
            {
                *pdwFileBufSize = 0;

                AVIFileExit();
                CoUninitialize();

                return FALSE;
            }
        }   // end for files

        //AVIFileExit();
        //CoUninitialize();

        *pdwFileBufSize = dwBufUsed;

        return bReturn;
    } // end apiGetFileDirInfo()

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暖阳 2024-12-12 09:47:35

我怀疑问题在于您指定了 Charset=CharSet.Ansi,因此默认封送行为是将返回的字符串转换为 ANSI。这会引起问题。

您可能想要指定字符串 Charset=CharSet.Unicode,并可能为某些字符串指定自定义封送处理。请参阅 http://msdn.microsoft.com/en-us/library/ s9ts558h.aspx#cpcondefaultmarshalingforstringsanchor5 有关如何更改各个参数的字符串封送行为的信息。

I suspect the problem is that you're specifying Charset=CharSet.Ansi, so the default marshaling behavior is to convert the returned string to ANSI. That's going to cause a problem.

You probably want to specify string Charset=CharSet.Unicode, and possibly specify custom marshaling for some strings. See http://msdn.microsoft.com/en-us/library/s9ts558h.aspx#cpcondefaultmarshalingforstringsanchor5 for information on how to change the string marshaling behavior for individual parameters.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文