之前的方法在放到服务器上有诸多的限制,这边最后使用了一个C的二维数组来读取txt文件,这个程序可能还有不妥之处,比如行列要指定之类的,先上调用的这段c的代码封装,感谢john在这边付出了很多努力把32位的转换为64位上再部署到服务中。
// OptionsPlay.SharedFile.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <stdio.h> #include <sys\timeb.h> #include <stdlib.h> #include<windows.h> //#define LINENUM 174 //#define LINESIZE 428 #define TESTTIME 100 #define _CRT_SECURE_NO_DEPRECATE //#pragma comment( linker, "/subsystem:\"windows\" /entry:\"DllMain\"" ) extern "C"_declspec(dllexport) int ReadSharedFolderByJohn(char p[173 * 427]); void resetLoc(int *loc) { *loc = 0; } int ReadSharedFolderByJohn(char p[173 * 427]){ char quotation[174][428]; int loc = 0; //FILE *fp = fopen("D:\\FirstCapital\\HQ\\mktdt03.txt", "r"); FILE *fp = fopen("Z:\\mktdt73.txt", "r"); while (fgets(quotation[loc], 428, fp) != NULL) { loc++; } for (int i = 1; i < 173; i++){ for (int j = 0; j < 427; j++){ p[(i - 1) * 427 + j] = quotation[i][j]; } } /*for (int i=0;i<10;i++) p[i] = '1';*/ //printf("hello, it's OK"); return 0; }接下来,这段主要是把二维的缓冲区转换为一维以便于这边C#来读取,因为二维的方法在C#里真不好操作,之前有朋友贴出在用托管的C++来定义二维数组传地址给C封装动态链接库,但是未果,还是这种方法吧.
[DllImport("OptionsPlay.SharedFile.dll", EntryPoint = "ReadSharedFolderByJohn", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] //public static extern int ReadSharedFolderByJohn(IntPtr p, int LINENUM, int LINESIZE); public static extern int ReadSharedFolderByJohn(IntPtr p); public static byte[] GetData(string folder, string fileName, int filetypeFlag) { try { if (filetypeFlag == 1) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int LINENUM = 174; int LINESIZE = 428; IntPtr p = Marshal.AllocHGlobal(sizeof(char) * 173 * 427); //ReadSharedFolderByJohn(p, LINENUM, LINESIZE); ReadSharedFolderByJohn(p); byte[] b = new byte[173 * 427]; Marshal.Copy(p, b, 0, 173 * 427); stopwatch.Stop(); Logger.Debug(string.Format("File {0} Copied in {1}ms", fileName, stopwatch.ElapsedMilliseconds)); return b; } else { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); string path = Path.Combine(folder, fileName); byte[] result = File.ReadAllBytes(path); stopwatch.Stop(); Logger.Debug(string.Format("File {0} Copied in {1}ms", fileName, stopwatch.ElapsedMilliseconds)); return result; } } catch (Exception ex) { Logger.Error("FromLocalDrive GetData Error", ex); throw; } }
最后用marshell列集申请堆栈来获得这个一维数据。
折腾了一个月才知道:
FILE *fp = fopen("Z:\\mktdt73.txt", "r");
要写成FILE *fp = fopen("\\10.224.200.37\c$\HQ", "r");这种UNC的路径格式才能够开启,同时服务启动的用户权限必须localsystem,既带有administrator用户权限。
https://support.microsoft.com/zh-cn/kb/180362/en-us
这里引一段上面的话:
A service should not directly access local or network resources through mapped drive letters. Additionally, a service should not use the WNetXXXXXXX APIs to add, remove, or query any mapped drive letters. Although the WNetXXXXXXX APIs may return successfully, the results will be incorrect. A service (or any process that is running in a different security context) that must access a remote resource should use the Universal Naming Convention (UNC) name to access the resource.
If a service that is running in the LocalSystem security context establishes a drive mapping, only that service or another process running in the LocalSystem account can call WNetCancelConnection2() to disconnect the drive.
Note All processes that are running in the LocalSystem account are running in the same logon session.
这边要感谢john不懈的坚持,我对这个方法几尽放弃!