nant script c# compilation error - c#

Unfortunately my knowledge of NANT stuff is very limited but embarked today on updating our build to run some code. We use cruisecontrol.
This works fine - however I need to process two folders so was trying to put common code into a traditional c# method.
<echo message="Ensure only 4 directories in the backup directory"/>
<script language="C#">
<code>
<![CDATA[
public static void ScriptMain(Project project)
{
string path = project.Properties["build.ReleasesShareLocation.BackupParent"];
string [] folders = System.IO.Directory.GetDirectories(path,"*", System.IO.SearchOption.TopDirectoryOnly);
System.Collections.ArrayList dirlist = new System.Collections.ArrayList();
foreach (string folder in folders)
{
dirlist.Add(new System.IO.DirectoryInfo(folder));
}
dirlist.Sort(new DirectoryInfoDateComparer());
dirlist.Reverse();
for (int i = 4; i < dirlist.Count; i++)
{
string foldername = ((System.IO.DirectoryInfo)dirlist[i]).Name;
try
{
((System.IO.DirectoryInfo)dirlist[i]).Delete(true);
project.Log(Level.Info, String.Format("Deleted folder {0}", foldername));
}
catch { project.Log(Level.Warning, String.Format("Unable to delete folder {0}", foldername)); }
}
}
internal class DirectoryInfoDateComparer : System.Collections.IComparer
{
public int Compare(object x, object y)
{
System.IO.DirectoryInfo di1 = (System.IO.DirectoryInfo)x;
System.IO.DirectoryInfo di2 = (System.IO.DirectoryInfo)y;
return di1.CreationTime.CompareTo(di2.CreationTime);
}
}
]]>
</code>
</script>
Rather than repeat all the code - I tried to add a static class with a method to do all the processing so that the main only passes the two paths. But in running the build on the server (is there a way for me to "compile" this locally??) it errored.
This is the code that errored - I'm not sure if I've missed a simple syntax error (I did try to copy and paste the code in visual studio to make sure the brackets and stuff matched up) or if there is a different way I need to do it in NANT build..
<echo message="Ensure only 4 directories in the backup directory"/>
<script language="C#">
<code>
<![CDATA[
public static void ScriptMain(Project project)
{
string path = project.Properties["build.ReleasesShareLocation.BackupParent"];
string path2 = project.Properties["build.DeltaScriptFileShareLocation.BackupParent"];
Processor.ProcessFolder(path);
Processor.ProcessFolder(path2);
}
internal static class Processor
{
public static void ProcessFolder(string path)
{
string [] folders = System.IO.Directory.GetDirectories(path,"*", System.IO.SearchOption.TopDirectoryOnly);
System.Collections.ArrayList dirlist = new System.Collections.ArrayList();
foreach (string folder in folders)
{
dirlist.Add(new System.IO.DirectoryInfo(folder));
}
dirlist.Sort(new DirectoryInfoDateComparer());
dirlist.Reverse();
for (int i = 4; i < dirlist.Count; i++)
{
string foldername = ((System.IO.DirectoryInfo)dirlist[i]).Name;
try
{
((System.IO.DirectoryInfo)dirlist[i]).Delete(true);
project.Log(Level.Info, String.Format("Deleted folder {0}", foldername));
}
catch { project.Log(Level.Warning, String.Format("Unable to delete folder {0}", foldername)); }
}
}
}
internal class DirectoryInfoDateComparer : System.Collections.IComparer
{
public int Compare(object x, object y)
{
System.IO.DirectoryInfo di1 = (System.IO.DirectoryInfo)x;
System.IO.DirectoryInfo di2 = (System.IO.DirectoryInfo)y;
return di1.CreationTime.CompareTo(di2.CreationTime);
}
}
]]>
</code>
</script>
Thanks for any assistance :)
Edit:
I went back through the CC logs and re-read the error message - this time understanding what it was trying to tell me. Turns out I needed to pass my new method the Project parameter. :)
Is there a way to be able to compile the code without having to run a build to find errors like this? I tried pasting it into Visual Studio but as I didn't have the Nant library referenced it wasn't highlighting the error effectively. Or is there something you can download and install on a dev machine to reference appropriate dlls?

