c# get value from registry without parameters - c#

I am trying to get the path to AcroRd32.exe by invoking the following code:
public static string acrobatPath = Registry.GetValue(#"HKEY_CLASSES_ROOT\Applications\AcroRD32.exe\shell\Read\command", "", 0).ToString();
What I receive is the right value:
"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe" "%1"
but I want only the path to AcroRd32.exe without "%1".
I could now use the split command:
public static string acrobatPath = Registry.GetValue(#"HKEY_CLASSES_ROOT\Applications\AcroRD32.exe\shell\Read\command", "", 0).ToString();
string[] split = new string[2];
split = acrobatPath.Split('"');
// mask path with ""
acrobatPath = "\"" + split[1] + "\""; //get only path
but the value acrobatPath cannot be changed because of static attribute.
I also cannot use substr() because path can differ e.g. if there is no parameter at the end ("%1").
How can I extract the path and set the static variable in one go?

Use static constructor for your class, and do all the work for string manipulation there.
class YourClass
{
public static string acrobatPath;
// This static constructor will be called before first access to your type.
static YourClass()
{
acrobatPath = Registry.GetValue(#"HKEY_CLASSES_ROOT\Applications\AcroRD32.exe\shell\Read\command", "", 0).ToString();
string[] split = new string[2];
split = acrobatPath.Split('"');
// mask path with ""
acrobatPath = "\"" + split[1] + "\""; //get only path
}
}

but the value acrobatPath cannot be changed because of static attribute.
This statement makes no sense. You can change a static variable. The way your using the static string to be set the to the value of the register key ( which isn't going to change if it does exist ) is the reason you cannot change it.
The solution would be to change how the code works to be a method.
As you have already accepted Vladimir Perevalov's answer I won't go into a great amount of detail. What I would do is the following:
1) Get the installation directory of Adobe Reader by reading the installation directory. I would set this to a variable which I was able to modify at will.
2) I would modify the string only to get the path
3) I would set the current value of this string I just create to the static variable.
This does exactly what Vladimir Perevalov's code does, it simply uses a function, instead of a class. Of course the method would be static and in the same class as the static variable. Of course there is nothing wrong with using a STATIC constructor, I always have considered a constructor to be a specialized method, I just wanted to point out you CAN modify a static variable.

Related

Unable to parse simple command line with commandlineparser

I have to parse an imposed command line which mix single/double dash args, args with = or as separator,etc (not very proper....)
The command line is like myexe.exe -Url=https://blabla.com/ --TestValue=val1 -monoapp -Ctx "default ctx" Open -Test2=CO0ZJP6f-ca
I'm trying to do that with commandlineparser.
(I suppose it's able to manage that, right ? )
So first I'm trying to parse the first parameter (myexe.exe -Url=https://blabla.com/).
public class CommandLineOptions
{
[Option("Url", Required = true)]
public string Url { get; set; }
}
....... In another file but in the same assembly
static void Main(string[] args) // args[0] = "-Url=https://blabla.com/"
{
var commandLineOptions = new CommandLineOptions();
var parseResult = Parser.Default.ParseArguments<CommandLineOptions>(args).WithParsed(result => commandLineOptions = result);
System.Console.WriteLine(parseResult.Tag); //NotParsed
System.Console.WriteLine(commandLineOptions.Url);
}
With that code, I have 2 errors CommandLine.MissingRequiredOptionError and CommandLine.UnknownOptionError.
(The MissingRequiredOptionError is produced beacause it cannot find the Url parameter)
So do you know where is my mistake ?
Thanks in advance for your help ;)
So final dev from commandlineparser said it isn't possible to parse it.
A single line option must be one char option.
The only way to bypass that is to preprocess the arguments.
I did this, it's working but it not allow short option composition (like in tar -xvf for example)
args = args.Select(arg => Regex.IsMatch(arg, "^-\\w{2,}") ? "-" + arg : arg ).ToArray();

Path.Combine() returns unexpected results

I'm trying to create a path using Path.Combine() but I am getting unexpected results.
using System;
using System.IO;
namespace PathCombine_Delete
{
class Program
{
static void Main(string[] args)
{
string destination = "D:\\Directory";
string destination02 = "it";
string path = "L:\\MyFile.pdf";
string sourcefolder = "L:\\";//In other instances, it could be L:\\SomeFolder\AndMayBeAnotherFolder
string replacedDetails = path.Replace(sourcefolder + "\\", "");
string result = Path.Combine(destination, destination02, replacedDetails);
Console.WriteLine(result);
Console.ReadKey();//Keep it on screen
}
}
}
I would expect the result D:\\Directory\it\MyFile.pdf but instead, I get L:\MyFile.pdf
I can't see why? I admit it's late in the evening here, but still, I've used Path.Combine many times, and since .NET 4.0 it allows the string param to be passed. However, it appears to be ignoring the first 2 and only reading the last.
Here is the error
string replacedDetails = path.Replace(sourcefolder + "\\" , "");
You are adding another backslash and nothing is found to be replaced.
Removing the added backslash gives the correct string to search for and replace
string replacedDetails = path.Replace(sourcefolder , "");
however you could avoid all that replace stuff and intermediate variables just with
string result = Path.Combine(destination, destination02, Path.GetFileName(path));
I would recommend using:
string replacedDetails = Path.GetFileName(path);
That will handle removing the source folder from the path without using string replacement, which isn't necessarily reliable if you're getting the path from elsewhere (eventually).
Have you read the documentation? Have you verified what you're passing to Path.Combine()? The documentation says, and I quote:
path1 should be an absolute path (for example, "d:\archives" or "\archives\public").
If path2 or path3 is also an absolute path, the combine operation discards all
previously combined paths and resets to that absolute path.
That should hint at the problem.

How to get the second to last directory in a path string in C#

For example,
string path = #"C:\User\Desktop\Drop\images\";
I need to get only #"C:\User\Desktop\Drop\
Is there any easy way of doing this?
You can use the Path and Directory classes:
DirectoryInfo parentDir = Directory.GetParent(Path.GetDirectoryName(path));
string parent = parentDir.FullName;
Note that you would get a different result if the path doesn't end with the directory-separator char \. Then images would be understood as filename and not as directory.
You can also use a subsequent call of Path.GetDirectoryName
string parent = Path.GetDirectoryName(Path.GetDirectoryName(path));
This behaviour is documented here:
Because the returned path does not include the DirectorySeparatorChar
or AltDirectorySeparatorChar, passing the returned path back into the
GetDirectoryName method will result in the truncation of one folder
level per subsequent call on the result string. For example, passing
the path "C:\Directory\SubDirectory\test.txt" into the
GetDirectoryName method will return "C:\Directory\SubDirectory".
Passing that string, "C:\Directory\SubDirectory", into
GetDirectoryName will result in "C:\Directory".
This will return "C:\User\Desktop\Drop\" e.g. everything but the last subdir
string path = #"C:\User\Desktop\Drop\images";
string sub = path.Substring(0, path.LastIndexOf(#"\") + 1);
Another solution if you have a trailing slash:
string path = #"C:\User\Desktop\Drop\images\";
var splitedPath = path.Split('\\');
var output = String.Join(#"\", splitedPath.Take(splitedPath.Length - 2));
var parent = "";
If(path.EndsWith(System.IO.Path.DirectorySeparatorChar) || path.EndsWith(System.IO.Path.AltDirectorySeparatorChar))
{
parent = Path.GetDirectoryName(Path.GetDirectoryName(path));
parent = Directory.GetParent(Path.GetDirectoryName(path)).FullName;
}
else
parent = Path.GetDirectoryName(path);
As i commented GetDirectoryName is self collapsing it returns path without tralling slash - allowing to get next directory.Using Directory.GetParent for then clouse is also valid.
Short Answer :)
path = Directory.GetParent(Directory.GetParent(path)).ToString();
Example on the bottom of the page probably will help:
http://msdn.microsoft.com/en-us/library/system.io.path.getdirectoryname(v=vs.110).aspx
using System;
namespace Programs
{
public class Program
{
public static void Main(string[] args)
{
string inputText = #"C:\User\Desktop\Drop\images\";
Console.WriteLine(inputText.Substring(0, 21));
}
}
}
Output:
C:\User\Desktop\Drop\
There is probably some simple way to do this using the File or Path classes, but you could also solve it by doing something like this (Note: not tested):
string fullPath = "C:\User\Desktop\Drop\images\";
string[] allDirs = fullPath.split(System.IO.Path.PathSeparator);
string lastDir = allDirs[(allDirs.length - 1)];
string secondToLastDir= allDirs[(allDirs.length - 2)];
// etc...

Remove part of the full directory name?

I have a list of filename with full path which I need to remove the filename and part of the file path considering a filter list I have.
Path.GetDirectoryName(file)
Does part of the job but I was wondering if there is a simple way to filter the paths using .Net 2.0 to remove part of it.
For example:
if I have the path + filename equal toC:\my documents\my folder\my other folder\filename.exe and all I need is what is above my folder\ means I need to extract only my other folder from it.
UPDATE:
The filter list is a text box with folder names separated by a , so I just have partial names on it like the above example the filter here would be my folder
Current Solution based on Rob's code:
string relativeFolder = null;
string file = #"C:\foo\bar\magic\bar.txt";
string folder = Path.GetDirectoryName(file);
string[] paths = folder.Split(Path.DirectorySeparatorChar);
string[] filterArray = iFilter.Text.Split(',');
foreach (string filter in filterArray)
{
int startAfter = Array.IndexOf(paths, filter) + 1;
if (startAfter > 0)
{
relativeFolder = string.Join(Path.DirectorySeparatorChar.ToString(), paths, startAfter, paths.Length - startAfter);
break;
}
}
How about something like this:
private static string GetRightPartOfPath(string path, string startAfterPart)
{
// use the correct seperator for the environment
var pathParts = path.Split(Path.DirectorySeparatorChar);
// this assumes a case sensitive check. If you don't want this, you may want to loop through the pathParts looking
// for your "startAfterPath" with a StringComparison.OrdinalIgnoreCase check instead
int startAfter = Array.IndexOf(pathParts, startAfterPart);
if (startAfter == -1)
{
// path not found
return null;
}
// try and work out if last part was a directory - if not, drop the last part as we don't want the filename
var lastPartWasDirectory = pathParts[pathParts.Length - 1].EndsWith(Path.DirectorySeparatorChar.ToString());
return string.Join(
Path.DirectorySeparatorChar.ToString(),
pathParts, startAfter,
pathParts.Length - startAfter - (lastPartWasDirectory?0:1));
}
This method attempts to work out if the last part is a filename and drops it if it is.
Calling it with
GetRightPartOfPath(#"C:\my documents\my folder\my other folder\filename.exe", "my folder");
returns
my folder\my other folder
Calling it with
GetRightPartOfPath(#"C:\my documents\my folder\my other folder\", "my folder");
returns the same.
you could use this method to split the path by "\" sign (or "/" in Unix environments). After this you get an array of strings back and you can pick what you need.
public static String[] SplitPath(string path)
{
String[] pathSeparators = new String[]
{
Path.DirectorySeparatorChar.ToString()
};
return path.Split(pathSeparators, StringSplitOptions.RemoveEmptyEntries);
}

Get source code filename of file from a type in debug build

Given a Type object in .NET, is it possible for me to get the source code filename? I know this would only be available in Debug builds and that's fine, I also know that I can use the StackTrace object to get the filename for a particular frame in a callstack, but that's not what I want.
But is it possible for me to get the source code filename for a given System.Type?
I encountered a similar problem. I needed to found the file name and line number of a specific method with only the type of the class and the method name. I'm on an old mono .net version (unity 4.6). I used the library cecil, it provide some helper to analyse your pbd (or mdb for mono) and analyse debug symbols. https://github.com/jbevain/cecil/wiki
For a given type and method:
System.Type myType = typeof(MyFancyClass);
string methodName = "DoAwesomeStuff";
I found this solution:
Mono.Cecil.ReaderParameters readerParameters = new Mono.Cecil.ReaderParameters { ReadSymbols = true };
Mono.Cecil.AssemblyDefinition assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(string.Format("Library\\ScriptAssemblies\\{0}.dll", assemblyName), readerParameters);
string fileName = string.Empty;
int lineNumber = -1;
Mono.Cecil.TypeDefinition typeDefinition = assemblyDefinition.MainModule.GetType(myType.FullName);
for (int index = 0; index < typeDefinition.Methods.Count; index++)
{
Mono.Cecil.MethodDefinition methodDefinition = typeDefinition.Methods[index];
if (methodDefinition.Name == methodName)
{
Mono.Cecil.Cil.MethodBody methodBody = methodDefinition.Body;
if (methodBody.Instructions.Count > 0)
{
Mono.Cecil.Cil.SequencePoint sequencePoint = methodBody.Instructions[0].SequencePoint;
fileName = sequencePoint.Document.Url;
lineNumber = sequencePoint.StartLine;
}
}
}
I know it's a bit late :) but I hope this will help somebody!
Considering that at least C# supports partial class declarations (say, public partial class Foo in two source code files), what would "the source code filename for a given System.Type" mean? If a type declaration is spread out over multiple source code files within the same assembly, there is no single point in the source code where the declaration begins.
#Darin Dimitrov: This doesn't seem like a duplicate of "How to get the source file name and the line number of a type member?" to me, since that is about a type member, whereas this question is about a type.
I've used code like this to get a source file and line number from the method that is running:
//must use the override with the single boolean parameter, set to true, to return additional file and line info
System.Diagnostics.StackFrame stackFrame = (new System.Diagnostics.StackTrace(true)).GetFrames().ToList().First();
//Careful: GetFileName can return null even though true was specified in the StackTrace above. This may be related to the OS on which this is running???
string fileName = stackFrame.GetFileName();
string process = stackFrame.GetMethod().Name + " (" + (fileName == null ? "" : fileName + " ") + fileLineNumber + ")";

Categories