项目环境:win10,框架 .net 6.0
问题描述:客户现场有一台测量设备,测量数据存放在测量设备本地SQLLite中,应用服务器存在另一台电脑上,客户希望通过共享文件方式读取SQLLite中的数据定时同步到应用服务器上进行查询展示。
解决方案:
网上搜了一下资料整理了一下大概两种方法:
1.没有账号密码限制的,可以将共享文件夹映射成网络驱动器的方式读取,数据库连接配置映射的驱动器路径: Data Source=Z:\OP140\test.db
2.通过advapi32.dll访问需要账号密码登录的共享文件夹读取,数据库连接使用共享文件路径:Data Source=//192.168.1.1/OP140/test.db
示例代码:
using Dapper;
using Microsoft.Win32.SafeHandles;
using System.Data.SQLite;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace MyApp
{
/// <summary>
/// 读取共享sqllite DEMO
/// </summary>
internal class Program
{
static void Main(string[] args)
{
//方法1:共享文件夹映射成网络驱动器的方式读取>>>
using (var dbConnection = new SQLiteConnection($"Data Source=Z:\\OP140\\test.db"))
{
var querySql1 = $"查询语句";
var query1 = dbConnection.Query<dynamic>(querySql1).ToList();
}
//方法1:共享文件夹映射成网络驱动器的方式读取<<<
//方法2:通过advapi32.dll访问需要账号密码登录的共享文件夹读取>>>
Func<string, string> func = (string floder) =>
{
var file = GetNewestDbjFile("\\\\192.168.1.1\\OP140", "test.db");
if (file is null)
{
return "false";
}
var sqlliteConnStr = file.FullName.Replace(@"\", "/");
using (var dbConnection = new SQLiteConnection($"Data Source={sqlliteConnStr}"))
{
var querySql = $"查询语句";
var query = dbConnection.Query<dynamic>(querySql).ToList();
return "true";
}
};
if (Program.ImpersonateValidUser("192.168.1.1", "账号", "密码", "\\\\192.168.1.1\\OP140", func) == "true")
{
//查询成功
}
//方法2:通过advapi32.dll访问需要账号密码登录的共享文件夹读取<<<
}
/// <summary>
/// 链接共享路径,并且读取指定的文件
/// </summary>
/// <param name="path">共享路径</param>
/// <param name="fileName">文件名</param>
/// <returns></returns>
private static FileInfo GetNewestDbjFile(string path, string fileName)
{
try
{
var directoryFile = new DirectoryInfo(path);
FileInfo[] file = directoryFile.GetFiles();
if (file.Length != 0)
{
return file.Where(x => x.Name.Equals(fileName)).First();
}
else
{
//没有文件处理
}
}
catch (Exception ex)
{
//错误处理
}
return null;
}
//logon types
private const int Logon32_Logon_Interactive = 9;
// logon providers
private const int Logon32_Provider_Default = 0;
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out SafeAccessTokenHandle phToken);
/// <summary>
/// 模拟本地用户
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="domain">域名</param>
/// <param name="username">账号</param>
/// <param name="password">密码</param>
/// <param name="path">共享文件夹路径</param>
/// <param name="func"></param>
/// <returns></returns>
private static T ImpersonateValidUser<T>(string domain, string username, string password, string path, Func<string, T> func) where T : class
{
SafeAccessTokenHandle safeAccessTokenHandle;
bool isSuccess = LogonUser(username, domain, password, Logon32_Logon_Interactive, Logon32_Provider_Default, out safeAccessTokenHandle);
if (isSuccess == false)
{
return default(T);
}
return WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>
{
return func(path);
}
);
}
}
}
参考链接:
C#调用advapi32.dll访问需要账号密码登录的共享文件夹