File.Create from IIS locking the created File - asp.net

I have an ASP.NET running in IIS 7.5 that creates files on the local file system and then attempts to delete after performing some logic in between creation and deletion. I'm running into a situation though where deletion is failing with a response such as "The process cannot access the file 'C:...\Uploads\c1fe593f-85de-4de1-b5d1-7239e1fc0648_Tulips.jpg' because it is being used by another process.'" The file appears to be locked by IIS and I can't delete it. Here's an example of the code for creating and deleteing:
// File.WriteAllBytes(path, rawData); // this seems to leave the file open!
using (var file = File.Create(path))
{
file.Write(rawData, 0, rawData.Length);
file.Close(); // should close when it goes out of scope, but just to be safe
}
Is there some special option I need to pass into File.Create? How do I get around this?

File.WriteAllBytes(path, rawData); should work fine assuming the path parameter you are passing is unique and that you don't have concurrent requests one writing and other trying to read at the same time. To ensure this you could use a ReaderWriterLockSlim to synchronize the access if this situation could potentially occur. Also make sure that there are no other parts of the code that might leak the file handle.
Take a look at SysInternals Process Explorer which could allow you to know exactly where this file handle is leaked.

Related

Server.MapPath and running a command line utility from an ASP.NET application

I need to run an executable from an ASP.NET app using Process. The .exe file is located inside the ASP.NET project - 'ProjectRoot/Utilities/utility.exe'
Why does this code fail to run it:
string path = Server.MapPath("/Utilities/");
string args = " etc etc";
Process p = Process.Start(new ProcessStartInfo(path + "utility.exe", args));
p.WaitForExit(3000);
I've tried "\\utility.exe" too.
The answer depends on the type of the occuring exception. By the way, if the identity of application pool (which is the equal position to the process in a windows app) is set to a limited user (as it is by default) you can not execute a process on the server because of security issues.
If you know about the consequences and the server is your own, you can change the identity of the application pool to an authorized user, then your application can do such a thing without any hesitation.
Cheers
There's a few things to check here.
The first thing is to ensure that string path = Server.MapPath("/Utilities/"); is a valid path and that utility.exe is in the correct location.
You said that it does not throw an exception, so the invocation of utility.exe should at least be valid. However, utility.exe may swallow any exceptions it in turn encounters (depends on how it was coded), which may be why it does not appear to be working.
On top of that, your args variable may be specifying a file or some other resource that utility.exe accesses. If it does swallow exceptions, it could be masking a permissions error if the application pool identity does not have access to the resouce.

QLocalSocket::connectToServer failed with QLocalSocket::SocketAccessError if server is running with administrative privileges (Windows 7)

