8

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>
Julian
  • 33,915
  • 22
  • 119
  • 174
  • It should work but 1) You *must* unescape the StartProgram value so it appears as is in the Xml. 2) Once you've done that, make sure $(SolutionDir) is really what you think it is (it's not the project directory). To make sure, you can use a tool such as ProcMon from sysinternals, filter on devenv.exe and you should see where it's looking for exactly. – Simon Mourier Aug 17 '19 at 08:02
  • Please explain the downvote / how to improve this question – Julian Aug 18 '19 at 09:20
  • I gave you an upvote - did you try my answer? – Adrian Mole Aug 18 '19 at 20:00
  • Not yet. Will try this week :) – Julian Aug 18 '19 at 20:49

7 Answers7

9

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

Lev
  • 583
  • 3
  • 15
2

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
Adam Marczak
  • 2,257
  • 9
  • 20
1

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!

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • I tested this. Unfortunately It doesn't work. Have you tested it yourself? – Julian Aug 23 '19 at 14:17
  • 1
    I removed the erroneous `"` and `'` characters! I use very similar relative paths in my projects, but with `$(ProjectDir)` rather than `$(SolutionDir)` and they work just fine. – Adrian Mole Aug 23 '19 at 14:30
  • Are you sure that your `$(SolutionDir)` has at least 4 levels of hierarchy? If not, it **will** fail! – Adrian Mole Aug 23 '19 at 14:32
1

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

valerysntx
  • 506
  • 3
  • 7
1

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)
Julian
  • 33,915
  • 22
  • 119
  • 174
0

.net6 /.net7

In csproj just add, below TargetFramework

<StartWorkingDirectory>$(MSBuildProjectDirectory)</StartWorkingDirectory>
Jacob
  • 81
  • 2
  • 8
-1

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

Bozhidar Stoyneff
  • 3,576
  • 1
  • 18
  • 28