How to use long path in XmlDocument.Load()? - c#

I have a long-long path
var path = "\\?\C:\long\paht\to\file\myxml.xml"
I trying to read it:
var xmlDoc = new XmlDocument();
xmlDoc.Load(path);
And get exception here:
system.uriformatexception invalid uri the hostname could not be parsed
Everything else work with long path, but XmlDocument.Load() doesn't. What should i do here? Open file in regular stream and use xmlDoc.Load(stream)?

Trying to answer your question i would refer Microsoft article which states 2 prerequisites you must satisfy, in order to enable Long Path on Windows 10 from version 1607 on.
Supposing you already done those additional required settings, there's an option mostly probable that's the currently missing support in the underlying implementation of XmlDocument's Load method.
I've done your same test, in environment targeting .Net 4.6.2+ which doesn't require any additional config in the application config file (which would been required otherwise):
var path = #"\\?\C:\long\paht\to\file\myxml.xml";
var xmlDoc = new System.Xml.XmlDocument();
//xmlDoc.Load(path); => it breaks as you have seen
// avoid exception check for brevity
FileStream fs = File.Open(path, FileMode.Open);
xmlDoc.Load(fs);
This way you should been able to read the file you need and with, good code management, remove the unnecessary intermediate passage currently required.

Related

Hp Fortify: Path Manipulation erroe

I am getting the hp fortify warning for the following code:
FileStream fs = null;
StreamWriter writer = null;
try
{
fs = new FileStream(sFileName, FileMode.Open, FileAccess.Write);// Path Manipulation error
writer = new StreamWriter(fs);
I am not deleting the file in my code, So if user provide the path of some config its safe from my code, So I am not sure why this is giving warning?
Can anyone please suggest me any alternative?
Fortify doesn't know what the file is, where it is, or anything else. Write the code in a way that Fortify can see that the application is protected from malicious users.
Validate the path so that I can't pass a file named ../../../../cmdshell.aspx, don't rely on filesystem permissions. I'm assuming that at some later time you want to read that file, do the same kind of validation there.
I would also validate MIME type, file size, and check for weird characters.

Access to path denied but the file has no restrictions

I'm new to C# and not an expert at programming in general, but I can't seem to figure out what is causing this problem. I am letting the user pick a XML file and then I want to read it's contents. This is in C# making a universal windows 10 app
This is the error I'm getting:
An exception of type 'System.UnauthorizedAccessException' occurred in
mscorlib.ni.dll but was not handled in user code
Additional information: Access to the path 'C:\temp\file.xml' is
denied.
public async static void pickFile()
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.List;
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add(".xml");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var t = Task.Run(() => { reset(file.Path); });
}
}
then
private static void reset(string path)
{
String LocationDatafilename = path;
XmlReaderSettings settings = new XmlReaderSettings();
XmlReader reader = XmlReader.Create(LocationDatafilename, settings);
XmlDocument LocationDataXml = new XmlDocument();
LocationDataXml.Load(Globals.reader);
}
When I get to XmlReader.Create that's when I'm getting the error. When I look for the cause, the only thing I find is due to permissions, but that isn't the case. Any help would be appreciated. Thanks.
You need to operate on the StorageFile directly, since your app doesn't have permissions to directly read the user's files. You can either use the WinRT XML API or you can keep using the .NET API and use the stream-based Create function instead of the one that takes a file name.
Run sysinternal's ProcMon app, and at the same time run your application. Find the file in the procmon capture, and in the CreateFile entry, you'll find the creation Disposition. This will give you a clue why the creation failed. Also, select the "User" column to show the user performing the operation.
While Peter Torr's answer is correct and is the way Microsoft wants these things to be done, it is possible to make (at least parts of) the OP's code work as well. The reset method will work, if the path is to one of the directories you have permission for. To get these you can use ApplicationData.Current. This object contains properties like LocalFolder, LocalCacheFolder or (what could be interesting for your use case) SharedFolder.

Apparent bug in Silverlight 4 Resource Streams or Json Xml Dictionary Reader

