Unrar and delete files via script

Hi, I would like to create a script that given a rar file will unrar the file and then delete the original rar.

I have looked over the forums and there are some samples here and here. But these I believe only delete the first file in a spanned rar, and often don't confirm success.

I have done this in the past by using unrar.exe reading the output from that in to a string. Then checking the string for a success message, and finally pulling the files names of the rar files to be deleted. unrar.exe was the only console I could find that would tell me what files had been use in the extraction.

Given the changes in DO11, with new scripting and rar support what options do I have here?
When running a dos command can I read back the output?

Thanks

Hi wowbagger,

I know this might not be what you want (a 3rd party program called from Dopus instead of a Dopus script) but the end result should be the same.

I use Par-N-Rar for all my auto verify, extract then delete all par/rar's. It still works if there are no .par's. And I believe if the extract fails, the .rar's don't get auto deleted. Auto deleting can be set to use recycle bin as well.

I use this code to call the program to run on the current folder:

"C:\Program Files (x86)\ParNRar\ParNRar.exe" /m "{sourcepath$}" /go

hi ktbcrash, That's a interesting solution. Also I don't mind needing an exe application I planned to use the unrar.exe. Being able to par files as well is a bonus, I had not planned to script that. I would rather a console app as apps can be hidden but message boxes can become a pain.

dopus team: Aa the unrar.exe can output the list of files accessed, can the unrar.dll do the same?

I tried using jscript to run the dos command as the exec method can return the stdout, the but I could not get it to work. Also I the way the exec method is an async call, and jscript does not have sleep function. WScript has one but we dont have access to that do we?

I tried this

  var objShell = new ActiveXObject("WScript.Shell");
  var unrarCommand = "C:\\bin\\unrar\\UnRAR.exe x -y \"" + filePath + "\"";
  LogMessage("unrarCommand" + unrarCommand); 
  var result = objShell.Exec(unrarCommand);
  while (result.Status == 0)
  {
      //todo need a sleep here
      //WScript.Sleep(100);
  }
  LogMessage(result.Status);
  if (!result.StdOut.AtEndOfStream)
  {
    LogMessage("result: " + result.StdOut.Read(1)); 
  }

Can I get the stdout from the dopus command? Something like this:

  var unrarCommand = "C:\\bin\\unrar\\UnRAR.exe x -y \"" + filePath + "\"";
  cmd.SetType("msdos");
  var result = doCmd.RunCommand(unrarCommand);
  LogMessage(result.Status);
  LogMessage(result.StdOut);

Hi wowbagger.

If you work it out, then let me know too.
I always find myself hitting Shift-Delete on archives after I have extracted them.
If they could be deleted after a successful extraction, then that would be great.

The FSUtil object should let you read the contents of an archive.
The DOpus object provides a Delay method should you need it.

[quote="wowbagger"]But these I believe only delete the first file in a spanned rar, and often don't confirm success.
...
unrar.exe was the only console I could find that would tell me what files had been use in the extraction.[/quote]

Pulling in a list of archive part names from an external tool seems more complicated than you need it to be.

Can't you just use a wildcard/regex to delete all the parts?

RAR has two naming schemes (old .rar, .r[0-9]+ and new .part[0-9]+.rar). A script can easily tell which scheme is being used from the main part, then delete on the other parts without needing a list of them from somewhere else.

Hi Jon, Thanks for pointing that out, I had completely missed it.

You might be right here leo. What I like about this approach is that I'm letting the rar tool tell me if the extract was a success, and what files to remove. I feel comfortable that it wont delete the wrong file. But as you say some carefully crafted file matching should work as well.

Well that aside, I got it to work, not that happy with the solution so might try tweak it. I dont know if I can silence the popup that is generated by the jscript shell object when i run the unrar command.

Leo, Jon Would you consider having the RunCommand return the stdout for msdos commands?

//unrar file using unrar.exe, remove rars if success. Supports a span rar set.
function unrar(filePath, removeOriginal)
{
  removeOriginal = typeof removeOriginal !== 'undefined' ? removeOriginal : false;
  LogMessage("unrar " + (removeOriginal ? "removing rars" : "") + "file:" + filePath);
 
  var fso = new ActiveXObject("Scripting.FileSystemObject"); 
  if(!fso.FileExists(filePath))
  {
    LogMessage("Cant find file " + filePath);
    return;
  }
  
  var file = fso.GetFile(filePath);
  
  var unrarPath = Script.config.unrarPath;
  if(!fso.FileExists(unrarPath))
  {
    LogMessage("Cant find rar.exe  " + unrarPath);
    return;
  }
  
  var unrarCommand = "CMD /S /C \" \"" + unrarPath + "\" x -y \"" + filePath + "\" \"" + file.ParentFolder + "\" \"";
  LogMessage("unrar Command:" + unrarCommand); 
  
  var objShell = new ActiveXObject("WScript.Shell");
  var result = objShell.Exec(unrarCommand);
  while (result.Status == 0)
  {
      DOpus.Delay(250);
  }
  
  if(result.Status == 1 && removeOriginal)
  {
    var regexp_allok = /^All OK$/;
  
    var stdout = result.StdOut.ReadAll();
    var lines = stdout.split(/\r\n|\r|\n/g);
    var extractOk = false;
    for (i = 0; i < lines.length; i++) {
      if(regexp_allok.test(lines[i]))
      {
        extractOk = true;
      }
    }
    
    if(extractOk)
    {
      var regexp_rarFile = /^Extracting\sfrom\s(.*)$/;
      for (i = 0; i < lines.length; i++) {
        if(regexp_rarFile.test(lines[i]))
        {
          var matches = regexp_rarFile.exec(lines[i]);
          if(fso.FileExists(matches[1]))
          {
            fso.DeleteFile(matches[1], true);
          }
        }
      }
    }
  }
}

If you need to run an external program and capture command line output, Windows already provides a way to do that:

Exec Method (Windows Script Host)

The Exec method is what I ended up using, and got it working. The WshShell.Exec has a couple of draw backs compared to using the dopus command. While it can return the stdout, I don't think you can hide the windows it raises. It does not hold the thread, so you need a loop while waiting for it to finish. Also the command you run needs to be tweaked to run in shell.

The dopus command gives much cleaner and simpler code. If it could return the stdout would have saved some time.

Still all good, I have the code working and have posted it here. Folder clean up and unrar scripts.

Thanks for you help.

You could redirect stdout to a file if you want to use the Opus method and a blocking thread while the command runs. (That's probably needed anyway, if you want it to block the thread, otherwise things would deadlock if stdout was not being read at the same time it was being written to, since the small pipe buffer provided by Windows would became full and block any further writes.)