I am working on an UWP text editor. I have added desktop extension to it to modify system files and other read only files. The problem I have is there is no reliable way to detect if a file has read-only attribute. FileInfo.IsReadOnly doesn't work and StorageFile.Attributes has FileAttributes.ReadOnly when file is dragged and dropped from file explorer.
How do I reliably check whether the file has read only flag or not?
While there is no way to detect the readonly attribute by using dotnet methods, however GetFileAttributesExFromApp can be used to get a lot of attributes(readonly, hidden etc.) of the file that aren't available via StorageFile api. Also, SetFileAttributesFromApp can be used to change/remove these attributes.
Edit
After some research and deep dive in MSDN, I came to know about RetrievePropertiesAsync(IEnumerable<String>) and
SavePropertiesAsync(IEnumerable<KeyValuePair<String,Object>>) methods for Windows.Storage.FileProperties.StorageItemContentProperties which can be used to get and set properties by name (Full list of properties names), the name System.FileAttributes can be used to get file attributes and can be used to detect if read-only flag is present. While retrieving properties always works modifying properties will only work if app has write access to file (Windows.Storage.StorageFile.Attributes doesn't contain ReadOnly flag), although SetFileAttributesFromApp works for that scenario but limitation of SetFileAttributesFromApp is it won't work for sensitive file types (.bat, .cmd etc.). So both those methods could be used combined to have maximum effect.
You can see the Attributes property has ReadOnly or not.
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
foreach (string format in HelperUP.subtitlesFormat)
filePicker.FileTypeFilter.Add(format);
var file = await filePicker.PickSingleFileAsync();
if (file == null)
return;
Debug.WriteLine(file.Attributes);
The reason FileAttributes.ReadOnly throws an exception is that the System.IO APIs don't have access to arbitrary file locations on the hard drive in UWP.
On the other hand, a StorageFile opened in the app via drag & drop has this attribute set too, which is a problem that is continuously being discussed and hopefully will be fixed in a future version.
The only workaround I can think of (apart from always using the desktop extension) is declaring the broadFileSystemAccess capability (I have described the process here for example). This is a capability which gives you access to the whole filesystem and allows you to get a file using an arbitrary path with the StorageFile.GetFileFromPathAsync method (see Docs). Please note you will need to explain why this capability is required when you submit the application to the Microsoft Store.
With broad filesystem access, you could take the drag & drop StorageFile, take its Path and retrieve the same file again using StorageFile.GetFileFromPathAsync. This new copy of the file will no longer have the "false-positive" Read Only attribute and will reflect the actual attribute state from the filesystem.
Related
Im trying to use Microsoft.Office.Interop.Word._Document.Close() in a .net 3.5 windows form app.
No matter how much I search here and on Google I cannot find the correct parameters to put in the Close method.
I am using version 14.0.0.0 of Microsoft.Office.Interop.Word and I would like to close the document without saving and ideally ensure that the application can isolate the document thread so that users can still open word documents outside the running application.
See the Close method of the Document class described in MSDN. If you need to omit the parameter and use the default value - pass the Type.Missing parameter.
Try this:
object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
object missing = System.Reflection.Missing.Value;
_Document.Close(ref doNotSaveChanges, ref missing, ref missing);
This is the source
I'm not sure if you'll need the middle line or not. It's not from the original source it's from here
I am trying to create an app which has a predefined set of data(currently a text file) and it reads from it, now how should i implement the data storage such that when i share the app with someone else, i don't have to pass the text file or any other data file(if possible, i can encrypt the contents and give it using a different extension) externally. I just want to give one exe file to the person and the data should be included inside the exe.
anyway to do it ??
Thanks in advance
Include the text file as a resource.
You do not need to change the build (if you are using Visual Studio that is). Visual Studio will embed the resource/file and generate a readonly property for the file so you can access it directly from within your code:
string fileContent = YourResourceFile.TheEmbeddedFile;
You could split the fileConent per linebreak but the previous line will load the entire file into memory.
string[] lines = fileContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
If the file is too big to be read into memory at once, you could stream the resource as explained here.
You can change the build mode of the file to resource/embedded resource, reading from it works different then, this should be answered somewhere though.
I am trying to develop a plugin/component that can change the media file format from one to another. Specifically, I need it to convert the "tiff" file to array/single copy of "jpg" image file.
Kindly guide, how I can implement it or is there any kind of tutorial link from where either I can download it or take some help to develop it. Thanks in advance.
We did this in our CMS (built on CakePHP 1.2; sorry if there are any significant discrepancies I'm not aware of) using a behaviour. That makes the controller logic very easy (in fact we use a baked controller without any modification at all).
Unfortunately TIFF isn't a supported file format in GD (the default image manipulation library in PHP). You'll need to use ImageMagick or an equivalent tool to do the actual conversion itself, but the logic for implementing it in your CakePHP project won't be any different to what I describe here.
The behaviour (in our case) was used to generate images as thumbnails as well as page resolution and to convert the uploaded file format into JPEG.
In its beforeSave() method it checked that data was specified (and that there was no error), and then pulled the tmp_name value from the posted data (and removed the posted data object).
In its afterSave() method, it actually performed the image conversion task itself (putting the generated images in the expected location on disk), then updated any foreign keys on extended models with the uploaded image's ID. We do this in the afterSave() operation so we have a database ID to use to name the files on disk.
In its afterDelete() method we unlink the files on disk.
Using the behaviour in the model is as simple as telling the model (where ContentImage is the name of the behaviour):
var $actsAs = array('ContentImage');
Although we also use the model to define the output directory since we had a few models that implemented the behaviour, and it felt like the right thing to do, e.g. in the model:
function getThumbnailDir() {
return WWW_ROOT.'img'.DS.'upload'.DS.'thumb';
}
and in the behaviour itself the output path becomes:
$Model->getThumbnailDir().DS.$Model->id.'.jpg'
I'm including a number of images as "Content" in my deployed XAP for Mango.
I'd like to enumerate these at runtime - is there any way to do this?
I've tried enumerating resources like:
foreach (string key in Application.Current.Resources.Keys)
{
Debug.WriteLine("Resource:" + key);
}
But the images aren't included in the list. I've also tried using embedded resources instead - but that didn't help. I can read the streams using Application.GetResourceStream(uri) but obviously I need to know the names in order to do this.
This is no API baked in to WP7 that allows you to enumerate the contents of the Xap. You need to know the name of the content items before you can retreive them.
There probably is some code floating around somewhere that is able to sniff out the Zip catalog in the XAP however I would strongly recommend that you don't bother. Instead include some sensible resource such as an Xml file or ResourceDictionary that lists them.
Having found no practical way to read the Content files from a XAP I build such a list at design time using T4.
See an example at https://github.com/mrlacey/phonegap-wp7/blob/master/WP7Gap/WP7Gap/MainPage.xaml.cs
This seems the right way to go as:
a) I'd rather build the list once at design time rather than on every phone which needs the code.
and
b) I shouldn't ever be building the XAP without being certain about what files I'm including anyway.
Plus it's a manual step to set the build action on all such files so adding a manual step to "Run Custom Tool" once for each build isn't an issue for me.
There is no way to enumerate the files set as "Content".
However, there is a way to enumerate files at runtime, if you set your files as "Embedded Resource".
Here is how you can do this:
Set the Build Action of your images as "Embedded Resource".
Use Assembly.GetCallingAssembly().GetManifestResourceNames() to
enumerate the resources names
Use
Assembly.GetCallingAssembly().GetManifestResourceStream(resName)
to get the file streams.
Here is the code:
public void Test()
{
foreach (String resName in GetResourcesNames())
{
Stream s = GetStreamFromEmbeddedResource(resName);
}
}
string[] GetResourcesNames()
{
return Assembly.GetCallingAssembly().GetManifestResourceNames();
}
Stream GetStreamFromEmbeddedResource(string resName)
{
return Assembly.GetCallingAssembly().GetManifestResourceStream(resName);
}
EDIT : As quetzalcoatl noted, the drawback of this solution is that images are embedded in the DLL, so if you a high volume of images, the app load time might take a hit.
I write Silverlight games using XNA-based Silverlight engines. I have a previous game where I have files (MP3s and text files) with Build Action set to Embedded Resource, and no *.resx file to be seen in my solution.
The game runs fine; you can see the production version here.
On the other hand, my current project doesn't allow this. When I try to make files Embedded Resources, I get a MissingManifestResourceException thrown in my constructor of the main UserControl instance that starts my app. The error message is:
Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "DeenGames.Colosseum.Content.Audio.2.mp3.resources" was correctly embedded or linked into assembly "DeenGames.Colosseum" at compile time, or that all the satellite assemblies required are loadable and fully signed.
I'm very, very, very perplexed. Setting any item's Build Action to Embedded Resource, whether MP3, text, or image, causes this exception.
How the heck do I fix (or debug) this? I'm 99% sure I do not need a .resx file, because my previous projects don't have one.
There's this lovely MSDN page which assures the world that:
In particular, Silverlight embedded resources must always use the
Resource build action, and not the Embedded Resource build action,
which uses a format that Silverlight cannot recognize.
But there's a well-known solution using Assembly.GetExecutingAssembly().GetManifestResourceNames(). In my case, it doesn't show me the resource if it's just a Resource; if it's an Embedded Resource, I can see the file name with dot-delimited namespace (as expected).
Download and see for yourself a very simple working example here. It has two embedded files (.2dg and .map) and compiles/runs without any exceptions OR resx file.
You can also download a broken example here. Replace FlatRedBall.dll with RadiantWrench.dll and watch the working example break. (Use ScreenController.ShowScreen and remove all FRB-referenced code.)
Embedded Resource is a WinForms technology that is depreciated in the Silverlight runtime. Instead, a build action of Resource or Content should be used instead.
When you set an item to Embedded Resource, Silverlight expects this to be a .resx file because this is what happens inside the .csproj or .vbproj file when you create a .resx and add resources to it (the file is marked as Embedded Resource for MSBuild and its resources are simply a None inside of an <ItemGroup/> that are discovered by the ResXGenerator at runtime based off the relative URI folder of "Resources"). If it isn't, it removes it or sets it as Content. You can examine Microsoft.Silverlight.Common.targets (usually in your C:\Program Files (x86)\MSBuild\Microsoft\Silverlight\v4.0 folder) to see how it changes items marked as Embedded Resource - setting to content, setting to none or setting to a .resx file.
If you're looking to just query what resources you have in the project, you could try this somewhat cumbersome approach: Enumerating embedded resources
UPDATE: In looking at your project, this is not really using an Embedded Resource the way WinForms uses this Build Action type or even .resx, per say. It uses a function from the ToolsSilverlight.dll called EmbeddedResourceFileReader.ReadFile. The code for that is:
private static string ReadFile(string fileName, Assembly currentAssembly)
{
string text = EmbeddedResourceHelper.CheckAndSanitizePath(fileName);
string result = "";
using (Stream manifestResourceStream = currentAssembly.GetManifestResourceStream(text))
{
if (manifestResourceStream == null)
{
throw new ArgumentException("Couldn't open " + fileName + ". Make sure the file exists in that directory, and has Build Action set to Embedded Resource.");
}
using (StreamReader streamReader = new StreamReader(manifestResourceStream))
{
result = streamReader.ReadToEnd();
}
}
return result;
}
Your .csproject file lists your files as:
<ItemGroup>
<EmbeddedResource Include="Content\Qadar.2dg" />
<EmbeddedResource Include="Content\Maps\main.map" />
<None Include="Properties\AppManifest.xml" />
</ItemGroup>
All this does is embed, as mentioned with the Microsoft.Silverlight.Common.targets above, your files as common Resources (at a top level, not with the list of other actual resouces) and finds a way to read them. You can decompile your DLL with ILSpy to exam that these are indeed now common Resources under the Resources folder.
So how can you do this in your new project? Replicate the exact method you did in your first one - add ToolsSilverlight.dll, list your items as Embedded Resource, and call them using EmbeddedResourceFileReader.ReadFile. You may also want to ensure your .csproj file <ItemGroup/> structure is similar to original one. Not sure if <None Include="Properties\AppManifest.xml"/> is needed by EmbeddedResourceFileReader, but it may be.