Go to command prompt, navigate to the folder where you installed NANT, and type in your NANT build command manually, for example:
nant -f:MyBuildFile.build
That way you'll see the errors, and we can help further.

In re-reading the error logs I found within the wall of red text the answer.
Turns out I needed to pass my new method the Project parameter (as I was referring to Project properties).
So problem solved!

Related

System.UnauthorizedAccessException in File.Create c#

Edit: I noticed this doesn't happen when I just do: File.WriteAllText(#"C:\Users\(usr)\Documents\Test\Data\test.txt", "0"); without Globals.dmp so evidently it must be something with Path.Combine() I tried various variations of the composition but with same results.
I want to create a folder and a text file in my c# program made with Visual Studio. What I'm doing is having a check at Form Load to see if the file exists, and if it does not, create the file. I'm doing it like this:
if(!File.Exists(Globals.dmp))
{
File.Create(Globals.dmp);
File.WriteAllText(Globals.dmp, "0");
}
The composition of globals.dmp is the following:
public static string dmp = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Constants.dmp);
While Constants.dmp is like this:
public static string dmp = #"Test\Data\test.txt
This should work, but when I try to run it, Visual studio reports: System.UnauthorizedAccessException: 'Access to the path 'C:\Users\(usr)\Documents\Test\Data\test.txt' is denied.'The line that fails is: File.Create(Globals.dmp);I tried putting File.SetAttributes(Globals.dmp, new FileInfo(Globals.dmp).Attributes | FileAttributes.Normal); above File.Create but the same thing happens. Any insight is greatly appreciated.
Run your visual studio as administrator and see it works or not.
I solved the problem by adapting PathCombineAndCanonicalize1() from the second solution in this question
What I did is:
public static string PathCombineAndCanonicalize1(string path1, string path2)
{
string combined = Path.Combine(path1, path2);
return combined;
}
public partial class ProgramDirectories
{
public static string directory = #"DillData\";
public static string documentspath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
public static string pathforfiles = PathCombineAndCanonicalize1(documentspath, directory);
public static string sps = PathCombineAndCanonicalize1(pathforfiles, Constants.sps);
}
With Constants.sps="text.txt";
And then I could easily do:
if (!Directory.Exists(ProgramDirectories.pathforfiles))
{
Directory.CreateDirectory(ProgramDirectories.pathforfiles);
}
if(!File.Exists(ProgramDirectories.sps)
{
File.WriteAllText(ProgramDirectories.sps, "0");
}

Assembly.Load and its weirdness... "Could not find file or assembly" error

Our localization team was trying to use LocBaml (.NET Framework version, 4.6.1) to localize some resources. They kept on getting errors saying "Could not find file or assembly..." So, I looked into it, saw the note that the x.resources.dll file had to be in same directory as x.dll. ("x" just means some name). Tried that, still go the same error. I then built a debug version and also downloaded the .NET source code. Turns out some exception was occuring in the guts of .NET. If I could summarize, it was failing when trying to do Assembly.Load("x"). So I wrote a program trying to duplicate the situation...
using System;
using System.Reflection;
using System.Linq;
namespace Nothing
{
class Loader
{
public static void Main(string[] args)
{
try
{
if (args.Count() == 1)
{
Assembly asm = Assembly.Load(args[0]);
Console.WriteLine($"Name of asembly: {asm.FullName}");
}
else
{
Console.WriteLine("Need to specify filename");
}
}
catch (Exception x)
{
Console.WriteLine("Exception: {0}", x);
}
}
}
}
The file was named AsmLoader.cs and compiled to AsmLoader.exe.
Well from the directory x.dll was in, I typed in \path\to\AsmLoader.exe x.dll and \path\to\AsmLoader.exe x. Same error, "Could not find file or assembly..."
Looked at the stack trace for the exception and saw that "codebase" was an argument for some function on the stack. Gave it a thought, and copied AsmLoader.exe to the same directory as x.dll.
Gave .\AsmLoader.exe x.dll a try..still same error. Remembered that the argument to the exception was just "x". Tried .\AsmLoader.exe x .... bingo... worked. For grins, copied LocBaml.exe and it's .config file to the same directory, and tried .\LocBaml x.resources.dll ... ding, ding, ding... success. Finally.
So, for now, I'll just tell the localiztion team to copy LocBaml to the same directory as the files and all should be good.
However, I can't help but feel this could somehow be solved with code. How can I make changes to the code in the example so that AsmLoader.exe doesn't have to be in the same directory as the DLL I want to load? I had even changed my path environment variable to ensure AsmLoader.exe and both x.dll directories were in the path. That didn't work...
So what do I need to change for it to work in my base program...and then maybe I can do the same for LocBaml...???
Well, I came up with a solution to add an AssemblyResolve event handler to the current app domain. Solved it for this simple example and my rebuilt LocBaml...
In main, add:
AppDomain.CurrentDomain.AssemblyResolve += LoadFromCurrentDirectory;
Implement LoadFromCurrentDirectly like:
static Assembly LoadFromCurrentDirectory(object sender, ResolveEventArgs args)
{
string name = args.Name;
bool bCheckVersion = false;
int idx = name.IndexOf(',');
if (idx != -1)
{
name = name.Substring(0, idx);
bCheckVersion = true;
}
string sCurrentDir = Directory.GetCurrentDirectory();
if (!name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && !name.EndsWith(".exe"))
{
string[] exts = { ".dll", ".exe" };
foreach( string ext in exts)
{
string tryPath = Path.Combine(sCurrentDir, name + ext);
if (File.Exists(tryPath))
{
name = name += ext;
break;
}
}
}
string path = Path.Combine(sCurrentDir, name);
if (!string.IsNullOrEmpty(path) && File.Exists(path))
{
Assembly assembly = Assembly.LoadFrom(path);
if (assembly != null & bCheckVersion)
{
if (assembly.FullName != args.Name)
return null;
}
return assembly;
}
else
{
var reqAsm = args.RequestingAssembly;
if (reqAsm != null)
{
string requestingName = reqAsm.GetName().FullName;
Console.WriteLine($"Could not resolve {name}, {path}, requested by {requestingName}");
}
else
{
Console.WriteLine($"Could not resolve {args.Name}, {path}");
}
}
return null;
}
I'm sure it could be optimized to add a global list of directories, or to use the path when searching for files to load. However, for our use case, works just fine. When I added it to our LocBaml code, it solved the loading problem for us...also got rid of necessity of copying the en\x.resources.dll files to our output directory. As long as we run the program from the output directory, LocBaml finishes parsing.

Quantum Program The name 'BellTest' does not exist in the current context

This is my first Q# program and i'm following this getting started link.https://learn.microsoft.com/en-us/quantum/quantum-writeaquantumprogram?view=qsharp-preview
Error is
The name 'BellTest' does not exist in the current context
but its defined in the Bell.cs
I followed the steps and when building its having errors. I'm not sure how to import the operations from .qs file to driver c# file as this error looks like it can't find that operation.
Any help is really appreciated
Here is the code
Driver.cs
using Microsoft.Quantum.Simulation.Core;
using Microsoft.Quantum.Simulation.Simulators;
namespace Quantum.Bell
{
class Driver
{
static void Main(string[] args)
{
using (var sim = new QuantumSimulator())
{
// Try initial values
Result[] initials = new Result[] { Result.Zero, Result.One };
foreach (Result initial in initials)
{
var res = BellTest.Run(sim, 1000, initial).Result;
var (numZeros, numOnes) = res;
System.Console.WriteLine(
$"Init:{initial,-4} 0s={numZeros,-4} 1s={numOnes,-4}");
}
}
System.Console.WriteLine("Press any key to continue...");
System.Console.ReadKey();
}
}
}
Bell.qs
namespace Quantum.Bell
{
open Microsoft.Quantum.Primitive;
open Microsoft.Quantum.Canon;
operation Set (desired:Result,q1:Qubit) : ()
{
body
{
let current = M(q1);
if (desired != current)
{
X(q1);
}
}
}
operation BellTest (count : Int, initial: Result) : (Int,Int)
{
body
{
mutable numOnes = 0;
using (qubits = Qubit[1])
{
for (test in 1..count)
{
Set (initial, qubits[0]);
let res = M (qubits[0]);
// Count the number of ones we saw:
if (res == One)
{
set numOnes = numOnes + 1;
}
}
Set(Zero, qubits[0]);
}
// Return number of times we saw a |0> and number of times we saw a |1>
return (count-numOnes, numOnes);
}
}
}
I also got the same error, but I was able to do it by pressing the F5 key.
Perhaps the Visual Studio editor is not yet fully support to the .qs file.
Namespace sharing does not seem to be working properly between .cs file and .qs file.
I was able to execute using your code in my development environment.
--
IDE: Visual Studio Community 2017 (Version 15.5.2)
Dev Kit: Microsoft Quantum Development Kit (0 and 1)
I engage the same problem in microsoft.quantum.development.kit/0.3.1811.203-preview version.
The BellTest operation cannot recognised by VSC Pic of VSCode
What I do is,
save all but keep VSCode open
go to directory and delete anything in bin/ obj/ by /bin/rm -rf bin obj
dotnet run
you go back to check VSCode, the BellTest recognised by VSC now.

AppDomain.CurrentDomain.BaseDirectory does not return same folder for UnitTesting project [duplicate]

I have a web project like:
namespace Web
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
lbResult.Text = PathTest.GetBasePath();
}
}
}
The method PathTest.GetBasePath() is defined in another Project like:
namespace TestProject
{
public class PathTest
{
public static string GetBasePath()
{
return AppDomain.CurrentDomain.BaseDirectory;
}
}
}
Why it's display ...\Web\ while the TestProject assembly is compiled into bin folder(in other words it should display ...\Web\bin in my thought).
Now I got a troublesome if I modified method into:
namespace TestProject
{
public class FileReader
{
private const string m_filePath = #"\File.config";
public static string Read()
{
FileStream fs = null;
fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + m_filePath,FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fs);
return reader.ReadToEnd();
}
}
}
The File.config is created in TestProject. Now AppDomain.CurrentDomain.BaseDirectory + m_filePath will returen ..\Web\File.config (actually the file was be copied into ..\Web\bin\File.config), an exception will be thrown.
You could say that I should modified m_filePath to #"\bin\File.config". However If I use this method in a Console app in your suggest, AppDomain.CurrentDomain.BaseDirectory + m_filePath will return ..\Console\bin\Debug\bin\File.config (actually the file was copyed into .\Console\bin\Debug\File.config), an exception will be thrown due to surplus bin.
In other words, in web app, AppDomain.CurrentDomain.BaseDirectory is a different path where file be copyed into (lack of /bin), but in console app it's the same one path.
Any one can help me?
Per MSDN, an App Domain "Represents an application domain, which is an isolated environment where applications execute." When you think about an ASP.Net application the root where the app resides is not the bin folder. It is totally possible, and in some cases reasonable, to have no files in your bin folder, and possibly no bin folder at all. Since AppDomain.CurrentDomain refers to the same object regardless of whether you call the code from code behind or from a dll in the bin folder you will end up with the root path to the web site.
When I've written code designed to run under both asp.net and windows apps usually I create a property that looks something like this:
public static string GetBasePath()
{
if(System.Web.HttpContext.Current == null) return AppDomain.CurrentDomain.BaseDirectory;
else return Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"bin");
}
Another (untested) option would be to use:
public static string GetBasePath()
{
return System.Reflection.Assembly.GetExecutingAssembly().Location;
}
In case you want a solution that works for WinForms and Web Apps:
public string ApplicationPath
{
get
{
if (String.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath))
{
//exe folder for WinForms, Consoles, Windows Services
return AppDomain.CurrentDomain.BaseDirectory;
}
else
{
//bin folder for Web Apps
return AppDomain.CurrentDomain.RelativeSearchPath;
}
}
}
The above code snippet is for binaries locations.
The AppDomain.CurrentDomain.BaseDirectory is still a valid path for Web Apps, it's just the root folder where the web.config and Global.asax are, and is same as Server.MapPath(#"~\");
If you use AppDomain.CurrentDomain.SetupInformation.PrivateBinPath instead of BaseDirectory, then you should get the correct path.
When ASP.net builds your site it outputs build assemblies in its special place for them. So getting path in that way is strange.
For asp.net hosted applications you can use:
string path = HttpContext.Current.Server.MapPath("~/App_Data/somedata.xml");

