I'm trying to run a command-line process (which is extraction of a .7z archive) on a file that lies in a temporary folder on the windows user temp directory
(C:\Documents and Settings\User\Local Settings\Temp), using Process in my c# app.
I think the process return error that happens because of "access denied" because I can see a win32Exception with error code 5 when I dig in the prcoess object of .NET.
doing the same on some other location worked fine before, so I guess maybe it's something I'm not supposed to do ? (running a process to use a file on the the %TEMP%)
perhaps I need to pass security somehow?
Assuming that you are using regular .NET (not CF/Silverlight, etc) Accessing files in the user's temp area is entirely expected. I wonder if the problem isn't more that you've accidentally left the file open after creating it, perhaps by not using a "using" or similar?
I probably wouldn't suggest using environment variables (%TEMP% etc) when shelling out to a separate process; ideally you'd pass the full path to the file (less things to get wrong...), making sure to quote any path arguments (in case of space) - i.e. so your args are #"... ""c:\some path\whatever\tmp""..." (if you see what I mean).
Finally, if you are extracting files, you need to think about the existing contents. Path.GetTempFileName() is fine for creating a single file place-holder, but for extracting an archive you probably want to create a directory - guids are handy for this purpoes (while avioding conflicts, and remember to remove it afterwards):
string dir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
running the same process using command-line (cmd) helped to figure out my problem was that I specified path arguments to the process using long-path-name.
Solution to this can be found here:
standard way to convert to short path in .net
Related
I have a program that tracks changes on a local folder using a FileSystemWatcher object.
The issue is that sometimes, on some environments and situations (I do not know which ones), this watcher gives me an event on a DOS path ("/Hello/How/Are/You" becomes something like "/HE~1/HO~1/AR~1/YO~1").
What I am looking for is a way to force this path back into its full and normal aspect.
Or at least something that can tell me that the path is indeed a DOS path, so I can process the entry differently.
EDIT: it has to work on long paths (+260 chars), so Path.GetFullPath(sShortPath) does not work for me here!
Path.GetFullPath(#"/HE~1/HO~1/AR~1/YO~1") should do what you need.
The best method depends what you are looking for, if you just want to access the file once then the 8byte file names will work for internal file references
if you want to display to the user or store then there are 2 option
Path contains most of the tools you need to manipulate paths
fullPath = Path.GetFullPath(path1);
FileInfo and DirectoryInfo these 2 classes provide persistent access to files and directory information and while they can be created with any valid path both have a Full name property that provides access to the full path
As others said, Path.GetFullPath(sShortPath) works fine if not used on very long paths (+260 chars).
Here is a link I followed that worked for me.
GetLongPathName from kernel32.dll worked fine with me, I just had to change the 255 StringBuilder limit to a higher value to make it work with long paths.
I have many .exe files stored on IIS server (MSSQL) that contain reports and access to the file(s) on the servers . (These files will be change on Sundays .)
After connecting to the SQL Server and choosing an .exe file , I am Downloading(Select in SQL) , Now I have an array of bytes that assigned to a variable .
I cant creating a temporary file like "temp.exe" in an unknown directory because I know there are many ways to understand a new created file directory and ...
It is not secure because my users are professional and if one of them know these ways ...
So , I want know is it possible to run an .exe file from an array of bytes (as default as running from "Windows Explorer") without creating a temporay file ?!
tnx
update : Exe files are .net and Manager will be upload new files or change files .
Be warned that your belief of any extra security is illusory. If the user has access to the machine to read files, they will also be able to read the memory of your process.
However, to answer your question, what you are asking to do is simple enough and described here: Load an EXE File and Run It from Memory.
In essence you do the following:
Pass your byte array to Assembly.Load to create a new Assembly.
Read the entry point of that assembly using the EntryPoint property.
Create an instance using Assembly.CreateInstance, and invoke the method on that instance.
The code looks like this:
Assembly a = Assembly.Load(bytes);
MethodInfo method = a.EntryPoint;
if (method != null)
method.Invoke(a.CreateInstance(method.Name), null);
Doesn't sound safe either way, why are you storing exécutables in a db to begin with? Who uploads them? Wether they're on the filesystem or not they're just as dangerous if malicious.
Are those .net exes? If so you could load the assembly into a child appdomain with security restrictions and i'm pretty sure you can do that without copying to disk.
For regular native exe i don't think it's possible to just launch an exe without a physical file backing it (even in the task manager you can see the path from which a program was launched)
There are two different concerns for security here:
That someone can see the file that you've downloaded from the database.
That executing the file might be a security threat.
For the first concern: Create a directory on the server and restrict access to that directory so that no one but the user account that runs your server program can see/use it. Save the byte array into a temporary file in that directory, execute it, and once the process has completed, delete the temporary file.
For the second concern: You'll need to run that executable in a sandboxed environment. In .NET you can run code in a sandboxed environment by loading the code into a separate AppDomain that you've setup to only have partial trust. How to do that deserves another question on SO though.
I am using WritePrivateProfileString in c# (through DllImport) to store paths taken from textboxes on the interface. And the .ini file name is hardcoded in my application
string ini_file = ".\\config.ini";
However, when the file writing happens, the configuration file is written to the first path taken from the interface instead of writing it to the exe directory. Which is quite odd.
Debugging shows that the values are sent correctly to the WritePrivateProfileString but it still is written to the wrong location. Anyone knows why is that happenening?
I'd guess that something is changing the working directory of your process, most likely your code in the process. Note that the documentation has this to say:
If the lpFileName parameter does not contain a full path and file name for the file, WritePrivateProfileString searches the Windows directory for the file. If the file does not exist, this function creates the file in the Windows directory.
Now my guess is that this applies if you supply just a file name. Because your file name starts with . I believe that will force the function to start from the current working directory.
Having said all of that, and no matter what the cause of the problem is, you should use a fully-qualified path in order to make sure the file is written where you want it to be written. Whenever you want the file to go in a specific directory, it's always easiest to force that by using fully-qualified paths.
You can find the path to your executable using Application.ExecutablePath and then remove the file name part.
Another point to make is that the same directory as the executable may be a bad choice. If your program is installed under the Program Files directory then the directory which contains the executable will not be generally writeable. I think you should consider using a directory under in the user profile. Look for one of the Environment.SpecialFolder values.
Further to David Heffernan's answer - you can use
Path.GetDirectoryName(Application.ExecutablePath);
to safely get just the running application's folder part.
If you're in a dll rather than an executable, you can use
Path.GetDirectoryName(Assembly.GetAssembly(typeof(MyClass)).CodeBase);
Both require System.IO, and were originally posted here. Second example also requires System.Reflection).
Application data files are supposed to be written to the LocalApplicationData special folder.
string path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
You typically will not have permissions to write into the Program Files folder etc.
I have read a similar post, but i just cant figure out the problem.
I have changed the windows permissions and changed routes.
When i try to save a file it throws me the exception:
Access to the path **** denied.
string route="D:\\";
FileStream fs = new FileStream(route, FileMode.Create); <--here is the problem
StreamWriter write = new StreamWriter(fs);
patient person = new patient();
patient.name = textBox1.Text;
patient.name2 = textBox2.Text;
You are trying to create a FileStream object for a directory (folder). Specify a file name (e.g. #"D:\test.txt") and the error will go away.
By the way, I would suggest that you use the StreamWriter constructor that takes an Encoding as its second parameter, because otherwise you might be in for an unpleasant surprise when trying to read the saved file later (using StreamReader).
Did you try specifing some file name?
eg:
string route="D:\\somefilename.txt";
tl;dr version: Make sure you are not trying to open a file marked in the file system as Read-Only in Read/Write mode.
I have come across this error in my travels trying to read in an XML file.
I have found that in some circumstances (detailed below) this error would be generated for a file even though the path and file name are correct.
File details:
The path and file name are valid, the file exists
Both the service account and the logged in user have Full Control permissions to the file and the full path
The file is marked as Read-Only
It is running on Windows Server 2008 R2
The path to the file was using local drive letters, not UNC path
When trying to read the file programmatically, the following behavior was observed while running the exact same code:
When running as the logged in user, the file is read with no error
When running as the service account, trying to read the file generates the Access Is Denied error with no details
In order to fix this, I had to change the method call from the default (Opening as RW) to opening the file as RO. Once I made that one change, it stopped throwing an error.
I had this issue for longer than I would like to admit.
I simply just needed to run VS as an administrator, rookie mistake on my part...
Hope this helps someone <3
If your problem persist with all those answers, try to change the file attribute to:
File.SetAttributes(yourfile, FileAttributes.Normal);
You do not have permissions to access the file.
Please be sure whether you can access the file in that drive.
string route= #"E:\Sample.text";
FileStream fs = new FileStream(route, FileMode.Create);
You have to provide the file name to create.
Please try this, now you can create.
TLDR : On my end, it had something to do with AVAST ! => Whitelist your application.
All of a sudden, I also got this UnauthorizedAccessException problem in the windows WPF program I'm writing. None of the solutions worked - except I couldn't figure out how to elevate my application to full privileges (not using VS) while at the same time, being already on the administrator account, I didn't feel the need to dig that deep in permission concerns.
The files are image files (jpg, psd, webp, etc.) I wasn't trying to open/write a directory, it has always been a valid path to a file, and I needed to write to the file, FileAccess.ReadWrite was inevitable. The files (and any of their parent directory) were not readonly (I even checked by code prior calling new FileStream(path, mode, access, share) via FileInfo.IsReadOnly) - so what happenned all of a sudden ???
Thinking about : I had an had drive crash, so I unpacked a backup of my solution code from another drive. In the meantime, I added codes in my application to PInvoke APIs to directly read hard drive sectors physical bytes as well as USB plug/unplug monitoring.
I started to get the Exception when I added those, but even though I temporarly removed the related codes from the application, I still got the UnauthorizedAccessException.
Then I remembered one thing I've done long ago, a painstaking similar issue where I wanted my application to communicate sensible data via Wifi, which was to add the executable among AVAST exceptions, and the assembly directory aswell (My app was already among the authorized apps through firewall)
Just did it for my application in AVAST settings, AND THE EXCEPTION IS GONE !!! Two whole days I'm lurking StackOverflow and the web to get moving on, FINALLY !
Details : I can't pinpoint exactly what AVAST didn't like in my application as the only changes I made :
Retrieved then launched the backup code - it worked like a charm, files (images) opens/write without problems (3 days ago)
Added USB detection (3 days ago - Just tested the code, didn't tried to open an image)
Added PInvoke physical drive direct read (2 days ago - FileStream, and the logic to define where/how to scan the damaged drive - Just tested the code, didn't tried to open an image)
Added image format detection starting from Jpg/Jfif.. 2 days ago, got the exception upon testing the code.
While searching for solutions, added an Image Gallery WPF UserControl to diplay pictures based on their signature and check which files gives the exception : almost all of them (some files opens/write okay - why ???)
Tried everything I've found on SO (since the last 2 days) until I opened AVAST settings and whitelist my application.
... now I can move on into adding a bunch of file signatures to retrieve as many datas as I could.
If this may help those who like me, aren't failing on the "I'm passing a directory path instead that of a file", yet, have no time to learn exactly why antiviruses think our own code is a malware.
Just Using the below worked for me on OSX.
var path = "TempForTest";
I have a problem calling a batch file from another batch file when trying to run everything by using Process.Start. Basically I call the execution of a batch file from my c# program that looks like this:
call include.bat
//execute the rest of the batch file here
The include.bat file sets up paths and can be used by a number of other batch files. When I run the Process.Start sometimes this works and sometimes I get ERROR: cannot find include.bat. First of all any idea why this happens? And ideas on how to fix this from the batch file?
To switch to the directory your batch file is located in, use this:
cd %~dp0
I do this in almost all of my batch scripts. That way relative paths should always work.
I know this is an old question but I thought it would be worth noting that the approach promoted by the accepted answer (i.e. changing the working directory) may not always be appropriate.
A better general approach is to refer to dependencies by full path:
call "%~dp0include.bat"
(Since %~dp0 already ends with a backslash, we don't need to add another one.)
Here are some benefits of not changing the working directory:
The rest of the batch file can still use the original working directory.
The original working directory in the command prompt is preserved, even without "SETLOCAL".
If the first batch file is run via a UNC path (such as "\\server\share\file.bat"), the full-path call will succeed while changing the directory (even with "cd /d") will fail. (Using pushd/popd would handle this point, but they have their own set of problems.)
These benefits are particularly important for alias-type batch files, even if they are not as important for the specific situation that motivated this question.
Before the script, try CD /D %~dp0
First thing I'd try is to use full path information in the call statement for include.bat. If that fixes it, you probably are just not running the batch file from the proper location. I'm sure there's a "working directory" capability in C#, I'm just not sure what it is.
Do you set ProcessStartInfo.WorkingDirectory ( http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.workingdirectory.aspx ) on the ProcessStartInfo that you pass to Process.Start?
Since include.bat sometimes cannot be found, working directory may be wrong (not the folder where include.bat is located).