Change default application for .txt - c#

After a lot of searching on the internet without any success, I'm looking here for some help.
The problem seems to be quiet simple, but unfortunately I'm not able to solve it.
I want to change the default-application to open .txt-files. For example instead of using notepad I want to use Wordpad which is located at C:\Program Files\Windows NT\Accessories\wordpad.exe
So I've tried to change the registry at: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\OpenWithProgids with no success.
I've also found a solution which tries to change the group policy. This code looks like:
string tempFile = Path.GetTempFileName();
string xmlFile = tempFile.Replace(".tmp", ".xml");
File.Move(tempFile, xmlFile);
XDocument document = new XDocument(new XElement("DefaultAssociations",
new XElement("Association",
new XAttribute("Identifier", ".txt"),
new XAttribute("ProgId", "txtFile"),
new XAttribute("ApplicationName", "Editor"))));
document.Save(xmlFile);
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\System!DefaultAssociationsConfiguration",
xmlFile, RegistryValueKind.String);
But this also doesn't work.
I also tried to use the command-line with ftype but that also didn't work.
Can anybody tell me how to change the assoziated application for a given filetype?

I guess you want to this because you have some kind of Set as default option in your program, by the way I have spent the last hour trying to figure out why it doesn't work and here it is what I've found so far.
The step you need to take are the following:
Creates a registry key in ClassesRoot for the .custom extension.
(Period is important)
Code:
Registry.ClassesRoot.CreateSubKey(".custom").SetValue("", "customfile", Microsoft.Win32.RegistryValueKind.String);`
Creating the "Customfile" sub-key and the "customfile\open\command"
subkey that is needed to store the path to the application that will
open this file type.
Code:
Registry.ClassesRoot.CreateSubKey("Customfile\shell\open\command").SetValue("", PATH_TO_YOUR_EXE, Microsoft.Win32.RegistryValueKind.String);
And now the association has been made, your app will be registered as one of those which can open that extention.
The case of .txt (or other already associated extentions)
After messing a little bit around i found out that in order to do changes to an already associated extention you also need to edit the registry
Example (with .txt ext.)
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.txt\UserChoice
This key has an ProgId value which actually contains the default application set by the user, the value is a string. So you will also have do edit/delete this Registry as well.
I hope it helps :)!

Related

Need some clarification about app.config and user.config

So I have been poking around both here on SO and google for the last few days for information about app.config.
I am writing a program that will need to generate SQL scripts using values entered by a user. Originally I was using app.config to store some default values to load into the program when it is first started up. This worked fine until I tried to store the new values back into the app.config file. This is when I found that app.config is read only and I should have been using user.config.
I have several questions that I can't seem to find the answers to:
Is it recommended to use settings.Setting to declare all the values that I want to use app.config? Or is entering them in by hand is enough?
I keep reading about how user.config overrides app.config settings. But when I update my user.config file, the program still reads from the original app.config file
This is from my wrapper class
public NameValueCollection ReadSettings(string sectionName)
{
NameValueCollection scripts = null;
try
{
//read in the current values from the section
scripts = (NameValueCollection)ConfigurationManager.GetSection(sectionName);
if (scripts == null) throw new appConfigException(String.Format("The section {0} does not exists in app.config", sectionName));
}catch (Exception e){
//print out the log file
StreamWriter writer = new StreamWriter(DateTime.Now.ToString("d-MMM-yyyy") + "log.txt");
writer.WriteLine(e.ToString());
writer.Close();
//kill the application process so the user cannot advance further
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
return scripts;
}
is the ConfigurationManager supposed to automatically know to start reading from the user.config? Or do I need to change this section of code to reflect that?
Question 1: It is easier to use Settings.settings instead of creating your own configuration file yourApp.config. Because using the first option you can access your properties just using Properties.Settings.Default.MyProperty and with the app.config file instead you have to deal with ConfigurationManager object, and usually to access a property you need to know the name beforehand and it usually is hardcoded.
Question 2: Yes, you are right the app.config is different from Settings.setting. Because you could even create a new file temp.config which could also be used as a config file for your application.
Final question: Im not sure, but I don't think ConfigurationManager knows anything about that, just parse the app.config file.
Hope it helps.

How to read file in C# from POST data from web

Basically, I'm building a website that allows user to upload file.
From the front end (JavaScript), the user will browse a file, I can get the site to send POST data (the parameter "UploadInput" and it's value, which the value is the file)
In the backend (C#), I want to make a copy of the file and save it in a specific path.
Below is the way I did it.
var files = Request.Files;
file[0].SaveAs("\temp\\" + file[0].FileName);
The problem I ran into is that I got the error message saying index out of range. I tried Response.Write(files.Count) and it gives me 0 instead of 1.
I'm wondering where I did wrong and how to fix it, or if there's a better way of doing it.
Thanks!
Edit:
I am using HttpFox to debug. From HttpFox, I can see that under POST data, parameter is "UploadInput" and the value is "test.txt"
Edit 2:
So I tried the way Marc provides, and I have a different problem.
I am able to create a new file, however, the content is not copied over. I tried opening the new created file in notepad and all it says is "UploadInput = test.txt"
If they simply posted the file as the body content, then there will be zero "files" involved here, so file[0] will fail. Instead, you need to look at the input-stream, and simply read from that stream. For example:
using(var file = File.Create(somePath)) {
Request.InputStream.CopyTo(file);
}

UnauthorizedAccessException on newly created files

I have an application that is looking through some files for old data. In order to make sure we don't corrupt good projects, I'm copying the files to a temporary location. Some of the directories I'm checking are source-code directories, and they have .svn folders. We use Subversion to manage our code.
Once I've searched through all of the files, I want to delete the temp cache. Sounds easy, right?
For some reason, all of my .svn directories won't delete from the cache. They crash the app.
For reasons (too deep to go into here), I have to use the temp folder, so just "scan the original file" is out of the question for political reasons.
I can go into explorer and delete them. No problem. No warnings. Just deletes. But the code crashes with "Access to {file} is denied." I'm at my wits end with this one, so any help would be appreciated.
While I've simplified the function a LITTLE for sake of your sanity, the code REALLY is about this simple.
List<string> tmpCacheManifest = new List<string>();
string oldRootPath = "C:\\some\\known\\directory\\";
string tempPath = "C:\\temp\\cache\\";
foreach (string file in ListOfFilesToScan)
{
string newFile = file.Replace(oldRootPath, tempPath);
// This works just fine.
File.Copy(file, newFile);
tmpCacheManifest.add(newFile);
}
// ... do some stuff to the cache to verify what I need.
// Okay.. I'm done.. Delete the cache.
foreach (string file in tmpCacheManifest)
{
// CRASH!
File.Delete(file);
}
* Update *: The exception is UnauthorizedAccessException. The text is "Access to the path 'C:\temp\cache\some-sub-dirs\.svn\entries' is denied."
It happens under XP, XP-Pro and Windows 7.
* Update 2 * None of my validation even ATTEMPTS to look at subversion files. I do need them, however. That's part of the political crap. I have to show that EVERY file was copied... wheter it was scanned or not.
And I realize what the usual suspects are for File.Delete. I realize what UnauthorizedAccessException means. I don't have access. That's a no-brainer. But I just copied the file. How can I NOT have access to the file?
* Update 3 *
The answer was in the "read-only" flag. Here's the code I used to fix it:
foreach (string file in ListOfFilesToScan)
{
string newFile = file.Replace(oldRootPath, tempPath);
// This works just fine.
File.Copy(file, newFile);
//// NEW CODE ////
// Clear any "Read-Only" flags
FileInfo fi3 = new FileInfo(fn);
if ((fi3.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
{
fi3.Attributes = (FileAttributes)(Convert.ToInt32(fi3.Attributes) - Convert.ToInt32(FileAttributes.ReadOnly));
}
tmpCacheManifest.add(newFile);
}
// ... do some stuff to the cache to verify what I need.
As far as I recall, Subversion marks the files in its .svn subdirectories as read-only.
Try resetting the read-only attribute before deleting the file. I don't really know any C#, but a quick Google suggests this might do the trick:
File.SetAttributes(file, FileAttributes.Normal);
The only problem I see would be in this part:
// ... do some stuff to the cache to verify what I need.
If you do open the file and forget to close it, you still have exclusive access to it, and thus can't delete it later on.
Sounds like you don't have access to delete the file...
system.io.file.delete
The above link says you get UnauthorizedAccessException when:
The caller does not have the required permission.
-or-
path is a directory.
-or-
path specified a read-only file.
It's one of those.
Sounds like a permissions issue. Tricky one though as you obviously have write access if the File.Copy already works....
Only thing I could think of is the file still has a handle opened somewhere (as others have suggested perhaps in your do some stuff to the cache part).
First of all: "Crash" means an exception, right? Which one? Can you catch it and show it?
Second thing: You are copying subversion repositories, although you don't care about the subversion metadata? That's what svn export is about (no .svn directory in the target).
The answer to the first question is what you really need to provide. Maybe something grabs the .svn and locks some files. TortoiseSVN maybe (to give you nice overlay icons..)?
If a folder contains read only files, Directory.Delete won't delete it and raise the exception you're getting. For future visitors of this page, I've found a simple solution which doesn't require us to recurse through all the files and changing their read-only attribute:
Process.Start("cmd.exe", "/c " + #"rmdir /s/q C:\Test\TestDirectoryContainingReadOnlyFiles");
(Change a bit to not to fire a cmd window momentarily, which is available all over the internet)
Not understanding what you want to do so much, but what about chmoding it to 777 or 775. :-/
Edit:
Noticed your on windows. You'd have to change the permissions. Don't know how windows does that :-/

.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.

Unbelievable strange file creation time problem

I have a very strange problem indeed! I wonder if the problem is in the framework, OS or maybe it's just me, misunderstanding things...
I have a file, which might be created a long time ago, I use the file, and then I want to archive it, by changing it's name. Then I want to create a new file, with the same name as the old file had, before it was renamed. Easy enough!
The problem that really puzzles me, is that the newly created file gets wrong "created"-timestamp! That's a problem since it's that timestamp that I want to use for determing when to archive and create a new file.
I've created a very small sample that shows the problem. For the sample to work, there must be a file 1.txt in the Files folder. Also, the file attribute must also be set back in time (with one of the tools available, I use Nomad.NET).
static void Main(string[] args)
{
// Create a directory, if doesnt exist.
string path = Path.GetDirectoryName(Application.ExecutablePath) + "\\Files";
Directory.CreateDirectory(path);
// Create/attach to the 1.txt file
string filename = path + "\\1.txt";
StreamWriter sw = File.AppendText(filename);
sw.WriteLine("testing");
sw.Flush();
sw.Close();
// Rename it...
File.Move(filename, path + "\\2.txt");
// Create a new 1.txt
sw = File.AppendText(filename);
FileInfo fi = new FileInfo(filename);
// Observe, the old files creation date!!
Console.WriteLine(String.Format("Date: {0}", fi.CreationTime.Date));
Console.ReadKey();
}
This is the result of an arcane "feature" going way back to the old days of Windows. The core details are here:
Windows NT Contains File System Tunneling Capabilities (Archive)
Basically, this is on purpose. But it's configurable, and an anachronism in most of today's software.
I think you can create a new filename first, then rename old->old.1, then new->old, and it'll "work". I don't remember honestly what we did when we ran into this last a few years back.
I recently ran into the same problem described in the question. In our case, if our log file is older than a week, we delete it and start a new one. However, it's been keeping the same date created since 2008.
One answer here describes renaming the old file and then creating a new one, hopefully picking up the proper Creation Date. However, that was unsuccessful for us, it kept the old date still.
What we used was the File.SetCreationTime method, and as its name suggests, it easily let us control the creation date of the file, allowing us to set it to DateTime.Now. The rest of our logic worked correctly afterwards.
File.SetCreationTime("file", DateTime.Now);

Categories