指定したフォルダー配下全てのOfficeファイルのパスワードを解除する


沢山の同じパスワードがかかったファイルを一括で解除したいときに実行する。
パスワードはもちろん知っている必要がある。 

```bat:使用方法
cscript decrypt.js
```
上のコマンドを実行するか、単純にダブルクリックすれば実行したディレクトリ以下のファイルのパスワードを全て解除する。

スクリプトは下の通り。 ``CONSTS.defaultPassword`` の値を変更する必要がある。

```js:decrypt.js
/**
   Decrypt office file password recursively from current folder by WSH.
   This script decrypt office file password by using default password.
   So you must know password.  
*/
CONSTS ={
  defaultPassword: "your_password", // **set your password**
  verbose: false,
  FSO: new ActiveXObject("Scripting.FileSystemObject"),
  Word :new ActiveXObject("Word.Application"),
  Excel: new ActiveXObject("Excel.Application"),
  PowerPoint: new ActiveXObject("Powerpoint.Application")
};

// Force to run using CScript. see https://gist.github.com/sstur/4482361
(function(ws) {
  if (ws.fullName.slice(-12).toLowerCase() !== '\\cscript.exe') {
    var cmd = 'cscript.exe //nologo "' + ws.scriptFullName + '"';
    var args = ws.arguments;
    for (var i = 0, len = args.length; i < len; i++) {
      var arg = args(i);
      cmd += ' ' + (~arg.indexOf(' ') ? '"' + arg + '"' : arg);
    }
    new ActiveXObject('WScript.Shell').run(cmd);
    ws.quit();
  }
})(WScript);


/** 
    Utility
*/
function puts(message){
  WScript.echo(message);
}
function eachCollection(collection,f){
  var enumerator = new Enumerator(collection);
  for(;!enumerator.atEnd();enumerator.moveNext()){
    f(enumerator.item());
  }
}

Object.create = function(parent) {
    var F = function() {};
    F .prototype = parent;
    return new F();
};

/**
   Super class
*/
function OfficeFile(path){
  this.path = path;
  this.app = this.getOleObject();
}
OfficeFile.prototype ={
  close: function(){
    if(typeof this.file != "undefined" && this.file != null){
      this.file.close(-1); // -1 and true are same in jscript.
    }
  },
  decrypt : function(){
    this.open();
    if(this.file.hasPassword){
      this.file.password = "";
      this.file.saved = false;
      this.file.save(); 
      this.decrypted = true;
    }
  }
};

/**
   ExcelFile class
*/
var ExcelFile = function(path){
  this.path = path;
  this.app = CONSTS.Excel;
  this.file = null;
};
ExcelFile.prototype = Object.create(OfficeFile.prototype);
ExcelFile.prototype.open = function(){
  this.file = this.app.Workbooks.Open(this.path,0,false,5,CONSTS.defaultPassword);      
}

/**
   WordFile class
*/
var WordFile = function(path){
  this.path = path;
  this.app = CONSTS.Word;
  this.file = null;
};
WordFile.prototype = Object.create(OfficeFile.prototype);
WordFile.prototype.open = function(){
  this.file = this.app.Documents.open(this.path,false,false,false,CONSTS.defaultPassword);
}

/**
   PowerPointFile class
*/
var PowerPointFile = function(path){
  this.path = path;
  this.app = CONSTS.PowerPoint;
  this.file = null;
};
PowerPointFile.prototype= Object.create(OfficeFile.prototype);
PowerPointFile.prototype.open = function(){
  this.file = this.app.Presentations.open(this.path + "::" + CONSTS.defaultPassword,false,false,false);
}
PowerPointFile.prototype.close = function(){
  if(typeof this.file != "undefined" && this.file != null){
    this.file.close();
  }
}
PowerPointFile.prototype.decrypt = function(){
  this.open();
  this.file.password = "";
  if(!this.file.saved){
    this.file.saved = false;
    this.file.save();
    this.decrypted = true;
  }
};

/**
   Factory method
*/
var fileFactory = function(path){
  var extension = CONSTS.FSO.getExtensionName(path);
  var fileName = CONSTS.FSO.getFileName(path);

  if(/^[^~].*\.xls[x]?$/.test(fileName)){
      return(new ExcelFile(path));
  }else if(/^[^~].*\.doc[x]?$/.test(fileName)){
      return(new WordFile(path));
  }else if(/^[^~].*\.ppt[x]?$/.test(fileName)){
      return(new PowerPointFile(path));
  }else {
    return(null);
  }
};

/**
   This function decrypt all office file in passed folder path with default password.
*/
function decryptOfficeFileInFolder(path){
  var folder = CONSTS.FSO.getFolder(path);
  eachCollection(folder.files,function(file){
    if(CONSTS.verbose){
      puts("Processing : " + file.path);
    }
    var officeFile = fileFactory(file.path);
    if(officeFile != null){
      try{
        officeFile.decrypt();
        if(officeFile.decrypted){
          puts("O: Decrypted : " + officeFile.path);
        }
      }catch(e){
        puts("X: Failed : " + officeFile.path );
        puts("    This file may not used default password. See below message.");
        puts("    (" +e.description + ")");
      }finally{
        officeFile.close();
      }
    }
  });
  eachCollection(folder.subFolders,function(folder) {
    decryptOfficeFileInFolder(folder.path);        
  });
}

/**
   main
*/

try{
  decryptOfficeFileInFolder(".");
}catch(e){
  puts(e.number + ":" + e.description );
}finally{
  puts("Release OLE object");
  CONSTS.Word.quit();
  CONSTS.Excel.quit();
  CONSTS.PowerPoint.quit();
  puts("Finished.");
}
```

WSHのJScriptで継承とかやろうとすると骨が折れる・・。