I'm working on an out-of-browser Silverlight program, and I have successfully gotten it to open local files by means of an OpenFileDialog. However, now I need it to open a file from within its own XAP (no browsing necessary, the file to open is hard-coded). I am trying to use this code, but it's not working:
using (StreamReader reader = new StreamReader("Default.txt"))
{
TextBox1.Text = reader.ReadToEnd();
}
This code throws a SecurityException that says "File operation not permitted. Access to path 'Default.txt' is denied." What am I doing wrong?
Your code is trying to open a file called "Default.txt" that is somewhere out in the user's file system. Where exactly I don't know, as it depends on where the Silverlight app's executing from. So yes, in general you don't have permission to go there.
To pull something out of your XAP, you need ton construct the stream differently. It will be along these lines:
Stream s = Application.GetResourceStream(
new Uri("/MyXap;component/Path/To/Default.txt", UriKind.Relative)).Stream;
StreamReader reader = new StreamReader(s);
Note, this means your Default.txt should be set to 'Resource', not 'Embedded Resource'. By being a 'Resource' it will get added to the XAP. Embedded Resource will add it to the assembly.
More info: http://nerddawg.blogspot.com/2008/03/silverlight-2-demystifying-uri.html
Note: In cases where your Silverlight program has multiple assemblies, check that the "/MyXap" part of the Uri string references the name of assembly containing the resource. For example if you have two assemblies "ProjectName" and "ProjectName.Screens", where "ProjectName.Screens" contains your resource, then use the following:
new Uri("ProjectName.Screens;component/Path/To/Default.txt", UriKind.Relative))
Related
I am working on a desktop application that internally creates a StringBuilder that errors get appended to and ultimately gets written to a txt file.
I get an exception that says 'Access to the path 'C:\Users\Me\Documents\test_dir\5_hundred_thousand_rows_Logs.txt' is denied.'
Below is the code that performs the creation of the .txt file. The exception catches on the File.OpenWrite(tempfile)) line
string tempfile="C:\\Users\\Me\\Documents\\test_dir\\5_hundred_thousand_rows_Logs.txt";
using (Stream fileStream = File.OpenWrite(tempfile))//exception here
{
string data = logFileContent.ToString();
Byte[] filecontent = new UTF8Encoding(true).GetBytes(data);
fileStream.Write(filecontent, 0, filecontent.Length);
}
Process.Start(tempfile);
I have double checked and the tempfile does indeed have the file extension and is not attempting to create a directory.
I've tried wrapping the using statement with the following to attempt to "grant" access but to no avail:
var permissionSet = new PermissionSet(PermissionState.None);
var writePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess, Path.GetDirectoryName(tempfile));
writePermission.Demand();
permissionSet.AddPermission(writePermission);
FileAttributes attributes = File.GetAttributes(Path.GetDirectoryName(tempfile));
if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
{
// using statement
}
I am wanting this desktop application to be able to be handed to anyone and they be able to use this without having the user deal with folder permissions or something. Granted I'm really only expecting it to try to access MyDownloads, MyDocuments, directories on flash drives or other similar devices.
I would greatly appreciate any help provided.
EDIT:
It appears that this may be a Windows issue. The file is set to readonly in its properties (was not this way originally), and attempting to set the file as not readonly doesn't work as Windows apparently just resets it back to readonly. However if the file is not in a folder and is just sitting on the bare drive (such as a different drive eg: D:/5_hundred_thousand_rows_Logs.txt) it seems to work just fine. If there's a programmatic way to get around this I would appreciate it, but if this is a Windows issue this may require making this a different question.
According to the documentation the exception is thrown when you don't have the permissions, or the file is readonly.
To test if you don't have permissions, try and run your application as administrator. To verify the second case, right click the file in explorer, choose properties, and make sure it's not readonly.
Besides that string tempfile="C:\\Users\\Me\\Documents\\test_dir\\5_hundred_thousand_rows_Logs.txt"; is a weird path, because it's using the user me which definitelly doesn't exist on every machine. If you like to get the documents folder of the current user you can use: Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); This will create the correct path for you.
I have an application where users can define custom elements by adding their own xaml files. These files are loaded by the application on startup. The idea is to be able to extend the application without having to recompile it. These elements will be shown on screen to the user, and the xaml files may contain resource keys which are not included in the resx files of the application itself. So I have a requirement to have separate resx files which the user can edit, that will also be loaded at runtime.
I've looked at the ResourceManager class, and I know that it can be set to access resources from various other assemblies. But from what I gather the resources must be part of an assembly, which is precisely what I don't want. What I want is to have a bunch of files like these:
%ProgramData%\MyApplication\Resources\strings.resx
%ProgramData%\MyApplication\Resources\strings.de-DE.resx
%ProgramData%\MyApplication\Resources\strings.zh-CN.resx
and I want my application to be able to load these files and access the strings in them.
This article https://msdn.microsoft.com/en-us/library/gg418542(v=vs.110).aspx shows two approaches using ResXResourceReader and ResXResourceSet. However, it appears that these classes take a path to a specific file (or a stream), and therefore won't be able to pick the correct file according to current culture and the naming convention. I know I can code this myself, and that's what I'll do if I don't find a better solution. But ideally I'd want something that handles this for me. For instance if it would be possible to point a ResourceManager to a folder instead of an assembly. Is something like this possible?
after a long long searching i found this:
If i understand you in the right way you want to create user defined forms in WPF at runtime using xaml.
I am not sure but, i think the resource files will not help you out, because all xaml forms precompiled in the assembly. I found something that maybe sounds like a solution for your problem. Its called Sattalite Assembly. In the first step you have to create a new resource file. Second step is to link it with the Assembly Linker (Al.exe). form .net Framework. MSDN Creating Satellite Assemblies
First step create a ResourceFile at Runtime (here a little help)
public static void CreateResourceFile()
{
string resourceFileName = "externeresource";
System.Xml.XmlDocument xmldoc = new XmlDocument();
XmlTextReader reader = new XmlTextReader("/runtimeWPForm.xml");
reader.WhitespaceHandling = WhitespaceHandling.None;
xmldoc.Load(reader);
ResourceWriter resourceWriter = new ResourceWriter(resourceFileName);
/*Add XmlDocument must be Serializable to store it in
resourceWriter.AddResource("xamlgrid", xmldoc.ToString());
the Resource, so i stored a String here. (not testet)*/
resourceWriter.Close();
MessageBox.Show("File " + resourceFileName + " created");
reader.Close();
}
Second step create a Sattlelite Assembly from resource file with Assembly Linker Al.exe
Last step is to load the xaml Forms from the Sattalite Assembly (here a little help)
Uri GridUri = new Uri(/*Note1*/, UriKind.Relative);
Windows.Resources.StreamResourceInfo sri = Application.GetResourceStream(GridUri);
System.Windows.Markup.XamlReader xrdr = new System.Windows.Markup.XamlReader();
Grid grd = (Grid)xrdr.LoadAsync(sri.Stream);
this.Content = grd;
Note1:
Resource file - referenced assembly Pack URIs in WPF
Uri uri = new Uri("/ReferencedAssembly;component/ResourceFile.xaml",UriKind.Relative);
Here some usefull Information as i think Construct XAML Forms at Runtime with Resource Files
This is all i found for you and no guarantee for functionallity.
Im interested in if this will work for you, so please send an answer on success or if you solved your issue.
PS.: if this works i think you only have to restart you main application to load the new sattalite assembly. Maybe you have to start an ohter application that do the job and after finish automaticly start your main app again.
Best reguards
GatewayToCode
Thanks to the below link, I've found out how to load a TXT file into my Windows Phone 8.1 app. My question is specifically tied to WHY my code doesn't work. (My code begins after link to the other StackOverflow question).
This is the same question, with a working answer.
Read text file in project folder in Windows Phone 8.1 Runtime
I set the StorageFile as the relative location of the file on the phone. I then try and use that location to open a StreamReader. This small snippet compiles fine, however on execution, encounters a runtime error, and "firstFile" is empty/null.
const string filename = "FileToRead.txt";
StorageFile firstFile = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
using (StreamReader streamFirstFile = new StreamReader(await firstFile.OpenStreamForReadAsync()))
{
loadText_Button.Text = await streamFirstFile.ReadToEndAsync();
}
To hopefully further clarify this specific question, are the following two lines of code the same, and if not, how am I using it wrong?
ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
StorageFile.GetFileFromApplicationUriAsync(new Uri(#"ms-appx:///Assets/FileToRead.txt"))
I even tried to set it as follows:
ApplicationData.Current.LocalFolder.GetFileAsync(String.Format("{0}{1}", "Assets/", fileName);
Thank you all in advance.
If you want to read a file from your package then you should refer to Package.Current.InstalledLocation, not LocalFolder. You should also check if your resource has Build Action set to Content.
You can access your file in two ways - either getting it from InstalledLocation folder:
StorageFile file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(#"Data\" + fileName);
or by Uri:
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(#"ms-appx:///Data/"+fileName));
Few notes:
files in package are read-only,
you can also access files in shared projects by providing its name before folder name
watch out for Build Action - some files are by default set as Content by VS and some not.
You can also find some useful information at this post.
A note for the unwary.
If the name of the file you placed in your Assets folder ends with ".json", the file won't be accessible from your code using the above given function calls. Simply rename the file so that it ends with ".txt".
I would have made this a comment but I don't have the required reputation.
I'm trying to open a really old (binary) Word-file using C#/.NET and Microsoft.Office.Interop.Word. Whenever I try to open this file using the snippet below, it fails with a COMException telling me that "You are attempting to open a file type that is blocked by your File Block settings in the Trust Center."
This also used to happen when opening the same file in MS Word, but after adjusting the settings found in the Trust Center this now works just fine. However, I still cannot open the file using C#. Does anyone know if VS2010 caches these settings, or use its own settings somewhere? I have also tried to create a new project (after fixing the settings in Word) with the same snippet to see if that helped, but it did not.
Word.Application app;
string file = "<filename>";
app = new Word.Application();
try
{
app.Documents.Open(file);
}
catch (COMException e)
{
string s = e.Message;
}
This is implemented with an alternate data stream, supported by the NTFS file system. You access such a stream with the filename:stream syntax. The stream name that stores the info for the file blocking feature is Zone.Identifier:$DATA. It is written by whatever program copied the file, usually a browser.
You can see them with the DIR /R option. The SysInternals' Streams utility permits listing and deleting them. A silly way to get rid of it is copying it to a file system that doesn't support alternate data streams, like a .zip archive or a flash drive and copying it back.
You can look at the content of the stream or edit it with a command like notepad filename:zone.identifier, you'll see this:
[ZoneTransfer]
ZoneId=3
The ZoneId value identifies the origin of the file. Values are -1=unspecified, 0=local machine, 1=intranet, 2=trusted, 3=internet, 4=untrusted. What notepad can do is however not possible in .NET, it explicitly forbids using the : character in file names. The intention is for a human to deal with this, explicitly overriding the file blocking feature. Right-click the file in Explorer, Properties and click the Unblock button. That deletes the stream. Note the Powershell cmdlets mentioned in the first link.
I'm working on a simple progam, and part of it populates a list from a txt file.
this probably is not a smart question but, I didn't find any info on this.
I was wondering where is the best place to put text files in the application directory.
O know about the Resouces but, I wasn't able to get the path of the file I stored there.
so 2 questions:
where is the best place to put a txt file? (or any other importent file to use in the application)
if I put files in the Resources how do I get its path ?
(sorry fo my English)
If these are files that you do not need to expose to the users and only serve an internal purpose, then you can embed them in your assembly as resources, and extract them when you need them.
To do this, create a new directory in your application. Let's call it 'Resources'. Then, add text files to it. Use the properties window of each text file to change the BuildAction setting to "Embedded Resource". Then, in your code once you need the contents of the file you can use code like this to extract it:
using System.Reflection;
// ...
using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MyApplication.Resources.MyFile.txt")) {
using (StreamReader reader = new StreamReader(stream)) {
string contents = reader.ReadToEnd();
// Do stuff with the text here
}
}
If you don't want to do this, the correct location to place files is in a directory you create under the AppData directory. This is a known system path, which you can obtain like this:
string folderLocation = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string myPath = Path.Combine(folderLocation, "MyAppName");
You can then use a StreamReader or other class in System.IO to find/enumerate and read the files.
When an application has associated/companion data files it sometimes makes sense to embed them as a Resource, because then there is less chance for them to be tampered with e.g. deleted, or the data modified.
And other times it makes sense to keep the file loose....so you have to decide the best place to store them....you can locate these in the place where the application is installed, or in the Application Data/AppData directory.
For embedding files in Resources have a look at this link:
http://support.microsoft.com/kb/319292
It has a step-by-step guide showing how to embed a file (e.g. a Text file into Resources), and then using a StreamReader to access it and read its contents.
To store the files and access them from a suitably located directory you can use:
System.Environment.SpecialFolder.ApplicationData
with
Environment.GetFolderPath()
to find out where the AppData directory is.
Then when you create your application Setup/Installer, you should get it to create a directory for your application underneath AppData, and then you can decide what files you want to be installed into that location.
See:
Saving a file to Application Data in c#
Note, ApplicationData "roams"...i.e. when you logon to a different machine, the files are transferred onto that machine as part of your profile....you may not want this....so you could instead use:
System.Environment.SpecialFolder.CommonApplicationData