顯示具有 c# 標籤的文章。 顯示所有文章
顯示具有 c# 標籤的文章。 顯示所有文章

2024年11月20日 星期三

c# 台灣載具正規表達式

目前查了一下台灣載具規則如下
載具規則
1.總長度8碼
2.第一碼必為[/]
3.後七碼為[半形]數字[0-9]、英文大寫[A-Z]、符號[.][-][+]
以下為驗證,如有錯誤請告知
using System.Text.RegularExpressions;
 public static bool taiwancarrier(string input) {
    return  Regex.IsMatch(input, @"^/[0-9A-Z.+-]{7}$");
 }
 
參考資料
手機條碼、自然人憑證條碼與捐贈碼檢核規則
用 regular expression 驗證電子發票手機條碼格式 。E-invoice mobile barcode validator by regular expression.

2024年2月19日 星期一

c# Unix Timestamp轉換

近期專案接觸到很多API
發現目前大多數日期都是數字,查了一下是Unix Timestamp
寫了兩個Function來互轉
時間轉數字
public static double DateToDouble(DateTime? pNow = null)
{
    DateTime mNow = DateTime.Now;
    if (pNow != null && pNow.HasValue)
    {
        mNow = pNow.Value;
    }
    DateTimeOffset t = DateTimeOffset.Parse(mNow.ToString("yyyy-MM-dd HH:mm:ss"));
    return Convert.ToDouble(t.ToUnixTimeSeconds());
}
數字轉時間
  public static DateTime DoubleToDate(double? pDate = 0)
  {
      double d = 0;
      if (pDate != null && pDate.HasValue)
      {
          d = pDate.Value;
      }

      if (d > 9999999999)
          d = d / 1000;

      DateTime StartComputerFirstDay = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
      return StartComputerFirstDay.AddSeconds(d).ToLocalTime();
  }
