SQLの窓

2018年10月19日


C# : SQLServer( SQLExpress ) の SMO を使用してテーブルの CREATE TABLE 文 を取得する

SMO のダウンロード方法は、C# : VB.net : SQLExpress(SQLServer) : SQL-DMO と同等の SMO によるバックアップ を参照して下さい。

こちらは、同じコードを PowerShell で実行します

参考ページ : Generate Scripts for database objects with SMO for SQL Server
※ 参考ページでは、いろいろなオプションが紹介されています。

using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SQLExpress_backup
{
	class Program
	{
		static void Main(string[] args)
		{

			{

				UTF8Encoding UTF8N_Enc = new UTF8Encoding();
				// false は上書き
				StreamWriter WriteFile = new StreamWriter("sqlexpress.sql", false, UTF8N_Enc);

				// サーバー
				Server srv;
				// インスタンス
				srv = new Server();

				// サーバーインスタンスの情報
				srv.ConnectionContext.AutoDisconnectMode = AutoDisconnectMode.NoAutoDisconnect;
				srv.ConnectionContext.LoginSecure = false;
				srv.ConnectionContext.Login = "sa";
				srv.ConnectionContext.Password = "";
				// 接続
				srv.ConnectionContext.Connect();

				// バージョンの表示
				Console.WriteLine(srv.Information.Version);

				// 参考
				// https://www.mssqltips.com/sqlservertip/1833/generate-scripts-for-database-objects-with-smo-for-sql-server/
				// Scripter scripter = new Scripter(srv);

				Database myDb = srv.Databases["lightbox"];
				foreach (Table myTable in myDb.Tables)
				{

					StringCollection tableScripts = myTable.Script();
					foreach (string script in tableScripts)
					{
						WriteFile.WriteLine(script);
					}
				}

				WriteFile.Close();
				WriteFile.Dispose();

				srv.ConnectionContext.Disconnect();

			}


		}
	}
}


結果サンプル

