7z command line to compress folders - c#

I am trying to zip/7z folders using the command line of 7zG.exe. The code I have works for files but not folders. Could someone please show me the correct way using 7z command line to compress folders? Here is the sample code that works for files only. Whenever I try running this code 7zip shows a messagebox saying "Invalid Parameter"
string sourceName = "Folder\Folder1";
string targetName = "Example.gz";
// 1
// Initialize process information.
//
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = "7zG.exe";
// 2
// Use 7-zip
// specify a=archive and -tgzip=gzip
// and then target file in quotes followed by source file in quotes
//
p.Arguments = "a -tgzip \"" + targetName + "\" \"" + sourceName + "\" -mx=9";
p.WindowStyle = ProcessWindowStyle.Hidden;
// 3.
// Start process and wait for it to exit
//
Process x = Process.Start(p);
x.WaitForExit();

as stated in to comment section, you are supposed to use 7za.exe
This link gives you a complete example line
Your code will look like this:
string sourceName = "Folder\Folder1";
string targetName = "Example.gz";
ProcessStartInfo p = new ProcessStartInfo();
//first change
p.FileName = "7za.exe";
//second change
p.Arguments = "a -tzip \"" + targetName + "\" \"" + sourceName + "\" -mx=9";
p.WindowStyle = ProcessWindowStyle.Hidden;
Process x = Process.Start(p);
x.WaitForExit();

gzip as well as bzip2 are only compression algorithms and cannot be used to compress a file-system structure (e.g. folders, folders with files etc.).
In fact, they are usually preceded by tar compression (that support folders), to get the famous (in particular in unix-based systems) tar.gz and tar.bz2 archives.
In your case you can use -tzip or -t7zip to directly compress a folder:
p.Arguments = "a -t7z \"" + targetName + "\" \"" + sourceName + "\" -mx=9";
By the way, you should use 7za.exe instead of 7zG.exe since the latter is the GUI module, while the former is the command-line standalone version of 7zip (i.e. it does not depend on any other dll), as stated in 7zip manual:
7z.exe is the command line version of 7-Zip. 7z.exe uses 7z.dll from
the 7-Zip package. 7z.dll is used by the 7-Zip File Manager also.
7za.exe (a = alone) is a standalone version of 7-Zip. 7za.exe supports
only 7z, lzma, cab, zip, gzip, bzip2, Z and tar formats. 7za.exe
doesn't use external modules.
You can find 7za.exe in the extra package, for example for version 9.22 you can find it in the archive called 7z922_extra.7z (link).

try with this command:
7za -tzip <archive-name> <folder-name>

Related

Self-Updating, Download, Extract, and Replace Exe

I'm using Visual Studio 2015, C#, WPF.
I'm trying to give MyProgram.exe the ability to easily update itself.
I have code that downloads the file MyProgram.7z to %UserProfile%\AppData\Local\Temp\.
From the 7z it extracts MyProgram.exe to the currently running MyProgram.exe's directory.
While the 7-Zip extraction is starting, the program closes itself to allow overwriting the exe.
// AppData Temp Directory
string tempDir = System.IO.Path.GetTempPath();
// MyProgram.exe Current Directory
string currentDir = Directory.GetCurrentDirectory().TrimEnd('\\') + #"\";
// ...
//
// Download Code Here
// Saves MyProgram.7z to AppData Temp
//
// ...
// Unzip MyProgram.7z
// Overwrite MyProgram.exe
//
using (Process extract = new Process())
{
extract.StartInfo.UseShellExecute = false;
extract.StartInfo.CreateNoWindow = false;
extract.StartInfo.RedirectStandardOutput = true;
extract.StartInfo.FileName = "7z.exe";
extract.StartInfo.Arguments = "-r -y e " + "\"" + tempDir + "MyProgram.7z" + "\"" + " -o\"" + currentDir + "\"" + " *";
// 7z.exe -r -y e "C:\Users\Matt\AppData\Local\Temp\MyProgram.7z" -o"C:\Program Files\MyProgram\" *
extract.Start();
}
// Exit Program
// 7-Zip will continue to run in the background after MyProgram.exe has exited
//
Environment.Exit(0);
I've tested it and it appears to work.
Is there a better way of doing this? Is there anything that can go wrong with this way? I'like to have it within the program and not in a separate helper program. I also need to use 7z.exe in this case.
Is there a way to instead launch cmd and chain commands into it like timeout 5 && 7z.exe ... and have it relaunch the program after extraction?
You may want to check out Squirrel. It is an open-source library that completely manages both installation and updates of desktop Windows applications.
There is a getting starting guide available on GitHub: https://github.com/Squirrel/Squirrel.Windows/blob/master/docs/getting-started/0-overview.md.
There is also the ClickOnce deployment technology from Microsoft: https://msdn.microsoft.com/en-us/library/142dbbz4(v=vs.90).aspx.
No reason to reinvent the wheel.
Instead of launching 7z process directly you can also:
launch cmd /c process that will wait 5 seconds, then unzip, the relaunch the app
shutdown yourself
cmd /c timeout 5 & [your unzip command] & MyProgram.exe
PS. & is used to execute multiple commands one after another