參考資料
[C#] 時間轉換為Unix TimeStamp
Epoch (computing)
The Current Epoch Unix Timestamp

2023年10月27日 星期五

c# 變更ClickOnce產生出的setup.exe的icon

使用ClickOnce會自動更新,所以有時給user時會直接給setup.exe
但icon的話就有可能跟別的重複,比較不好分辨
以下方法可修改icon
1.開啟Visual Studio
2.檔案 > 開啟 > 檔案 > 選擇setup.exe
3.icon > 加入資源
4.匯入 > 選擇icon
5.確保匯入後的編號在前面即可
PS.windows有時候不會即時變更顯示,須重開機
參考資料
【转】vs2012 打包安装更改 setup.exe的图标
How to change Setup.exe icon when publishing through clickonce

2022年2月10日 星期四

c# ViewModel To Model

這方法也是今天才發現
但真的還蠻實用的
如下兩個Class,StaffViewModel繼承了Staff
public class Staff
{
    public int id { get; set; }
    public string name { get; set; }
}

public class StaffViewModel :Staff
{ 
    public int departid { get; set; }
}
如果後端存檔時前端回傳是StaffViewModel但存檔只需要Staff資料
就需要轉換目前網路上看最多人推之一AutoMapper
後來發現如果有繼承關係在時被繼承的List中可直接塞入繼承類別如下
private List<Staff> Merge(List<StaffViewModel> model)
{
     List<Staff> result = new List<Staff>(0);
     foreach (var item in model)
         result.Add(item);
            
     return result;
}       
如果以上不是BUG的話設計時能多用原本存在的方式就能少裝些插件
真的可以省下很多時間減少安裝插件後的問題

2022年1月21日 星期五

c# DirectoryInfo應用

DirectoryInfo di = new DirectoryInfo(@"\\192.168.0.1\old");
//所有檔案列表包含子資料夾
var queryfileall = di.GetFiles("*", SearchOption.AllDirectories);
//指定單一副檔名
var queryfileone = di.GetFiles("*.jpg", SearchOption.AllDirectories);
//指定多重副檔名
string[] extensions = new[] { ".jpg", ".mp3"};
var queryfilemultiple  = di.GetFiles("*", SearchOption.AllDirectories).Where(x => extensions.Contains(x.Extension.ToLower())).ToArray();

//建立資料夾
string newpath =  @"\\192.168.0.1\new";
if (!Directory.Exists(newpath))
{
	Directory.CreateDirectory(newpath);
}
           

foreach (var item in queryfile)
{
	try
   {
   	   //可自行變化...
   	   //複製檔案
		if (!File.Exists(newpath + item.Name))
         item.MoveTo(newpath + item.Name);
   }
   catch (Exception ex)
   {

      throw new Exception(ex.Message);
   }   
}

//方法2
  DirectoryInfo root = new DirectoryInfo(@"\\192.168.0.1\old");
  FileInfo[] files = root.GetFiles();
  foreach (var item in files)
 {}
參考來源
Get multiple files with different extension

2020年10月15日 星期四

C# 登入網路磁碟機且輸入帳號密碼(with .net core 2024 update)

Can you explain why DirectoryInfo.GetFiles produces this IOException?
以下程式碼來源如參考網站
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace Company.Security
{
    public class ImpersonateUser : IDisposable
    {
        [DllImport("advapi32.dll", SetLastError=true)]
        private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

        [DllImport( "kernel32", SetLastError = true )]
        private static extern bool CloseHandle(IntPtr hObject);

        private IntPtr userHandle = IntPtr.Zero;
        private WindowsImpersonationContext impersonationContext;

        public ImpersonateUser( string user, string domain, string password )
        {
            if ( ! string.IsNullOrEmpty( user ) )
            {
                // Call LogonUser to get a token for the user
                bool loggedOn = LogonUser( user, domain, password,
                    9 /*(int)LogonType.LOGON32_LOGON_NEW_CREDENTIALS*/,
                    3 /*(int)LogonProvider.LOGON32_PROVIDER_WINNT50*/,
                    out userHandle );
                if ( !loggedOn )
                    throw new Win32Exception( Marshal.GetLastWin32Error() );

                // Begin impersonating the user
                impersonationContext = WindowsIdentity.Impersonate( userHandle );
            }
        }

        public void Dispose()
        {
            if ( userHandle != IntPtr.Zero )
                CloseHandle( userHandle );
            if ( impersonationContext != null )
                impersonationContext.Undo();
        }
    }
}
使用方法
using ( new ImpersonateUser( "UserID", "Domain", "Password" ) )
{
    // Any IO code within this block will be able to access the remote server.
}
.net Core(20240219更新) Only windows server
 [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
 public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeAccessTokenHandle phToken);

 const int LOGON32_PROVIDER_DEFAULT = 0;
 //This parameter causes LogonUser to create a primary token. 
 const int LOGON32_LOGON_INTERACTIVE = 2;
 // Call LogonUser to obtain a handle to an access token. 
 SafeAccessTokenHandle safeAccessTokenHandle;
 public IActionResult X()
 {
            try
            {
               
                bool returnValue = LogonUser("test", "mydomain", "test123", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeAccessTokenHandle);
                if (!returnValue)
                    throw new Exception("登入unc路徑錯誤!!");

 
                WindowsIdentity.RunImpersonated(safeAccessTokenHandle, () =>
                {
                    var basepath = @"\\192.168.0.1\testFiles";

                    if (!Directory.Exists(basepath))
                    {
                        throw new Exception("無資料夾-" + basepath);
                    }

                    DirectoryInfo root = new DirectoryInfo(basepath);
                    FileInfo[] files = root.GetFiles();
                    foreach (var item in files)
                    {
                        try
                        {
                            
                           // item.Delete();
                                

                        }
                        catch (Exception ex)
                        {
                            throw new Exception( ex.Message);
                        }
                    }
                });
 

            }
            catch (Exception ex)
            {
                sb.Append($"error:{ex.Message}");
            }
 
 }
參考來源
Can you explain why DirectoryInfo.GetFiles produces this IOException?
How to pass unc credential in .net corev

2020年3月12日 星期四

c# 基礎連接已關閉: 無法為 SSL/TLS 安全通道建立信任關係。

公司將一些網站改走SSL後發現有些POST取資料功能失效了
出現基礎連接已關閉: 無法為 SSL/TLS 安全通道建立信任關係
解法辦法

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;<=加入
 ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;<=加入

參考來源
[faq]解決C#呼叫有ssl憑證問題的網站出現遠端憑證是無效的錯誤問題
C# HttpReques 基礎連接已關閉: 無法為 SSL/TLS 安全通道建立信任關係 強制跳過 TLS驗證
C# 連線 HTTPS 網站發生驗證失敗導致基礎連接已關閉

2019年9月26日 星期四

c# 日期區間小撇步

單一日期查詢只需比對大於and小於
但若日期開兩個欄位,
一個是日期起,
一個是日期迄,
如何查詢區間內的資料?

舉例:
想知道2019-09-01到2019-09-30之前有哪些人在職
稍微畫個圖後有了靈感
((到職日期 <= 2019-09-30 && 離職日期 >= 2019-09-01)  || (離職日期 =null ))
會就在這個區間


2018年10月25日 星期四

c# string.Format、StringBuilder.AppendFormat 輸入字串格式不正確

今天早上發生了一個錯誤"輸入字串格式不正確"
程式從頭檢查到尾有字串相加、string.Format、StringBuilder.AppendFormat
所有都檢查過了{0},{1}...也都詳細檢查過了該帶入的都帶入了
後來程式上沒問題就將目標轉到文章上去
發現了其中一筆資料中內容文字{X}有這樣的字元出現
然後檢查了程式剛好是sb.AppendFormat(item.context);
所以{X}部分被當作要取代的索引然後就錯了
最簡單解法改為sb.Append (item.content);
單純加入文字

2018年5月31日 星期四

c# 判斷日期區間遇到幾次生日

最近用到寫的日期區間遇到幾次生日
也可以用來判斷日期區遇到日期幾次
也許有更好的可以交流
public static int GetBetweenBirthdayCount(DateTime pFrom, DateTime pTo, DateTime pBirthday)
        {
            int mBirthdayCount = 0;//會過幾次生日

            int TotalYear = pTo.Year - pFrom.Year;//看區間有幾年

            for (int i = 0; i <= TotalYear; i++)
            {

                int y = pFrom.AddYears(i).Year;
                string m = pBirthday.Month.ToString().PadLeft(2, '0');
                string d = pBirthday.Day.ToString().PadLeft(2, '0');
               
                //如果他是生日229的要判斷
                if (m == "02" && d == "29")
                {//四除的盡就算閏年
                    if (y % 4 != 0)
                    {
                        d = "28";
                    }
                }


                DateTime EveryBirthday = DateTime.Parse(y + "-" + m + "-" + d);

                if (pFrom <= EveryBirthday && pTo >= EveryBirthday)
                {
                    mBirthdayCount++;
                }
            }

            return mBirthdayCount;
        }

2016年4月15日 星期五

c# WinForm鍵盤對應畫面輸入例如小鍵盤

這功能應該網路上都找的到
因為比較少寫winform所以自己記錄一下
1.首先winform 建構式時要設定
this.KeyPreview = true;
2.覆寫Form.ProcessCmdKey大致上這樣就可以了
  protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.NumPad1:
                case Keys.D1:

                     //按下1或鍵盤1時處理      
                     return true; 
                case Keys.Enter:

                    //按下Enter時處理                  
                    return true; 
                case Keys.Escape:

                    //按下Esc時處理
                    return true;
            }

            return base.ProcessCmdKey(ref msg, keyData);

        }
