|
I am having a problem when I run this on Win2K advanced server. Are the shell api's supported on this platform?
|
|
|
|
|
I believe the zip extensions to the SHELL API was added with XP.
|
|
|
|
|
Hi,
I want to set the overwrite option of DestFlder.CopyHere(items, 20) to "Yes To All". What is the option value I should use, or where can I get a list of the .CopyHere() option values?
e-dub
|
|
|
|
|
|
Hi, I am using this tutorial to partial satisfaction.
I cannot no matter what I doget it to do Yes To All on the dialog boxes.
20, as in the tutorial by my reconing should be Yes To All and No File copy dialog
16 = Yes To All
4 = No copy file dialog
I have tried 16 on its own as
0x14, 0x0014, 16 and combined with 4 as 20.
Yet to no avail I still always get asked if I want to overrite the file.
The function in situe (Without the extra returns mid comamnd thats just to make it readable here) is as follows:
public static void unzip(int UpdateNumber)
{
Shell32.ShellClass sc = new Shell32.ShellClass();
Shell32.Folder SrcFlder = sc.NameSpace(
String.Format("{1}\\{0}.zip", UpdateNumber, System.Environment.CurrentDirectory)
);
Shell32.Folder DestFlder = sc.NameSpace(
String.Format("{0}\\", System.Environment.CurrentDirectory)
);
Shell32.FolderItems items = SrcFlder.Items();
DestFlder.CopyHere(items, 20);
File.Delete(
String.Format("{1}\\{0}.zip", UpdateNumber, System.Environment.CurrentDirectory)
);
}
It is part of a distributable update program I have wished to implement for a while now, and I don't trust the user to always click yes to all.
Am I flogging a dead horse? Will this work?
Many Thanks
Hugh Wood
IMRI Technical Services
|
|
|
|
|
What I have found is the vOptions parameter does not work. This is what led me to making this article in the first place. I wanted to use the vOptions paramter '4' to tell it to NOT display a dialog box at all... but it simply does not work. To get around this I used the console app approach where I can tell it to not show any output.
You probably have already found this page, but just in case ... Microsoft's reference says...
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/objects/folder/copyhere.asp[^]
vOptions Optional. Specifies options for the copy operation. This value can be zero or a combination of the following values. These values are based upon flags defined for use with the fFlags member of the C++ SHFILEOPSTRUCT structure. These flags are not defined as such for Microsoft Visual Basic, Visual Basic Scripting Edition (VBScript), or Microsoft JScript, so you must define them yourself or use their numeric equivalents.
4 Do not display a progress dialog box.
8 Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists.
16 Respond with "Yes to All" for any dialog box that is displayed.
64 Preserve undo information, if possible.
128 Perform the operation on files only if a wildcard file name (*.*) is specified.
256 Display a progress dialog box but do not show the file names.
512 Do not confirm the creation of a new directory if the operation requires one to be created.
1024 Do not display a user interface if an error occurs.
2048 Version 4.71. Do not copy the security attributes of the file.
4096 Only operate in the local directory. Don't operate recursively into subdirectories.
9182 Version 5.0. Do not copy connected files as a group. Only copy the specified files.
-- modified at 13:22 Tuesday 18th July, 2006
|
|
|
|
|
Ok ty, what I will do is checkif the file exists first using IO and delete it, the only problem then is the folders because if the other optiosn dont work, I doubt 512 works, I will try.
Thank you for your instantanious response.
Hugh Wood
Imri Technical Services
|
|
|
|
|
why would they put that documentation in there if it doesn't work?
|
|
|
|
|
When I try and zip a large group of files directly from the console app, i'm finding that it is stopping after the in-built delay (default 1s) is reached, leaving a large amount of my files "unzipped" - i.e. left out of the zip file. If I increase the delay, the program will zip more of the files - but this is not an ideal solution.
I haven't tried using the front-end app, as my final app that this will be used in will be console only, and i'm not concerned about the popup progress bar.
I've tried putting the main logic into it's own thread, and from Main() monitoring the IsAlive property with a while loop - puttting repeated delays into the loop body, but this has the same effect as putting all the code into Main().
Is there any way of keeping the thing running until the zip file has been completely created?
|
|
|
|
|
Sorry it has taken me so long to get back to you. I have been very busy. However I was able to reproduce your issue and came up with this code... It replaces the entire zip class in the console app. Basically I never tested the console app with a large source to zip. This code solves the issue by 1) Setting a timeout incase you do not want to continue ziping beyond a certain time period ... 2) checking the number of FolderItems in the source and comparing that number to the number of FolderItems in the new zip file every few seconds 3) looping over and over until the number of FolderItems in the zip matches the number in the source folder (which means the zip process is finished) and THEN the console app exits... I will add more to the article later to include this code.
The one issue I ran into however with this code is that an error pops up from Windows saying that it can not put empty folders into a zip IF you happen to have an empty folder in the source your are ziping. If you use the right click in Windows to zip the very same folder heirarchy with an empty folder no such error occurs ... I do not know why it does occur when you call the Shell API yourself, but it does. You could loop through your source and if you find any folders that are empty either delete them or put a small text file in them or something automatically so that Windows will not throw that error (which stops the zip process)
<br />
using System;<br />
using System.IO;<br />
<br />
namespace zip<br />
{<br />
class Class1<br />
{<br />
[STAThread]<br />
static void Main(string[] args)<br />
{<br />
<br />
byte[] emptyzip = new byte[] { 80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };<br />
<br />
FileStream fs = File.Create(args[1]);<br />
fs.Write(emptyzip, 0, emptyzip.Length);<br />
fs.Flush();<br />
fs.Close();<br />
fs = null;<br />
<br />
Shell32.ShellClass sc = new Shell32.ShellClass();<br />
Shell32.Folder SrcFlder = sc.NameSpace(args[0]);<br />
Shell32.Folder DestFlder = sc.NameSpace(args[1]); <br />
Shell32.FolderItems items = SrcFlder.Items();<br />
<br />
<br />
<br />
int OriginalItemCount = RecurseCount(items);<br />
<br />
DestFlder.CopyHere(items, 1024);<br />
<br />
DateTime timeoutDeadline = DateTime.Now.AddMinutes(30);<br />
<br />
for( ;; )<br />
{<br />
if(DateTime.Now > timeoutDeadline)<br />
{<br />
break;<br />
}<br />
<br />
<br />
System.Threading.Thread.Sleep(5000);<br />
<br />
if(OriginalItemCount == RecurseCount(DestFlder.Items()))<br />
{<br />
break;<br />
}<br />
} <br />
}<br />
<br />
<br />
<br />
private static int RecurseCount(Shell32.FolderItems Source)<br />
{<br />
int ItemCount = 0;<br />
<br />
foreach(Shell32.FolderItem item in Source)<br />
{<br />
if(item.IsFolder == true)<br />
{ <br />
ItemCount++;<br />
<br />
<br />
ItemCount += RecurseCount(((Shell32.Folder)item.GetFolder).Items());<br />
<br />
}<br />
else<br />
{ <br />
ItemCount++;<br />
<br />
}<br />
}<br />
<br />
return ItemCount;<br />
}<br />
}<br />
}<br />
-- modified at 14:32 Thursday 2nd March, 2006
|
|
|
|
|
|
When I try your code out I get the following exception:
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in system.dll
Additional information: The system cannot find the file specified
I can't tell if it can't find the zip file, or can't find unzip.exe. I originally thought I just implemented your code incorrectly, but I just downloaded your solution and got the same problem. I've tried multiple zip files with different output folders, under win2k and xp.
|
|
|
|
|
Sorry I don't have an exact answer, but if I get more info I can probably help. I wonder what file it cannot find? Do you have the file Interop.Shell32.dll in the application folder with the unzip.exe? Are you sure the path to the zip file is correct?
|
|
|
|
|
Do you have Interop.Shell32.dll in the same directory as your exe?
I found I was getting the same error until I did this.
|
|
|
|
|
The problem was I didn't have unzip.exe in the same directory as the executable. Does anyone know why it can't just use the environment variable and run the exe from any location? If I open a command prompt unzip.exe works just fine without calling it with an absolute path.
-Brian
|
|
|
|
|
Thanks for the article, quite useful.
Have you noticed that when you uncompress a zip file using the code you've mentionned a temporary folder is created in your account temp directory, and then this folder is not removed after the unzip operation ? This is quite a problem if you're unzipping large files! When you do the similar operation through the Explorer, this temporary folder appears as well, but it is cleared when you close the explorer view of the zip file.
Do you have a clue about this issue ?
Thanks
Phil
|
|
|
|
|
Yes I noticed that. What I saw in my temp directory were alot of those files from other zip operations I had done in the past using Windows zip/unzip and I figured that it was just the way Windows zipping worked. But now I just went and did a test and it appears to have something to do with how you decompress the files. If you right click a zip in Windows and use the Extract function it does not create the temp folder ..or it does, but deletes it very quickly. However if you open the zip in a window and then copy and paste the files out then the folder does get created in the temp directory and only is deleted after you close the window showing the contents of the zip file. It could be that if you do not let the thread that is doing the decompression to shutdown until all the files have been extracted THEN let the thread die you will end up with the folder being deleted from the temp directory.
|
|
|
|
|
J# has functionality of java. There exists package java.util.zip.
Only add reference to vjslib.dll having istalled J# redistributable packages.
There was already a description about it in codeproject.
Of course, if you are sure that your program will work on Windows XP (I understand that from this version of windows you have zip util in shell), and you do not want to install J# redistributable packages, then it is better to use this solution (but it still runs separate process...).
It is still strange that in "normal" dotNet there is still no util for multiple-files zip (only simple zipping stream is available). Maybe someone know the solution of decompressing zip archives with multiple files, using only dotnet 2.0 and not using J# redistributable packages?
Krzysztof Marzencki
|
|
|
|
|
|
I've worked with java.util.zip and found there is a problem when filenames of compressed files are not in UTF-8 (you get an exception). But I was able to decompress the same zip file with WinZip (manually)
|
|
|
|
|
How do you zip files using the Shell API?
Tony
|
|
|
|
|
This works ...for me ...
//Create an empty zip file
byte[] emptyzip = new byte[]{80,75,5,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
FileStream fs = File.Create(@"C:\Test\test.zip");
fs.Write(emptyzip, 0, emptyzip.Length);
fs.Flush();
fs.Close();
fs = null;
//Copy a folder and its contents into the newly created zip file
Shell32.ShellClass sc = new Shell32.ShellClass();
Shell32.Folder SrcFlder = sc.NameSpace(@"C:\MyFolderToZip\");
Shell32.Folder DestFlder = sc.NameSpace(@"C:\Test\test.zip");
Shell32.FolderItems items = SrcFlder.Items();
DestFlder.CopyHere(items, 20);
|
|
|
|
|
Thanks, I'll try it out.
tony
|
|
|
|
|
I couldn't create zip files using the Windows API as mentioned in the article. However, I got this to work successfully in Visual C# Express and .NET 2.0.5. I created a new solution, and dropped a new button on to the form. I doubled click on the button, pasted the source code in the onClick event handler, and made the following changes:
1. Add a reference to Shell32 (Microsoft Shell Controls And Automation) in the solution explorer. (Right click on references in the right panel, and then click on add reference, and then the COM tab)
2. Add a reference to the source code of the Form1 class. Just type using Shell32; at the top.
3. Changed the fs instance creation line to the following:
System.IO.FileStream fs = System.IO.File.Create(@"C:\test.zip");
4. Changed all directories to ones that existed on the machine.
That worked for me. Now I have to work on reading the file!
|
|
|
|
|
Hi
Could you tell me what namespace you used for "Shell32"
or what Dll reference you have given for this.
|
|
|
|
|