※ sqlexpress.sql に出力された内容です
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[コード名称マスタ](
	[区分] [int] NOT NULL,
	[コード] [nvarchar](10) COLLATE Japanese_CI_AS NOT NULL,
	[名称] [nvarchar](50) COLLATE Japanese_CI_AS NULL,
	[数値1] [int] NULL,
	[数値2] [int] NULL,
	[作成日] [datetime] NULL,
	[更新日] [datetime] NULL
) ON [PRIMARY]

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[社員マスタ](
	[社員コード] [nvarchar](4) COLLATE Japanese_CI_AS NOT NULL,
	[氏名] [nvarchar](50) COLLATE Japanese_CI_AS NULL,
	[フリガナ] [nvarchar](50) COLLATE Japanese_CI_AS NULL,
	[所属] [nvarchar](4) COLLATE Japanese_CI_AS NULL,
	[性別] [int] NULL,
	[作成日] [datetime] NULL,
	[更新日] [datetime] NULL,
	[給与] [int] NULL,
	[手当] [int] NULL,
	[管理者] [nvarchar](4) COLLATE Japanese_CI_AS NULL,
	[生年月日] [datetime] NULL
) ON [PRIMARY]

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[取引データ](
	[取引区分] [nvarchar](2) COLLATE Japanese_CI_AS NOT NULL,
	[伝票番号] [int] NOT NULL,
	[行] [int] NOT NULL,
	[取引日付] [datetime] NULL,
	[取引先コード] [nvarchar](4) COLLATE Japanese_CI_AS NULL,
	[商品コード] [nvarchar](4) COLLATE Japanese_CI_AS NULL,
	[数量] [int] NULL,
	[単価] [int] NULL,
	[金額] [int] NULL,
	[更新済] [nvarchar](1) COLLATE Japanese_CI_AS NULL
) ON [PRIMARY]

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[商品マスタ](
	[商品コード] [nvarchar](4) COLLATE Japanese_CI_AS NOT NULL,
	[商品名] [nvarchar](50) COLLATE Japanese_CI_AS NULL,
	[在庫評価単価] [int] NULL,
	[販売単価] [int] NULL,
	[商品分類] [nvarchar](3) COLLATE Japanese_CI_AS NULL,
	[商品区分] [nvarchar](1) COLLATE Japanese_CI_AS NULL,
	[作成日] [datetime] NULL,
	[更新日] [datetime] NULL,
	[備考] [ntext] COLLATE Japanese_CI_AS NULL,
	[削除フラグ] [nvarchar](1) COLLATE Japanese_CI_AS NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[得意先マスタ](
	[得意先コード] [nvarchar](4) COLLATE Japanese_CI_AS NOT NULL,
	[得意先名] [nvarchar](50) COLLATE Japanese_CI_AS NULL,
	[得意先区分] [nvarchar](1) COLLATE Japanese_CI_AS NULL,
	[担当者] [nvarchar](4) COLLATE Japanese_CI_AS NULL,
	[郵便番号] [nvarchar](7) COLLATE Japanese_CI_AS NULL,
	[住所1] [nvarchar](100) COLLATE Japanese_CI_AS NULL,
	[住所2] [nvarchar](100) COLLATE Japanese_CI_AS NULL,
	[作成日] [datetime] NULL,
	[更新日] [datetime] NULL,
	[締日] [int] NULL,
	[締日区分] [int] NULL,
	[支払日] [int] NULL,
	[備考] [nvarchar](100) COLLATE Japanese_CI_AS NULL
) ON [PRIMARY]

SET ANSI_NULLS (Transact-SQL)
SET ANSI_NULLS が ON の場合、WHERE column_name = NULL を使用する SELECT ステートメントを実行すると、column_name に NULL 値が入っていた場合は条件は成り立たず、行が返されません。逆に、SET ANSI_NULLS が OFF の場合は、ISO 標準が適用されません。 WHERE column_name = NULL を使用する SELECT ステートメントでは、column_name に NULL 値を持つ行が返されます。

SET ANSI_NULLS OFF;
select * from [社員マスタ] where 手当 = null;

この SQL では、手当が NULL の行が戻されます


SET QUOTED_IDENTIFIER ON にすると、テーブル名等の識別市子を "(ダブルクォート)で囲む事ができます

SET QUOTED_IDENTIFIER OFF; 
select * from "社員マスタ"

この SQL はエラーとなります
posted by lightbox at 2018-10-19 14:10 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2018年09月04日


C# : DataGridView に TKMP.DLL の IMAP(POP3) で受信したメールを非同期に表示する( 添付ファイルも取得 )

※ BasicImapLogon => BasicPopLogon, ImapClient => PopClient で POP3 も同じです

DataGridView の作成方法の注意点は、『C# でDataTable と DataSource を使用して、DataGridView にデータを表示するテンプレート( 行をダブルクリックしてダイアログを表示して行データを処理 )』を参照して下さい

画面のテンプレートのダウンロード


行をダブルクリックすると、本文を表示します。ここでは、サンプルして行のカラムに本文を保存していますが、本来は外部に保存します。



▼ スプリットコンテナを使用していますが、配置方法は基本的に直感的なものと逆です。


※ 重要
Gmail では安全性の低いアプリの許可を『有効』にする必要があります
※ サーバーは imap.gmail.com
※ Yahoo! メールでは、接続はできるのですが、メールが取得できません ( imap.mail.yahoo.co.jp )。
※ BasicImapLogon => BasicPopLogon, ImapClient => PopClient に変更すると、Yahoo! で接続できました
( POP3 : pop.mail.yahoo.co.jp : 995 )

.NET用メール送受信クラスライブラリ (TKMP.DLL) 
※ 2018-06-20 時点で 3.1.8( 2017/02/15 作成 )



using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TKMP.Net;
using TKMP.Reader;

namespace MailRecTest
{
	public partial class Form1 : Form
	{
		// ******************************************************
		// 画面レイアウト作成方法は以下を参照
		// http://logicalerror.seesaa.net/article/459948736.html
		// ******************************************************

		private DataTable table;
		private DataColumn column;
		private DataRow row;

		private SynchronizationContext sc = null;
		private ImapClient client = null;
		private int mailCounter = 0;
		private string[] bodyText = new string[20];

		// 接続解除用
		private int endCounter = 0;
		private int maxCount = 20;

		public Form1()
		{
			InitializeComponent();
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			// 非同期内からの UI スレッドへのアクセス用
			sc = SynchronizationContext.Current;

			this.toolStripStatusLabel1.Text = "ツールバーのボタンで受信してください";
		}

		private void toolStripButton1_Click(object sender, EventArgs e)
		{
			if (MessageBox.Show("メールを受信しますか?", "確認", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
			{
				return;
			}

			// IMAP 用基本認証
			BasicImapLogon logon = new BasicImapLogon("アカウント", "パスワード");
			// IMAP 用ログイン( 993 は、SSL 用 )
			ImapClient client = new ImapClient(logon, "サーバードメイン", 993);

			// SSL で接続する
			client.AuthenticationProtocol = AuthenticationProtocols.SSL;

			try
			{
				if (!client.Connect())
				{
					MessageBox.Show("接続できませんでした");
					return;
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("接続エラーが発生しました");
				return;
			}

			// メールデータ一覧を格納するオブジェクト
			IMailData[] mailData = client.GetMailList();

			// データがありません
			if (mailData == null)
			{
				MessageBox.Show("データがありません");
				return;
			}

			// メールデータの数
			toolStripStatusLabel1.Text = mailData.Length.ToString();
			mailCounter = mailData.Length;
			if (mailCounter < maxCount)
			{
				maxCount = mailCounter;
			}

			// 読込み制限
			int idx = 0;


			// DataTable の作成
			table = new DataTable("TKMP");

			// 列情報 の作成
			column = new DataColumn();
			column.DataType = Type.GetType("System.String");
			column.ColumnName = "差出人";
			table.Columns.Add(column);

			// 列情報 の作成
			column = new DataColumn();
			column.DataType = Type.GetType("System.String");
			column.ColumnName = "件名";
			table.Columns.Add(column);

			// 列情報 の作成
			column = new DataColumn();
			column.DataType = Type.GetType("System.String");
			column.ColumnName = "受信日時";
			table.Columns.Add(column);

			// 列情報 の作成
			column = new DataColumn();
			column.DataType = Type.GetType("System.String");
			column.ColumnName = "本文";
			table.Columns.Add(column);

			// 非同期でメールデータを表示するループ
			foreach (var data in mailData)
			{

				idx++;
				if (idx > maxCount)
				{

					break;
				}

				// 個別にイベント登録
				data.BodyLoaded += new EventHandler(MailData_BodyLoaded);
				// 非同期処理の受信を一件づつ開始
				data.ReadBodyAnsync();

			}

		}

		private void MailData_BodyLoaded(object sender, EventArgs e) {


			IMailData MailData = (IMailData)sender;

			// 本文無し( 本文が必要な場合は、false で、reader.MainText )
			MailReader reader = new MailReader(MailData.DataStream, false);

			if (reader.FileCount == 0)
			{
				Console.WriteLine("添付ファイルはありません");
			}

			//添付ファイルのコレクションを検査します
			foreach (TKMP.Reader.File file in reader.FileCollection)
			{
				// 保存場所は事前に作成する必要があります
				// (メールとの関連は、アプリケーション側で工夫する必要があります)
				file.FileSave(@"c:\temp\data\");
			}
			//Console.WriteLine(reader.MainText);

			// UI スレッドへの処理( この場合、post_state は null )
			sc.Post((object post_state) =>
			{


				// 新規行
				row = table.NewRow();

				// 本文をメモリ内保存( 本来はファイルかデータベースに書きだす )
				row["本文"] = reader.MainText;

				// ヘッダの一覧より、目的のヘッダを探す
				foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection)
				{

					if (headerdata.Name == "From")
					{
						row["差出人"] = headerdata.Data;
					}
					if (headerdata.Name == "Subject")
					{
						row["件名"] = headerdata.Data;
					}
					if (headerdata.Name == "Date")
					{
						Console.WriteLine(headerdata.Data);

						string target = headerdata.Data;
						target = target.Replace(" (JST)", "");
						target = target.Replace(" (PDT)", "");
						try
						{
							DateTime dt = System.DateTime.ParseExact(target, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None);
							row["受信日時"] = string.Format("{0}", dt);
						}
						catch (Exception ex)
						{
							row["受信日時"] = headerdata.Data;
							Console.WriteLine("フォーマット変換できませんでした");
						}

					}

				}

				// 行を追加
				table.Rows.Add(row);


				// 接続解除用
				endCounter++;
				if (endCounter == maxCount)
				{

					endCounter = 0;

					// 受信終了
					client.Close();

					// データーソース経由で DataGridView を表示
					dataGridView1.DataSource = table;

					this.dataGridView1.Columns[3].Visible = false;

					// 第3カラム(受信日)で逆ソート
					dataGridView1.Sort(dataGridView1.Columns[2], ListSortDirection.Descending);
					// 自動整列
					dataGridView1.AutoResizeColumns();

				}


			}, null);

			// イベント削除
			MailData.BodyLoaded -= new EventHandler(MailData_BodyLoaded);


		}

		private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
		{
			int rowNumber = e.RowIndex;
			if (rowNumber < 0 ){
				return;
			}

			this.textBox1.Text = this.dataGridView1["本文",rowNumber].Value.ToString();
		}
	}
}


関連する記事

C# と VB.net : TKMP.DLL を使って IMAP でメール本文の一覧を取得する( コンソール )

C# : TKMP.DLLを使った、メール送信テンプレート



posted by lightbox at 2018-09-04 21:46 | VS(C#) | このブログの読者になる | 更新情報をチェックする

C# : TKMP.DLLを使った、メール送信テンプレート

C:\Users\ユーザ\Documents\Visual Studio 20XX\Templates\ProjectTemplates\Visual C# に保存して下さい


( TKMP.DLL 同梱 )

※ TKMP.DLL は 32ビット用です。





テンプレートが古いので、Microsoft の SMTP サーバーは pop-mail.outlook.com に変更して下さい

久しぶりにメールの処理の検証をしてみようと、最新(周辺)の Microsoft の Framework をチェックしてみたのですが、相変わらず標準的なものはなさそうなので、最新の TKMP.DLL で検証してみました。TKMP.DLL は運用はした事がありませんが、メール送信に非同期処理が無い事を除いて、たいていは間に合いそうな気がします。

しかし、いかに簡単に使えるように設計されていても、メール処理はそれなりに煩雑なので、単に『メール送信』に特化してクラスを作成しました。

メールは Hotmail でなくても使えますが、送信用のクラスを作成する為のテストに Hotmail を使って行い、Hotmail の特性に従ってエラー処理もしています。

Hotmail を使用する場合は、ひとつ注意が必要で、エラーになる原因としてメールサービスがスパム対策として確認用の画像を読ませてログインさせようとする場合があるようです。
MailClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TKMP.Writer;
using TKMP.Net;

namespace TKMP_SendMail_Sakura1 {
	class MailClass {
		private MailWriter mw = null;

		public string SmtpServer { get; set; }
		public int Port { get; set; }
		public string User { get; set; }
		public string Pass { get; set; }
		public AuthenticationProtocols Protocol { get; set; }

		private string err_message = "";

		public class MailClassErrorArg {
			public string Message { get; set; }
		}

		public delegate void MailClassError(MailClassErrorArg e);

		public bool SendMail(string To, string From, string Subject, string Body, string To_J, string From_J, MailClassError mce) {
			bool bResult = true;

			mw = new MailWriter();

			try {
				mw.ToAddressList.Add(To);
			}
			catch (Exception ex) {
				bResult = false;
			}
			if (!bResult) {
				if (mce != null) {
					MailClassErrorArg e = new MailClassErrorArg() { Message = "宛先が正しくありません" };
					mce(e);
				}
				return bResult;
			}

			// From が未指定や正しくない文字列の場合
			try {
				mw.FromAddress = From;
			}
			catch (Exception ex) {
				// ユーザが正しければ、以下のように設定しても『ユーザ名 <メールアドレス>』に変換される
				mw.FromAddress = "______@hotmail.co.jp";
			}

			TextPart tp = new TextPart(Body);
			mw.MainPart = tp;

			if (To_J != null) {
				mw.Headers.Add("To", To_J + " <" + To + ">");
			}
			else {
				mw.Headers.Add("To", To);
			}
			if (From_J != null) {
				mw.Headers.Add("From", From_J + " <" + From + ">");
			}
			else {
				// Hotmail では、自動的に 『ユーザ名 <メールアドレス>』に変換される
				mw.Headers.Add("From", From);
			}

			mw.Headers.Add("Subject", Subject);
			mw.Headers.Add("X-Mailer", "TKMP Version 3.1.2");

			var logon = new TKMP.Net.AuthLogin(User, Pass);
			SmtpClient sc = new SmtpClient(SmtpServer, Port, logon);
			sc.AuthenticationProtocol = Protocol;

			try {
				if (!sc.Connect()) {
					err_message = "接続に失敗しました";
					bResult = false;
				}
				else {
					sc.SendMail(mw);
					sc.Close();
				}
			}
			catch (Exception ex) {
				err_message = ex.Message;
				bResult = false;
			}
			if (!bResult) {
				if (mce != null) {
					MailClassErrorArg e = new MailClassErrorArg() { Message = err_message };
					// このメソッドの引数である、ErrorHandler デリゲートを呼び出す
					mce(e);
				}
			}

			return bResult;
		}

		public bool SendMail(string To, string From, string Subject, string Body, string To_J, string From_J) {
			return SendMail(To, From, Subject, Body, To_J, From_J, null);
		}

		public bool SendMail(string To, string From, string Subject, string Body) {
			return SendMail(To, From, Subject, Body, null, null, null);
		}

	}

}

エラー処理は、引数にデリゲートを渡す仕様にしているので、Java の 引数へのインターフェイス渡しのような感じで『ラムダ式』を使ってその場で記述する事を想定しています。

これによって、細かいエラー情報が必要な場合は記述し、そうでない場合はオーバーロードされた引数の少ないメソッドを使って成功が失敗かだけをチェックすればいいようになっています。
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Mail;
using System.Net;
using TKMP.Writer;
using TKMP.Net;

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

		private void button1_Click(object sender, EventArgs e)
		{

			MailClass mc = new MailClass()
			{
				SmtpServer = "smtp.live.com",
				Port = 587,
				User = "ユーザ名@hotmail.co.jp",
				Pass = "パスワード",
				Protocol = AuthenticationProtocols.TLS
			};

			var result = mc.SendMail(
				"宛先メールアドレス",
				"ユーザ名@hotmail.co.jp",
				this.subject.Text,
				this.body.Text,
				null,   // 必要な場合、宛先を日本語で
				null,   // 必要な場合、差出人を日本語で
				(MailClass.MailClassErrorArg _e) =>
				{
					this.error.Text = _e.Message;
				}
			);

			if (result)
			{
				MessageBox.Show("メールを送信しました");
			}

		}

	}
}

Hotmail の仕様に関しては、正式には 『Outlook.com の POP、IMAP、および SMTP の設定』というページにあります

IMAP サーバー名: imap-mail.outlook.com

IMAP ポート: 993

IMAP 暗号化方法: TLS

POP サーバー名: pop-mail.outlook.com

POP ポート: 995

POP 暗号化方法: TLS

SMTP サーバー名: smtp-mail.outlook.com

SMTP ポート: 587

SMTP 暗号化方法: STARTTLS
一般的にどこのメールサービスでも、TLS または SSL と書かれていますが、TLS で 587、SSL で 465 です。( このへんはかなり仕様がわかり難いです / Microsoft は、TLS のみ。Google は、両方。他は SSL のみだったり ) メッセージのソースの様子 ( ソースは GMail で確認するのが一番良さそうです )
From: =?iso-2022-jp?B?GyRCOjk9UD9NGyhCQg==?= <______@hotmail.co.jp>
To: =?iso-2022-jp?B?GyRCMDhAaBsoQkI=?= <______@gmail.com>
Date: Tue, 23 Jul 2013 20:10:15 +0900
MIME-Version: 1.0
Subject: =?iso-2022-jp?B?GyRCN29MPhsoQg==?=
X-Mailer: TKMP Version 3.1.2
Content-Type: text/plain; charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit

$BK\J8$N(B
$BFbMF(B

Gmail 用テンプレート

コードは同じですが、smtp サーバーが、『smtp.gmail.com(TLS/587)』になります。ユーザは、Hotmail ではメールアドレスでしたが、Gmail では、ユーザ名部分だけで認証します(メールアドレスでもOKなはずです)。

安全性の低いアプリの許可を『有効』にします

Nifty 用テンプレート

同様に、コードは同じです。smtp サーバーは、『smtp.nifty.com(SSL/465)』になります。ユーザは、NiftyID を使用したメールアドレスを使いますが、From では通常の別名を使用します。

Yahoo 用テンプレート

同様です。smtp サーバーは、『smtp.mail.yahoo.co.jp(SSL/465)』になります。アカウントは、「@yahoo.co.jpより前の部分」となります。

関連する記事

(C#) / VS2010 または VS2012 : TKMP.DLL(3.1.2 または 3.1.8)を使った、『さくらインターネット』用メール送信テンプレート

さくらインターネット用



C# : DataGridView に TKMP.DLL の IMAP(POP3) で受信したメールを非同期に表示する( 添付ファイルも取得 )



posted by lightbox at 2018-09-04 21:21 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2018年06月20日


C# と VB.net : TKMP.DLL を使って IMAP でメール本文の一覧を取得する( コンソール )

※ 重要
Gmail では安全性の低いアプリの許可を『有効』にする必要があります

.NET用メール送受信クラスライブラリ (TKMP.DLL) 
※ 2011-10-01 時点で 3.0.1
※ 2018-06-20 時点で 3.1.8( 2017/02/15 作成 )

TKMP は、VB.net や C# から日本語環境を気にしないでメールの送受信が行える貴重なライブラリですが、IMAP に対応しておられるのに添付されているドキュメントや、WEB 上のサンプルコードにその記述がありませんでしたので作成しました。

※ IMAP は 2011/08/11 に対応されています。
オンラインドキュメント

C#
using System;
using TKMP.Net;
using TKMP.Reader;

namespace MailRecTestCs
{
    class Program
    {
        static void Main(string[] args)
        {
            // IMAP 用基本認証
            BasicImapLogon logon = new BasicImapLogon("アカウント", "パスワード");
            // IMAP 用ログイン( 993 は、SSL 用 )
            ImapClient client = new ImapClient(logon, "サーバードメイン", 993);

            // SSL で接続する
            client.AuthenticationProtocol = AuthenticationProtocols.SSL;

            // 接続
            client.Connect();

            // メールデータ一覧の取得
            IMailData[] md_i = client.GetMailList();

            // メールデータの数
            Console.WriteLine(md_i.Length);

            // メールデータの本文を取得
            MailReader reader = null/* TODO Change to default(_) if this is not a reference type */;
            System.IO.Stream Body_data = null;

            // 全て表示
            for (int i = 0; i <= md_i.Length - 1; i++)
            {

                // メッセージを読み込む( 同期処理 )
                md_i[i].ReadBody();

                // 読み出しの為にストリームを取得
                Body_data = md_i[i].DataStream;

                // メールリーダで本文を解析
                reader = new TKMP.Reader.MailReader(Body_data, false);

                // マルチパートの時は最初に見つかったテキストセクションの本文
                Console.WriteLine(reader.MainText);

                // ヘッダ情報の取得
                foreach (TKMP.Reader.Header.HeaderString headerdata in reader.HeaderCollection)
                {
                    if (headerdata.Name == "From")
                        Console.WriteLine(string.Format("From : {0}", headerdata.Data));

                    if (headerdata.Name == "Subject")
                        Console.WriteLine(string.Format("Subject : {0}", headerdata.Data));

                    if (headerdata.Name == "Date")
                    {
                        Console.WriteLine(string.Format("Date オリジナル : {0}", headerdata.Data));
                        string target = headerdata.Data;
                        // 日付データの最後に(おそらく)改行が含まれていたので (JST) + 1 で6バイト除去しています
                        target = target.Substring(0, target.Length - 6);
                        try
                        {
                            DateTime dt = System.DateTime.ParseExact(target, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None);
                            Console.WriteLine(string.Format("Date : {0}", dt));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("フォーマット変換できませんでした");
                        }
                    }
                }
            }

            // 接続解除
            client.Close();

            Console.ReadLine();
        }
    }
}

VB.net
Imports TKMP.Net
Imports TKMP.Reader

Module Module1

    Sub Main()

        ' IMAP 用基本認証
        Dim logon As BasicImapLogon = New BasicImapLogon("アカウント", "パスワード")
        ' IMAP 用ログイン( 993 は、SSL 用 )
        Dim client As ImapClient = New ImapClient(logon, "サーバードメイン", 993)

        ' SSL で接続する
        client.AuthenticationProtocol = AuthenticationProtocols.SSL

        ' 接続
        client.Connect()

        ' メールデータ一覧の取得
        Dim md_i As IMailData() = client.GetMailList()

        ' メールデータの数
        Console.WriteLine(md_i.Length)

        ' メールデータの本文を取得
        Dim reader As MailReader = Nothing
        Dim Body_data As System.IO.Stream = Nothing

        ' 全て表示
        For i As Integer = 0 To md_i.Length - 1

            ' メッセージを読み込む( 同期処理 )
            md_i(i).ReadBody()

            ' 読み出しの為にストリームを取得
            Body_data = md_i(i).DataStream

            ' メールリーダで本文を解析
            reader = New TKMP.Reader.MailReader(Body_data, False)

            ' マルチパートの時は最初に見つかったテキストセクションの本文
            Console.WriteLine(reader.MainText)

            ' ヘッダ情報の取得
            For Each headerdata As TKMP.Reader.Header.HeaderString In reader.HeaderCollection

                If headerdata.Name = "From" Then
                    Console.WriteLine(String.Format("From : {0}", headerdata.Data))
                End If

                If headerdata.Name = "Subject" Then
                    Console.WriteLine(String.Format("Subject : {0}", headerdata.Data))
                End If

                If headerdata.Name = "Date" Then
                    Console.WriteLine(String.Format("Date オリジナル : {0}", headerdata.Data))
                    Dim target As String = headerdata.Data
                    ' 日付データの最後に(おそらく)改行が含まれていたので (JST) + 1 で6バイト除去しています
                    target = target.Substring(0, target.Length - 6)
                    Try
                        Dim dt As DateTime = System.DateTime.ParseExact(target, "ddd, d MMM yyyy HH':'mm':'ss zzz", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.None)
                        Console.WriteLine(String.Format("Date : {0}", dt))
                    Catch ex As Exception
                        Console.WriteLine("フォーマット変換できませんでした")
                    End Try
                End If
            Next

        Next

        ' 接続解除
        client.Close()

        Console.ReadLine()

    End Sub


End Module

関連する Microsfot のドキュメント

POP3 アクセス用および IMAP4 アクセス用の TLS と SSL の構成: Exchange 2010 SP1 のヘルプ




posted by lightbox at 2018-06-20 11:05 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2018年06月12日


C# でDataTable と DataSource を使用して、DataGridView にデータを表示するテンプレート( 行をダブルクリックしてダイアログを表示して行データを処理 )



画面はメインとなる DataGridView を最初に作成して Dock を Fill にします。Fill を設定したコントロールの上下にコントロールを使用する場合は、レイアウトは見たままでは無く Fill にしたものを一番上に置いて他のコントロールを下にします。



ステータスバー、ツールバー、メニューバーと順序が見ている位置と逆にして、それぞれの Dock プロパティを設定します。( ステータスとメニューはデフォルトで OK )

DataGridView のプロパティは重要なので以下に設定内容を自動作成されたコードで示します
            this.dataGridView1 = new System.Windows.Forms.DataGridView();

            this.dataGridView1.AllowUserToAddRows = false;
            this.dataGridView1.AllowUserToDeleteRows = false;
            this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
            this.dataGridView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.dataGridView1.Location = new System.Drawing.Point(0, 49);
            this.dataGridView1.MultiSelect = false;
            this.dataGridView1.Name = "dataGridView1";
            this.dataGridView1.ReadOnly = true;
            this.dataGridView1.RowTemplate.Height = 21;
            this.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
            this.dataGridView1.Size = new System.Drawing.Size(813, 407);
            this.dataGridView1.TabIndex = 0;
            this.dataGridView1.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView1_CellDoubleClick);

            public System.Windows.Forms.DataGridView dataGridView1;
ハイライトの行は、最初に設定する3つの編集を許可するかどうかのプロパティで、全て使用不可にしています。

1) 選択は単一行にする : MultiSelect = false
2) 選択表示は行全体にする : SelectionMode = FullRowSelect
3) 行のダブルクリックイベントは、CellDoubleClick で行う
4) Form2 から直接参照可能なように、public で定義する( Modifiers = Public )

次に、Form1 のソースコードですが、表示するデータは環境変数の一覧を使用しています( 実際に変更せずに DataGridView にデータを戻すまでの処理を行います )
    public partial class Form1 : Form
    {
        private DataTable table;
        private DataColumn column;
        private DataRow row;
        private Form nextWindow;

        public Form1()
        {
            InitializeComponent();
        }

        // ツールバーのボタンをクリック
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            // DataTable の作成
            table = new DataTable("EnvironmentVariables");

            // 列情報 の作成
            column = new DataColumn();
            column.DataType = Type.GetType("System.String");
            column.ColumnName = "環境変数";
            table.Columns.Add(column);

            // 列情報 の作成
            column = new DataColumn();
            column.DataType = Type.GetType("System.String");
            column.ColumnName = "値";
            table.Columns.Add(column);

            // 環境変数一覧より、行情報の作成
            foreach (DictionaryEntry dict in Environment.GetEnvironmentVariables())
            {
                row = table.NewRow();
                row["環境変数"] = dict.Key;
                row["値"] = dict.Value;
                table.Rows.Add(row);
            }

            // データーソース経由で DataGridView を表示
            dataGridView1.DataSource = table;
            // 第一カラムでソート
            dataGridView1.Sort(dataGridView1.Columns[0], ListSortDirection.Ascending);
            // 自動整列
            dataGridView1.AutoResizeColumns();

        }

        // 行をダブルクリックしてダイアログを表示
        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            int rowNumber = e.RowIndex;
            if (rowNumber < 0 ){
                return;
            }

            // 行=>列=>からの参照
            string value = dataGridView1.Rows[rowNumber].Cells["値"].Value.ToString();
            Console.WriteLine(value);

            // モーダルダイアログとして開く
            using (nextWindow = new Form2(rowNumber))
            {
                nextWindow.ShowDialog(this);
            }

        }
    }