參考來源
Form.ProcessCmdKey 方法 (Message, Keys)
c# - 在 WinForm 中讓 Enter 鍵變成 Tab 鍵

2015年6月5日 星期五

c# INotifyPropertyChanged實作

網路上已經有許多INotifyPropertyChanged的文章
看了許多但還是不太懂所以看著msdn實作了一次
1.先新增一個class
        public int id { get; set; }
        public string name { get; set; }
2.將class繼承INotifyPropertyChanged
        using System.ComponentModel;
        public class member : INotifyPropertyChanged
3.實作INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
4.修改class
  public int id { get; set; }

        private string _name;
        public string name
        {
            get { return this._name; }
            set
            {
                if (value != this._name)
                {
                    this._name = value;
                    NotifyPropertyChanged("Name");
                }
            }
        }
5.新增一個list(抓假資料如果是資料庫也可直接改)
  public List GetMember(int pCount)
        {
            List lst = new List();
            string name = "test";
            for (int i = 0; i < pCount; i++)
            {
                member create = new member()
                {
                    id = i,
                    name = name + i.ToString()
                };
                lst.Add(create);
            }
            return lst;
        }
6.抓出資料
 member script = new member();
 List lst = script.GetMember(10);
 dataGridView1.DataSource = lst;
7.寫另一個頁面去修改name
會發覺改了後dataGridview1的name也會跟著改
太神奇又好用了
參考網址
HOW TO:實作 INotifyPropertyChanged 介面
範例下載
INotifyPropertyChanged實作

