//──────────────────────────────────────── #endregion #region アクション //──────────────────────────────────────── /// <summary> /// 実行します。 /// </summary> /// <param name="filePathList">保存するファイルの相対パスの一覧。「起動アプリケーション・ファイル(.exe)からの相対パス」として設定してあること。</param> /// <param name="oDateBackupBaseDirectory"></param> /// <param name="d_Thread"></param> public void Perform( Log_Reports log_Reports ) { Log_Method pg_Method = new Log_MethodImpl(); pg_Method.BeginMethod(Info_Operating.Name_Library, this, "Perform", log_Reports); // // // // Exception err_Excp; string err_SFpatha_Source; string err_SFpatha_Dst; if (null == this.Expression_Filepath_Backuphome) { // エラー goto gt_Error_BkFolder;//todo:バックアップを無視する。 } // // バックアップ・ディレクトリーの絶対パス // // 例:「editor-backup」 // string sFpatha_BkHome = this.Expression_Filepath_Backuphome.Execute4_OnExpressionString( EnumHitcount.Unconstraint, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } //.WriteLine(this.GetType().Name + "#Perform: バックアップディレクトリーの絶対パス=[" + backupAbsFilePath + "]" ); // 日付フォルダー名(FOlder Name) string sDateFon = DatebackupImpl.CreateDateFolderName(this.Name_Sub); Configurationtree_Node s_ParentNode = new Configurationtree_NodeImpl("!ハードコーディング_DataBackup#Perform", null); // バックアップ・フォルダー下の日付ファイル名 // 日付フォルダーパス(「…略…\20091201」など) string sFopatha_date; { Expression_Node_Filepath ec_Dir; { Configurationtree_NodeFilepath cf_dir = new Configurationtree_NodeFilepathImpl("ファイルパス出典未指定L03_3", s_ParentNode); cf_dir.InitPath(sFpatha_BkHome, sDateFon, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } ec_Dir = new Expression_Node_FilepathImpl(cf_dir); } if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } sFopatha_date = ec_Dir.Execute4_OnExpressionString( EnumHitcount.Unconstraint, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } } // temp日付フォルダーパス(「…略…\temp20091201」など) string sFopatha_dateTemp; { Expression_Node_Filepath ec_Dir; { Configurationtree_NodeFilepath s_dir = new Configurationtree_NodeFilepathImpl("ファイルパス出典未指定L03_4", s_ParentNode); s_dir.InitPath(sFpatha_BkHome, "temp" + sDateFon, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } ec_Dir = new Expression_Node_FilepathImpl(s_dir); } if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } sFopatha_dateTemp = ec_Dir.Execute4_OnExpressionString( EnumHitcount.Unconstraint, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } } //.WriteLine(this.GetType().Name + "#Perform: absDateDirTemp=[" + absDateDirTemp + "]"); if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } // 今日の日付のフォルダーの有無を確認します。 if (Directory.Exists(sFopatha_date)) { // ある場合 // バックアップは取りません。 // 注意書きを出力してみる。 //.WriteLine(this.GetType().Name + "#Perform: バックアップを取りません。バックアップ・フォルダーに、既に今日の日付フォルダーがあるので。[" + absDateDir + "]"); // スキップ goto gt_EndMethod; } // // まず、今日の日付のテンポラリーファイル(「temp20091201」など)が存在すれば、削除します。 // if (Directory.Exists(sFopatha_dateTemp)) { // ある場合 // 該当する「tempXXXXXXXX」フォルダーを削除します。 // フォルダーの中身も破棄します。 Directory.Delete(sFopatha_dateTemp, true); } // // 今日の日付のテンポラリー・ディレクトリーを作成します。 // // Directory.CreateDirectory(sFopatha_dateTemp); // 作っておかないと、自作のクラスの中で「存在しないファイルパス・エラー」という事前チェックが誤発動してしまいます。 // バックアップを取ります。 foreach (Expression_Node_Filepath ec_Fpath_WrittenPlace in list_Expression_Filepath_Request) { //.WriteLine(this.GetType().Name + "#Perform: バックアップを取りたいファイルのパス sourceFilePath.HumanInputText=[" + oWrittenPlaceFilePath.HumanInputText + "]"); // 保存先 Expression_Node_Filepath ec_Fpath_Dst; { Configurationtree_NodeFilepath cf_fpath_Destination = new Configurationtree_NodeFilepathImpl("ファイルパス出典未指定L03_5", s_ParentNode); cf_fpath_Destination.InitPath( sFopatha_dateTemp, ec_Fpath_WrittenPlace.Humaninput, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } ec_Fpath_Dst = new Expression_Node_FilepathImpl(cf_fpath_Destination); } if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } string sFpatha_Source = ec_Fpath_WrittenPlace.Execute4_OnExpressionString( EnumHitcount.Unconstraint, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } // 人間オペレーターが記述しているファイルパス。 // 「相対パス」か「絶対パス」のどちらか。 string sFpath_HumanInput = ec_Fpath_Dst.Humaninput; // // 絶対パスで指定されたファイルを、バックアップに保存する方法 // // 例: 例えば、「C:\」を「C@\」に置換し、日付フォルダーの下に保存します。 // // 注意:「C:」より長い文字列と置換すると、文字列の長さ制限に引っかかることがあります。 // // 「絶対パス」か、「相対パス」かを判断します。 bool bPathRooted = Utility_Configurationtree_Filepath.IsRooted_Path(sFpath_HumanInput, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } // 絶対パスへの対応。 if (bPathRooted) { // 絶対パスであれば、「C:\」といった文字列が先頭に来ることが予想されます。 // 文字「:」が 2文字目 だけに存在することを想定して、 // 「:」を「@」に置換します。 // // 「絶対パスのようなもの」を、バックアップ日付フォルダーの下に作る想定です。 // ファイル名が長くなりすぎるので、この後、ファイル名を縮める処理になることが多い。 // //.WriteLine(this.GetType().Name + "#Perform: バックアップを取りたいファイルのパス名 humanInputFilePathStr=[" + humanInputFilePathStr + "]"); string sNewRelHPath3 = sFpath_HumanInput.Replace(":", "@"); //.WriteLine(this.GetType().Name + "#Perform: コロン記号を置換した後のファイルパス名 newRelHPathStr3=[" + newRelHPathStr3 + "]"); // 絶対パスでバックアップ対象ファイルが指定されていた場合 // // 「C:\banana」は、「C@\banana」に置換 // // 設定のし直し。 // 出力ファイルの絶対パスが長すぎると真。 bool isTooLong_Path = Utility_Configurationtree_Filepath.IsTooLong_Path( sNewRelHPath3, log_Reports, s_ParentNode ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } if (isTooLong_Path) { // 強引に短縮。 sNewRelHPath3 = DatebackupImpl.ReplaceToJammingFilePath( sNewRelHPath3, this.NSubstitutionFileNumber, this.GetType().Name + "#Perform:" ); this.NSubstitutionFileNumber++; //.WriteLine(this.GetType().Name + "#Perform: 短くした保存先ファイルパス名 newRelHPathStr3=[" + newRelHPathStr3 + "]"); // それでも、出力ファイルの絶対パスが長すぎると、後ろのプログラムで例外を投げます。 } // (2010-02-24 ※修正) // 保存先ファイルパスをセット。 ec_Fpath_Dst.SetHumaninput( sNewRelHPath3, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } } // 絶対パスへの対応終了 if (!log_Reports.Successful)// 異常時はスキップ { goto gt_EndMethod; } // もう一回、絶対パスの取得し直し string sFpatha_Dst = ec_Fpath_Dst.Execute4_OnExpressionString( EnumHitcount.Unconstraint, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } // ファイルのコピーで作成します。 //.WriteLine(this.GetType().Name + "#Perform: [" + sourceAbsFilePath + "]を"); //.WriteLine(this.GetType().Name + "#Perform: [" + absDstPathStr + "]にコピーします。"); try { string sDestinationParent = Path.GetDirectoryName(sFpatha_Dst); if (!Directory.Exists(sDestinationParent)) { // 指定のファイルの、ディレクトリーが存在しなかった場合。 // ディレクトリーを作成します。 Directory.CreateDirectory(sDestinationParent); } } catch (Exception e) { // エラー err_Excp = e; goto gt_Error_MissIo; } try { // todo: 同名のファイルがあれば、「aaa(1).txt」「aaa(2).txt」といった風に番号を付けていきたい。 // ファイルのコピー System.IO.File.Copy(sFpatha_Source, sFpatha_Dst, false); } catch (Exception e) { // エラー err_Excp = e; err_SFpatha_Source = sFpatha_Source; err_SFpatha_Dst = sFpatha_Dst; goto gt_Error_MissCopy; } } if (!log_Reports.Successful) { // 異常時はスキップ goto gt_EndMethod; } try { // テンポラリーフォルダーを、正規の名前にリネームします。 Directory.Move(sFopatha_dateTemp, sFopatha_date); } catch (Exception e) { // エラー err_Excp = e; goto gt_Error_MissMove; } // 「バックアップ日付フォルダー」が11個以上あるとき、 // 日付が新しいものを(指定)個残して 他の日付フォルダーを破棄します。 this.DeleteOldBackup( sFpatha_BkHome, sName_Sub, log_Reports ); // 異常時は、「temp20091202」といった、処理を中断したゴミ・ファイルが残ることがあります。 goto gt_EndMethod; // // #region 異常系 //──────────────────────────────────────── gt_Error_BkFolder: if (log_Reports.CanCreateReport) { Log_RecordReports r = log_Reports.BeginCreateReport(EnumReport.Error); r.SetTitle("▲エラー508!", pg_Method); Log_TextIndented s = new Log_TextIndentedImpl(); s.Append("バックアップ・フォルダーが指定されていません。"); // ヒント r.Message = s.ToString(); log_Reports.EndCreateReport(); } goto gt_EndMethod; //──────────────────────────────────────── gt_Error_MissIo: if (log_Reports.CanCreateReport) { Log_RecordReports r = log_Reports.BeginCreateReport(EnumReport.Error); r.SetTitle("▲エラー65507!", pg_Method); Log_TextIndented s = new Log_TextIndentedImpl(); s.Append("エラー:"); // // ヒント s.Append(r.Message_SException(err_Excp)); r.Message = s.ToString(); log_Reports.EndCreateReport(); } goto gt_EndMethod; //──────────────────────────────────────── gt_Error_MissCopy: if (log_Reports.CanCreateReport) { Log_RecordReports r = log_Reports.BeginCreateReport(EnumReport.Error); r.SetTitle("▲エラー65506!", pg_Method); StringBuilder t = new StringBuilder(); t.Append("ファイルのコピーに失敗。"); t.Append(Environment.NewLine); t.Append(Environment.NewLine); t.Append("["); t.Append(err_SFpatha_Source); t.Append("]"); t.Append("を"); t.Append(Environment.NewLine); t.Append("["); t.Append(err_SFpatha_Dst); t.Append("]"); t.Append("へコピーしようとしたとき。"); t.Append(Environment.NewLine); // // ヒント t.Append(r.Message_SException(err_Excp)); r.Message = t.ToString(); log_Reports.EndCreateReport(); } goto gt_EndMethod; //──────────────────────────────────────── gt_Error_MissMove: if (log_Reports.CanCreateReport) { Log_RecordReports r = log_Reports.BeginCreateReport(EnumReport.Error); r.SetTitle("▲エラー65508!", pg_Method); Log_TextIndentedImpl t = new Log_TextIndentedImpl(); t.Append("ファイルのリネーム(Move)に失敗。"); // // ヒント t.Append(r.Message_SException(err_Excp)); r.Message = t.ToString(); log_Reports.EndCreateReport(); } goto gt_EndMethod; //──────────────────────────────────────── #endregion // // gt_EndMethod: pg_Method.EndMethod(log_Reports); }
//──────────────────────────────────────── /// <summary> /// 今日の分のバックアップを取ります。 /// </summary> public override string Execute5_Main(Log_Reports log_Reports) { // // // //()メソッド開始 // // // Log_Method log_Method = new Log_MethodImpl(0, Log_ReportsImpl.BDebugmode_Static); log_Method.BeginMethod(Info_Functions.Name_Library, this, "Execute5_Main",log_Reports); if (this.EnumEventhandler == EnumEventhandler.O_Lr) { // 日付毎のバックアップ(バックアップ対象ファイルを、設定ファイルから読取り後) if (log_Reports.Successful) { // 正常時 // 1日につき1回まで、バックアップを取ります。 DatebackupImpl dateBackup = new DatebackupImpl(); dateBackup.Keptbackups = this.Owner_MemoryApplication.MemoryBackup.BackupKeptbackups; // アプリケーション個別に付ける「フォルダ・サブ名」 dateBackup.Name_Sub = this.Owner_MemoryApplication.MemoryBackup.Name_SubFolder; // // バックアップ・フォルダー // Expression_Node_Filepath ec_Fopath_BackupBase; { XenonNameImpl o_Name_Variable = new XenonNameImpl( NamesVar.S_SP_BACKUP_FOLDER, new Configurationtree_NodeImpl("!ハードコーディング_ExAction00031#", null) ); // 変数名。 Expression_Leaf_StringImpl ec_Atom = new Expression_Leaf_StringImpl(o_Name_Variable.SValue, null, o_Name_Variable.Cur_Configuration); // フォルダーパス。 log_Reports.Log_Callstack.Push(log_Method, "⑥"); ec_Fopath_BackupBase = this.Owner_MemoryApplication.MemoryVariables.GetExpressionfilepathByVariablename( ec_Atom, true, log_Reports ); log_Reports.Log_Callstack.Pop(log_Method, "⑥"); } dateBackup.List_Expression_Filepath_Request = this.Expression_FilepathList_Backup;// バックアップ対象のファイルのパス一覧。 dateBackup.Expression_Filepath_Backuphome = ec_Fopath_BackupBase; dateBackup.Name_Sub = this.Owner_MemoryApplication.MemoryBackup.Name_SubFolder; dateBackup.Perform(log_Reports); } } goto gt_EndMethod; // // gt_EndMethod: log_Method.EndMethod(log_Reports); return ""; }
//──────────────────────────────────────── /// <summary> /// このアプリケーションが担当する「バックアップ日付フォルダー」が /// (指定)個以上あるとき、 /// 日付が新しいものを(指定)個残して /// このアプリケーションが担当する他の「バックアップ日付フォルダー」を破棄します。 /// </summary> private void DeleteOldBackup( string sFilepathabsolute_Backuphome, string sName_Sub, Log_Reports log_Reports ) { // バックアップ・フォルダー直下のフォルダーの絶対パス string[] sFpatha_FolderArray = Directory.GetDirectories(sFilepathabsolute_Backuphome); // 日付フォルダーの名前のリストを作成します。 List <string> sList_Name_MyDateFolder = new List <string>(); foreach (string sFpatha_Folder in sFpatha_FolderArray) { // 区切り文字の次。 char[] separatorChars = new char[] { '\\', '/' }; int nFolderNameIndex = sFpatha_Folder.LastIndexOfAny(separatorChars) + 1; // 絶対パスから、最下層の「フォルダー名」だけを切り抜き。 string sFolderName = sFpatha_Folder.Substring(nFolderNameIndex, sFpatha_Folder.Length - nFolderNameIndex); //allFolderNames.Add(folderName); try { // 次の2つは、担当する日付フォルダーとして扱います。 // ・ファイル名が8桁の数字 // ・ファイル名の先頭8桁が数字で、アンダースコアが続く。 // ・フォルダー・オーナー名が、このアプリケーションのものと一致する。 int nDammyDateNumber = 0; string sFolderOwnerName = ""; bool bDateFolder = DatebackupImpl.IsDateFolderName( sFolderName, ref nDammyDateNumber, ref sFolderOwnerName); // フォルダー名の書式と、オーナー判定 if (bDateFolder && sFolderOwnerName == sName_Sub) { sList_Name_MyDateFolder.Add(sFolderName); } } catch (Exception) { // 無視して続行 } } // 日付フォルダー名の日付の逆順(数字の降順)にソート。同値は順が不安定。 sList_Name_MyDateFolder.Sort( delegate(string sName_Folder1, string sName_Folder2) { int nDateNumber1 = 0; int nDateNumber2 = 0; string sDammyFolderOwnerName = ""; // 日付フォルダーでない場合は、dateNumberN に-1が入ります。 bool bDate1 = DatebackupImpl.IsDateFolderName(sName_Folder1, ref nDateNumber1, ref sDammyFolderOwnerName); bool bDate2 = DatebackupImpl.IsDateFolderName(sName_Folder2, ref nDateNumber2, ref sDammyFolderOwnerName); return(nDateNumber2 - nDateNumber1); } ); // 日付の数字が大きい先頭から(指定数)件以外を、 // 削除するフォルダー名のリストに追加します。 List <string> sList_Name_DeleteeFolder = new List <string>(); int nCount = 0; foreach (string sName_DateFolder in sList_Name_MyDateFolder) { if (nCount < this.Keptbackups) { // (指定)件の間は無視。 } else { // (指定)件を超過した分は、削除リストに追加。 sList_Name_DeleteeFolder.Add(sName_DateFolder.ToString()); } nCount++; } sList_Name_MyDateFolder = null;//使用終了 foreach (string sName_DeleteeFolder in sList_Name_DeleteeFolder) { // 指定のフォルダーを削除 // 絶対パスの作成 Expression_Node_Filepath ec_Fpath; { Configurationtree_Node parent_Configurationtree_Node = new Configurationtree_NodeImpl("!ハードコーディング_DataBackup#DeleteOldBackup", null); Configurationtree_NodeFilepath cf_Fpath = new Configurationtree_NodeFilepathImpl("ファイルパス出典未指定L03_6", parent_Configurationtree_Node); cf_Fpath.InitPath( sFilepathabsolute_Backuphome, sName_DeleteeFolder, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } ec_Fpath = new Expression_Node_FilepathImpl(cf_Fpath); } string sFopath_Deletee; if (log_Reports.Successful) { // 正常時 sFopath_Deletee = ec_Fpath.Execute4_OnExpressionString( EnumHitcount.Unconstraint, log_Reports ); if (!log_Reports.Successful) { // 既エラー。 goto gt_EndMethod; } } else { sFopath_Deletee = ""; } if (log_Reports.Successful) { // 正常時 Directory.Delete(sFopath_Deletee, true); } } goto gt_EndMethod; // // gt_EndMethod: return; }