Dynamically Detecting the Data Directory
My Slideshow control (which I discussed in a previous post) looks in a data directory called images for the images it wishes to display. This adds a curious twist to application development and deployment. When I deploy an application using ClickOnce, I will want to include these files in the data directory for that application. (See Accessing Local and Remote Data in ClickOnce Applications for the 411 on data directories.) Under ClickOnce, the data directory is a long, garbled path, such as C:\Documents and Settings\username\Local Settings\Apps\2.0\Data\DXQV72TZ.3GR\EERQ26OC.Y91\test..tion_9d0ab10300fca701_0001.0000_edbfed2eeae795d5\Data. I can find the value of this path (deliberately obscured to foil easy discovery of my app's data) by calling Application.UserAppDataPath.
However, when I'm debugging my app in Visual Studio, the data directory path is set to C:\Documents and Settings\username\Application Data\Publisher Name\App Name\Version Number. Now, I could manually stuff my data files in here for the purposes of debugging. Indeed, for most of my project, that's what I did. But this makes it difficult to ship the project to other developers and have it work out of the box. Also, it requires that I switch the files around whenever I update the version, or alter the application or publisher name. The chance that data files will become out of sync during development is high.
To get around this mess, I wrote a small snippet of code that detects where the data directory resides for the current instance of the application. If ApplicationDeployment.IsNetworkDeployed is true, I use Application.UserAppDataPath as the data directory. If I'm not running as a ClickOnce application, I first look at Application.ExecutablePath to see if the images directory is in the same directory as the executable. If it isn't, I assume I'm running in debug mode under Visual Studio, and look two directories up for my precious data.
Private Function GetDataDirectory() As String Dim _ExeDir As String Dim _PathStr As String
If (ApplicationDeployment.IsNetworkDeployed) Then _PathStr = Application.UserAppDataPath & "\images" Else ' Check if it's in the exe directory, or in a debug folder dir. _ExeDir = Application.ExecutablePath.Substring(0, _ Application.ExecutablePath.LastIndexOf("\")) _PathStr = _ExeDir & "\images"
If (Not Directory.Exists(_PathStr)) Then _PathStr = _ExeDir & "\..\..\images" If (Not Directory.Exists(_PathStr)) Then Throw New DirectoryNotFoundException("Cannot find directory " & _PathStr & ". Fatal error.") End If End If End If
GetDataDirectory = _PathStr End Function
This code not only allows the app to switch between debug testing and ClickOnce deployment. It it also supports good ol' xcopy deployment. So long as the images directory is at the same level as the EXE, I'm good to go.
Populating the Data Directory for ClickOnce Deployment
How do I add the images directory and its files to my ClickOnce deployment? As far as Visual Studio is concerned, this is the easy part!