Recently I faced with an issue during reading/generating Excel files using OpenXML from PowerShell. Long story short, during unpacking Excel (which is essentially a CAB file) if allocated memory exceeds some limit (10 MB) it switches from memory stream to isolated storage. An exception is thrown when getting access to isolated storage since assembly's evidence could not be resolved from PowerShell. More information on this could be found here.
Stack trace:
The solution to fix this is fairly simple - just run the excel specific code from regular application, e.g. Console. However in this case you'd lose all the flexibility of PowerShell and you'd need to recompile your code (on Production? ) every time you need to change anything.
Therefore it has been decided to run PowerShell code from application. There are enough examples on how to create custom PowerShell host similar to PowerShell ISE. However it's cumbersome to find how to create regular PS console from managed console application.
It turns out that it could be achieved by writing 2 lines of code:
Stack trace:
at System.IO.IsolatedStorage.IsolatedStorage._GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, Object& oNormalized)at System.IO.IsolatedStorage.IsolatedStorage.GetAccountingInfo(Evidence evidence, Type evidenceType, IsolatedStorageScope fAssmDomApp, String& typeName, String& instanceName)at System.IO.IsolatedStorage.IsolatedStorage._InitStore(IsolatedStorageScope scope, Evidence domainEv, Type domainEvidenceType, Evidence assemEv, Type assemblyEvidenceType, Evidence appEv, Type appEvidenceType)at System.IO.IsolatedStorage.IsolatedStorage.InitStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)at System.IO.IsolatedStorage.IsolatedStorageFile.GetStore(IsolatedStorageScope scope, Type domainEvidenceType, Type assemblyEvidenceType)at MS.Internal.IO.Packaging.PackagingUtilities.GetDefaultIsolatedStorageFile()at MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32 retryCount, String& fileName)at MS.Internal.IO.Packaging.SparseMemoryStream.EnsureIsolatedStoreStream()at MS.Internal.IO.Packaging.SparseMemoryStream.SwitchModeIfNecessary()at MS.Internal.IO.Packaging.DeflateEmulationTransform.Decompress(Stream source, Stream sink)at MS.Internal.IO.Packaging.CompressEmulationStream..ctor(Stream baseStream, Stream tempStream, Int64 position, IDeflateTransform transformer)at MS.Internal.IO.Packaging.CompressStream.ChangeMode(Mode newMode)at MS.Internal.IO.Packaging.CompressStream.Seek(Int64 offset, SeekOrigin origin)at MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Read(Byte[] buffer, Int32 offset, Int32 count)at System.IO.StreamReader.ReadBuffer(Char[] userBuffer, Int32 userOffset, Int32 desiredChars, Boolean& readToUserBuffer)at System.IO.StreamReader.Read(Char[] buffer, Int32 index, Int32 count)at System.IO.TextReader.ReadBlock(Char[] buffer, Int32 index, Int32 count)at OfficeOpenXml.ExcelWorksheet.GetWorkSheetXml(Stream stream, Int64 start, Int64 end, Encoding& encoding)at OfficeOpenXml.ExcelWorksheet.CreateXml()at OfficeOpenXml.ExcelWorksheet..ctor(XmlNamespaceManager ns, ExcelPackage excelPackage, String relID, Uri uriWorksheet, String sheetName, Int32 sheetID, Int32 positionID, eWorkSheetHidden hide)at OfficeOpenXml.ExcelWorksheets..ctor(ExcelPackage pck, XmlNamespaceManager nsm, XmlNode topNode)at OfficeOpenXml.ExcelWorkbook.get_Worksheets()at OfficeOpenXml.ExcelWorkbook.GetDefinedNames()at OfficeOpenXml.ExcelPackage.get_Workbook()
The solution to fix this is fairly simple - just run the excel specific code from regular application, e.g. Console. However in this case you'd lose all the flexibility of PowerShell and you'd need to recompile your code (on Production? ) every time you need to change anything.
Therefore it has been decided to run PowerShell code from application. There are enough examples on how to create custom PowerShell host similar to PowerShell ISE. However it's cumbersome to find how to create regular PS console from managed console application.
It turns out that it could be achieved by writing 2 lines of code:
References to these assemblies are required:static void Main(string[] args){var config = RunspaceConfiguration.Create();ConsoleShell.Start(config, "Awesome Powershell Host", string.Empty, args);}
- System.Management.Automation
- Microsoft.PowerShell.ConsoleHost