2014年9月30日 星期二

c# Entity Framework ConnectionString 不支援關鍵字: 'data source'。

時代在進步從ado到Entity Framework
不變的都是有connection string 只是寫法不一樣
今天問題的發生點是公司"希望"connection string 需要加密
以下為EF的conn我想大部份的人憑空也寫不出來吧當然咪兔
原本使用工具產生的connectionstring
 
metadata=res://*/Models.Model.csdl|res://*/Models.Model.ssdl|res://*/Models.Model.msl;provider=System.Data.SqlClient;provider connection string=&Quot;Data Source=192.168.1.1;initial catalog=test;user id=sa;password=1234;multipleactiveresultsets=True;App=EntityFramework&Quot;
寫一個function
 
  public static string getEntitiesConn()
        {
            string test = CodeClass.Decrypt(System.Configuration.ConfigurationManager.ConnectionStrings["testEntities"].ToString());
            return test;
        }
解密出來
 
metadata=res://*/Models.Model.csdl|res://*/Models.Model.ssdl|res://*/Models.Model.msl;provider=System.Data.SqlClient;provider connection string=&Quot;Data Source=192.168.1.1;initial catalog=test;user id=sa;password=1234;multipleactiveresultsets=True;App=EntityFramework&Quot;
看起來一樣吧
 
testEntities db = new testEntities(Conn.getEntitiesConn());
 
不支援關鍵字: 'data source'。
是那裡有問題阿仔細一下 &Quot;這東西不就是雙引號嗎
後來把要加密的connectionstring裡的 &Quot;改成雙引號再加密讀出來就OK有沒有那麼神阿@@
在此記錄一下希望以後類似問題能不被卡住

2014年7月3日 星期四

c# Parameters.AddWithValue DBNull

在Inser or Update時難免遇到的問題
第一個想法會寫個function來判斷DBNull 或是文字
或者是用三元運算子
今天看到更短的寫法順便學一下
 
cmd.Parameters.AddWithValue("@abc", (object)item.abc ?? DBNull.Value);
參考網址
點我前往

2014年5月9日 星期五

c# 遮罩電話 xxx

這function效能非最佳只不過目前剛好用到
所以隨手寫了一下
如有更好的方式可提供喔謝謝!!
 
   /// 
        /// 遮罩電話 (十個字 手機市話)(九個字 市話)(十個字以上前四後三)(四個字以下回傳空白)
        /// 
        /// 字串    
        /// string
        public static string MaskString(string pStr)
        {
            string mReturn = "";

            if (pStr.Length == 9 && pStr.StartsWith("0")) //9碼的如高雄
            {
                mReturn = pStr.Substring(0,2) + "-XXX-" + pStr.Substring(5,4);
            }
            else if (pStr.Length == 10 && pStr.StartsWith("09"))//手機
            {             

                mReturn = pStr.Substring(0, 4) + "-XXX-" + pStr.Substring(7, 3);

            }
            else if (pStr.Length == 10 && pStr.StartsWith("0"))//台北市話
            {
                mReturn = pStr.Substring(0, 2) + "-XXXX-" + pStr.Substring(6, 4);
            }
            else
            {
                if (pStr.Length > 10)//十個字以上
                {
                    for (int i = 0; i < pStr.Length ; i++)
                    {
                        if ((i == 0 || i <= 3) || (i >= pStr.Length - 3)) //前四個字 後三個字出現
                        {
                            mReturn += pStr.Substring(i,  1);
                        }
                        else
                        {
                            mReturn += "X";
                        
                        }
                    }                   
                }
                else  if(pStr.Length >= 4)//四個字以上才會做
                {
                    for (int i = 0; i < pStr.Length; i++)
                    {
                        if (i >= pStr.Length - 3) //後三個字出現
                        {
                            mReturn += pStr.Substring(i, 1);
                        }
                        else
                        {
                            mReturn += "X";
                        }
                    }
                }            
            }
            return mReturn;
        }

2013年8月2日 星期五

c# DataTableToLinq常用語法(附原碼)

記得剛開始在寫程式時公司是用VB那時LINQ剛出,於是就用了LINQ+ ADO.NET Entity Framework ,一開始也是相當不順,但用久就習慣了。