how to give address of parts to copy command in c#

when i run copy command in my c# code it produce no error or exception because it is not finding the parts path i do not know how to give full directory path or path of every part which i am joining.actually i am merging file parts to a single file using coy/b by using this code...
string strCmdText;
strCmdText = "/C copy/b test.txt.10485760.0000.part" +
"test.txt.10485760.0001.part" +
"test.txt.10485760.0002.part" +
"test.txt.10485760.0003.part" +
"test.txt.10485760.0004.part" +
"test.txt.10485760.0005.part test.txt";
System.Diagnostics.Process.Start("CMD.exe", strCmdText);
You can specify the path of your files as the working path of the process. For example:
var startInfo = new System.Diagnostics.ProcessStartInfo
{
WorkingDirectory = #"THE\PATH\OF\FILES",
WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal,
FileName = "cmd.exe",
Arguments = "YOUR COMAND HERE";
};
Process process = Process.Start(startInfo);
For your command, note that you can copy all files into one using a wildcard for the parts:
copy *.part test.txt
/b is for binary data, so i think is not needed in your case.
You can also set other properties for a process, for more info check the doc: ProcessStartInfo.
For such a complex task, I would use the process as a bash rather then just an execution tool.
Create a Process
Redirect it's streams (Input, Output)
With a StreamReader and StreamWriter u can now access the cmd
Now just control it the way u need it, like setting the working directory to the path and do ur command.
If this is not what u want, u can allways set the working directory on the ProcessStartInfor -> Link

C# archiving using 7zip, keeps hanging on wildcard call