Following problem occurs in Microsoft Windows 7 Implementation of Qt 4.8.1:
A QLocalServer (named pipe) is waiting for clients to connect, and it is running as an server application that runs with administrative privileges (system service for example).
How is it possible to allow an non privileged QLocalSocket client to connect to that server? Connection attempts are always denied with error code 3 (QLocalSocket::SocketAccessError). Is there a solution?
Edit: As I found out, the solution is to change pipe security by allowing full access to "Everyone" Sid. The only problem here is, that a call to SetSecurityInfo always fails with "access denied" error.
First we have to obtain a pipe handle. Since the pipe is already created by Qt, we will open it with CreateNamedPipe.
HANDLE hPipe = CreateNamedPipe(
(const wchar_t *)_Server->fullServerName().utf16(), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_BYTE | // byte type pipe
PIPE_READMODE_BYTE | // byte-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
0, // output buffer size
0, // input buffer size
3000, // client time-out
0 // Default Security
);
// Same call to open/create pipe as in qlocalserver_win.cpp
// Code here to add/change ACEs
if (SetSecurityInfo(hPipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
0, 0, NewAcl, 0) == ERROR_SUCCESS) {
// Success
}
Even if NewAcl is set to NULL the call fails. So what could cause that "access denied" error?
I know, it's a little to late now, but this may help other people with the same Problem. Please notice this solution only works, if the server is your application to.
If thats the case, simply call server.setSocketOptions(QLocalServer::WorldAccessOption); or one of the other values of QLocalServer::​SocketOption before you call listen.
I am not familiar with Qt and so don't know what security characteristics are created by default when you use QtLocalServer in this way. However, in general there are two distinct mechanisms which could be causing the "Access denied" error.
The first is the DACL (Discretionary Access Control List) associated with the pipe. This works the same way as DACLs on any securable object in Windows (c.f. file security). There has to be an access control entry (ACE) in the list which grants your client user the desired type of access to the pipe. As you correctly indicate, adding an ACE for the "EVERYONE" SID allowing read/write access would remove any DACL barrier confronting your client. However, note that the code which amends the DACL will have to have WRITE_DAC access to the pipe already, otherwise it will be unable to open a handle through which the DACL can be amended. Your code doesn't even request WRITE_DAC access in the call to CreateNamedPipe, so this is a further reason why your call to SetSecurityInfo is failing.
The second mechanism is the Mandatory Integrity Control mechanism introduced in Windows Vista and later versions. It is not clear from your description whether this is in play here, but in general a client process can never have write access to a securable resource which is associated with a lower integrity level than that of the resource. If that is the issue here (and since your title refers specifically to Windows 7, I guess it might be) the only solution is to change the Mandatory Integrity Label on the pipe to lower the pipe's integrity level to that of your client. To do that you need to have access to the first pipe handle opened by the server (this Q&A explains why) because the integrity label is a special ACE contained in the System Access Control List (SACL) of the pipe, which you need WRITE_OWNER premission to change. Whether it is at all feasible in Qt to get hold of this pipe handle is something I have no knowledge of.
I found a solution for the Qt problem. Since one can not use the handle created by CreateNamedPipe after calling QLocalServer::listen(), we can call CreateNamedPipe before Qt is doing it. If we call it with WRITE_DAC | FILE_FLAG_FIRST_PIPE_INSTANCE we can change anything.
Then we can change security settings as stated by Chris Dickson.

Adobe AIR HTTP Connection Limit