How do you get the current project directory from C# code when creating a custom MSBuild task?

Instead of running an external program with its path hardcoded, I would like to get the current Project Dir. I'm calling an external program using a process in the custom task.
How would I do that? AppDomain.CurrentDomain.BaseDirectory just gives me the location of VS 2008.
using System;
using System.IO;
// This will get the current WORKING directory (i.e. \bin\Debug)
string workingDirectory = Environment.CurrentDirectory;
// or: Directory.GetCurrentDirectory() gives the same result
// This will get the current PROJECT bin directory (ie ../bin/)
string projectDirectory = Directory.GetParent(workingDirectory).Parent.FullName;
// This will get the current PROJECT directory
string projectDirectory = Directory.GetParent(workingDirectory).Parent.Parent.FullName;
You can try one of this two methods.
string startupPath = System.IO.Directory.GetCurrentDirectory();
string startupPath = Environment.CurrentDirectory;
Tell me, which one seems to you better
If a project is running on an IIS express, the Environment.CurrentDirectory could point to where IIS Express is located ( the default path would be C:\Program Files (x86)\IIS Express ), not to where your project resides.
This is probably the most suitable directory path for various kinds of projects.
AppDomain.CurrentDomain.BaseDirectory
This is the MSDN definition.
Gets the base directory that the assembly resolver uses to probe for assemblies.
The proper1 way to get the root folder of a C# project is to leverage the [CallerFilePath] attribute to obtain the full path name of a source file, and then subtract the filename plus extension from it, leaving you with the path to the project.
Here is how to actually do it:
In the root folder of your project, add file ProjectSourcePath.cs with the following content:
internal static class ProjectSourcePath
{
private const string myRelativePath = nameof(ProjectSourcePath) + ".cs";
private static string? lazyValue;
public static string Value => lazyValue ??= calculatePath();
private static string calculatePath()
{
string pathName = GetSourceFilePathName();
Assert( pathName.EndsWith( myRelativePath, StringComparison.Ordinal ) );
return pathName.Substring( 0, pathName.Length - myRelativePath.Length );
}
}
The string? requires a pretty late version of C# with #nullable enable; if you don't have it, then just remove the ?.
The Assert() function is my own; you can replace it with your own, or omit it, if you like living your life dangerously.
The function GetSourceFilePathName() is defined as follows:
using System.Runtime.CompilerServices
public static string GetSourceFilePathName( [CallerFilePath] string? callerFilePath = null ) //
=> callerFilePath ?? "";
Once you have the above, you can use it as follows:
string projectSourcePath = ProjectSourcePath.Value;
1 'proper' as in: fool-proof; sure-fire; without presumptions; not being held together by shoestrings; not bound to work for some projects but fail for others; not likely to horribly break without a warning when you change unrelated things; etc.
This will also give you the project directory by navigating two levels up from the current executing directory (this won't return the project directory for every build, but this is the most common).
System.IO.Path.GetFullPath(#"..\..\")
Of course you would want to contain this inside some sort of validation/error handling logic.
If you want ot know what is the directory where your solution is located, you need to do this:
var parent = Directory.GetParent(Directory.GetCurrentDirectory()).Parent;
if (parent != null)
{
var directoryInfo = parent.Parent;
string startDirectory = null;
if (directoryInfo != null)
{
startDirectory = directoryInfo.FullName;
}
if (startDirectory != null)
{ /*Do whatever you want "startDirectory" variable*/}
}
If you let only with GetCurrrentDirectory() method, you get the build folder no matter if you are debugging or releasing. I hope this help! If you forget about validations it would be like this:
var startDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.FullName;
Based on Gucu112's answer, but for .NET Core Console/Window application, it should be:
string projectDir =
Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"..\..\.."));
I'm using this in a xUnit project for a .NET Core Window Application.
If you really want to ensure you get the source project directory, no matter what the bin output path is set to:
Add a pre-build event command line (Visual Studio: Project properties -> Build Events):
echo $(MSBuildProjectDirectory) > $(MSBuildProjectDirectory)\Resources\ProjectDirectory.txt
Add the ProjectDirectory.txt file to the Resources.resx of the project (If it doesn't exist yet, right click project -> Add new item -> Resources file)
Access from code with Resources.ProjectDirectory.
This solution works well for me, on Develop and also on TEST and PROD servers with ASP.NET MVC5 via C#:
var projectDir = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
If you need project directory in project configuration file use:
$(ProjectDir)
I was looking for this too. I've got a project that runs HWC, and I'd like to keep the web site out of the app tree, but I don't want to keep it in the debug (or release) directory. FWIW, the accepted solution (and this one as well) only identifies the directory the executable is running in.
To find that directory, I've been using
string startupPath = System.IO.Path.GetFullPath(".\\").
using System;
using System.IO;
// Get the current directory and make it a DirectoryInfo object.
// Do not use Environment.CurrentDirectory, vistual studio
// and visual studio code will return different result:
// Visual studio will return #"projectDir\bin\Release\netcoreapp2.0\", yet
// vs code will return #"projectDir\"
var currentDirectory = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
// On windows, the current directory is the compiled binary sits,
// so string like #"bin\Release\netcoreapp2.0\" will follow the project directory.
// Hense, the project directory is the great grand-father of the current directory.
string projectDirectory = currentDirectory.Parent.Parent.Parent.FullName;
I had a similar situation, and after fruitless Googles, I declared a public string, which mods a string value of the debug / release path to get the project path. A benefit of using this method is that since it uses the currect project's directory, it matters not if you are working from a debug directory or a release directory:
public string DirProject()
{
string DirDebug = System.IO.Directory.GetCurrentDirectory();
string DirProject = DirDebug;
for (int counter_slash = 0; counter_slash < 4; counter_slash++)
{
DirProject = DirProject.Substring(0, DirProject.LastIndexOf(#"\"));
}
return DirProject;
}
You would then be able to call it whenever you want, using only one line:
string MyProjectDir = DirProject();
This should work in most cases.
Another way to do this
string startupPath = System.IO.Directory.GetParent(#"./").FullName;
If you want to get path to bin folder
string startupPath = System.IO.Directory.GetParent(#"../").FullName;
Maybe there are better way =)
Yet another imperfect solution (but perhaps a little closer to perfect than some of the others):
protected static string GetSolutionFSPath() {
return System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.Parent.FullName;
}
protected static string GetProjectFSPath() {
return String.Format("{0}\\{1}", GetSolutionFSPath(), System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
}
This version will return the current projects' folder even if the current project is not the Startup Project for the solution.
The first flaw with this is that I've skipped all error checking. That can be fixed easy enough but should only be a problem if you're storing your project in the root directory for the drive or using a junction in your path (and that junction is a descendant of the solution folder) so this scenario is unlikely. I'm not entirely sure that Visual Studio could handle either of these setups anyway.
Another (more likely) problem that you may run into is that the project name must match the folder name for the project for it to be found.
Another problem you may have is that the project must be inside the solution folder. This usually isn't a problem but if you've used the Add Existing Project to Solution option to add the project to the solution then this may not be the way your solution is organized.
Lastly, if you're application will be modifying the working directory, you should store this value before you do that because this value is determined relative to the current working directory.
Of course, this all also means that you must not alter the default values for your projects' Build->Output path or Debug->Working directory options in the project properties dialog.
Try this, its simple
HttpContext.Current.Server.MapPath("~/FolderName/");
string projPath = Path.GetFullPath(#"..\..\..\");
Console.WriteLine(projPath);
This consistently works well for me. Give it a go.
After I had finally finished polishing my first answer regarding the us of public strings to derive an answer, it dawned on me that you could probably read a value from the registry to get your desired result. As it turns out, that route was even shorter:
First, you must include the Microsoft.Win32 namespace so you can work with the registry:
using Microsoft.Win32; // required for reading and / or writing the registry
Here is the main code:
RegistryKey Projects_Key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\VisualStudio\9.0", false);
string DirProject = (string)Projects_Key.GetValue(#"DefaultNewProjectLocation");
A note on this answer:
I am using Visual Studio 2008 Professional Edition. If you are using another version, (i.e. 2003, 2005, 2010; etc.), then you mayt have to modify the 'version' part of the SubKey string (i.e. 8.0, 7.0; etc.).
If you use one of my answers, and if it is not too much to ask, then I would like to know which of my methods you used and why. Good luck.
dm
Use this to get the Project directory (worked for me):
string projectPath =
Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
I have used following solution to get the job done:
string projectDir =
Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"..\.."));
Try:
var pathRegex = new Regex(#"\\bin(\\x86|\\x64)?\\(Debug|Release)$", RegexOptions.Compiled);
var directory = pathRegex.Replace(Directory.GetCurrentDirectory(), String.Empty);
This is solution different from the others does also take into account possible x86 or x64 build.
(Because 22 answers are not enough... here's one more....)
Mike Nakis posted a great answer, to which I added a few enhancements. This is just a slightly spiffed up version of his very nice code.
As Mike pointed out, this class file must be in the root of the project.
I did not run into any problems with the below, but perhaps there are nuances I'm not aware of. YMMV.
using System.IO;
using System.Runtime.CompilerServices;
namespace Whatever
{
internal static class ProjectPathInfo
{
public static string CSharpClassFileName = nameof(ProjectPathInfo) + ".cs";
public static string CSharpClassPath;
public static string ProjectPath;
public static string SolutionPath;
static ProjectPathInfo() {
CSharpClassPath = GetSourceFilePathName();
ProjectPath = Directory.GetParent(CSharpClassPath)!.FullName;
SolutionPath = Directory.GetParent(ProjectPath)!.FullName;
}
private static string GetSourceFilePathName( [CallerFilePath] string? callerFilePath = null ) => callerFilePath ?? "";
}
}
Ok, 2021, a bit late to the party... but very annoyed by all possibilities I found in many projects:
bin/Debug
bin/x86/Debug
bin/Debug/net5.0-windows
...
Come on... I just need a one-liner (or almost) to address some files in test units; I need to use it on all past, current, (maybe future) projects.
So, if the project name is the same of relative folder which it lies in:
use the assembly name to pick project root folder name;
go back until that name is found.
Code sample:
string appName = Assembly.GetExecutingAssembly().GetName().Name;
var dir = new DirectoryInfo(Environment.CurrentDirectory);
while (dir.Name != appName) {
dir = Directory.GetParent(dir.FullName);
}
return dir.FullName;
The best solution
string PjFolder1 =
Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).
Parent.Parent.FullName;
Other solution
string pjFolder2 = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)));
Test it, AppDomain.CurrentDomain.BaseDirectory worked for me on past project, now I get debug folder .... the selected GOOD answer just NOT WORK!.
//Project DEBUG folder, but STILL PROJECT FOLDER
string pjDebugFolder = AppDomain.CurrentDomain.BaseDirectory;
//Visual studio folder, NOT PROJECT FOLDER
//This solutions just not work
string vsFolder = Directory.GetCurrentDirectory();
string vsFolder2 = Environment.CurrentDirectory;
string vsFolder3 = Path.GetFullPath(".\\");
//Current PROJECT FOLDER
string ProjectFolder =
//Get Debug Folder object from BaseDirectory ( the same with end slash)
Directory.GetParent(pjDebugFolder).
Parent.//Bin Folder object
Parent. //Project Folder object
FullName;//Project Folder complete path
This works on VS2017 w/ SDK Core MSBuild configurations.
You need to NuGet in the EnvDTE / EnvDTE80 packages.
Do not use COM or interop. anything.... garbage!!
internal class Program {
private static readonly DTE2 _dte2;
// Static Constructor
static Program() {
_dte2 = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.15.0");
}
private static void FindProjectsIn(ProjectItem item, List<Project> results) {
if (item.Object is Project) {
var proj = (Project) item.Object;
if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
results.Add((Project) item.Object);
else
foreach (ProjectItem innerItem in proj.ProjectItems)
FindProjectsIn(innerItem, results);
}
if (item.ProjectItems != null)
foreach (ProjectItem innerItem in item.ProjectItems)
FindProjectsIn(innerItem, results);
}
private static void FindProjectsIn(UIHierarchyItem item, List<Project> results) {
if (item.Object is Project) {
var proj = (Project) item.Object;
if (new Guid(proj.Kind) != new Guid(Constants.vsProjectItemKindPhysicalFolder))
results.Add((Project) item.Object);
else
foreach (ProjectItem innerItem in proj.ProjectItems)
FindProjectsIn(innerItem, results);
}
foreach (UIHierarchyItem innerItem in item.UIHierarchyItems)
FindProjectsIn(innerItem, results);
}
private static IEnumerable<Project> GetEnvDTEProjectsInSolution() {
var ret = new List<Project>();
var hierarchy = _dte2.ToolWindows.SolutionExplorer;
foreach (UIHierarchyItem innerItem in hierarchy.UIHierarchyItems)
FindProjectsIn(innerItem, ret);
return ret;
}
private static void Main() {
var projects = GetEnvDTEProjectsInSolution();
var solutiondir = Path.GetDirectoryName(_dte2.Solution.FullName);
// TODO
...
var project = projects.FirstOrDefault(p => p.Name == <current project>);
Console.WriteLine(project.FullName);
}
}
I didn't see a solution by using string.Join and string.Split + SkipLast 4 elements, so here it is.
string projectDir =
string.Join('/', AppDomain.CurrentDomain.BaseDirectory
.Split(new char[] { '/' })
.SkipLast(4));
/* /home/freephoenix888/Programming/csharpProject/bin/Debug/net7.0/csharpProject */
Console.WriteLine(Environment.CurrentDirectory);
/* /home/freephoenix888/Programming/csharpProject/ */
Console.WriteLine(Directory.GetParent(Environment.CurrentDirectory).Parent.Parent.Parent.FullName);
Try:
{
OpenFileDialog fd = new OpenFileDialog();
fd.Multiselect = false;
fd.Filter = "Image files (*.bmp, *.jpg)|*.bmp;*.jpg|All files (*.*)|*.*";
if (fd.ShowDialog() == true)
{
if (fd.CheckFileExists)
{
var fileNameToSave = GetTimestamp(DateTime.Now) + Path.GetExtension(fd.FileName);
var pathRegex = new Regex(#"\\bin(\\x86|\\x64)?\\(Debug|Release)$", RegexOptions.Compiled);
var directory = pathRegex.Replace(Directory.GetCurrentDirectory(), String.Empty);
var imagePath = Path.Combine(directory + #"\Uploads\" + fileNameToSave);
File.Copy(fd.FileName, imagePath);
}
}
}
catch (Exception ex)
{
throw ex;
}
this is the code for uploading image into wpf upload directory
Directory.GetParent(Directory.GetCurrentDirectory()).Parent.Parent.Parent.Parent.FullName
Will give you the project directory.

Categories

Resources