Hey all quick question for you. I am trying to archive a directory of files into a zip folder using 7zip as a system process but I am running into an odd error. Whenever I do a wildcard specification in my source file name such as "*.txt" it works fine. However, once I use the wildcard * around the actual file name (Which I need to and can't work around that), 7zip just seems to hang. I can see the archive directory get created in the folder but I can't open it and I have to close 7zip down via task manager.
Any advice?
Code is below:
public static void archiveFiles(string executionDirectory,string workDirectory,
string[] files)
{
string sourceName = #"C:\mypath\*testfile*"; <----// This seems to be my issue
string targetName = #"C:\\testcompress\archive.zip";
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = #"C:\program files\7-zip\7z.exe";
p.Arguments = "a -t7z \"" + targetName + "\" \"" + sourceName + "\" -mx=9";
p.WindowStyle = ProcessWindowStyle.Hidden;
Process x = Process.Start(p);
x.WaitForExit();
}
You're most likely getting this issue because your path #"C:\mypath*testfile*" is a verbatim string, thus using the "*" character, or other such wildcards, are being taken as literal in the path instead of wildcards. Trying taking the # off the beginning of strings containing wildcards and that should fix your problem. You can find a more thorough explanation of what the "#" character, used in context of a prefix to strings, does here:
Verbatim Strings
I think you are having issues with your \'s as well as the fact that you should be using 7za.exe and not 7z.exe. Make sure your application has access to write to the directory in question.
string sourceName = #"C:\mypath\*testfile*";
string targetName = #"C:\testcompress\archive.zip";
ProcessStartInfo p = new ProcessStartInfo();
p.FileName = #"C:\program files\7-zip\7za.exe";
p.Arguments = string.Format ( "a -t7z {0} {1} -mx=9",targetName,sourceName);
p.WindowStyle = ProcessWindowStyle.Hidden;
Process x = Process.Start(p);
x.WaitForExit();
console.writeline(string.format("7zip returned with exit code {0}",x.ExitCode));
7zip exit codes can be found here
Remember you can test it in a command prompt window to be sure that it works.
C:\program files\7-zip\7za.exe a -t7z C:\program files\7-zip\7za.exe C:\mypath*testfile* -mx=9

Calling G++ from C# Program

I've made a C++ code editor in C# and now am trying to invoke g++ to compile the source files. So I've copied the TDM-GCC installation besides my program and wrote a small batch script to call that.
#echo off
#set PATH="%~dp0TDM-GCC-32\bin\";%PATH%
call "%~dp0TDM-GCC-32\mingwvars.bat"
cd %1
"%~dp0TDM-GCC-32\bin\g++.exe" %2 -o %3
And from C# code, I'm trying to call this script by using CMD like in this script of code.
string fileName = Path.GetFileName(CurrentFile);
string exeName = Path.GetFileNameWithoutExtension(CurrentFile) + ".exe";
string workingDir = Directory.GetParent(CurrentFile) + "";
string compile = Directory.GetParent(Application.ExecutablePath) + "\\compile.cmd";
File.Delete(Path.Combine(workingDir, exeName));
StartProcess(true, "cmd", "/c", "\"" + compile + "\"", workingDir, fileName, exeName);
And here is the StartProcess method:
void StartProcess(bool hidden, string command, params string[] args)
{
ProcessStartInfo pStartInfo = new ProcessStartInfo();
pStartInfo.FileName = command;
pStartInfo.Arguments = string.Join(" ", args);
pStartInfo.UseShellExecute = false;
if (hidden)
{
pStartInfo.RedirectStandardError = true;
pStartInfo.RedirectStandardOutput = true;
pStartInfo.CreateNoWindow = true;
}
Process proc = new Process();
proc.StartInfo = pStartInfo;
proc.Start();
logBox.Clear();
if (hidden)
{
while (!proc.StandardError.EndOfStream)
{
logBox.AppendText(GetTimestamp() + " Error: " + proc.StandardError.ReadLine() + Environment.NewLine);
}
}
}
Update: 26-9-14
I doubted whether the batch file is ever called, because if I call it from cmd, it simply works. So I tried to echo to the standard error from the batch file like this:
echo %PATH% 1>&2
And I can see that the GCC's bin folder is in the path too, but for some reason, the exe is not getting created. But sometimes, the script works, and the exe gets created.
But whenever I execute this, there will be nothing in the LOG and also, no executable is being created. I know that the TDM-GCC's bin folder must be in the PATH, but that is what the second line of the batch script needs to do. Dunno what this is and why this error.
End of update
Any suggestions on how can I get it working?
Thanks.
I don't know if anything written below really helps on this issue. But at least those hints should be useful in any case.
I suggest for the batch file
#echo off
call "%~dp0TDM-GCC-32\mingwvars.bat"
set "PATH=%~dp0TDM-GCC-32\bin;%PATH%"
cd /D %1
"%~dp0TDM-GCC-32\bin\g++.exe" %2 -o %3
PATH is modified after execution of mingwvars.bat. It could be that this batch file also modifies PATH. Or it runs commands like find.exe with the executables expected in %SystemRoot%\System32, but perhaps also existing in directory bin. I have seen already several times not working logon batch scripts because PATH on client computer contained as first folder path the bin directory of a compiler ported from Unix to Windows with executables also found in %SystemRoot%\System32, but working completely different as ported from Unix.
Folder paths should be added to environment variable PATH always without double quotes even if the folder path contains 1 or more spaces. The double quotes used in third line just make sure that a trailing space is not added additionally to PATH and that command set works even with not typical folder paths like an ampersand in path.
And folder paths should be added to environment variable PATH without a trailing backslash.
On command cd the parameter /D is additionally used in case of a change to a different drive must be performed, too. The command cd would not change the current directory if the specified path is on a different drive without parameter /D.
In C# code you have to make sure that workingDir, fileName and exeName are finally on execution of cmd.exe enclosed in double quotes in the arguments string as Erti-Chris Eelmaa already wrote.
And it would be perhaps better to read in your C# application the value of environment variable ComSpec and use this value instead of just cmd for executing the batch file.
This might, or might not be part of the problem, but you don't take care of spaces.
pStartInfo.Arguments = string.Join(" ", args);
you probably would want something like this:
pStartInfo.Arguments = string.Join(" ", args.Select(x => "\"" + x + "\""));

Exception: string filename too long (Process)

I am using the code below to pass an argument to a process
ProcessStartInfo StartInfo = new ProcessStartInfo();
StartInfo.FileName = HttpContext.Current.Server.MapPath(#"\highcharts\phantomjs.exe");
StartInfo.Arguments = HttpContext.Current.Server.MapPath(#"\highcharts\highcharts-convert.js");
StartInfo.Arguments += #" -outfile " + path + #"\chart" + templateData[i].ReportTemplateChartId + ".png -width 800 -infile " + chartoptions1;
StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
StartInfo.CreateNoWindow = false;
In chartoptions1 I was using a JSON string, but it throws an exception saying string filename too long, so I created a text file and tried to pass it, but the chart image is not generated.
From this MSDN page,
On Windows Vista and earlier versions of the Windows operating
system, the length of the arguments added to the length of the full
path to the process must be less than 2080. On Windows 7 and later
versions, the length must be less than 32699.
Did you check the length of StartInfo.Arguments ?
On the other part, a quick look at this wiki page on Github,
-infile: The file to convert, assumes it's either a JSON file, the script checks for the input file to have the extension '.json', or
otherwise it assumes it to be an svg file.
So, -infile should be a file and not a JSON content. I suppose your chartoptions1 is quite large, so you have the error message string filename too long.
Highcharts may also check the length of the infile path (256 ?)
The running script should have at least read access to the infile and should be resolvable ; especially if you don't specified a working directory, you have to add the full path with infile and not just the filename.
To debug, a working directory issue, simply test with a constant path such as c:\test

Categories

Resources