How to unzip a folder with multiple files using SSIS script task C# 2005 or 2008?

后端 未结 2 668
刺人心
刺人心 2021-01-20 03:06

There is a requirement in my project that I need to unzip some zip folder. I googled and came to know without using external libraries I can not achieve this or with G

2条回答
  •  庸人自扰
    2021-01-20 03:38

    I didn't want to use the 7zip approach or an external library because that makes it slightly more complicated to deploy the SSIS package. So I went with a similar approach to the Gallery Script referenced by @StackTrace and also documented here and here. I already had a Script Task performing other logic so I just needed the C# code to do it. I found that the Script Task was being executed on an MTA thread but the Shell32 code needs to execute using STA thread, so I ended up with this code. Hopefully helps someone else:

    /// 
    /// Ugh! SSIS runs script tasks on MTA threads but Shell32 only wants to 
    /// run on STA thread. So start a new STA thread to call UnZip, block 
    /// till it's done, then return. 
    /// We use Shell32 since .net 2 doesn't have ZipFile and we prefer not to 
    /// ship other dlls as they normally need to be deployed to the GAC. So this 
    /// is easiest, although not very pretty.
    /// 
    /// File to unzip
    /// Folder to put the unzipped files
    public static void UnZipFromMTAThread(string zipFile, string folderPath)
    {
        object[] args = new object[] { zipFile, folderPath };
        if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
        {
            UnZip(args);
        }
        else
        {
            Thread staThread = new Thread(new ParameterizedThreadStart(UnZip));
            staThread.SetApartmentState(ApartmentState.STA);
            staThread.Start(args);
            staThread.Join();
        }
    }
    
    /// 
    /// From http://www.fluxbytes.com/csharp/unzipping-files-using-shell32-in-c/ but with 
    /// args packed in object array so can be called from new STA Thread in UnZipFromMTAThread().
    /// 
    /// object array containing: [string zipFile, string destinationFolderPath]
    public static void UnZip(object param)
    {
        object[] args = (object[]) param;
        string zipFile = (string)args[0];
        string folderPath = (string)args[1];
    
    
        if (!File.Exists(zipFile))
            throw new FileNotFoundException();
    
        if (!Directory.Exists(folderPath))
            Directory.CreateDirectory(folderPath);
    
        Shell32.Shell objShell = new Shell32.Shell();
        Shell32.Folder destinationFolder = objShell.NameSpace(folderPath);
        Shell32.Folder sourceFile = objShell.NameSpace(zipFile);
    
        foreach (var file in sourceFile.Items())
        {
            // Flags are: No progress displayed, Respond with 'Yes to All' for any dialog, no UI on error
            // I added 1024 too although not sure it's relevant with Zip files. 
            // See https://msdn.microsoft.com/en-us/library/windows/desktop/bb787866%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
            destinationFolder.CopyHere(file, 4 | 16 | 1024); 
        }
    }
    

    Then you can just call it from elsewhere in a Script Task like this:

    string zipFilename = "C:\\temp\\awesome-zip-file.zip";
    string targetDirectory = "C:\\temp\\my-output-folder";
    UnZipFromMTAThread(zipFilename, targetDirectory);
    

提交回复
热议问题