Use relative paths for working directory & start in C# project

5.3k Views Asked by At

In a C# project I try to use relative paths for "Start external program" and for "Working directory".

enter image description here

I tried relative paths starting with ../ and relative paths with $(SolutionDir) / $(ProjectDir)

With all tries I get an error popup. (The external program cannot be found / the working directory you entered does not exist) - see screenshots.

enter image description here

Is it possible to use relative paths and how? I also searched on msdn but there is almost no info about the csproj.user file.

We need this as we don't like to force a folder structure for all developers.

This is stored in the csproj.user file (myproject.csproj.user) like this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProjectView>ProjectFiles</ProjectView>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
    <StartAction>Program</StartAction>
    <StartWorkingDirectory>%24%28SolutionDir%29\..\..\..\..\mydir</StartWorkingDirectory>
    <StartProgram>%24%28SolutionDir%29\..\..\dir\myapplication.exe</StartProgram>
  </PropertyGroup>
</Project>
7

There are 7 best solutions below

0
On BEST ANSWER

I tested all the ideas. Unfortunately none of the answers did work or had enough detail, so I added my own.

  • $(ProjectDir), $(MSBuildProjectDirectory) and $(SolutionDir) won't work. Not in the csproj and not in the csproj.user. Also not escaped, quotes etc. This is clear from the error popup when running:

enter image description here

  • Relative paths does work, but StartProgram and StartWorkingDirectory has different initial directories!

  • StartProgram starts in the directory where the solution file (.sln) is located

  • StartWorkingDirectory starts in the bin directory of the project.

So I have now working for me:

  • Start Program: ..\mydir\myapplication.exe
  • Start Working Directory: ..\..\..\..\..\mydir (same directory as the myapplication.exe)
3
On

I think the problem is that the file/folder controls in the congif window you've shown aren't translating the $(SoultionDir) macro. Don't know how to get round that but, you can probably edit the .csproj.user file, with the following changes to the 2 'offending' lines:

<StartWorkingDirectory>$(SolutionDir)..\..\..\..\mydir</StartWorkingDirectory>
<StartProgram>$(SolutionDir)..\..\dir\myapplication.exe</StartProgram>

Also, note that the $(SolutionDir) macro already ends with a \ so you don't need to have that one immediately after it! Try it and see!

0
On

You might have the wrong motivation:

We need this as we don't like to force a folder structure for all developers.

First of all, if all this you've shown was possible you'll do exactly this - force them to create that structure on their drives. Moreover, they have to create that structure manually because it is located outside of the solution folder, thus not source controlled. I.e., you don't deliver myprogram.exe through the source control (not that the source control is the right place for .exe-s, but that's another question). Finally, the ugly truth is that YOU NEED A FOLDER STRUCTURE of a kind to use whatever tool you need - it must be located somewhere, right? So I propose you to stop fighting your environment and instead get it to work for you.

Designate a folder, relative to your project to contain the tool(s) you need. Then you can use the relative path to reach that folder. By doing so, your motive to not force developers to create a folder structure is also satisfied, because that folder might be uploaded to the source control, hence one can download it by simply getting the latest. Better yet, create a NuGet package and publish it. Then install that NuGet package into the said project and keep your source control clean of .exe-s

3
On

Edit directly in the .csproj file without escaping the characters, like this:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProjectView>ProjectFiles</ProjectView>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
    <StartAction>Program</StartAction>
    <StartWorkingDirectory>$(SolutionDir)..\..\..\..\mydir</StartWorkingDirectory>
    <StartProgram>$(SolutionDir)..\..\dir\myapplication.exe</StartProgram>
  </PropertyGroup>
</Project>

Also there is no need for the slash after $(SolutionDir)

enter image description here

2
On

Try to use tags without condition, like

 <PropertyGroup>
    <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
  </PropertyGroup>

Also, consider using the $(MSBuildProjectDirectory) variable, that is filled by default, when parameters are passed via cli, e.g. dotnet run -p testmvc

0
On

I know this might sound the same as others, I just want to be clear you did exactly this.

You should

  1. close visual studio - it's important as it might override your file if you keep it open
  2. open myproject.csproj.user using notepad.
  3. enter this

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <ProjectView>ProjectFiles</ProjectView>
      </PropertyGroup>
      <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
        <StartAction>Program</StartAction>
        <StartWorkingDirectory>$(SolutionDir)..\..\..\..\mydir</StartWorkingDirectory>
        <StartProgram>$(SolutionDir)..\..\dir\myapplication.exe</StartProgram>
      </PropertyGroup>
    </Project>
    
  4. Close notepad

  5. Open Visual Studio
  6. Go to project properties and confim you see this enter image description here
1
On

.net6 /.net7

In csproj just add, below TargetFramework

<StartWorkingDirectory>$(MSBuildProjectDirectory)</StartWorkingDirectory>