I'm working on an Adobe AIR application which can upload files to a web server, which is running Apache and PHP. Several files can be uploaded at the same time and the application also calls the web server for various API requests.
The problem I'm having is that if I start two file uploads, while they are in progress any other HTTP requests will time out, which is causing a problem for the application and from a user point of view.
Are Adobe AIR applications limited to 2 HTTP connections, or is something else probably the issue?
From searching about this issue I've not found much but one article did indicated that it wasn't limited to just two connections.
The file uploads are performed by calling the File classes upload method, and the API calls are done using the HTTPService class. The development web server I am using is a WAMP server, however when the application is released it will be talking to a LAMP server.
Thanks,
Grant
Here is the code I'm using to upload the file:
protected function btnAddFile_clickHandler(event:MouseEvent):void
{
// Create a new File object and display the browse file dialog
var uploadFile:File = new File();
uploadFile.browseForOpen("Select File to Upload");
uploadFile.addEventListener(Event.SELECT, uploadFile_SelectedHandler);
}
private function uploadFile_SelectedHandler(event:Event):void
{
// Get the File object which was used to select the file
var uploadFile:File = event.target as File;
uploadFile.addEventListener(ProgressEvent.PROGRESS, file_progressHandler);
uploadFile.addEventListener(IOErrorEvent.IO_ERROR, file_ioErrorHandler);
uploadFile.addEventListener(Event.COMPLETE, file_completeHandler);
// Create the request URL based on the download URL
var requestURL:URLRequest = new URLRequest(AppEnvironment.instance.serverHostname + "upload.php");
requestURL.method = URLRequestMethod.POST;
// Set the post parameters
var params:URLVariables = new URLVariables();
params.name = "filename.ext";
requestURL.data = params;
// Start uploading the file to the server
uploadFile.upload(requestURL, "file");
}
Here is the code for the API calls:
private function sendHTTPPost(apiFile:String, postParams:Object, resultCallback:Function, initialCallerResultCallback:Function):void
{
var httpService:mx.rpc.http.HTTPService = new mx.rpc.http.HTTPService();
httpService.url = AppEnvironment.instance.serverHostname + apiFile;
httpService.method = "POST";
httpService.requestTimeout = 10;
httpService.resultFormat = HTTPService.RESULT_FORMAT_TEXT;
httpService.addEventListener("result", resultCallback);
httpService.addEventListener("fault", httpFault);
var token:AsyncToken = httpService.send(postParams);
// Add the initial caller's result callback function to the token
token.initialCallerResultCallback = initialCallerResultCallback;
}
If you are on a windows system, Adobe AIR is using Microsofts WinINet library to access the web. This library by default limits the number of concurrent connections to a single server to 2:
WinInet limits the number of simultaneous connections that it makes to a single HTTP server. If you exceed this limit, the requests block until one of the current connections has completed. This is by design and is in agreement with the HTTP specification and industry standards.
... Connections to a single HTTP 1.1 server are limited to two simultaneous connections
There is an API to change the value of this limit but I don't know if it is accessible from AIR.
Since this limit also affects page loading speed for web sites, some sites are using multiple DNS names for artifacts such as images, javascripts and stylesheets to allow a browser to open more parallel connections.
So if you are controlling the server part, a workaround could be to create DNS aliases like www.example.com for uploads and api.example.com for API requests.
So as I was looking into this, I came across this info about using File.upload() in the documentation:
Starts the upload of the file to a remote server. Although Flash Player has no restriction on the size of files you can upload or download, the player officially supports uploads or downloads of up to 100 MB. You must call the FileReference.browse() or FileReferenceList.browse() method before you call this method.
Listeners receive events to indicate the progress, success, or failure of the upload. Although you can use the FileReferenceList object to let users select multiple files for upload, you must upload the files one by one; to do so, iterate through the FileReferenceList.fileList array of FileReference objects.
The FileReference.upload() and FileReference.download() functions are
nonblocking. These functions return after they are called, before the
file transmission is complete. In addition, if the FileReference
object goes out of scope, any upload or download that is not yet
completed on that object is canceled upon leaving the scope. Be sure
that your FileReference object remains in scope for as long as the
upload or download is expected to continue.
I wonder if something there could be giving you issues with uploading multiple files. I see that you are using browserForOpen() instead of browse(). It seems like the probably do the same thing... but maybe not.
I also saw this in the File class documentation
Note that because of new functionality added to the Flash Player, when publishing to Flash Player 10, you can have only one of the following operations active at one time: FileReference.browse(), FileReference.upload(), FileReference.download(), FileReference.load(), FileReference.save(). Otherwise, Flash Player throws a runtime error (code 2174). Use FileReference.cancel() to stop an operation in progress. This restriction applies only to Flash Player 10. Previous versions of Flash Player are unaffected by this restriction on simultaneous multiple operations.
When you say that you let users upload multiple files, do you mean subsequent calls to browse() and upload() or do you mean one call that includes multiple files? It seems that if you are trying to do multiple separate calls that that may be an issue.
Anyway, I don't know if this is much help. It definitely seems that what you are trying to do should be possible. I can only guess that what is going wrong is perhaps a problem with implementation. Good luck :)
Reference: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#upload()
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/FileReference.html#browse()
Just because I was thinking about a very similar question because of an error in one of my actual apps, I decided to write down the answer I found.
I instantiated 11
HttpConnections
and was wondering why my Flex 4 Application stopped working and threw an HTTP-Error although it was working pretty good formerly with just 5 simultanious HttpConnections to the same server.
I tested this myself because I did not find anything regarding this in the Flex docs or on the internet.
I found that using more than 5 HTTPConnections was the reason for the Flex application to throw the runtime error.
I decided to instantiate the connections one after another as a temporally workaround: Load the next one after the other has received the data and so on.
Thats of course just temporally since one of the next steps will be to alter the responding server code in that way that it answers a request that contains the results of requests to more then one table in one respond. Of course the client application logic needs to be altered, too.

