views:

243

answers:

7

I want to extract .rar files using cmd shell so I wrote this code:

string commandLine = @"c:\progra~1\winrar\winrar e  c:\download\TestedU.rar c:\download";
ProcessStartInfo PSI = new ProcessStartInfo("cmd.exe");
PSI.RedirectStandardInput = true;
PSI.RedirectStandardOutput = true;
PSI.RedirectStandardError = true;
PSI.UseShellExecute = false;
Process p = Process.Start(PSI);
StreamWriter SW = p.StandardInput;
StreamReader SR = p.StandardOutput;
SW.WriteLine(commandLine);
SW.Close(); 

The first time it worked fine, the second time it displayed nothing.

+1  A: 

You might skip the middle step and call the winrar.exe with the parameters straight instead of first instanciating cmd.exe

Also you might take a look at the 7-zip SDK

Kjartan Þór Kjartansson
A: 

You forgot to add a stream for reading errors. If WINRAR is behaving properly, you will find your error output when you add the stream to read it.

P.Brian.Mackey
+3  A: 

See also http://stackoverflow.com/questions/11737/net-library-to-unzip-zip-and-rar-files

Ron Klein
The Chilkat library referenced in the above works a treat. Only irritation is that its unmanaged code.
Murph
+1  A: 

You can use this lib directly: http://sevenziplib.codeplex.com/

Best

Vagaus
A: 

Use SevenZipSharp as it's a bit better way of doing things then working with some .exe's.

private ReadOnlyCollection<string> ExtractArchive(string varPathToFile, string varDestinationDirectory) {
        ReadOnlyCollection<string> readOnlyArchiveFilenames;
        ReadOnlyCollection<string> readOnlyVolumeFilenames;
        varExtractionFinished = false;
        varExtractionFailed = false;
        SevenZipExtractor.SetLibraryPath(sevenZipDll);
        string fileName = "";
        string directory = "";
        Invoke(new SetNoArgsDelegate(() => {
                                         fileName = varPathToFile;
                                         directory = varDestinationDirectory;
                                     }));
        using (SevenZipExtractor extr = new SevenZipExtractor(fileName)) {
            //string[] test = extr.ArchiveFileNames.

            readOnlyArchiveFilenames = extr.ArchiveFileNames;
            readOnlyVolumeFilenames = extr.VolumeFileNames;
            //foreach (string dinosaur in readOnlyDinosaurs) {
            //MessageBox.Show(dinosaur);
            // }
            //foreach (string dinosaur in readOnlyDinosaurs1) {
            // // MessageBox.Show(dinosaur);
            // }
            try {
            extr.Extracting += extr_Extracting;
            extr.FileExtractionStarted += extr_FileExtractionStarted;
            extr.FileExists += extr_FileExists;
            extr.ExtractionFinished += extr_ExtractionFinished;

                extr.ExtractArchive(directory);
            } catch (FileNotFoundException error) {
                if (varExtractionCancel) {
                    LogBoxTextAdd("[EXTRACTION WAS CANCELED]");
                } else {
                    MessageBox.Show(error.ToString(), "Error with extraction");
                    varExtractionFailed = true;
                }
            }
        }
        varExtractionFinished = true;
        return readOnlyVolumeFilenames;
    }

  private void extr_FileExists(object sender, FileOverwriteEventArgs e) {
        listViewLogFile.Invoke(new SetOverwriteDelegate((args) => LogBoxTextAdd(String.Format("Warning: \"{0}\" already exists; overwritten\r\n", args.FileName))), e);
    }
    private void extr_FileExtractionStarted(object sender, FileInfoEventArgs e) {
        listViewLogFile.Invoke(new SetInfoDelegate((args) => LogBoxTextAdd(String.Format("Extracting \"{0}\"", args.FileInfo.FileName))), e);
    }
    private void extr_Extracting(object sender, ProgressEventArgs e) {
        progressBarCurrentExtract.Invoke(new SetProgressDelegate((args) => progressBarCurrentExtract.Increment(args.PercentDelta)), e);
    }
    private void extr_ExtractionFinished(object sender, EventArgs e) {
        Invoke(new SetNoArgsDelegate(() => {
                                         //pb_ExtractWork.Style = ProgressBarStyle.Blocks;
                                         progressBarCurrentExtract.Value = 0;
                                         varExtractionFinished = true;
                                         //l_ExtractProgress.Text = "Finished";
                                     }));
    }

Of course you need to adjust things a bit, and use some of your own stuff. But for the sake of example I've added some additional methods.

MadBoy
A: 

As Kjartan suggested, using 7-Zip SDK may be a better option than spawning an external executable depending on your use:

7-Zip SDK is a C/C++ library but http://sevenzipsharp.codeplex.com/ has a .Net library of it around the 7-Zip SDK which makes it easier to use in .NET.

Kharlos Dominguez
A: 

This is best Answer .

UnRar("C:\Download\sampleextractfolder\", filepath2);

private static void UnRar(string WorkingDirectory, string filepath) {

        // Microsoft.Win32 and System.Diagnostics namespaces are imported

        //Dim objRegKey As RegistryKey
        RegistryKey objRegKey;
        objRegKey = Registry.ClassesRoot.OpenSubKey("WinRAR\\Shell\\Open\\Command");
        // Windows 7 Registry entry for WinRAR Open Command

        // Dim obj As Object = objRegKey.GetValue("");
        Object obj = objRegKey.GetValue("");

        //Dim objRarPath As String = obj.ToString()
        string objRarPath = obj.ToString();
        objRarPath = objRarPath.Substring(1, objRarPath.Length - 7);

        objRegKey.Close();

        //Dim objArguments As String
        string objArguments;
        // in the following format
        // " X G:\Downloads\samplefile.rar G:\Downloads\sampleextractfolder\"
        objArguments = " X " + " " + filepath + " " + " " + WorkingDirectory;

        // Dim objStartInfo As New ProcessStartInfo()
        ProcessStartInfo objStartInfo = new ProcessStartInfo();

        // Set the UseShellExecute property of StartInfo object to FALSE
        //Otherwise the we can get the following error message
        //The Process object must have the UseShellExecute property set to false in order to use environment variables.
        objStartInfo.UseShellExecute = false;
        objStartInfo.FileName = objRarPath;
        objStartInfo.Arguments = objArguments;
        objStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        objStartInfo.WorkingDirectory = WorkingDirectory + "\\";

        //   Dim objProcess As New Process()
        Process objProcess = new Process();
        objProcess.StartInfo = objStartInfo;
        objProcess.Start();
        objProcess.WaitForExit();


        try
        {
            FileInfo file = new FileInfo(filepath);
            file.Delete();
        }
        catch (FileNotFoundException e)
        {
            throw e;
        }



    }
Hanad