[C# - VB] How to restart program in Winform

Xin chào các bạn, bài viết này mình sẽ hướng dẫn các bạn cách khởi động lại chương trình ứng dụng C#, Visual Basic, Winform.


[C# - VB] Hướng dẫn khởi động lại chương trình ứng dụng winform

[C# - VB] Hướng dẫn khởi động lại chương trình ứng dụng winform

Các bạn sử dụng đoạn script sau để thực hiện khởi động lại ứng dụng của mình:

FULL CODE CSHARP:

private void RestartProgram()
{
    // Get file path of current process 
    var filePath = Assembly.GetExecutingAssembly().Location;
    //var filePath = Application.ExecutablePath;  // for WinForms
 
    // Start program
    Process.Start(filePath);
     
    // For Windows Forms app
    Application.Exit();
                 
    // For all Windows application but typically for Console app.
    //Environment.Exit(0);
}

FULL CODE VISUAL BASIC:

Private Sub RestartProgram()
    Dim filePath = Assembly.GetExecutingAssembly().Location
    Process.Start(filePath)
    Application.[Exit]()
End Sub

Chúc các bạn thành công với thủ thuật đơn giản này.

on Thứ Bảy, 3 tháng 2, 2024 | , | A comment?

[BUY] TEMPLATE JAGODESAIN BLOGSPOT

Hi mọi người, sau một thời gian sữ dụng giao diện jagodesain của nldblog chia sẽ trên trang blog cá nhân, mình đã thay đổi giao diện và kiểm tra tốc độ tải trang cũng rất ổn, nhưng đến ngày hôm nay. 


Sau một hồi loay hoay sữa đổi giao diện và mình đã chỉnh sữa lại giao diện đó cũng khá ổn, và tộc độ tải trang và chuẩn seo đã đạt 100% như mình mong muốn.

Bên dưới là hình ảnh mình kiểm tra.

Kiểm tra giao diện mobile.


Kiểm tra giao diện desktop.


Qua hình ảnh phía trên các bạn cảm nhận thế nào về giao diện mình tuỳ biến, mình cảm thấy bản thân mình tuỳ biến như vậy cũng đã ok cho bản thân sữ dụng, và giao diện nó vẫn mặc định như vậy nhưng mình đã xoá bỏ đi một số thứ mà anh PAGESPEED đánh giá không tốt cho blog nhé.
 
Nếu các bạn cũng muốn tuỳ biến theo bản thân thì có thể sang trang này để tải bản chia sẽ của NLDBLOG chia sẽ nhé.

Trang giao diện được chia sẽ rất nhiều trên internet : sata.code.pro.vn, nldblog.com, sosialhits.com...v.v
Đó là một số trang đang chia sẽ giao diện tuyệt vời này nhé. Phủ hợp cho các bạn đang chia sẽ về ứng dụng game hoặc tuỳ biến lại để làm trang blog cá nhân nhé.
 
Và giao diện của mình các bạn có thể kiểm tra giao diện này mình chỉnh sữa tốc độ tải trang và seo tại đây nhé.

Đây là giao diện của tác giả : https://apmody.blogspot.com/

Nếu các bạn muốn giao diện của tác giả thì tất cả mọi thứ sẽ ok, nhưng khi các bạn dùng bản FREE thì nó không hoàn hảo như trang demo đâu các bạn nhé.

Và giao diện này nếu ai muốn nhận giao diện do mình tuỳ biến thì có giá 200k nhé, và mình không chia sẽ miễn phí nữa nhé. Vì có một số thành phần sữ dụng những thứ mình làm được đem đi bán để kiếm lời cho bản thân. Và chèn một số thứ không tốt vào blog để làm lợi cho bản thân và mất đi uy tính của mình.

DEMO


Nếu các bạn có muốn mua thì có thể liên hệ cho mình tại Facebook nhé.
https://hung.pro.vn/facebook
Chúc các bạn sỡ hữu được một giao diện tốt cho blog nhé.

on Thứ Bảy, 27 tháng 1, 2024 | , | A comment?

[DEVEXPRESS] How to make Label Report in c# winform

Xin chào các bạn, bài viết hôm nay mình chia sẻ các bạn source code, tạo báo cáo report in tem nhãn dùng quản lý thông tin thiết bị, tài sản của công ty hoặc cá nhân.

[DEVEXPRESS] Chia sẻ source code tạo báo cáo report in tem nhãn label trên C# winform

Dưới đây là hình ảnh demo ứng dụng C#:

[DEVEXPRESS] How to make Label Report in c# winform

Source code C#:

1, Code FormMain.cs
using DevExpress.Export;
using DevExpress.XtraPrinting;
using DevExpress.XtraReports.UI;
using System;
using System.Data;
using System.Data.OleDb;
using System.Windows.Forms;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraEditors;
using report;

namespace VNSoftware.frmDongThung
{
    public partial class TaoMaVachcs : DevExpress.XtraEditors.XtraForm
    {
        private DataTable yourDataTable;



        public TaoMaVachcs()
        {
            InitializeComponent();
            InitializeDataTable();
            InitDataDemo();
            dtgv.DataSource = yourDataTable;
        }

        private void InitializeDataTable()
        {           
            yourDataTable = new DataTable();
            yourDataTable.Columns.Add("MA HANG", typeof(string));
            yourDataTable.Columns.Add("VERSION", typeof(string));
            yourDataTable.Columns.Add("SO LUONG/ THUNG", typeof(string));
            yourDataTable.Columns.Add("Ma Cty", typeof(string));
            yourDataTable.Columns.Add("MA VUNG", typeof(string));
            yourDataTable.Columns.Add("LOT DH", typeof(string));
            yourDataTable.Columns.Add("SO TT THUNG", typeof(string));
            yourDataTable.Columns.Add("Ma trong", typeof(string));
            yourDataTable.Columns.Add("QRCODE", typeof(string));
        }
        public int GetRandomNumber(int min, int max)
        {
            Random random = new Random();
            return random.Next(min, max + 1);
        }
        private void InitDataDemo()
        {
            try
            {
                string mahang = "SP240116-01";
                mahang = mahang.PadRight(22);
                string ver = "0";
                ver = ver.PadRight(12);
                string soluong = GetRandomNumber(1, 1500).ToString();
                soluong = soluong.PadRight(14);
                string macty = "LAPTRINHVB2015";
                macty = macty.PadRight(16);
                string mavung = "VBNET";
                string lot = "123456";
                string matrong ="0";
                int j = 0;
                int k = 100;


              
                for (int i = j; i <= k; i++)
                {
                   string sothutu = i.ToString("0000");
                  string qrcode = $"{mahang}{ver}{soluong}{macty}{mavung}{lot}{sothutu}{matrong}";
                    DataRow newRow = yourDataTable.NewRow();
                    newRow["MA HANG"] = mahang;
                    newRow["VERSION"] = ver;
                    newRow["SO LUONG/ THUNG"] = soluong.Trim();
                    newRow["Ma Cty"] = macty;
                    newRow["MA VUNG"] = mavung;
                    newRow["LOT DH"] = lot;
                    newRow["SO TT THUNG"] = sothutu;
                    newRow["Ma trong"] = matrong;
                    newRow["QRCODE"] = qrcode;                
                    yourDataTable.Rows.Add(newRow);
                }           
                gridView1.BestFitColumns();
            }
            catch (FormatException)
            {
                MessageBox.Show("Không thể chuyển đổi chuỗi sang số nguyên.");
            }

        }

        private void btnInNhan_Click(object sender, EventArgs e)
        {
            if (yourDataTable.Rows.Count <= 0)
            {
                XtraMessageBox.Show("Chưa có dữ liệu để in nhãn");
                return;
            }
            var loaiReport = 1;
            var formPrintPreview = new FrmPrintPreview(loaiReport, yourDataTable);
            formPrintPreview.Show();
        }
    }
}

2. Source code form FrmPrintPreview.cs

amespace report
{
    public partial class FrmPrintPreview : DevExpress.XtraBars.Ribbon.RibbonForm
    {
        public int _loaiReport;
        public object _dataTable;
        public FrmPrintPreview(int loaiReport, object dataTable)
        {
            InitializeComponent();
            this._loaiReport = loaiReport;
            this._dataTable = dataTable;

        

        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
           
            switch (_loaiReport)
            {
                case 1:
                    {
                        Text = @"IN TEM NHÃN LABEL";
                        var rpt = new reportLabel1();
                        documentViewer1.PrintingSystem = rpt.PrintingSystem;
                        rpt.DataSource = _dataTable;
                        rpt.BindData();
                        rpt.CreateDocument();
                    }
                    break;
            }
        }
    }
}

3. Source code reportLabel1.cs

namespace report
{
    public partial class reportLabel1 : DevExpress.XtraReports.UI.XtraReport
    {
        public reportLabel1()
        {
            InitializeComponent();
        }

        public void BindData()
        {
            txtMaHang.DataBindings.Add("Text", DataSource, "MA HANG");
            txtSoThuTu.DataBindings.Add("Text", DataSource, "SO TT THUNG");
            txtVersion.DataBindings.Add("Text", DataSource, "VERSION");
            txtSoluong.DataBindings.Add("Text", DataSource, "SO LUONG/ THUNG").FormatString = "{0:#,###.##} Pcs";

            txtLotDH.DataBindings.Add("Text", DataSource, "LOT DH");
            txtMaVung.DataBindings.Add("Text", DataSource, "MA VUNG");
            xrBarCode1.DataBindings.Add("Text", DataSource, "QRCODE");
        }
    }
}

Chúc các bạn thành công với thủ thuật trên, để tích hợp để phù hợp với công việc của các bạn nhé

DOWNLOAD SOURCE CODE


PASSWORD UNZIP : HUNG.PRO.VN

on Thứ Sáu, 26 tháng 1, 2024 | , , | A comment?

[C#] GET, DELETE, UPLOAD, DOWNLOAD FILE GOOGLE STORAGE CLOUD API

Xin chào các bạn bài viết hôm nay, mình sẽ tiếp tục chia sẽ đến các bạn các lấy danh sách, xóa, upload, download file từ Google Cloud Storage API C# Winform.


[C#] Hướng dẫn lấy danh sách, xóa, upload, download file Google Cloud Storage API


Cloud storage hay lưu trữ đám mây là một thuật ngữ dùng để chỉ các hành động lưu giữ, sắp xếp, quản lý, chia sẻ, và sao lưu dữ liệu của cá thể sở hữu nó trên một hệ thống lưu trữ bên ngoài ổ cứng được duy trì bởi các nhà cung cấp (hay bên thứ ba). Dịch vụ này cho phép khách hàng hay người dùng có thể truy cập được tất cả các tệp tin của họ từ xa tại bất kỳ vị trí địa lý nào.

Dịch vụ này cho phép khách hàng hay người dùng có thể truy cập được tất cả các tệp tin của họ từ xa tại bất kỳ vị trí địa lý nào.

Dưới đây là giao diện demo ứng dụng sử dụng Api: Google Storage Cloud C#

Trong bài viết này, mình có tích hợp các chức năng cơ bản để làm việc với cloud storage: Lấy danh sách, xóa, upload và download file có bất đồng bộ có progress Bar.

Source code Google Cloud Storage API C#:

using Google.Apis.Auth.OAuth2;
using Google.Cloud.Storage.V1;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MimeMapping;
using Google.Apis.Upload;
using System.Threading;
using Google.Apis.Download;
using System.Collections;

namespace GoogleCloud
{
    public partial class Form1 : Form
    {
        GoogleCredential credential = null;
        string bucketName;
        StorageClient storageClient;
        public Form1()
        {
            InitializeComponent();
            using (var jsonStream = new FileStream("laptrinhvb-c96be-e4ea5c001fd4.json", FileMode.Open,
                    FileAccess.Read, FileShare.Read))
            {
                credential = GoogleCredential.FromStream(jsonStream);
            }
            bucketName = "laptrinhvb-c96be.appspot.com";
            storageClient = StorageClient.Create(credential);
        }
        private async void button1_Click(object sender, EventArgs e)
        {  
            var dlg = new OpenFileDialog();
            if(dlg.ShowDialog() == DialogResult.OK)
            {
               
                
                using (var fileStream = new FileStream(dlg.FileName, FileMode.Open,
                    FileAccess.Read, FileShare.Read))
                {
                    progressBar1.Maximum = (int)fileStream.Length;

                    var uploadObjectOptions = new UploadObjectOptions
                    {
                        ChunkSize = UploadObjectOptions.MinimumChunkSize
                    };
                    var progressReporter = new Progress<IUploadProgress>(OnUploadProgress);
                    await storageClient.UploadObjectAsync(bucketName, Path.GetFileName(dlg.FileName), MimeUtility.GetMimeMapping(dlg.FileName), fileStream, uploadObjectOptions,progress: progressReporter).ConfigureAwait(true);
                    btn_getFiles_Click(sender, e);
                    
                }
            }
        }
     
        // Called when progress updates
        void OnUploadProgress(Google.Apis.Upload.IUploadProgress progress)
        {
            switch (progress.Status)
            {
                case Google.Apis.Upload.UploadStatus.Starting:
                    progressBar1.Minimum = 0;
                    progressBar1.Value = 0;

                    break;
                case Google.Apis.Upload.UploadStatus.Completed:
                    progressBar1.Value = progressBar1.Maximum;
                    break;
                case Google.Apis.Upload.UploadStatus.Uploading:
                    UpdateProgressBar(progress.BytesSent);

                    break;
                case Google.Apis.Upload.UploadStatus.Failed:
                    MessageBox.Show("Upload failed"
                                                   + Environment.NewLine
                                                   + progress.Exception);
                    break;
            }
        }

        void UpdateProgressBar(long value)
        {
            progressBar1.BeginInvoke(new Action(()=> {
                progressBar1.Value = (int)value;               
            }));
        }

        public string BytesToReadableValue(long number)
        {
            var suffixes = new List<string> { " B", " KB", " MB", " GB", " TB", " PB" };

            for (int i = 0; i < suffixes.Count; i++)
            {
                long temp = number / (int)Math.Pow(1024, i + 1);

                if (temp == 0)
                {
                    return (number / (int)Math.Pow(1024, i)) + suffixes[i];
                }
            }

            return number.ToString();
        }

        private void btn_getFiles_Click(object sender, EventArgs e)
        {
           var files = new List<fileInfo>();
            foreach (var obj in storageClient.ListObjects(bucketName, ""))
            {
                var file = new fileInfo();
                file.id = obj.Generation.ToString();
                file.md5 = obj.Md5Hash;
                file.name = obj.Name;
                file.size = obj.Size + "";
                file.sizeText = BytesToReadableValue(long.Parse(obj.Size.ToString()));
                files.Add(file);
            }
            dataGridView1.DataSource = files;
            lbl_file.DataBindings.Clear();
            lbl_file.DataBindings.Add("text", files, "name");
            lbl_byte.DataBindings.Clear();
            lbl_byte.DataBindings.Add("text", files, "size");
        }

        private async void btn_download_Click(object sender, EventArgs e)
        {

            var dlg = new SaveFileDialog();
            dlg.FileName = lbl_file.Text;
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                var token = new CancellationTokenSource().Token;

                using (var fileStream = File.Create(dlg.FileName))
                {
                    progressBar1.Maximum = int.Parse(lbl_byte.Text);

                    var downloadObjectOptions = new DownloadObjectOptions
                    {
                        ChunkSize = UploadObjectOptions.MinimumChunkSize
                    };
                    var progressReporter = new Progress<IDownloadProgress>(OnDownloadProgress);
                    await storageClient.DownloadObjectAsync(bucketName, Path.GetFileName(dlg.FileName), fileStream, downloadObjectOptions, token, progress: progressReporter).ConfigureAwait(true);
                }
            }

                
        }

        void OnDownloadProgress(IDownloadProgress progress)
        {
            switch (progress.Status)
            {
                case DownloadStatus.Completed:
                    progressBar1.Value = progressBar1.Maximum;
                    break;
                case DownloadStatus.Downloading:
                    UpdateProgressBar(progress.BytesDownloaded);

                    break;
                case DownloadStatus.Failed:
                    MessageBox.Show("Download failed"
                                                   + Environment.NewLine
                                                   + progress.Exception);
                    break;
            }
        }

        private void btn_delete_Click(object sender, EventArgs e)
        {
            storageClient.DeleteObject(bucketName, lbl_file.Text);
            btn_getFiles_Click(sender, e);
        }
    }
    public class fileInfo
    {
        public string id { get; set; }
        public string md5 { get; set; }
        public string name { get; set; }
        public string size { get; set; }
        public string sizeText { get; set; }
    }
}


Video Demo ứng dụng c#:

Chúc các bạn thành công.

DOWNLOAD SOURCE CODE


PASSWORD UNZIP: HUNG.PRO.VN 

[FACEBOOK] Script gửi tin nhắn hàng loạt facebook messenger v2

Tiếp tục với seri "Auto Chúc Tết" thì có một số vấn đề nhỏ khi dùng bản v1 đó là tốc độ quá chậm, vậy thì bài viết mới này mình sẽ làm bản v2 nhé.


[FACEBOOK] Script gửi tin nhắn hàng loạt facebook messenger v2



Bước1: Chúng ta sẽ copy đoạn code dưới đây

var html = document.body.textContent
let stringger = html.split('chat_sidebar_contact_rankings')[1].split('</script>')[0]
text = stringger.split('{"status":0')
let id = '', name = '', uniCode = ''
let ids = {}
for (let t of text) {
	if (t.includes('buddy_id')) {
		id = t.split('"buddy_id":"')[1].split('"')[0]
		uniCode = t.split('"name":"')[1].split('"')[0]
		name = JSON.parse('"' + uniCode + '"')
		ids[id] = name
	}
}
console.log(ids)

Bước 2: Chúng ta vào https://www.facebook.com, click chuột phải chọn Inspect rồi chọn tab Console hoặc tổ hợp ctrl + shift + i (sẽ vào thẳng tab Console luôn) Sau đó chúng ta paste đoạn code ở Bước 1 vào và nhấn Enter. Màn hình sẽ trả về một đoạn Object (nôm na thì nó là danh sách bạn bè của các bạn thôi). Chúng ta click chuột phải, chọn Copy object và paste tạm vào một chỗ nào đó để tý nữa dùng tiếp nhé.


Bước 3: Tiếp tục chúng ta copy đoạn code dưới đây - nhân vật chính...

function sendMsg(uid, msg, name) {
	var xhr1 = new XMLHttpRequest()
	xhr1.open('GET', `https://m.facebook.com/messages/read/?fbid=${uid}`, true)
	xhr1.onreadystatechange = function () {
		if (xhr1.readyState === 4 && xhr1.status === 200) {
			let html = xhr1.responseText
			let tids = html.match(/tids=([^&]+)&amp;/)[1].replace('%3A', ':')
			let formAction = html.match(/action="([^"]+)"/)[1].replace(/&amp;/g, '&')
			let fb_dtsg = html.split('name="fb_dtsg" value="')[1]
			let jazoest = html.split('name="jazoest" value="')[1].split('"')[0]

			msg = msg.includes('<name>') ? msg.replace(/<name>/g, name) : msg

			let formData = new FormData()
			formData.append('tids', tids)
			formData.append('wwwupp', 'C3')
			formData.append(`ids[${uid}]`, uid)
			formData.append('platform_xmd', '')
			formData.append('body', msg)
			formData.append('waterfall_source', 'message')
			formData.append('action_time', Date.now())
			formData.append('fb_dtsg', fb_dtsg)
			formData.append('jazoest', Number(jazoest))
			let url = 'https://m.facebook.com' + formAction

			var xhr2 = new XMLHttpRequest();
			xhr2.open('POST', url, true)
			xhr2.send(formData)
			xhr2.onreadystatechange = function () {
				if (xhr2.readyState === 4 && xhr2.status === 200) {
					console.log(`[${uid}: ${name}] Thành công`)
				}
			}
		}
	}
	xhr1.send()
}

var msgList = [];
var inputVal;
var listUid = ''

do {
	inputVal = prompt('Nhập xong mỗi tin nhắn thì nhấn [ENTER] hoặc [Ok], tiếp tục..., kết thúc bằng cách nhấn nút [Cancel]\nNgoài ra có thể dùng <name> để gửi tin nhắn kèm tên của người nhận, ví dụ:\nXin chào <name> nhé')
	if (inputVal !== null) {
		msgList.push(inputVal)
	}
} while (inputVal !== null)

listUid = prompt('Nhập danh sách facebook uid:')
let delay = prompt('Nhập thời gian delay (khuyến nghị để ~> 1000)')
var listID = JSON.parse(listUid)

for (let i in listID) {
	let msg = msgList[Math.floor(Math.random() * msgList.length)]
	let uid = i
	let nL = listID[i].split(' ').length
	let name = listID[i].split(' ')[nL - 1]
	if (msg.length > 0) {
		setTimeout(() => {
			sendMsg(Number(uid), msg, name)
		}, Number(delay))
	}
}

Bước 4: Vào https://m.facebook.com và tiếp tục lick chuột phải chọn Inspect rồi chọn tab Console hoặc tổ hợp ctrl + shift + i (sẽ vào thẳng tab Console luôn) Sau đó paste đoạn code Bước 3 vào, nhấn enter, và nhập lần lượt các tin nhắn, sau mỗi tin nhắn thì nhấn OK hoặc nhấn Enter, khi hết tin nhắn thì nhấn Cancel là được Ngoài ra phần nhập danh sách bạn bè nếu các bạn không muốn gửi cho ai thì xóa người đó đi là được, lưu ý người ở cuối danh sách không có dấu "," (dấu phẩy) ở sau cùng nhé, không là lỗi đó nha.


Time delay thì nên để > 1000 (ms) để tránh bị ban nick nhé.

Lưu ý là script này sẽ random các tin nhắn để gửi nhé, nên mọi người soạn đa dạng tý rồi gửi cũng được. Một lưu ý nhỏ nữa, là người nhận tin nhắn có thể là người ngoài cũng được, nghĩa là bạn có thể custom cái danh sách bạn bè theo ý muốn. Và toàn bộ Id (kể cả bạn bè) thì bạn phải nhắn tin với người đó ít nhất một câu (lần) thì mới không lỗi, lỗi này mình có để cập ở video trong bản v1, các bạn xem tại đây.

Video hướng dẫn cụ thể từng bước, chúc các bạn thành công.



Chúc các bạn thành công với thủ thuật này.
Khi các bạn sữ dụng cũng đừng quá lạm dụng nhé. Tránh bị facebook khoá tài khoản.

Theo H2

on Chủ Nhật, 21 tháng 1, 2024 | , | A comment?

[C#] Use Polly library to resend http request on error

Xin chào các bạn, bài viết hôm nay mình xin giới thiệu các bạn thư viện Polly, dùng để gửi lại request http api khi lỗi request xảy ra: web api lỗi, rớt mạng, timeout...


[C#] Sử dụng thư viện Polly gửi lại request api khi request bị lỗi hay rớt mạng


Ví dụ: Khi các bạn sử dụng http request để lấy dữ liệu tự API Server, nhưng nếu lúc này api đang bị lỗi 503-Service Unavailable.

Thì chúng ta làm sao, nó tiếp tục request thêm n lần: 3,4,5... đảm bảo chúng ta luôn luôn lấy được dữ liệu.

Nếu bình thường, chúng ta tự code thì cũng đơn giản như sau:
private readonly HttpClient _client = new HttpClient(); 

public async Task<HttpResponseMessage> SendRequestWithRetry()
{
    HttpResponseMessage response;
    var sendCount = 0;
    do
    {
        var request = new HttpRequestMessage(HttpMethod.Get, new Uri("https://laptrinhvb.net"));
        response = await _client.SendAsync(request);
        sendCount++;
    }
    while (sendCount < 10 && response.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable);

    return response;
}

Ở source này, các bạn thấy mình sử dụng cấu trúc lệnh do...while để gởi, nếu gởi nó sẽ tiếp tục gởi tiếp 10 lần.

Trong này này mình giới thiệu các bạn thư viện Polly chuyên dụng thể thực hiện công việc này.

Các bạn, cài đặt thư viện Polly từ nuget:
dotnet add package Polly


Ở hình trên các bạn thấy khi nó request lỗi, nó sẽ tiếp tục request tiếp. Source code demo C#, Console:
using Polly;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Retry_requests_poly
{
    internal class Program
    {
        static async Task Main()
        {
           var data =  await MakeHttpRequestWithRetry("http://127.0.0.1:8081/pages/login.html?1152");

            Console.WriteLine("Done!");
            Console.Read();
        }

        static async Task<string> MakeHttpRequestWithRetry(string apiUrl)
        {
            var retryPolicy = Policy
                .Handle<HttpRequestException>()

                  .WaitAndRetryAsync(60, retryAttempt => TimeSpan.FromSeconds(retryAttempt),
                (exception, timeSpan, context) =>
                {
                    Console.WriteLine($"Error: {exception.Message}");
                    Console.WriteLine($"Waiting for internet connection. Retrying in {timeSpan.TotalSeconds} seconds...");
                });

            //.WaitAndRetryForeverAsync(retryAttempt => TimeSpan.FromSeconds(retryAttempt));

            try
            {
               var data = await retryPolicy.ExecuteAsync(async () =>
                {
                    using (HttpClient httpClient = new HttpClient())
                    {
                      
                        HttpResponseMessage response = await httpClient.GetAsync(apiUrl);
                        response.EnsureSuccessStatusCode();                      
                        string responseBody = await response.Content.ReadAsStringAsync();
                        Console.WriteLine("Received data: " + responseBody);
                        return responseBody;
                    }
                });
                return data;
            }
            catch (HttpRequestException ex)
            {
                Console.WriteLine($"Error: {ex.Message}");                
            }
            return null;
        }
    }
}

Chúc các bạn thành công.
DOWNLOAD SOURCE CODE

PASSWORD UNZIP: HUNG.PRO.VN

on Thứ Bảy, 20 tháng 1, 2024 | , , | A comment?

[C#] Login Form Sliding Animtion Effect Winform

Xin chào các bạn, bài viết này mình hướng dẫn các bạn cách tích hợp login form html và css vào Winform C#, và cách gọi thông tin giữa web với C# qua JS bằng ExcuteJavascript qua trình duyệt Webview2.


[C#] Login Form Sliding Animtion Effect Winform

[C#] Tạo form đăng nhập và đăng ký với hiệu ứng Sliding Animation Effect

Video demo ứng dụng:

Để thực hiện bài viết, các bạn cần tìm hiểu về control webview2 trên website.

Webview2 có thể chạy tốt: CSS3, ReactJS, VueJS, AngularJs...

Ở bên tập lệnh javascript chúng ta viết lệnh như sau:
document.addEventListener('click', function (event)
{
    let elem = event.target;
    let jsonObject =
    {
        Key: 'click',
        Value: elem.id    //elem.name || elem.id || elem.tagName || "Unkown"
    };
    window.chrome.webview.postMessage(jsonObject);
});

Các bạn thấy ở hàm này, nó sẽ lắng nghe sự kiện trên toàn bộ trang web, khi nó bắt được sự kiện click. Nó sẽ lấy thông tin ID, các bạn có thể thay thế bằng: Name, id, tagname... và dùng lệnh:

Window.chrome.webview.postMessage về. Thì ở C#, chúng ta sẽ bắt được ở sự kiện:
private async void WebView21_WebMessageReceived(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs e)
{
    var jsonObject = JsonConvert.DeserializeObject<JsonObject>(e.WebMessageAsJson);
    var idElemnt = jsonObject.Value;
    switch (jsonObject.Key)
    {
        case "click":
            if(idElemnt != null && idElemnt != "")
            {
                if(idElemnt == "btnLogin")
                {
                   await ProcessLogin();
                }
            }
            break;

    }
}

Ở C#, chúng ta sẽ biết được nó vừa click ở id hoặc element nào.

Chi tiết các bạn có thể download source code bên dưới về để tham khảo.

Full source code C# form login.cs:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AnimationSliding_Sign_In_Sign_Up
{
    public partial class FrmLogin : Form
    {
        private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
        public FrmLogin()
        {
            InitializeComponent();
            webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
            webView21.EnsureCoreWebView2Async();
            InitLoadHtml();

        }

        private void InitLoadHtml()
        {          

            webView21.CoreWebView2InitializationCompleted += WebView21_CoreWebView2InitializationCompleted;
            webView21.Dock = DockStyle.Fill;
            this.Controls.Add(webView21);
        }

        private void WebView21_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
        {
            string curDir = Directory.GetCurrentDirectory();
            var uri = new Uri(String.Format("file:///{0}/html/index.html", curDir));
            webView21.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
          
            webView21.CoreWebView2.Navigate(uri.ToString());
            webView21.WebMessageReceived += WebView21_WebMessageReceived;
        }
        public struct JsonObject
        {
            public string Key;
            public string Value;
        }

        private  async Task<string> GetTextboxValue(string elementId)
        {
            string script = $"document.getElementById('{elementId}').value";
            var result = await webView21.CoreWebView2.ExecuteScriptAsync(script);
            return result.Trim('"');
        }

        private async Task SetFocus(string elementId)
        {
            string script = $"setFocusOnInput('{elementId}');";
            var result = await webView21.CoreWebView2.ExecuteScriptAsync(script);
           
        }

        private async Task ShowSnackBar(string message, int timeout = 3000)
        {
            message = $"<i class="fa fa-exclamation-triangle" style="color: white; font-size: 16px;"> </i> {message}";
            string script = $"showSnackbar('{message}', {timeout});";
            var result = await webView21.CoreWebView2.ExecuteScriptAsync(script);
          
        }

        private async void WebView21_WebMessageReceived(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebMessageReceivedEventArgs e)
        {
            var jsonObject = JsonConvert.DeserializeObject<JsonObject>(e.WebMessageAsJson);
            var idElemnt = jsonObject.Value;
            switch (jsonObject.Key)
            {
                case "click":
                    if(idElemnt != null && idElemnt != "")
                    {
                        if(idElemnt == "btnLogin")
                        {
                           await ProcessLogin();
                        }
                    }
                    break;

            }
        }

        private async Task ProcessLogin()
        {
            var username = await GetTextboxValue("txtUsername");
            var password = await GetTextboxValue("txtPassword");
            if(username == "")
            {
                await ShowSnackBar("Chưa nhập tên đăng nhập, bạn ơi.");
                await SetFocus("txtUsername");
                return;
            }

            if (password == "")
            {
                await ShowSnackBar("Chưa nhập mật khẩu, bạn ơi.");
                await SetFocus("txtPassword");
                return;
            }

            if( password == "admin")
            {
                var frm = new FrmMain(username);
                frm.Show();
                this.Hide();
            }
            else
            {
                await ShowSnackBar("Tên đăng nhập hoặc mật khẩu không đúng, bạn ơi.");
            }

        }
    }
}

Chúc các bạn với thủ thuật tuyệt với này.

DOWNLOAD SOURCE CODE

PASSWORD UNZIP: HUNG.PRO.VN

on Thứ Sáu, 12 tháng 1, 2024 | , , , , | A comment?

[C#] Cách thanh toán qua mã vạch VietQR sử dụng payOS API

Xin chào các bạn, bài viết hôm nay mình hướng dẫn các bạn cách tạo thanh toán hóa đơn trực tiếp qua mã vạch VietQR sử dụng payOS API.


[C#] Hướng dẫn tạo thanh toán đơn hàng qua mã vạch VietQR sử dụng API PayOS hoàn toàn miễn phí

Các bạn có thể đăng ký api payOS hoàn toàn miễn phí tại website.
https://payos.vn


Các bạn, thường mua hàng ở các website, khi thanh toán các bạn thường gặp có thể thanh toán trực tiếp bằng cách quét mã vạch như: Momo, Zalopay, Viettel money...

Những Api này thường bạn đăng ký phải là tổ chức doanh nghiệp.

Với payOS, mình có thể đăng ký một tài khoản cá nhân bình thường, cách bước thực hiện các bạn đăng nhập vào website và tạo một tài khoản và liên kết ngân hàng như hướng dẫn.

Để viết bài này, mình đã đăng ký một tài khoản Ngân Hàng Phương Đông (OCB) để liên kết với payOS.

Khi các bạn đăng ký thành công, có bạn sẽ có các thông tin: clientID, apiKey, checkSumKey.
Để các bạn sử dụng gọi API.

Khi tạo một kênh thanh toán, sẽ có thông tin như hình bên dưới:

Và ở C# chúng ta sẽ cài đặt thư viện payOS từ nuget:
dotnet add package payOS --version 1.0.2

Các bạn khai báo thông tin cấu hình vào:
namespace DemoPayOS
{
    public  class Constants
    {
       public static string clientId = "";
        public static string  apiKey = "";
        public static string  checksumKey = "";
    }
}

Dưới đây là source code ứng dụng demo, thường các bạn sẽ build trên Website, nhưng bài viết này mình demo ở Winform netCore 6
using Net.payOS;
using Net.payOS.Types;
using System.Diagnostics;

namespace DemoPayOS
{
    public partial class Form1 : Form
    {
        PayOS payOS;
      
        public Form1()
        {
            InitializeComponent();
            payOS = new PayOS(Constants.clientId, Constants.apiKey, Constants.checksumKey);
        }

        private async void btnTaoLinkTT_ClickAsync(object sender, EventArgs e)
        {
            var name = txtSanPham.Text;
            var soluong = Convert.ToInt32(txtSoluong.Text);
            var thanhtien = Convert.ToInt32(txtThanhTien.Text);
           
            ItemData item = new ItemData(name, soluong, thanhtien);
            List<ItemData> items = new List<ItemData>();
            items.Add(item);

            var noidung = "Thanh toán tiền nhậu";
            var orderID = 2005;
            var tongGiaTien = 2000; // 2 ngàn vnđ

            PaymentData paymentData = new PaymentData(orderID, tongGiaTien, noidung,
                 items,  "https://localhost:3002",  "https://localhost:3002");

            CreatePaymentResult createPayment = await payOS.createPaymentLink(paymentData);

            var linkCheckOut = createPayment.checkoutUrl;
            Process.Start(new ProcessStartInfo
            {
                FileName =  @"C:\Program Files\Google\Chrome\Application\chrome.exe",
                Arguments = linkCheckOut
            });

        }
    }
}

Khi tạo thành công, chúng ta sẽ được một đường link api website thanh toán, và chúng ta sẽ mở cho khách hàng thanh toán. Giao diện thanh toán:

Các bạn có thể nhấn nút Hủy thanh toán, để hủy bỏ đơn hàng này.

payOS cũng cung cấp cho chúng ta http callback, để chúng ta có thể cập nhật tình trạng thông tin đơn hàng đã được thanh toán hay hủy bỏ vào cơ sở dữ liệu của mình.

Khi các bạn đăng ký thành công, payOS có tài liệu hướng dẫn các sử dụng cụ thể, chi tiết các bạn có thể tham khảo ở trên đó.
 
Video demo ứng dụng thanh toán VietQR via payOS api:


P/s: Bài viết chỉ mang tính hướng dẫn, không có tính quảng cáo cho payOS api hay vietQR gì, chi tiết các bạn đọc kỹ ở phần đăng ký payOS trên trang chủ.

Chúc các bạn thành công.

DOWNLOAD SOURCE CODE

Password Unzip: HUNG.PRO.VN

on Thứ Tư, 10 tháng 1, 2024 | , , , | A comment?

[SOFTWARE] Actived Sublime Text 4 version 4107

Xin chào các bạn, bài viết hôm nay mình sẽ hướng dẫn các bạn cách Actived Sublimet Text 4, phiên bản hiện tại mình đang sử dụng là 4107.


[SOFTWARE] Actived Sublime Text 4 4107

Dưới đây là giao diện mình đã actived thành công.
[SOFTWARE] Actived Sublime Text 4 version 4107

Đầu tiên, các bạn truy cập vào website sau:
https://hexed.it/

Sau đó, các bạn chọn open file đến file Sublime_text.exe ở trong thư mục program files cài đặt của các bạn

Sau đó các bạn chỉnh lại tìm và chỉnh lại thông số như sau:
80 38 00 => FE 00 90

Như hình dưới đây:

Các save file này vào thư mục Program files.
Tiếp đến các bạn điền key vào như sau:
----- BEGIN LICENSE ----- 
TwitterInc 
200 User License 
EA7E-890007 
1D77F72E 390CDD93 4DCBA022 FAF60790 
61AA12C0 A37081C5 D0316412 4584D136 
94D7F7D4 95BC8C1C 527DA828 560BB037 
D1EDDD8C AE7B379F 50C9D69D B35179EF 
2FE898C4 8E4277A8 555CE714 E1FB0E43 
D5D52613 C3D12E98 BC49967F 7652EED2 
9D2D2E61 67610860 6D338B72 5CF95C69 
E36B85CC 84991F19 7575D828 470A92AB 
------ END LICENSE ------

Vậy là xong, chúc các bạn thành công với thủ thuật đơn giản này, và mọi người không cần phải lên mạng tìm kiếm những chương trình bé khoá nữa nhé mà hay tự mình bẻ khoá chương trình này. 
on Thứ Hai, 8 tháng 1, 2024 | , , | A comment?

[C#] Building a project that target .NET Framework 4.5.2 in Visual Studio 2022

Xin chào các bạn, bài viết hôm nay mình sẻ hướng dẫn các bạn fix lỗi Visual not support Target NetFramework trên Visual Studio 2022.


[C#] Hướng dẫn fix lỗi Visual Studio 2022 not Support Target Net Framework 4.5.2


Khi các bạn mở Solution net framework 4.5.2 trên Visual Studio 2022, nếu gặp thông báo như trên.

Visual Studio not support Target Framework như: 4.5, 4.5.2

Tuy nhiên, khi mình chọn option 2 để download .NET Framework về, thì hệ thống báo trong máy tính đã cài đặt Net framework 4.5.2, nhưng mở VS 2022 vẫn hiện thị thông báo trên, thì các bạn fix như sau.
Bước 1: Các bạn vào Nuget tải NetFramework về, ở bài này mình sẽ tải Net 4.5.2

Bước 2: Sau khi các bạn tải về xong, các bạn đổi tên file ở phần mở rộng tập tin thành .zip và giải nén file đó ra

Bước 3: Copy
build\.NETFramework\v4.5.2 => vào C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2

Bước 4: Khởi động lại Visual Studio 2022
Thanks for watching!

[C#] Show log to console Winform

Xin chào các bạn, bài viết hôm nay mình hướng dẫn các bạn sử dụng Serialog để show log ra Richtextbox giống trên console windows.


[C#] Hướng dẫn ghi log ra RichTextBox giống Console trên Winform sử dụng thư viện Serilog

Dưới đây, là hình ảnh demo ứng dụng:
Đầu tiên, các bạn cài đặt cho mình thư viện Serilog bên dưới từ Nuget.
NuGet\Install-Package Serilog.Sinks.RichTextBox.WinForms.Colored -Version 1.2.0

Giao diện show log ứng dụng:

Các bạn có thể show nhiều định dạng log như: Error, Warning, Information, Faltal...
Xem video hướng dẫn thực hiện step by step.

Full source code C# Form1.cs:

using Serilog.Events;
using Serilog.Sinks.RichTextBoxForms.Themes;
using Serilog.Sinks.RichTextBoxForms;
using Serilog;
using System.Windows.Forms;

namespace SerilogDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private RichTextBoxSinkOptions _options = null!;

        private void Initialize()
        {
            _options = new RichTextBoxSinkOptions(ThemePresets.Dark, 200, 5, true);
            var sink = new RichTextBoxSink(richTextBox1, _options);
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .WriteTo.Sink(sink, LogEventLevel.Verbose)
                .CreateLogger();

            Log.Debug("Started logger.");

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Initialize();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Log.Error("Error messge Oops....");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Log.Information("Error messge Oops....");
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Log.Warning("Error messge Oops....");
        }

        private void button4_Click(object sender, EventArgs e)
        {
            var frm = new Form2();
            frm.Show();
        }
    }
}

Source code Form2.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Serilog;

namespace SerilogDemo
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                for (int i = 0; i < 1000; i++)
                {
                    Log.Information($"Processing line: {i}");
                    Thread.Sleep(300);

                    Log.Fatal($"Falal line: {i}");
                    Thread.Sleep(300);
                }
            });
        }
    }
}

Chúc các bạn thành công với thủ thuật trên.
DOWNLOAD SOURCE CODE

PASSWORD UNZIP: HUNG.PRO.VN

on Thứ Bảy, 6 tháng 1, 2024 | , , | A comment?

[C#] TUTORIAL USE COOKIE IN SELEMIUM

Xin chào các bạn, bài viết hôm nay mình sẽ hướng dẫn các bạn cách tích hợp cookie vào Selemium C#.


[C#] Hướng dẫn sử dụng Cookie trong Selemium

Thường các bạn sử dụng Selemium để test hoặc thực hiện một công việc gì đó tự động.

Thì thường chúng ta sẽ điền thông tin username và mật khẩu đăng nhập vào, chúng ta cũng có thể đăng nhập bằng cách khác.

Bằng cách là sử dụng Cookie để đăng nhập tự động.

Trong bài viết này mình sẽ demo login tự động vào trang website One Signal sử dụng Cookie.

Sau khi đăng nhập thành công các bạn mở Web Developer tools để lấy cookie.

Sau đó mình dùng tham số này để add cookie vào Selemium.

Sau khi các bạn có key rồi các bạn code C# như sau:
public void run()
        {
            var driverService = ChromeDriverService.CreateDefaultService();
            driverService.HideCommandPromptWindow = true;
            ChromeOptions options = new ChromeOptions();         
            options.AddArguments("--incognito");
            options.AddArgument(@"--start-maximized");
            options.AddArgument(@"--disable-infobars");
            IWebDriver driver = new ChromeDriver(driverService, options);
            var firingDriver = new EventFiringWebDriver(driver);
            firingDriver.ExceptionThrown += new EventHandler<WebDriverExceptionEventArgs>(firingDriver_ExceptionThrown);
            driver = firingDriver;
            Cookie name = new Cookie("remember_user_token", "my cookie");
           
            driver.Manage().Cookies.DeleteAllCookies();
           
            driver.Navigate().GoToUrl("https://onesignal.com/");
            driver.Manage().Cookies.AddCookie(name);
            driver.Navigate().GoToUrl("https://onesignal.com/");
          
        }

Chúc các ban thành công với thủ thuật trên. 

on Thứ Năm, 4 tháng 1, 2024 | , | A comment?

[BLOGGER] TEMPLATE STORYIFY REMOVE LICENSE

Hi mọi người, hôm nay mình tìm hiểu về giao diện blogger thì thấy giao diện cũng khá là ổn, giao diện STORYIFY tập trung vào nội dung tuyệt vời, phù hợp cho các nhà hoạt động, nhà báo, và nhà văn tác giả. Mẫu giao diện này đã tối giản và có độ phản hồi cao và hoạt động tốt trên tất cả mọi thiết bị bảo gồm máy tính bảng, thiệt bị di động hoặc máy tính để bàn. Và nó có thể tự động điều chình chính thước của nó. Và nó chứa các chế độ sáng tối để phù hợp với mọi cách nhìn của người dùng. 


Mẫu giao diện STORYIFY đã được tối ưu SEO và cung cấp tốc độ tải siếu nhanh. Bạn sẽ nhận được kết quả tìm kiếm tốt trên các công cụ tìm kiếm khác nhau, nó được phát hành trên HTML, SCSS, JS và CSS.
Qua hình ảnh bên trên các bạn cũng đã thấy tốc độ tải giao diện của template STORYIFY ở chế độ Mobile và Windows thế nào rồi chứ :D. Hoặc có thể bạn xem trực tiếp tại đây

Và TEMPLATE STORYIFY  đó mình đã mua bàn quyền rồi nhé. Nếu ai muốn sữ dụng có thể để lại email mình gửi mật khẩu giải nén giao diện nhé. 


DEMO GIAO DIỆN  DOWNLOAD
Cảm ơn các bạn đã quan tâm.

Nếu mọi người muốn mua giao diện này thì có thể sang trang blog của người thiết kế giao diện này tại đây để tìm hiểu và mua nhé.

on Thứ Bảy, 16 tháng 12, 2023 | , , , | A comment?