DataTable の考え方は、SQL 文の cerate tableを実行して列の定義を行った上で、テーブルに行を追加して行くというものです。そのテーブル情報全てを DataSource にセットする事で DataGridView への表示が完了します。

※ 列のタイトルは、ColumnName にセットされた内容が表示されます

そして、行をダブルクリックして 行=>列=>からの参照でデータを取得していますが、ここでは確認の為に表示しているだけで、実際は Form2 から直接に [列,行] という形で参照しています。
    public partial class Form2 : Form
    {
        private int rowNumber;
        private DataGridView grid;

        // コンストラクタで処理する行を渡す
        public Form2(int rowNumber)
        {
            this.rowNumber = rowNumber;
            InitializeComponent();

        }

        // データ変更ボタンで親内の DataGridView を直接変更
        private void button1_Click(object sender, EventArgs e)
        {
            grid["値", rowNumber].Value = textBox2.Text;
            grid["値", rowNumber].Style.BackColor = Color.Pink;

            Console.WriteLine("表示データを書き換えました");
            this.Close();
        }

        // キャンセル( フォームのデフォルトボタン )
        private void button2_Click(object sender, EventArgs e)
        {
            Console.WriteLine("キャンセルされました");
            this.Close();
        }

        // 初期フォーカス
        private void Form2_Shown(object sender, EventArgs e)
        {
            textBox1.Focus();

        }

        // 親フォームからの情報を取得
        private void Form2_Load(object sender, EventArgs e)
        {
            grid = ((Form1)Owner).dataGridView1;
            textBox1.Text = grid["環境変数",rowNumber].Value.ToString();
            textBox2.Text = grid["値",rowNumber].Value.ToString();

        }
    }

