app data path during development versus deployment

2019-09-07 20:52发布

问题:

I have an old Windows Forms .Net application that on Windows XP was "deployed" by copying all the files to the application folder.

Now I plan to deploy to newer windows OS's using either InstallShield or Advanced Installer, and will be placing the dlls in app install folder, and the content files in ProgramData and/or user's AppData.

So the content files will be in one location during debugging under Visual Studio 2010 (probably just keep them where they are now, in app's bin/debug folder), and another location when deployed.

How do I make access to these files work the same way, during Visual Studio debugging, as during deployment?

If I had a global string that contains the base path for the content files, then I could access the files with a path relative to that string. But I am unsure how to create a string that has correct path during debugging, and then a different path during deployment.

I know I can test Debug vs Release flags, but that isn't quite the same thing. (switching to release build just moves the files to ../bin/Release instead of ../bin/Debug; might still not be deployed.)

Is there a simple example of how to accomplish this?

To be clear, I'm not asking about the details of accessing a path relative to a base directory. I'm asking how to distinguish between running deployed, and running during development.

So knowing how to detect "I am deployed" is the minimum help I need. Even better would be a mini-example or link to tutorial that shows accessing content files in one location during development, and a different location when deployed.


UPDATE

What is the best way in c# to determine whether the programmer is running the program via IDE or it's user? covers the most important case, so I would use it if there were no other solution. However, it does not work correctly if a developer double-clicks directly on the .exe within the development project's bin/debug folder. Because they aren't running within IDE (nor are we using vshost.exe), but the base folder is the same as if they were.

UPDATE

Upon further reflection, that stackoverflow Q&A suggested above is not at all the same thing. I don't care whether a debugger is attached (one could attach a debugger to the installed/deployed version, and it would still be a deployed version, not a development version).

I was originally thinking that there might be some standard flag or config setting somewhere that the app could use to determine that it is installed.

How do people know where to look for their content files, given that they won't be in the same place during development versus an installation? (Unless you do the "old school" approach of putting content files in your app install folder. Which is what I had before, but now need to do differently.)


UPDATE

Finally had the epiphany that I shouldn't be trying to keep content files in the bin/debug folder during development - was only doing that because that's how it was before. Haven't decided whether to move them all to the location they will be once they are deployed, or to some other location on the development machines.

I am still curious how other people specify location of content files during development, but perhaps that is a different question...

回答1:

I solved this by explicitly looking for a file in two possible locations. Then caching the directory path for future content access. In my case, the "development" location is a "content" folder that is next to the "bin" folder.

' Language: Visual Basic (VB)
' ... this is inside a VB module ...
Public g_AppRelativePath As String = "CompanyName\AppName"
Private _contentPathRootWithSlash As String

Public Function ContentPath(relPath As String) As String
  If _contentPathRootWithSlash Is Nothing Then
    ' --- first try to find "development" content ---
    ' Folder containing .exe.
    Dim pathRoot As String = Application.StartupPath
    Dim binIndex As Integer = pathRoot.LastIndexOf("bin", StringComparison.Ordinal)
    If binIndex >= 0 Then
      ' "content" folder that has been prepared as a sibling of "bin".
      pathRoot = pathRoot.Remove(binIndex) & "content"
    End If
    Dim pathRootWithSlash As String = pathRoot & "\"

    If File.Exists(pathRootWithSlash & relPath) Then
      _contentPathRootWithSlash = pathRootWithSlash

    Else
      ' --- "development" content does not exist; look for "deployed" content. ---
      '' Use this, if want files to be in User's AppData\Roaming.
      'pathRootWithSlash = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\"
      ' Use this, if want files to be shared by all users, in ProgramData.
      pathRootWithSlash = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) & "\"
      ' g_AppRelativePath was previously set to "CompanyName\AppName", which matches logic in our installer.
      pathRootWithSlash = pathRootWithSlash & g_AppRelativePath & "\"
      If File.Exists(pathRootWithSlash & relPath) Then
        _contentPathRootWithSlash = pathRootWithSlash

      Else
        ' Failed to find.
        MsgBox(String.Format("Can't find content file ""{0}""", relPath))
        Return Nothing
      End If
    End If
  End If

  Return _contentPathRootWithSlash & relPath
End Function