Replacing SQLite database while accessing it

I am completely new to SQLite and I intend to use it in a M2M / client-server environment where a database is generated on the server, sent to the client as a file and used on the client for data lookup.
The question is: can I replace the whole database file while the client is using it at the same time?
The question may sound silly but the client is a Linux thin client and to replace the database file a temporary file would be renamed to the final file name. In Linux, a program which has still open the older version of the file will still access the older data since the old file is preserved by the OS until all file handles have been closed. Only new open()s will access the new version of the file.
So, in short:
client randomly accesses the SQLite database
a new version of the database is received from the server and written to a temporary file
the temporary file is renamed to the SQLite database file
I know it is a very specific question, but maybe someone can tell me if this would be a problem for SQLite or if there are similar methods to replace a database while the client is running. I do not want to send a bunch of SQL statements from the server to the client to update the database.
No, you cannot just replace an open SQLite3 DB file. SQLite will keep using the same file descriptor (or handle in Windows-speak), unless you close and re-open your database. More specifically:
Deleting and replacing an open file is either useless (Linux) or impossible (Windows). SQLite will never get to see the contents of the new file at all.
Overwriting an SQLite3 DB file is a recipe for data corruption. From the SQLite3 documentation:
Likewise, if a rogue process opens a
database file or journal and writes
malformed data into the middle of it,
then the database will become corrupt.
Arbitrarily overwriting the contents of the DB file can cause a whole pile of issues:
If you are very lucky it will just cause DB errors, forcing you to reopen the database anyway.
Depending on how you use the data, your application might just crash and burn.
Your application may try to apply an existing journal on the new file. Sounds painful? It is!
If you are really unlucky, the user will just get back invalid results from any queries.
The best way to deal with this would be a proper client-server implementation where the client DB file is updated from data coming from the server. In the long run that would allow for far more flexibility, while also reducing the bandwidth requirements by sending updates, rather than the whole file.
If that is not possible, you should update the client DB file in three discrete steps:
Send a message to the client application to close the DB. This allows the application to commit any changes, remove any journal files and clean-up its internal state.
Replace/Overwrite the file.
Send a message to the client application to re-open the DB. You would have to setup all prepared statements again, though.
If you do not want to close the DB file for some reason, then you should have your application - or even a separate process - update the original DB file using the new file as input. The SQLite3 backup API might be of interest to you in that case.

Return values from exe in javascript

i have to call an executable in the client machine in asp.net and get the return parameters, i been looking for an example but i couldn't find it.
it this possible to recover the output parameters from one exe in JavaScript?
i know that can i write:
var WshShell = new ActiveXObject("WScript.Shell");
var oExec = WshShell.Exec("My.exe");
but the clients executable returns 0 or 1 that values are the ones i need to collect
Thanks in advance
Browser-based JavaScript can't call executable files on client machines; to do so would be a catastrophic security problem. If you have to run an executable on the client machine, consider asking the user to install a .NET application, an ActiveX control, or something like Java if you want to be platform-independent.
Depending on what you're trying to do, you may not need to run an EXE on the client machine; you can do a LOT with standard cloud-type scenarios (JS or SilverLight on the client, Web services or WCF on the server). Without more information about your situation, however, it's impossible to tell.
EDIT: Based on your comments that you're using the ActiveXObject.Exec method, you can use the StdOut property of the WshScriptExec object that method returns. From MSDN's article on the StdOut property:
if (!oExec.StdOut.AtEndOfStream)
{
input += oExec.StdOut.Read(1);
//...
}

Resources