I am storing attachments in my applications.
These gets stored in SQL as varbinary types.
I then read them into byte[] object.
I now need to open these files but dont want to first write the files to disk and then open using Process.Start().
I would like to open using inmemory streams. Is there a way to to this in .net. Please note these files can be of any type
You can write all bytes to file without using Streams:
System.IO.File.WriteAllBytes(path, bytes);
And then just use
Process.Start(path);
Trying to open file from memory isn't worth the result. Really, you don't want to do it.
MemoryStream has a constructor that takes a Byte array.
So:
var bytes = GetBytesFromDatabase(); // assuming you can do that yourself
var stream = new MemoryStream(bytes);
// use the stream just like a FileStream
That should pretty much do the trick.
Edit: Aw, crap, I totally missed the Process.Start part. I'm rewriting...
Edit 2:
You cannot do what you want to do. You must execute a process from a file. You'll have to write to disk; alternatively, the answer to this question has a very complex suggestion that might work, but would probably not be worth the effort.
MemoryMappedFile?
http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx
My only issue with this was that I will have to make sure the user has write access to the path where I will place the file...
You should be able to guarantee that the return of Path.GetTempFileName is something to which your user has access.
...and also am not sure how I will detect that the user has closed the file so I can delete the file from disk.
If you start the process with Process.Start(...), shouldn't you be able to monitor for when the process terminates?
If you absolutely don't want to write to disk yourself you can implement local HTTP server and serve attachemnts over HTTP (like http://localhost:3456/myrecord123/attachment1234.pdf).
Also I'm not sure if you get enough benefits doing such non-trivial work. You'll open files from local security zone that is slightly better then opening from disk... and no need to write to disk yourself. And you'll likely get somewhat reasonable warning if you have .exe file as attachment.
On tracking "process done with the attachment" you more or less out of luck: only in some cases the process that started openeing the file is the one that is actually using it. I.e. Office applications are usually one-instance applications, and as result document will be open in first instance of the application, not the one you've started.
Related
I want to lock a file ( lets use a image for example ). So I have this image "myImage.jpg" and I want it to only be accessible by using my application, such as my own image visualizer. The problem is that i dont know how to do it. Someone have suggested me to alter its extension ( myImage.jpg to myImage.whatever ). But someone could just alter it back to jpg, or click the "open with" button and select any image visualizer and it would work. So is that a way of doing it only accessible trough my app? And is there a way to make such an app that could lock the image that way? And is it possible to do it manually? I only know C# ( and im not an exepert on it yet ) in Visual Studio so...
You can control whether others can read/write the file while you're using it.
But once your application is closed, the file just sits there, and can be passed through the same reading logic you would execute, but by a different program. You could flip all the bytes of the file and hope "they" don't figure it out. You could encrypt it and decrypt it in run-time, if you really want to go far.
You can't prevent someone from deleting or renaming or moving your file, however, when you aren't using the file yourself.
No, there's no way to lock a file in the manner you're asking about. All files consist of a structure of bytes, and there's no way to "lock out" other applications from reading from or writing to a file.
If you want, you could hold open a handle to the file - FileStream's constructor takes overloads that specify file sharing modes, and one of those modes is 'no sharing'.
FileStream stream = new FileStream(
sourcePath,
FileMode.Open,
FileAccess.ReadWrite,
FileShare.None
);
As long as you hold that stream open, nothing else will be able to access the file, read or write.
You could save the file in a format only your program understands, eg by prefixing some number of bytes.
I would like to say an approach which sparked on my mind.
zip the image/ file using encrypted password.
unzip with password and and use that image/file.
Thanks,
We have a process that has SQL Server Reporting Services create a pdf file via
ReportExecutionService.Render
from data in the database. Then we save the byte array that Render returns to the database. Later I get the byte array and do a
File.WriteAllBytes
to write it to disk before attaching it to an email and sending it. The problem I'm running into is that after writing the file to disk, it is corrupt somehow. I'm not sure what to look at, can anyone help?
Thanks
EDIT:
I can write the file from SSRS to disk before saving the byte array to the database and I can view that fine.
If you work with the byte[] returned by render, then things are fine, but if once you write that to the DB and read it back, you have problems, correct?
Why don't you compare the array written in to the DB with the one you retrieve to find the problem? Then start looking into your DB write and read routines, finally your DB storage.
I've done similar things without problems, such as taking the results of a Reporting Services call into a bytestream and attaching that directly to an email, both using a memorystream and an on-disk file. So the basics of this are sound and should work.
Not sure if this is your issue or not, but if the PDF file itself is corrupt you might want to look at how it's being written. If Windows Preview can view the PDF but Adobe cannot, it may have to do with the fact that Adobe is expecting %PDF in the first 1024 bytes of the file (otherwise it will consider it corrupt).
I need to know if my file is audio file: mp3, wav, etc...
How to do this?
Well, the most robust way would be to write a parser for the file types you want to detect and then just try – if there are no errors, it's obviously of the type you tried. This is an expensive approach, however, but it would ensure that you can successfully load the file as well since it will also check the rest of the file for semantic soundness.
A much less expensive variant would be to look for “magic” bytes – signatures at the start or known offsets of the file. For example, if a file starts with an ID3 tag you can be reasonably sure it's an MP3 file. If a file starts with RIFF¼↕☻ WAVEfmt, then it's a WAV file. However, such detection cannot guarantee you that the file is really of that type – it could just be the signature and following that garbage.
While you can use the extension to make a reasonable guess as to what the file is it's not guaranteed to work 100% of the time. If you are targeting Windows then it will work 99.9% of the time as that's how Windows keeps track of what file is what type.
If you are getting your files from non-Windows sources the only sure way is to open the file and look for a specific string or set of bytes which will unambiguously identify it. For example, you could look for the ID3 tags in an mp3 file:
The ID3v1 tag occupies 128 bytes, beginning with the string TAG.
or
ID3v2 tags are of variable size, and usually occur at the start of the file, to aid streaming media.
How far you go depends on how robust you want your solution to be, and does rely on there being a header or pattern that's always present.
Doing it this way can help guard against malicious content where someone posts a piece of malware as a mp3 file (say) and hopes that it will just be run by a program prone to some exploit (a buffer overrun perhaps).
You can use the file extension to figure it out:
using System.IO;
class Program
{
static void Main()
{
string filepath = #"C:\Users\Sam\Documents\Test.txt";
string extension = Path.GetExtension(filepath);
if (extension == ".mp3")
{
Console.WriteLine(extension);
}
}
}
The file extension is the first point of call for the OS to figure out what file type it's dealing with, if you really want to know the file type 100% the only way to do it is read into the file. But this comes with a catch, image files are easy as they include headers in a pretty easy to read format, however it can get a little more complex with a completely variable file type.
You could check out this post on an old post for a bit of help. Here is a post about finding just media file types.
Ultimately it depends on why your trying to do this.
Path.GetExtension(PathToFile)
See this post. You end up passing the first (up to) 256 bytes of data from the file to FindMimeFromData (part of the Urlmon.dll).
I have a portable executable that saves data to a file in the same folder as the executable. Is there any way that I can save data into the executable itself when I close the app?
This maybe weird, but taking the data with me and only have one file for the exe and data would be great.
Would prefer if this was made with C#, but is not a requisite.
You cannot modify your own EXE to contain stored data in anything approaching an elegant or compact way. First off, the OS obtains a lock on the EXE file while the application contained within is being run. Second, an EXE comes pre-compiled (into MSIL at least), and modification of the file's source data usually requires recompilation to reset various pointers to code handles, or else a SERIOUS knowledge on a very esoteric level about what you're doing to the file.
The generally-accepted methods are the application config file, a resource file, or some custom file you create/read/modify at runtime, like you're doing now. Two files for an application should not be cause for concern
You can, by reserving space through the means of using a string resource and pad it out. You need to do a bit of detective work to find out exactly where in the offset to the executable you wish to dump the data into, but be careful, the file will be "in use", so proceed cautiously with that.
So right now you're using an app.config (and Settings.settings) file?
I believe this is the most compact way to save data close to the .exe.
I would highly doubt you can alter the manifest of the .exe, or any other part of it.
Edit: Apparently, there might be some ways after all: http://www.codeproject.com/KB/msil/reflexil.aspx
There is one way using multiple streams, but only works in NTFS filesystems.
NTFS allows you to define alternative "named" streams in one file. The usual content is in the main = unnamed stream. It has something to do with the extra info you can see when you right click a file and check properties.
Unfortunatly C# has no support for multiple streams, but there are open source pojects that can help you.
See this link for a nice wrapper to read and write multiple streams to one single file in C#
Alternate data streams might work. By using the ::stream syntax you can create a data stream within your exe and read/write data.
Edit:
to create/access an alternate data stream, you will use a different filename. Something like:
applicAtion.exe:settings:$data
this will access a data stream named "settings" within application.exe. To do this you need to add the :settings:$data to the filename when reading or writing to the file. This functionality is provided by ntfs so it shold work in c# and should work when the application is running.
Additional information is available at: http://msdn.microsoft.com/en-us/library/aa364404(VS.85).aspx
If you want to take the data with you and only have one file for the exe and data, .zip them into a self-extracting .exe.
you can add data to end of executable file :
var executableName = Process.GetCurrentProcess().MainModule.FileName;
// rename executable file
var newExecutableName = fullPath.Replace(".exe", "_.exe");
FileInfo fi = new FileInfo(executableName);
fi.MoveTo(newExecutableName);
// make copy of executable file to original name
File.Copy(newExecutableName, executableName);
// write data end of new file
var bytes = Encoding.ASCII.GetBytes("new data...");
using (FileStream file = File.OpenWrite(executableName))
{
file.Seek(0, SeekOrigin.End);
file.Write(bytes, 0, bytes.Length);
}
// we can delete old file when exited
In my application, the user selects a big file (>100 mb) on their drive. I wish for the program to then take the file that was selected and chop it up into archived parts that are 100 mb or less. How can this be done? What libraries and file format should I use? Could you give me some sample code? After the first 100mb archived part is created, I am going to upload it to a server, then I will upload the next 100mb part, and so on until the upload is finished. After that, from another computer, I will download all these archived parts, and then I wish to connect them into the original file. Is this possible with the 7zip libraries, for example? Thanks!
UPDATE: From the first answer, I think I'm going to use SevenZipSharp, and I believe I understand now how to split a file into 100mb archived parts, but I still have two questions:
Is it possible to create the first 100mb archived part and upload it before creating the next 100mb part?
How do you extract a file with SevenZipSharp from multiple splitted archives?
UPDATE #2: I was just playing around with the 7-zip GUI and creating multi-volume/split archives, and I found that selecting the first one and extracting from it will extract the whole file from all of the split archives. This leads me to believe that paths to the subsequent parts are included in the first one (or is it consecutive?). However, I'm not sure if this would work directly from the console, but I will try that now, and see if it solves question #2 from the first update.
Take a look at SevenZipSharp, you can use this to create your spit 7z files, do whatever you want to upload them, then extract them on the server side.
To split the archive look at the SevenZipCompressor.CustomParameters member, passing in "v100m". (you can find more parameters in the 7-zip.chm file from 7zip)
You can split the data into 100MB "packets" first, and then pass each packet into the compressor in turn, pretending that they are just separate files.
However, this sort of compression is usually stream-based. As long as the library you are using will do its I/O via a Stream-derived class, it would be pretty simple to implement your own Stream that "packetises" the data any way you like on the fly - as data is passed into your Write() method you write it to a file. When you exceed 100MB in that file, you simply close that file and open a new one, and continue writing.
Either of these approaches would allow you to easily upload one "packet" while continuing to compress the next.
edit
Just to be clear - Decompression is just the reverse sequence of the above, so once you've got the compression code working, decompression will be easy.