後來也有人問我說用VB寫LINQ語法不會卡卡的嗎,我到覺得用ADO.NET Entity Framework 才會卡卡因為必需規劃的很詳細,不然很麻煩,所以後來我都用Datatable,可能在自由度會比較高,但是如果自己打錯字就完了。

後來常會遇到有些相當麻煩的語法,想起了LINQ相當好用於是找了LINQ來搭配Datatable(當然dataset也可),解決了許多已經撈出資料後做處理的問題,我覺得只要搭配的好不一定真的要用全新的功能,所以以下原始碼給大家參考使用,當然裡面只是小部份而且寫法也可多變,只是讓我自己在忘記時能快速查到使用方式。

2013-08-02
內含以下語法
distinct
groupby
join
leftjoin
like
orderby
top
where

原始碼點我下載去

2011年12月8日 星期四

c# 三位一撇+小數點??位

最近做到有關金額的所以常用
就寫成function 來用比較快

這之前好像有了

///  
/// 判斷是否為數字 
/// 
/// 傳入判斷的字串。
public static bool IsNumeric(String pNumber)
{
Regex NumberPattern = new Regex("[^0-9.-]");
return !NumberPattern.IsMatch(pNumber);
}


/// 
/// 三位一撇 + 小數??位
///  
/// 傳入字串數字。
/// 傳入字串。
public static string ToThree(string pInt,string p0)
{

string mReturn = string.Empty;

if (pInt != "")
{
if (IsNumeric(pInt))
{
mReturn = string.Format("{0:N"+ p0+"}", Convert.ToDecimal(pInt));
}
}
else
{
mReturn = string.Format("{0:N" + p0 + "}", "0");

}
return mReturn;
}

2011年11月30日 星期三

c# DatatableTo Linq Group by

找出dt1裡的以尺寸跟顏色來Group by
統計數量

下面是將文字變0

///  
/// 回傳數字Decimal,非數字及空白都變成0 
///  
/// 傳入字串。
public static Decimal ToDecimal(string pInt)
{
Decimal mReturn = 0;
if (pInt == "")
{
mReturn = 0;
}
else
{
if (IsNumeric(pInt))
{
mReturn = Convert.ToDecimal(pInt);
}
else
{
mReturn = 0;
}
}
return mReturn;
}


var QueryA =( from u in dt1.AsEnumerable() 
group u by new { CX_Size = u["CX_Size"], CX_Color_Name = u["CX_Color_Name"] } into g
select new
{
CX_Size = g.Key.CX_Size,
CX_Color_Name = g.Key.CX_Color_Name,
CX_Quantity = g.Sum(p => Convert.ToDecimal(PublicClass.ToDecimal(p["CX_Quantity"].ToString()))),
CX_Amount = g.Sum(p => Convert.ToDecimal(PublicClass.ToDecimal(p["CX_Amount"].ToString())))
}).ToList();
最後再用迴圈來統計

foreach (var mRowA in QueryA)
{
//做處理 

}

c# 簡單做流水號的方法

註我的流水號是 (民國年三碼) + 月月 + 三碼流水號
所以後面有-1911
這是做月份的方式以此類推後面可以有日的


//取得流水號
string Sql1 = " select top 1 convert(int,substring(CX_Order_No,6,3)) as maxNo from QuoteList where substring(CX_Order_No,1,5)=@yyyMM order by convert(int,substring(CX_Order_No,6,3)) desc ";
SqlCommand cmd1 = new SqlCommand(Sql1, conn);

decimal myyy = PublicClass.ToDecimal(DateTime.Now.Year.ToString() )- 1911;
myyyyMM = myyy.ToString() + int.Parse(DateTime.Now.Month.ToString()).ToString("00");
cmd1.Parameters.AddWithValue("@yyyMM", myyyyMM);
DataTable dt1 = new DataTable();
SqlDataAdapter da1 = new SqlDataAdapter(cmd1);
da1.Fill(dt1);

if (dt1.Rows.Count > 0)
{
myyyyMM = myyyyMM + int.Parse( ( PublicClass.ToDecimal(dt1.Rows[0]["maxNo"].ToString()) + 1).ToString()).ToString("000");//有時給他加1
}
else
{
myyyyMM = myyyyMM + "001";//沒有時就給他001
}

c# 不足位數補0

月份補成兩位數
string test = int.Parse(DateTime.Now.Month.ToString()).ToString("00");


string test = string.Format("{0:00}", Convert.ToInt16(mNow.Month));