I've encountered what feels like a bug in Silverlight 4, because I can't find anything in the MSDN docs that says this shouldn't work, but it's crashing my application:
var info = Application.GetResourceStream(DocumentUri);
using (var stream = info.Stream)
using (var reader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max))
{
// Content doesn't matter, could be empty.
}
The end result of this block is a NotSupportedException from MS.Internal.InternalMemoryStream.Flush. Stream.Flush is a bit under documented, but it would imply that the enclosing reader should call Stream.CanSeek and/or Stream.CanWrite before calling Flush.
If anyone else has run into this issue, I'd appreciate any references you have.
EDIT: I've uploaded a minimal project that's crashing here: http://sdrv.ms/x9GLNR
I've now been able to reproduce your error. I agree with you in that this is a bug in Silverlight. Quite simply, there's no other reasonable explanation for a NotSupportedException being thrown from deep within classes under the MS or System namespaces.
Nonetheless, I found that your code worked if I changed the Build Action of your document.json file to Resource instead of Content, and changed the URI used to read the file as follows:
var info = Application.GetResourceStream(new Uri("/HelloApp;component/document.json", UriKind.Relative));

Writing to XML resource file through serialization

So I'm writing a C# app that has a couple of XML files added as resources. I read from these XML files to populate objects in the code using XML serialization and it works perfectly. So I can access the files like so (I've left some code out, just have the important bits):
using TestApp.Properties;
XmlSerializer serializer = new XmlSerializer(typeof(MapTiles));
StringReader sr = new StringReader(Resources.Maps);
mapTiles = (MapTiles)serializer.Deserialize(sr);
Now however, I'd like to do the opposite. I'd like to take some data and write it to these XML resource files. However, I seem to be running into trouble with this aspect and was hoping someone could see something I'm messing up or let me know what I need to do? Here's what I'm trying to do:
XmlSerializer serializer = new XmlSerializer(typeof(MapTiles));
TextWriter writer = new StreamWriter(Resources.Maps);
serializer.Serialize(writer, tempGroup);
writer.Close();
When I run this code though, I get an error on the 2nd line that says ArgumentException was unhandled - Empty path name is not legal.
So if anyone has any thoughts I would greatly appreciate some tips. Thanks so much.
The exception is being raised because you are passing Resources.Maps into StreamWriter. StreamWriter is handling this as a string and assuming it is file path for the stream. But the file path is empty so it is throwing an exception.
To fix out the StreamWriter line you could specify a local temporary file instead of Resources.Maps or use StringWriter with the default constructor e.g. new StringWriter().
If you are writing .resx files then ResXResourceWriter is the class you need. It will also handle your stream writing too. See http://msdn.microsoft.com/en-us/library/system.resources.resxresourcewriter.aspx and http://msdn.microsoft.com/en-us/library/ekyft91f.aspx. The second page has examples on how to use the class but breifly you would call something like this:
XmlSerializer serializer = new XmlSerializer(typeof(MapTiles));
using (StringWriter stringWriter = new StringWriter())
{
serializer.Serialize(stringWriter, tempGroup);
using (ResXResourceWriter resourceWriter = new ResXResourceWriter("~/App_GlobalResources/some_file.resx"))
{
resourceWriter.AddResource("Maps", stringWriter.ToString());
}
}
If you want to write out an assembly that has a dynamically created resource in it the you can emit a new assembly. In that case have a look here http://msdn.microsoft.com/en-us/library/8ye65dh0.aspx.
The StreamWriter constructor is throwing the exception because Resources.Maps is an empty string.
Check out the documentation on MSDN:
http://msdn.microsoft.com/en-us/library/fysy0a4b.aspx
Hmm, after trying some other things and doing even more research it appears that the problem is that you cannot write to a resource that is part of the application. Something to do with the resource being written into the assembly and therefore it's not writable. So I'll have to modify my approach and write the output to a different file.
Unless of course anyone does know differently. This is just what I've discovered so far. Thanks to those who had some ideas though, much appreciated.

.NET Exception Handling Application Configuration File

I apologize as this question is somewhat basic; however, after a great deal of searching, I have not found a suitable answer. I am building a windows forms application and need to reference an app.config file for the location to a data file. Before calling
XElement xml = XElement.Load(ConfigurationManager.AppSettings["EntityData"].ToString());
I want to ensure that the app.config file exists. I have tried multiple methods but it seems that it is a lot more work then it should be. For example I have been trying to use the following code to determine the path for the file
Uri uri = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
string fullConfigurationFilename = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(uri.AbsolutePath), configurationFilename);
but I run into issues with spaces in the path. Is there a better way to check for the existence of the app.config, do I even need to check?
Thank you
I don't think you need to verify that the config file exists. The following code should work without exceptions:
string temp = ConfigurationManager.AppSettings["EntityData"];
if (temp != null)
{
XElement xml = XElement.Load(temp);
}
Note that AppSettings will return a string if the key is found, so you don't need to call ToString to convert it. If the key does not exist, you should instead get a null reference that you can test for.
System.Configuration should do all of this work for you. There shouldn't be a need to manually load a config file.

Categories