親フォームの参照は、Owner プロパティを使用し、初期フォーカスの設定を Shown イベントで行うのが重要です。




posted by lightbox at 2018-06-12 12:42 | VS(C#) | このブログの読者になる | 更新情報をチェックする

2018年05月13日


C# コンソールアプリを AN HTTPD で実行

テストにはまだまだ使える(重宝する) AN HTTP Server の正しい使用方法

単純に、WEB アプリケーション初心者にブラウザとサーバーのやり取りを知ってもらう為に( 今は、開発者ツールがあるので途中の解説がしやすいですし )、C# で作った EXE をそのままブラウザで実行させます。

基本設定

EXE の列の『一般パスでも実行する』にチェックします



次に、一般パスに C# で作成された Debug フォルダを登録します。



後は、loclhost から実行するだけです。

ソースコード
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace WebApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //string formtype = "GET";
            string formtype = "POST";

            string[] param = {""};

            // ******************************
            // Console.WriteLine を UTF8 で
            // ******************************
            Console.OutputEncoding = Encoding.UTF8;

            // ******************************
            // メソッド
            // ******************************
            string method = Environment.GetEnvironmentVariable("REQUEST_METHOD");
            // ******************************
            // QUERY_STRING
            // ******************************
            string query_string = System.Environment.GetEnvironmentVariable("QUERY_STRING");

            // ******************************
            // HTTP ヘッダ
            // PHP の session_cache_limiter
            // ******************************
            Console.WriteLine("Content-Type: text/html; charset=utf-8");
            Console.WriteLine("Expires: Thu, 19 Nov 1981 08:52:00 GMT");
            Console.WriteLine("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
            Console.WriteLine("Pragma: no-cache");
            Console.WriteLine();

            string message = "<div>こんにちは世界</div>";

            // ******************************
            // HTML
            // ******************************
            string html = @"<!DOCTYPE html>
<html>
<head>
</head>
<body>
#{message}
<form method='#{formtype}'>
<p>氏名 : <input type='text' name='field1' value='#{field1}'></p>
<p>フリガナ : <input type='text' name='field2' value='#{field2}'></p>
<p>送信 : <input type='submit' name='send' value='送信'></p>
</form>
</body>
</html>";
            html = html.Replace("#{formtype}", formtype);

            // ******************************
            // GET
            // ******************************
            if (method == "GET")
            {
                param = query_string.Split('&');
            }

            // ******************************
            // POST
            // ******************************
            if (method == "POST")
            {
                string line = null;
                line = Console.ReadLine();
                param = line.Split('&');
            }

            foreach (string set in param)
            {
                string[] key_value = set.Split('=');
                if (key_value[0] == "field1")
                {
                    // System.Web を参照して using System.Web;
                    key_value[1] = HttpUtility.UrlDecode(key_value[1]);
                    html = html.Replace("#{field1}", key_value[1]);
                }
                if (key_value[0] == "field2")
                {
                    key_value[1] = HttpUtility.UrlDecode(key_value[1]);
                    html = html.Replace("#{field2}", key_value[1]);
                }
            }


            html = html.Replace("#{field1}", "");
            html = html.Replace("#{field2}", "");


            // #{} は Ruby の真似
            html = html.Replace("#{message}", message);

            Console.WriteLine(html);


        }
    }
}





posted by lightbox at 2018-05-13 00:34 | VS(C#) | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり