Archive for the ‘C#’ Category

実データを操作するプログラムを作るときに、必ずといっていいほどパスの結合を行う。
そんなときに、使うメソッドは、System.IO.Path.Combine(path1,path2)で
path1とpath2を結合して、ファイルパスとして生成してくれる。
こんな感じ

  1.  
  2. string path1 = @"C:\test\subtest\";
  3. string path2 = "test.txt";
  4. string filePath = System.IO.Path.Combine(path1, path2 );
  5. //filePathには"C:\test\subtest\test.txt"という値が入る
  6.  

非常に便利だが、
path2の先頭が\だと、予想外の動きに。。。

  1.  
  2. string path1 = @"C:\test\subtest\";
  3. string path2 = @"\test.txt";
  4. string filePath = System.IO.Path.Combine(path1, path2 );
  5. //filePathには"\test.txt"という値が入る
  6.  

検索してみるたら、参考になる記事を発見
【C#】パスが結合できない

さらに
MSDNでしらべてみたところ、こんな記述が

“path2 にルートが含まれていない (たとえば、path2 が区切り記号またはドライブ仕様で始まらない) 場合は、間に区切り記号が入った 2 つのパスの連結が返されます。 path2 にルートが含まれている場合は、path2 が返されます。 ”

つまり、区切り文字「\」から始まると、ルートと判断されて、path2だけが帰ってきてしまうのですね。。。
ちゃんと読まないとだけど、エラーとかにして欲しいかも。。。

アプリケーションを作っていて、設定ファイルの書き換えなどで、
再度、アプリケーションを最初から実行したいときが結構ある。
そのような場合に下記のコードで、アプリケーションの再起動ができる

  1.  
  2. Application.Restart();
  3.  

フォルダを選択させるときに、
次のような画面を使うケースが多々ある。

デフォルトフォルダ選択ダイアログ

デフォルトフォルダ選択ダイアログ

実際のソース

  1.  
  2. FolderBrowserDialog fb = new FolderBrowserDialog();
  3. DialogResult dr = fb.ShowDialog();
  4. if (dr == DialogResult.OK)
  5. {
  6.     textbox1.Text = fb.SelectedPath;
  7. }
  8.  

OKが押されたらtextBox1のテキストプロパティにそのパスを書くとしています。

以下の構文を使う

  1.  
  2. Environment.Exit(0);
  3.  

コマンドライン引数を取得する場合には、Main関数を以下のように 記述すると取得することができる

  1.  
  2. //引数ひとつで、フラグのON・OFFを指定する
  3. //Form1のコンストラクタでそのフラグを取得するようにしている
  4. static void Main(string[] args)
  5. {
  6.     Application.EnableVisualStyles();
  7.     Application.SetCompatibleTextRenderingDefault(false);
  8.     bool flag = false;
  9.     if (args.Length > 0 && args[0] == "1")
  10.     {
  11.          flag = true;
  12.     }
  13.     else
  14.     {
  15.           flag = false;
  16.     }
  17.     Application.Run(new Form1(flag));
  18. }
  19.  

以前書いた記事ファイルのMD5を取得する(お手軽)
を書いたが、この方法ではUNCパスで指定されるネットワークフォルダのファイルで大きいサイズ(700MBぐらい)の場合
かなりの時間がかかった。

なんとなく、一度メモリ等に展開してから計算しているようにみえるので、
転送時間+展開時間+計算時間がかかってしまっているのだと思った。

昔、Macで作ったソースを思い出して、
バッファに読み込んで、順次計算していく方法にしてみたところ
転送時間+αぐらいで計算できたので、
その方法をメモ

  1.  
  2. public string calcMD5(string path)
  3. {
  4.     string res = "";
  5.  
  6.     FileStream fs = new FileStream(path, FileMode.Open);
  7.  
  8.     MD5 crypto = new MD5CryptoServiceProvider();
  9.     long length = fs.Length;
  10.     int blockSize = 1024*1024*10;
  11.  
  12.     for (long offset = 0; offset < length; offset += blockSize)
  13.     {
  14.         byte[] byteValue = new byte[blockSize];
  15.         fs.Position = offset;
  16.         fs.Read(byteValue, 0, blockSize);
  17.         if (offset + blockSize < length)
  18.         {
  19.             crypto.TransformBlock(byteValue, 0, blockSize, null, 0);
  20.         }
  21.         else
  22.         {
  23.             crypto.TransformFinalBlock(byteValue, 0, (int)(length - offset));
  24.         }
  25.      }
  26.      fs.Close();
  27.  
  28.      byte[] hashValue = crypto.Hash;
  29.  
  30.      StringBuilder hashedText = new StringBuilder();
  31.      for (int i = 0; i < hashValue.Length; i++)
  32.      {
  33.          hashedText.AppendFormat("{0:x2}", hashValue[i]);
  34.      }
  35.  
  36.      res = hashedText.ToString();
  37.            
  38.      return res;
  39. }
  40.  
  41.  

ローカルのファイルの場合は、あまり変わらないので、
特にこの方法は取らなくていいかも

ファイルのデータを保証するために
ファイルのMD5を取得したいときの処理

  1.  
  2. using System.Security.Cryptography;
  3.  
  4. static public string calcMD5(string path)
  5. {
  6.     string res = ""; //結果が入る変数
  7.            
  8.     FileStream fs = new FileStream(path, FileMode.Open);
  9.     //MD5取得
  10.     res = BitConverter.ToString(MD5.Create().ComputeHash(fs)).ToLower().Replace("-", "");
  11.     fs.Close();
  12.  
  13.     return res;
  14. }
  15.  

参考にさせていただいたページ

ファイルのMD5チェックサムをとる-tsucchiの日記

アプリケーションの開発を行っていると、
2重起動防止の処理が必要な場合がある。
ただ、2重起動防止機能をつけて、
もし2重起動だった場合に、「すでに起動しています」というメッセージを
だすだけだとしたら、かなりしょぼい気がする。
それだったら、すでに起動しているアプリをアクティブにしてあげた方が
いい気がする。
(基本Machintoshはそうなってるし)

方法としては、外部アプリをアクティブにするためのメソッドが
VBに存在しているので、参照を追加し、
AppActiveを呼んでやればよい。

  1.  
  2. using System.Diagnostics;
  3. using Microsoft.VisualBasic;
  4.  
  5. static void Main(){
  6.     //2重起動防止
  7.     Process[] processList = Process.GetProcessesByName(
  8.                                       Process.GetCurrentProcess().ProcessName);
  9.     if (processList.Length > 1){
  10.        foreach (Process process in processList)
  11.        {
  12.                if (process.Id != Process.GetCurrentProcess().Id)
  13.                {
  14.                    //アクティブにして終了
  15.                    Interaction.AppActivate(process.Id);
  16.                    return;
  17.                }
  18.         }
  19.         //アクティブにせずに終了
  20.         return;
  21.     }
  22.  
  23.     Application.Run(new Form1());
  24. }
  25.  

起動したアプリと同じプロセス名からプロセスの一覧を取得し、
その中に、自分以外のプロセスがあったら、
そのプロセスに対して、Active命令を送る

アプリケーションの開発を行っていると、
2重起動防止の処理が必要な場合がある。

Program.csのメインに書けばよい

  1.  
  2. using System.Diagnostics;
  3.  
  4. static void Main(){
  5.     //2重起動防止
  6.     if (Process.GetProcessesByName(
  7.          Process.GetCurrentProcess().ProcessName).Length > 1){
  8.         MessageBox.Show("すでに起動しています");
  9.         return;
  10.     }
  11.  
  12.     Application.Run(new Form1());
  13. }
  14.  

やっていることは、起動したアプリ自身のアプリケーションのプロセスの名前を取得し、
その名前から同じ名前のプロセスを取得する。
名前からプロセスを取得し、その個数が2つ以上ある場合は、
すでに起動していると判断し、立ち上げたアプリを終了するようにする。

実行中にアプリ自身の名前が必要な場合がよくある

そんなときは、Application.ExecuteablePathを使用する

  1.  
  2. //using System.IO; ←これを追記する
  3.  
  4. string appPath; //アプリケーションのファイルパス
  5. string appFileName; //アプリケーションのファイル名
  6. string appName; //アプリケーションの拡張子を取り除いたアプリケーション名
  7.  
  8.  
  9. //パスの取得
  10. appPath = Application.ExecutablePath;
  11.  
  12. //アプリケーションのファイル名
  13. appFileName = File.GetFileName(appPath);
  14.  
  15. //拡張子を除いたアプリケーションファイル名
  16. appName = File.ChangeExtension(appFileName, null);
  17.  
  18.