DLL嵌入exe
生成单一exe文件, 程序打包为一个文件
方法一:【推荐】 nuget引入Costura.Fody即可
方法二:
1,在项目下面建个目录放dll,把dll包含到项目里面,右键dll属性设置为嵌入式资源
2,添加这个静态类LoadResoureDll
3,在Main()里面调用LoadResoureDll.RegistDLL();
方法三:
如果引入的dll需要调用另外的dll,又不是强引入,就要结合方法一和方法二
例如:引入SqlSugar(.Net Framework 版本),再访问mysql的时候需要MySql.Data.dll
这是需要同时使用方法一和方法二:方法一会嵌入SqlSugar,方法二会嵌入MySql.Data.dll
static void Main()
{
LoadResoureDll.RegistDLL(); //3,DLL嵌入exe
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
//2,添加这个静态类
public static class LoadResoureDll
{
/// <summary> 已加载DLL
/// </summary>
private static Dictionary<string, Assembly> LoadedDlls = new Dictionary<string, Assembly>();
/// <summary> 已处理程序集
/// </summary>
private static Dictionary<string, object> Assemblies = new Dictionary<string, object>();
/// <summary> 在对程序集解释失败时触发
/// </summary>
/// <param name="sender">AppDomain</param>
/// <param name="args">事件参数</param>
private static Assembly AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
//程序集
Assembly ass;
//获取加载失败的程序集的全名
var assName = new AssemblyName(args.Name).FullName;
//判断Dlls集合中是否有已加载的同名程序集
if (LoadedDlls.TryGetValue(assName, out ass) && ass != null)
{
LoadedDlls[assName] = null;//如果有则置空并返回
return ass;
}
else
{
return ass;//dev的dll 这里有问题,可以绕过
throw new DllNotFoundException(assName);//否则抛出加载失败的异常
}
}
catch (System.Exception ex)
{
MessageBox.Show("error1:\n位置:AssemblyResolve()!\n描述:" + ex.Message);
return null;
}
}
/// <summary> 注册资源中的dll
/// </summary>
/// <param name="pattern">*表示连续的未知字符,_表示单个未知字符,如*.dll</param>
public static void RegistDLL(string pattern = "*.dll")
{
System.IO.Directory.GetFiles("", "");
//获取调用者的程序集
var ass = new StackTrace(0).GetFrame(1).GetMethod().Module.Assembly;
//判断程序集是否已经处理
if (Assemblies.ContainsKey(ass.FullName))
{
return;
}
//程序集加入已处理集合
Assemblies.Add(ass.FullName, null);
//绑定程序集加载失败事件(这里我测试了,就算重复绑也是没关系的)
AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve;
//获取所有资源文件文件名
var res = ass.GetManifestResourceNames();
var regex = new Regex("^" + pattern.Replace(".", "\\.").Replace("*", ".*").Replace("_", ".") + "$", RegexOptions.IgnoreCase);
foreach (var r in res)
{
//如果是dll,则加载
if (regex.IsMatch(r))
{
try
{
var s = ass.GetManifestResourceStream(r);
var bts = new byte[s.Length];
s.Read(bts, 0, (int)s.Length);
var da = Assembly.Load(bts);
//判断是否已经加载
if (LoadedDlls.ContainsKey(da.FullName))
{
continue;
}
LoadedDlls[da.FullName] = da;
}
catch (Exception ex)
{
MessageBox.Show("error2:加载dll失败\n位置:RegistDLL()!\n描述:" + ex.Message);
}
}
}
}
}
IsNull
//空字符串或者空对象
public static bool IsNull(string str)
{
if (null == str || "" == str)
{
return true;
}
return false;
}
//表格对象为空,或者没有行
public static bool IsNull(DataTable dt)
{
if (null == dt || dt.Rows.Count <= 0)
{
return true;
}
return false;
}
//数据集对象为空,或者没有没有,或者表中没有行
public static bool IsNull(DataSet ds)
{
if (null == ds || null == ds.Tables || ds.Tables.Count <= 0 || IsNull(ds.Tables[0]))
{
return true;
}
return false;
}
ABP返回分页后的结果
//ABP返回分页后的结果
public static PagedResultDto<T> GetPagedResultDto<T>(IQueryable<T> query, int SkipCount, int MaxResultCount)
{
var totals = query.Count();
IReadOnlyList<T> list = query.Skip(SkipCount).Take(MaxResultCount).ToList();
var result = new PagedResultDto<T>(totals, list);
return result;
}
//ABP返回分页后的结果
public static PagedResultDto<T> GetPagedResultDto<T>(List<T> query, int SkipCount, int MaxResultCount)
{
var totals = query.Count();
IReadOnlyList<T> list = query.Skip(SkipCount).Take(MaxResultCount).ToList();
var result = new PagedResultDto<T>(totals, list);
return result;
}
把多个对象的属性赋值给一个对象,自动映射AutoMap
//把入参的属性赋值给出参, 1,所有属性必须设置{ get; set; } 2,入参有先后顺序, 如果两个入参有相同的属性, 后面的会覆盖前面的
public static T MapMulti2One<T>(params Object[] arrObj) where T : new()
{
Type typeT = typeof(T);
T objT = new T();
foreach (var item in arrObj)
{
if (item == null)
{
continue;
}
var propertiesA = item.GetType().GetProperties();
// 通过循环遍历所有属性,并将A对象的属性值赋值给B对象中对应的属性
foreach (var propertyA in propertiesA)
{
PropertyInfo propertyT = typeT.GetProperty(propertyA.Name);
if (propertyT != null && propertyT.PropertyType == propertyA.PropertyType)
{
//如果propertyT存在就赋值
propertyT.SetValue(objT, propertyA.GetValue(item));
}
}
}
return objT;
}
使用举例1:
var query = from a in _reportInstanceRepository.GetAll()
join b in _reportGroupRepository.GetAll() on a.ReportGroupId equals b.Id
join c in _clientReportRepository.GetAll() on a.Id equals c.ReportId
join d in _clientRepository.GetAll() on c.ClientId equals d.Id
where d.Id == 4
select MapMulti2One<ReportInstanceDto>(a, new{TemplateLength = a.Template.Length});
使用举例2:左连接
var list2 = from a in list
join b in listBind on a.Idcard equals b.Idcard into lb
from bind in lb.DefaultIfEmpty() //bind是左连接后的结果
join c in listPayRecord on a.DonBloodNo equals c.DonBloodNo into pr
from payRecode in pr.DefaultIfEmpty() //左连接
select MapMulti2One<PayInfoDto>(a, new { bind?.BindTime, bind?.WechatUserId }, new { PayTime = payRecode?.CreationTime, payRecode?.OrderNo });
Asp.net core 读取appsetting.config
// 例如appsetting中包含属性xxxConfig:{xxx}
{
...
"xxxConfig": {
"BaseUrl": "http://192.168.1.1:8088/api/",
"IsDebug": true
},
...
}
//1, 编写xxxConfig类与配置一致
public class xxxConfig
{
public string BaseUrl { get; set; }
public bool IsDebug { get; set; }
}
//2, 在Setup.cs中添加
services.Configure<xxxConfig>(_appConfiguration.GetSection("xxxConfig"));
//3, 在controller的构造函数中注入: IOptions<xxxConfig> option, 在构造函数中赋值
_xxxConfig= option.Value;
Winform读写配置文件
简单好用,没有依赖
//配置文件路径
private string configFileName = Application.StartupPath + "\\AppConfig.xml";
//读取
DataTable dataTable2 = new DataTable();
if (File.Exists(configFileName))
{
dataTable2.ReadXml(configFileName);
if (dataTable2 != null && dataTable2.Rows.Count == 1)
{
txtServer.Text = dataTable2.Rows[0]["Server"].ToString().Trim();
cmbLoginType.SelectedValue = dataTable2.Rows[0]["LoginType"].ToString().Trim();
txtUser.Text = dataTable2.Rows[0]["User"].ToString().Trim();
txtPwd.Text = dataTable2.Rows[0]["Pwd"].ToString().Trim();
dbName = dataTable2.Rows[0]["DBName"].ToString().Trim();
}
}
//写入
DataTable dataTable = new DataTable();
dataTable.TableName = "ExecConfig";
dataTable.Columns.Add("Server", typeof(string));
dataTable.Columns.Add("LoginType", typeof(string));
dataTable.Columns.Add("User", typeof(string));
dataTable.Columns.Add("Pwd", typeof(string));
dataTable.Columns.Add("DBName", typeof(string));
DataRow dataRow = dataTable.NewRow();
dataRow["Server"] = txtServer.Text.Trim();
dataRow["LoginType"] = cmbLoginType.SelectedValue;
dataRow["User"] = txtUser.Text.Trim();
dataRow["Pwd"] = txtPwd.Text.Trim();
dataRow["DBName"] = cmbDB.SelectedValue;
dataTable.Rows.Add(dataRow);
if (File.Exists(configFileName))
{
File.Delete(configFileName);
}
dataTable.WriteXml(configFileName, XmlWriteMode.WriteSchema);
MessageBox.Show("保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
打印日志到文件
/// <summary>
/// 打印文件日志
/// </summary>
/// <param name="info">信息</param>
/// <param name="path">日志文件的路径</param>
public void WriteToLog(string info, string path = "")
{
var logFilePath = "";
try
{
//string path = ""; // winform默认路径: Application.StartupPath + "/Log";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
logFilePath = path + "/log" + DateTime.Now.ToString("yyyMMddHH") + ".txt";
}
catch
{
//忽略日志写入错误
return;
}
try
{
StringBuilder str = new StringBuilder();
str.Append("Time: " + DateTime.Now.ToString("yyyyMMdd HH:mm:ss") + "\r\n");
if (!string.IsNullOrEmpty(info)) { str.Append("info: " + info + "\r\n"); }
str.Append("-----------------------------------------------------------\r\n");
StreamWriter sw;
if (!System.IO.File.Exists(logFilePath))
{
sw = System.IO.File.CreateText(logFilePath);
}
else
{
sw = System.IO.File.AppendText(logFilePath);
}
sw.Write(str.ToString());
sw.Close();
}
catch
{
//忽略日志写入错误
}
}
理解C#的委托Action和Func
static void Main(string[] args)
{
ExecBatCommand(m =>
{
var i = m(1);
i++;
i = m(i);
Console.WriteLine(i); //请问输出什么结果??
});
}
static void ExecBatCommand(Action<Func<int, int>> outMethod)
{
outMethod(i => i += 2);
}
导出到Excel通用方法
//导出到Excel通用方法
public ActionResult ExportToExcel(ExportInput input)
{
//得到一个DataTable,例如从存储过程获取
var dataTable = _fileDapperRepository.GetDataTableFromPro(input);
if (dataTable.Rows.Count == 0) throw new UserFriendlyException("没有查询到数据");
// If you are a commercial business and have
// purchased commercial licenses use the static property
// LicenseContext of the ExcelPackage class :
OfficeOpenXml.ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.Commercial;
// If you use EPPlus in a noncommercial context
// according to the Polyform Noncommercial license:
OfficeOpenXml.ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
using (OfficeOpenXml.ExcelPackage pck = new OfficeOpenXml.ExcelPackage())
{
OfficeOpenXml.ExcelWorksheet ws = pck.Workbook.Worksheets.Add("页签1");
ws.Cells["A1"].LoadFromDataTable(dataTable, true);
//样式修改
ws.Cells[2, 2, dataTable.Rows.Count + 1, 2].Style.Numberformat.Format = "yyyy/MM/dd";
int[] TimeCols = { 7, 9, 11, 14, 33 };
for (var item = 1; item < dataTable.Columns.Count; item++)
{
if(TimeCols.Contains(item))
ws.Cells[2, item, dataTable.Rows.Count + 1, item].Style.Numberformat.Format = "yyyy/MM/dd HH:mm:ss";
ws.Cells[2, item, dataTable.Rows.Count + 1, item].AutoFitColumns();//自动适应宽度
}
return File(pck.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "导出数据.xlsx");
}
}
C#音效播放PlaySound
[DllImport("winmm.dll", EntryPoint = "PlaySound")]
private static extern bool PlaySound(string pszSound, IntPtr hmod, uint fdwSound);
public const int SND_FILENAME = 0x00020000;
public const int SND_ASYNC = 0x0001;
//用API播放声音文件, 异步,覆盖播放(1,不会堵塞UI 2,播放第二个音效的时候,第一个音效自动停止)
void ReadSound(string WavFilePath)
{
PlaySound(WavFilePath, IntPtr.Zero, SND_FILENAME | SND_ASYNC);
}
微软TTS文字转语音并保存到wav文件中
public static void Speek()
{
var synthesizer = new SpeechSynthesizer();
synthesizer.SetOutputToDefaultAudioDevice();
MemoryStream ms = new MemoryStream();
synthesizer.SetOutputToWaveStream(ms);
synthesizer.Speak("微软TTS文字转语音并保存到wav文件中");
FileStream fs = new FileStream("C:\\a.wav", FileMode.OpenOrCreate);
BinaryWriter w = new BinaryWriter(fs);
w.Write(ms.ToArray());
fs.Close();
ms.Close();
}
设计模式之享元模式
class Program
{
public class OtherClass
{
public string c = "xiangyuan";
}
static void Main(string[] args)
{
string a = "xiangyuan";
string b = "xiangyuan";
Console.WriteLine(object.ReferenceEquals(a, b));
Console.WriteLine(object.ReferenceEquals(a, new OtherClass().c));
//请问输出结果什么? TT/TF/FT/FF (T=Ture, F=False)
}
}
请在评论区写出你的答案: TT/TF/FT/FF (T=Ture, F=False)
设计模式之隆过滤器
建布隆过滤器:
1, 建一个很长的二进制数组
2, 把数据经过用多个哈希算法得到的二进制值写到数组里面
用布隆过滤器
把需要检查的数据,经过相同的哈希算法得到的二进制, 在数组中匹配,全部1都匹配表示存在, 任意位不是1表示不存在
应用要点
1, 只需要判断是否存在
2, 集合的数量非常大
应用场景
垃圾邮箱黑名单
批量替换一段文本中的特殊标记字段{xxx}
//批量替换一段文本中的特殊标记字段{xxx}
public class StringReplaceDynamic
{
public static void Demo()
{
XElement root = XElement.Load(@"D:\space\test\ConsoleAppNetFramework\xml\BS004.xml");
Dictionary<string, string> a = new Dictionary<string, string>();
a.Add("patientId", "123");
a.Add("registerID", "321");
var b = StringReplace(root.ToString(), a);
Console.WriteLine(b);
}
public static void Demo2()
{
XElement root = XElement.Load(@"D:\space\test\ConsoleAppNetFramework\xml\BS004.xml");
DataTable dt = new DataTable();
dt.Columns.Add("patientId");
dt.Columns.Add("registerID");
DataRow dr = dt.NewRow();
dr["patientId"] = "123";
dr["registerID"] = "321";
dt.Rows.Add(dr);
var b = StringReplace(root.ToString(), dt);
Console.WriteLine(b);
}
//用Dictionary替换{xxx}
public static string StringReplace(string msg, Dictionary<string, string> dic)
{
foreach (var obj in dic)
{
string r = "{" + obj.Key + "}";
msg = msg.Replace(r, obj.Value);
}
return msg;
}
//用第一行的数据替换{xxx}
public static string StringReplace(string msg, DataTable dic)
{
foreach (var obj in dic.Columns)
{
string r = "{" + obj.ToString() + "}";
msg = msg.Replace(r, dic.Rows[0][obj.ToString()].ToString());
}
return msg;
}
}
开机自启动
string path = Application.ExecutablePath;
RegistryKey rk = Registry.CurrentUser;
RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
rk2.SetValue("BtmsPhoneNotify", path);
rk2.Close();
rk.Close();
// "已设置开机自启动"
SqliteHelper
public static class SqliteHelper
{
//从配置文本中读取连接字符串
private static string connStr = "data source=data.sqlite";
//执行命令的方法:insert,update,delete
//params:可变参数,目的是省略了手动构造数组的过程,直接指定对象,编译器会帮助我们构造数组,并将对象加入数组中,传递过来
public static int ExecuteNonQuery(string sql, params SQLiteParameter[] ps)
{
//创建连接对象
using (SQLiteConnection conn = new SQLiteConnection(connStr))
{
//创建命令对象
SQLiteCommand cmd = new SQLiteCommand(sql, conn);
//添加参数
cmd.Parameters.AddRange(ps);
//打开连接
conn.Open();
//执行命令,并返回受影响的行数
return cmd.ExecuteNonQuery();
}
}
//获取首行首列值的方法
public static object ExecuteScalar(string sql, params SQLiteParameter[] ps)
{
using (SQLiteConnection conn = new SQLiteConnection(connStr))
{
SQLiteCommand cmd = new SQLiteCommand(sql, conn);
cmd.Parameters.AddRange(ps);
conn.Open();
//执行命令,获取查询结果中的首行首列的值,返回
return cmd.ExecuteScalar();
}
}
//获取结果集
public static DataTable GetDataTable(string sql, params SQLiteParameter[] ps)
{
using (SQLiteConnection conn = new SQLiteConnection(connStr))
{
//构造适配器对象
SQLiteDataAdapter adapter = new SQLiteDataAdapter(sql, conn);
//构造数据表,用于接收查询结果
DataTable dt = new DataTable();
//添加参数
adapter.SelectCommand.Parameters.AddRange(ps);
//执行结果
adapter.Fill(dt);
//返回结果集
return dt;
}
}
}
sqlite数据初始化
public class SqliteDbInit
{
//创建所有表,可以反复执行,程序启动后都执行一次
public static void Init()
{
//打印类型对应的打印机
var tablePrinterName = "create table if not exists PrinterName (PrintType varchar(64), PrinterName varchar(512))";
SqliteHelper.ExecuteNonQuery(tablePrinterName);
//是否预览
var tableIsPreview = "create table if not exists IsPreview (PrintType varchar(64), IsPreview int)";
SqliteHelper.ExecuteNonQuery(tableIsPreview);
}
}
xml转DataTable
DataSet xmlDS = new DataSet();
var stream = new StringReader(xml);
xmlDS.ReadXml(stream);
DataTable table = xmlDS.Tables[0];
xml节点转成json数组再转成DataTable
public static DataTable GetList(string data)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(data);//创建xml对象
string jsonText = JsonConvert.SerializeXmlNode(doc); //xml对象转json字符串
JObject json = JObject.Parse(jsonText); //json字符串转jion对象
var json2 = json["result"]["item"].ToString(); //从json对象中得到json数组字符串,类似: [{},{},{}]
return JsonConvert.DeserializeObject<DataTable>(json2); //json数据转datatable
}
Winform重启
Process.Start(Application.ExecutablePath);
Application.Exit();
Winform的弹出消息
// 消息对话框, 2秒后自动消失
class MkMessage : Form
{
private Label label1;
private Timer timer;
public MkMessage()
{
InitializeComponent();
// 设置对话框的属性,居中,边框
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedSingle;
// 添加一个Label作为对话框的内容
label1.Text = "这是一个非模态对话框,将在2秒后消失。";
// 初始化Timer控件
timer = new Timer();
timer.Interval = 2000; // 2000毫秒后触发
timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, EventArgs e)
{
// 当Timer触发时关闭对话框
this.Close();
}
private void Show(string title, string msg)
{
label1.Text = msg;
// 显示对话框并启动计时器
this.Show();
timer.Start();
}
public static void Show(string msg)
{
new MkMessage().Show("", msg);
}
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
this.label1.Font = new System.Drawing.Font("微软雅黑", 15F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.label1.Location = new System.Drawing.Point(0, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(345, 116);
this.label1.TabIndex = 0;
this.label1.Text = "label1";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// MkMessage
//
this.ClientSize = new System.Drawing.Size(345, 116);
this.Controls.Add(this.label1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "MkMessage";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.ResumeLayout(false);
}
}
一次只能启动一个EXE
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Mutex instance = new Mutex(true, "ExeName", out bool createdNew);//一次只能启动一个程序
if (args.Length > 0)
{
// 有参数说明是程序自动重启, 不用判断
Application.Run(new Form5());
instance.ReleaseMutex();
}
else
{
if (createdNew)
{
// 加载窗口
Application.Run(new Form5());
instance.ReleaseMutex();
}
else
{
var form = new AutoCloseForm("程序已运行", 2000);
form.ShowDialog();
Application.Exit();
Mutex.OpenExisting("ExeName");
}
}
}
}
// 自动重启EXE
Application.Exit();
Process.Start(Application.ExecutablePath, "restart");
显示几秒后自动消失的对话框
public class AutoCloseForm : Form
{
private Timer _closeTimer;
public AutoCloseForm(string message, int timeoutMilliseconds)
{
// 设置窗体的属性
this.Size = new System.Drawing.Size(300, 100);
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.StartPosition = FormStartPosition.CenterScreen;
this.ControlBox = false; // 不显示控制框
// 添加标签来显示消息
Label messageLabel = new Label();
messageLabel.Text = message;
messageLabel.Dock = DockStyle.Fill;
messageLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.Controls.Add(messageLabel);
// 设置计时器
_closeTimer = new Timer();
_closeTimer.Interval = timeoutMilliseconds;
_closeTimer.Tick += (sender, e) =>
{
_closeTimer.Stop();
this.Close();
};
_closeTimer.Start();
}
}