メールの添付ファイルとして拡張子.zip
や.exe
が禁止されている環境で、
ファイルをリネームして展開するのが地味に面倒なので、Drag&Dropでリネームするツールを作ってみた。
(※添付ファイルを開くときは慎重に!)
2020.01.03追記:完全にこれですね。。
ITの7つの無意味な習慣
2020.06.13追記:Drag&Dropすらめんどくさいので、拡張子に関連付けるのがおすすめ!!!
機能
Drag&Dropしたファイルの拡張子をリネームする。
拡張子の変換規則はプログラム内で決め打ちにしてある。
ソースコード
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
// Note: "."が2つ以上ある場合は、最後の"."以降を拡張子とみなす
// 例: "hoge.tar.gz" の拡張子は "gz" とみなす
class FileRenamer : Form
{
static Dictionary<string,string> _defaultExtensionDict = new Dictionary<string,string>(){
// Key:変換前拡張子(小文字), Value:変換後拡張子
// "."は付けない
{"zi", "zip"},
{"zi_", "zip"},
{"ex", "exe"},
{"ex_", "exe"},
//{"", "zip"},
};
FileRenamer()
{
Text = "File Renamer";
ClientSize = new Size(200,200);
AllowDrop = true;
DragEnter += (sender,e)=>{
if (e.Data.GetDataPresent(DataFormats.FileDrop)){
e.Effect = DragDropEffects.Copy;
}
else{
e.Effect = DragDropEffects.None;
}
};
DragDrop += (sender,e)=>{
var fileNames = (string[]) e.Data.GetData(DataFormats.FileDrop, false);
foreach(string s in fileNames) {
RenameFile(_defaultExtensionDict, s);
}
};
}
static bool RenameFile(Dictionary<string,string> extentionConvertionDict, string partialFileName)
{
var fi = new FileInfo(partialFileName);
if ( !fi.Exists ) {
return false;
}
string newName = GetRenamedFullName(extentionConvertionDict, fi);
if ( newName == null ) {
return false;
}
Console.WriteLine(newName);
try {
File.Move(fi.FullName, newName);
}
catch (UnauthorizedAccessException e) {
Console.WriteLine(e);
}
catch (PathTooLongException e) {
Console.WriteLine(e);
}
catch (DirectoryNotFoundException e) {
Console.WriteLine(e);
}
catch (IOException e) {
Console.WriteLine(e);
}
return true;
}
// return null : 変更対象ではない or エラー
static string GetRenamedFullName(Dictionary<string,string> extentionConvertionDict, FileInfo fi)
{
string oldExtension;
int posDot = fi.Name.LastIndexOf(".");
if ( posDot < 0 ) { // 拡張子がない
oldExtension = "";
}
else if ( posDot == 0 ) { // "."から始まっている(ファイル名部分がない)
return null;
}
else if ( posDot == fi.Name.Length-1 ) { // "."で終わっている
return null;
}
else { // posDot >= 1 (拡張子がある)
oldExtension = fi.Name.Substring(posDot+1); // "."を含まない拡張子部分
}
oldExtension = oldExtension.ToLowerInvariant(); // 小文字に変換する
string newExtension;
if (extentionConvertionDict.TryGetValue(oldExtension, out newExtension)){
return Path.ChangeExtension(fi.FullName, newExtension);
}
else {
return null; // 置換対象ではない
}
}
[STAThread]
static void Main(string[] args)
{
if ( args.Length >= 1 ) {
foreach ( string s in args ) {
RenameFile(_defaultExtensionDict, s);
}
}
else {
Application.Run(new FileRenamer());
}
}
}
続編 - Outlookに添付されている.zi_や.ex_ファイルを楽に開く
.zi_
ファイル や .ex_
ファイル に関連付けして使用する想定。
Outlookの添付フォルダと思われるフォルダ(下記ソースコード中の_outlookAttachmentPath
で指定)内のファイルだった場合に、マイドキュメントに日時に依存する名前のフォルダを生成してファイルをコピーします。その後にzip
やexe
へのリネームをトライし、リネームできた場合は、そのまま開きます。
※作業ステップを極限まで減らしたことで、スパムを踏むリスクが上がる恐れがあります。(セキュリティ上はちょっと危険です。)
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
// Note: "."が2つ以上ある場合は、最後の"."以降を拡張子とみなす
// 例: "hoge.tar.gz" の拡張子は "gz" とみなす
class FileRenamer : Form
{
// Outlook添付ファイル C:\Users\UserName\AppData\Local
static readonly string _outlookAttachmentPath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Microsoft\Windows\INetCache\Content.Outlook\"); // "
static readonly string _temporaryDestPath = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
static readonly int _maxTemporaryDirN = 99;
static Dictionary<string,string> _defaultExtensionDict = new Dictionary<string,string>(){
// Key:変換前拡張子(小文字), Value:変換後拡張子
// "."は付けない
{"zi", "zip"},
{"zi_", "zip"},
{"ex", "exe"},
{"ex_", "exe"},
//{"", "zip"},
};
FileRenamer()
{
Text = "File Renamer";
ClientSize = new Size(200,200);
AllowDrop = true;
DragEnter += (sender,e)=>{
if (e.Data.GetDataPresent(DataFormats.FileDrop)){
e.Effect = DragDropEffects.Copy;
}
else{
e.Effect = DragDropEffects.None;
}
};
DragDrop += (sender,e)=>{
var fileNames = (string[]) e.Data.GetData(DataFormats.FileDrop, false);
foreach(string s in fileNames) {
RenameFile(_defaultExtensionDict, s);
}
};
}
static string RenameFile(Dictionary<string,string> extentionConvertionDict, string partialFileName)
{
var fi = new FileInfo(partialFileName);
if ( !fi.Exists ) {
return null;
}
string newName = GetRenamedFullName(extentionConvertionDict, fi);
if ( newName == null ) {
return null;
}
Console.WriteLine(newName);
try {
File.Move(fi.FullName, newName);
}
catch (UnauthorizedAccessException e) {
Console.WriteLine(e);
}
catch (PathTooLongException e) {
Console.WriteLine(e);
}
catch (DirectoryNotFoundException e) {
Console.WriteLine(e);
}
catch (IOException e) {
Console.WriteLine(e);
}
return newName;
}
// return null : 変更対象ではない or エラー
static string GetRenamedFullName(Dictionary<string,string> extentionConvertionDict, FileInfo fi)
{
string oldExtension;
int posDot = fi.Name.LastIndexOf(".");
if ( posDot < 0 ) { // 拡張子がない
oldExtension = "";
}
else if ( posDot == 0 ) { // "."から始まっている(ファイル名部分がない)
return null;
}
else if ( posDot == fi.Name.Length-1 ) { // "."で終わっている
return null;
}
else { // posDot >= 1 (拡張子がある)
oldExtension = fi.Name.Substring(posDot+1); // "."を含まない拡張子部分
}
oldExtension = oldExtension.ToLowerInvariant(); // 小文字に変換する
string newExtension;
if (extentionConvertionDict.TryGetValue(oldExtension, out newExtension)){
return Path.ChangeExtension(fi.FullName, newExtension);
}
else {
return null; // 置換対象ではない
}
}
static string HandleOutlookAttachment(Dictionary<string,string> extentionConvertionDict, string path)
{
if ( path.ToLower().StartsWith(_outlookAttachmentPath.ToLower()) ) {
DateTime dt = DateTime.Now;
string dtStr = dt.ToString("yyMMdd_HHmm");
string tmpDirBase = Path.Combine( _temporaryDestPath , "RenameZi_"+dtStr);
string tmpDir = null;
bool foundFlg = false;
for (int i=0;i<_maxTemporaryDirN;i++) {
tmpDir = tmpDirBase+"_"+i.ToString().PadLeft(2,'0');
if ( ! Directory.Exists(tmpDir) && ! File.Exists(tmpDir) ) {
foundFlg = true;// 未使用フォルダを発見できた
break;
}
}
if ( foundFlg ) {
Directory.CreateDirectory(tmpDir);
string newPath = Path.Combine(tmpDir, Path.GetFileName(path));
File.Copy(path, newPath);
return newPath;
}
else {
// failed to create temporary folder
return path;
}
}
else {
return path;
}
}
[STAThread]
static void Main(string[] args)
{
if ( args.Length >= 1 ) {
foreach ( string s in args ) {
string path = HandleOutlookAttachment(_defaultExtensionDict, s);
string renamedPath = RenameFile(_defaultExtensionDict, path);
if ( renamedPath != null ) {
// open with default program ※セキュリティ上はキケンです
System.Diagnostics.Process.Start(renamedPath);
}
}
}
else {
Application.Run(new FileRenamer());
}
}
}