I have a .Net-Core project that worked fine on 1.1 but is now failing on 2.0. The problem is happens when I try to unzip a zip archive with ZipFile.ExtractToDirectory (from System.IO.Compression). I get one or two files out but then it throws an exception with the message:
The process cannot access the file '<path to file>' because it is being used by another process.
As far as I can tell there is no other process that could possibly be using that file as it has just been extracted. It is actually present on the disk when I get the error.
The stack trace is:
at System.IO.Win32FileSystem.OpenHandle(String fullPath, Boolean asDirectory)
at System.IO.Win32FileSystem.SetLastWriteTimeInternal(String fullPath, DateTimeOffset time, Boolean asDirectory)
at System.IO.Win32FileSystem.SetLastWriteTime(String fullPath, DateTimeOffset time, Boolean asDirectory)
at System.IO.File.SetLastWriteTime(String path, DateTime lastWriteTime)
at System.IO.Compression.ZipFileExtensions.ExtractToFile(ZipArchiveEntry source, String destinationFileName, Boolean overwrite)
at System.IO.Compression.ZipFileExtensions.ExtractToDirectory(ZipArchive source, String destinationDirectoryName, Boolean overwrite)
at System.IO.Compression.ZipFile.ExtractToDirectory(String sourceArchiveFileName, String destinationDirectoryName, Encoding entryNameEncoding, Boolean overwrite)
at System.IO.Compression.ZipFile.ExtractToDirectory(String sourceArchiveFileName, String destinationDirectoryName)
at FunctionDataStore.PackageManagement.InstallPackage(String pkgFile, String pkgDir) in D:\Projects\Momo\UserPlatform\FunctionDataStore\PackageManagement.cs:line 250
I can go back to 1.1 for the time being but I need to move to 2.0.
Does anyone know what might be causing this exception and what I can do about it?
Added: 27 Nov 17
I thought I had the answer after a reboot. But now the problem remains no matter how many times I reboot the system. There is some problem with .NET Core 2.0 and System.IO.Compression.ZipFile. I have verified that no other process is actually using the extracted files when the error happens.
Addendum: 207 Nov 17
Since the stack trace shows ExtractToDirectory is failing on the SetLastWriteTime call, and I don't really care about the timestamps on the files, I replaced the ExtractToDirectory call with the following:
using (ZipArchive archive = ZipFile.Open(pkgFile, ZipArchiveMode.Read))
{
foreach (var entry in archive.Entries)
{
var filename = pkgDir + "\\" + entry.FullName;
var fileDir = Path.GetDirectoryName(filename);
Directory.CreateDirectory(fileDir);
using (BinaryWriter writer = new BinaryWriter(File.Open(filename, FileMode.Create)))
{
byte[] bytes = new byte[1024];
int numbytes;
var stream = entry.Open();
while ((numbytes = stream.Read(bytes, 0, 1024)) > 0)
{
writer.Write(bytes, 0, numbytes);
}
}
}
}
where pkgFile is the zip file to be read and pkgDir is the directory to extract to. This seems to work without problem.
I still don't know why the SetLastWriteTime is failing in ExtractToDirectory, though. But this workaround seems to be sufficient for my needs.
You can find which process is using your file to find root of error. to find which process is using your file download process explorer
run process explorer
press ctrl+f
type name of your file
this way you can find and kill process using your file
Related
I have a web site running in its own Application Pool (IIS 8). Settings for the pool are default i.e. recycle every 29 hours.
Our web server only has 8gb RAM and I have noticed that the worker process for this web site regularly climbs to 6gb RAM and slows the server to a crawl. This is the only site currently on the web server.
I also have SQL Express 2016 installed as well. The site is using EF version 6.1.3.
The MVC site is very straightforward. It has a GETPDF controller which finds a row in a table, gets PDF info stored in a field then serves it back to the browser as follows :-
using (eBillingEntities db = new eBillingEntities())
{
try
{
string id = model.id;
string emailaddress = Server.HtmlEncode(model.EmailAddress).ToLower().Trim();
eBillData ebill = db.eBillDatas.ToList<eBillData>().Where(e => e.PURL == id && e.EmailAddress.ToLower().Trim() == emailaddress).FirstOrDefault<eBillData>();
if (ebill != null)
{
// update the 'Lastdownloaded' field.
ebill.LastDownloaded = DateTime.Now;
db.eBillDatas.Attach(ebill);
var entry = db.Entry(ebill);
entry.Property(en => en.LastDownloaded).IsModified = true;
db.SaveChanges();
// Find out from the config record whether the bill is stored in the table or in the local pdf folder.
//
Config cfg = db.Configs.ToList<Config>().Where(c => c.Account == ebill.Account).FirstOrDefault<Config>();
bool storePDFDataInEBillTable = true;
if (cfg != null)
{
storePDFDataInEBillTable = cfg.StorePDFDataInEBillDataTable;
}
// End of Modification
byte[] file;
if (storePDFDataInEBillTable)
{
file = ebill.PDFData;
}
else
{
string pathToFile = "";
if (string.IsNullOrEmpty(cfg.LocalPDFDataFolder))
pathToFile = cfg.LocalBackupFolder;
else
pathToFile = cfg.LocalPDFDataFolder;
if (!pathToFile.EndsWith(#"\"))
pathToFile += #"\";
pathToFile += ebill.PDFFileName;
file = System.IO.File.ReadAllBytes(pathToFile);
}
MemoryStream output = new MemoryStream();
output.Write(file, 0, file.Length);
output.Position = 0;
HttpContext.Response.AddHeader("content-disposition", "attachment; filename=ebill.pdf");
return new FileStreamResult(output, "application/pdf");
}
else
return View("PDFNotFound");
}
catch
{
return View("PDFNotFound");
}
Are there any memory leaks here?
Will the file byte array and the memory stream get freed up?
Also, is there anything else I need to do concerning clearing up the entity framework references?
If the code looks OK, where would be a good place to start looking?
Regards
Are there any memory leaks here?
No.
Will the file byte array and the memory stream get freed up?
Eventually, yes. But that may be the cause of your excessive memory use.
Also, is there anything else I need to do concerning clearing up the entity framework references?
No.
If the code looks OK, where would be a good place to start looking?
If this code is the cause of your high memory use, it's because you are loading files into memory. And you're loading two copies of each file in memory, once in a byte[] and copying to a MemoryStream.
There's no need to do that.
To eliminate the second copy of the file use the MemoryStream(byte[]) constructor instead of copying the bytes from the byte[] to an empty MemoryStream.
To eliminate the first copy in memory, you can stream the data into a temporary file that will be the target of your FileStreamResult, or initialize the FileStreamResult using a ADO.NET stream.
See https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sqlclient-streaming-support
If you go to ADO.NET streaming your DbContext, will need to be scoped to your Controller, instead of a local variable, which is a good practice in any case.
In addition to David's advice. I noticed that I was doing the following
**db.eBillDatas.ToList<eBillData>()**
therefore I was getting all the data from the database then fetching it again with the where clause.
I didn't notice the problem until the database started to fill up.
I removed that part and now the IIS worker processing is about 100mb.
I'm trying to run a ScanContent processor on Apache Nifi, and whilst I can get the processor to run when scanning a text file, and using a .txt dictionary file with the search terms contained in it (and delimited by a newline character), I cannot get it to run when searching a file using the binary type of the processor for the dictionary file.
I am unsure whether I am simply using the wrong format for the binary dictionary file, or whether it needs to be encoded differently. I couldnt find any example dictionaries anywhere online that would be of any use (most things were related to the ScanAttributes instead).
The format of my dictionary file is:
(inside a .txt file)
32 00001001001000010000100001000000\n
The requirements according to the documentation are that the dictionary terms need to be a 4 byte integer, followed by the binary search term.
Does anyone have any experience of using this processor with a binary dictionary that might be able to help specify the format?
A binary dictionary file would typically be generated as the output of another program. There is an example in the ScanContent unit tests for how to accomplish this in Java:
#Test
public void testBinaryScan() throws IOException {
// Create dictionary file.
final String[] terms = new String[]{"hello", "good-bye"};
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (final DataOutputStream dictionaryOut = new DataOutputStream(baos);) {
for (final String term : terms) {
final byte[] termBytes = term.getBytes("UTF-8");
dictionaryOut.writeInt(termBytes.length);
dictionaryOut.write(termBytes);
}
final byte[] termBytes = baos.toByteArray();
final Path dictionaryPath = Paths.get("target/dictionary");
Files.write(dictionaryPath, termBytes, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
...
I want to change Virtual Path(The path is out of project means local system or Server.) of the file Which is save on the folder in asp.net.
Code is
DataTable dtFiles =
GetFilesInDirectory(HttpContext.Current.Server.MapPath(UPLOADFOLDER));
gv.DataSource = dtFiles;
gv.DataBind();
if (dtFiles != null && dtFiles.Rows.Count > 0)
{
double totalSize = Convert.ToDouble(dtFiles.Compute("SUM(Size)", ""));
if (totalSize > 0) lblTotalSize.Text = CalculateFileSize(totalSize);
}
private static string UPLOADFOLDER = "D:/Uploads";
And the error show "D:/Uploads is not a valid virtual path.".
If you want to get the files in a directory and you know the full path, then you don't need to use Server.MapPath(). Just use the path.
Incidentally, the path delimiter is incorrect in your code. The string "D:/Uploads" should be #"D:\Uploads" (note the leading # sign to denote a string that should be treated literally and not escaped).
Of course. You're telling your server to map path that is completely off the IIS. How is it supposed to do? If you're using a web application, try to avoid such ideas completely. Even though it is possible, it isn't a good idea because of security issues you can run into.
I am using SQLite for Windows Phone 7 (http://sqlitewindowsphone.codeplex.com/) and I have done every steps from this tutorial (http://dotnetslackers.com/articles/silverlight/Windows-Phone-7-Native-Database-Programming-via-Sqlite-Client-for-Windows-Phone.aspx)
Then I try to make some simple application with basic features like select and delete. App is working properly till I want to make one of this operations. After I click select or delete, compiler shows me errors that he is unable to open database file...
I have no idea why?
I used the same Sqlite client, and had the same problem. This problem occurs because the sqlite try to create file in IsolatedFileStorage "DatabaseName.sqlite-journal" and it does not have enough permissions for that. I solved the problem, so that created "DatabaseName.sqlite-journal" before copying database to IsolatedFileStorage. Here's my method that did it:
private void CopyFromContentToStorage(String assemblyName, String dbName)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
string uri = dbName + "-journal";
store.CreateFile(uri);
using (Stream input = Application.GetResourceStream(new Uri("/" + assemblyName + ";component/" + dbName,UriKind.Relative)).Stream)
{
IsolatedStorageFileStream dest = new IsolatedStorageFileStream(dbName, FileMode.OpenOrCreate, FileAccess.Write, store);
input.Position = 0;
CopyStream(input, dest);
dest.Flush();
dest.Close();
dest.Dispose();
}
}
it helped me, and worked well.
hope this will help you
Are you sure the file exists?
You can check like that:
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
exists = store.FileExists(DbfileName);
}
I have a text file inside the assembly say MyAssembly. I am trying to access that text file from the code like this :
Stream stream = Assembly.GetAssembly(typeof(MyClass)).GetFile("data");
where data is data.txt file containing some data and I have added that .txt as Embedded Resources. I have dome reading of the images from the Assebly as embedded resources with code like this :
protected Stream GetLogoImageStream()
{
Assembly current = Assembly.GetExecutingAssembly();
string imageFileNameFormat = "{0}.{1}";
string imageName = "myLogo.GIF";
string assemblyName = current.ManifestModule.Name;
int extensionIndex = assemblyName.LastIndexOf(".dll", StringComparison.CurrentCultureIgnoreCase);
string file = string.Format(imageFileNameFormat, assemblyName.Remove(extensionIndex, 4), imageName);
Stream thisImageStream = current.GetManifestResourceStream(file);
return thisImageStream;
}
However, this approach did not work while reading the .txt file from an the executing assembly. I would really appreciate if anybody can point me to the approach to read .txt file from an assembly. Please dont ask me why I am not reading the file from the drive or the network share. Just say that the requirement is to read the .txt file from the Assembly.
Thank you so much
GetManifestResourceStream is indeed the correct way to read the data. However, when it returns null, that usually means you have specified the wrong name. Specifying the correct name is not as simple as it seems. The rules are:
The VB.NET compiler generates a resource name of <root namespace>.<physical filename>.
The C# compiler generates a resource name of <default namespace>.<folder location>.<physical filename>, where <folder location> is the relative folder path of the file within the project, using dots as path separators.
You can call the Assembly.GetManifestResourceNames method in the debugger to check the actual names generated by the compiler.
Your approach should work. GetManifestResourceStream returns null, if the resource is not found. Try checking the run-time value of your file variable with the actual name of the resource stored in the assembly (you could check it using Reflector).
I really appreciate for everybody's help on this question. I was able to read the file with the code like this :
Assembly a = Assembly.GetExecutingAssembly();
string[] nameList = a.GetManifestResourceNames();
string manifestanme = string.Empty;
if (nameList != null && nameList.Length > 0)
{
foreach (string name in nameList)
{
if (name.IndexOf("c.txt") != -1)
{
manifestanme = name;
break;
}
}
}
Stream stream = a.GetManifestResourceStream(manifestanme);
Thanks and +1 for Christian Hayter for this method : a.GetManifestResourceNames();