private ClientConfigPaths(string exePath, bool includeUserConfig)
{
_includesUserConfig = includeUserConfig;
Assembly exeAssembly = null;
string applicationUri = null;
string applicationFilename = null;
// get the assembly and applicationUri for the file
if (exePath == null)
{
// First check if a configuration file has been set for this app domain. If so, we will use that.
// The CLR would already have normalized this, so no further processing necessary.
AppDomain domain = AppDomain.CurrentDomain;
AppDomainSetup setup = domain.SetupInformation;
_applicationConfigUri = setup.ConfigurationFile;
// Now figure out the application path.
exeAssembly = Assembly.GetEntryAssembly();
if (exeAssembly != null)
{
_hasEntryAssembly = true;
applicationUri = exeAssembly.CodeBase;
bool isFile = false;
// If it is a local file URI, convert it to its filename, without invoking Uri class.
// example: "file:///C:/WINNT/Microsoft.NET/Framework/v2.0.x86fre/csc.exe"
if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_LOCAL))
{
isFile = true;
applicationUri = applicationUri.Substring(FILE_URI_LOCAL.Length);
}
// If it is a UNC file URI, convert it to its filename, without invoking Uri class.
// example: "file://server/share/csc.exe"
else if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_UNC))
{
isFile = true;
applicationUri = applicationUri.Substring(FILE_URI.Length);
}
if (isFile)
{
applicationUri = applicationUri.Replace('/', '\\');
applicationFilename = applicationUri;
}
else
{
applicationUri = exeAssembly.EscapedCodeBase;
}
}
else
{
StringBuilder sb = new StringBuilder(MAX_PATH);
int noOfTimes = 1;
int length = 0;
// Iterating by allocating chunk of memory each time we find the length is not sufficient.
// Performance should not be an issue for current MAX_PATH length due to this change.
while (((length = UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity)) == sb.Capacity) &&
Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER &&
sb.Capacity < MAX_UNICODESTRING_LEN)
{
noOfTimes += 2; // increasing buffer size by 520 in each iteration - perf.
int capacity = noOfTimes * MAX_PATH < MAX_UNICODESTRING_LEN ? noOfTimes * MAX_PATH : MAX_UNICODESTRING_LEN;
sb.EnsureCapacity(capacity);
}
sb.Length = length;
applicationUri = Path.GetFullPath(sb.ToString());
applicationFilename = applicationUri;
}
}
else
{
applicationUri = Path.GetFullPath(exePath);
if (!FileUtil.FileExists(applicationUri, false))
{
throw ExceptionUtil.ParameterInvalid("exePath");
}
applicationFilename = applicationUri;
}
// Fallback if we haven't set the app config file path yet.
if (_applicationConfigUri == null)
{
_applicationConfigUri = applicationUri + ConfigExtension;
}
// Set application path
_applicationUri = applicationUri;
// In the case when exePath was explicitly supplied, we will not be able to
// construct user.config paths, so quit here.
if (exePath != null)
{
return;
}
// Skip expensive initialization of user config file information if requested.
if (!_includesUserConfig)
{
return;
}
bool isHttp = StringUtil.StartsWithIgnoreCase(_applicationConfigUri, HTTP_URI);
SetNamesAndVersion(applicationFilename, exeAssembly, isHttp);
// Check if this is a clickonce deployed application. If so, point the user config
// files to the clickonce data directory.
if (this.IsClickOnceDeployed(AppDomain.CurrentDomain))
{
string dataPath = AppDomain.CurrentDomain.GetData(ClickOnceDataDirectory) as string;
string versionSuffix = Validate(_productVersion, false);
// NOTE: No roaming config for clickonce - not supported.
if (Path.IsPathRooted(dataPath))
{
_localConfigDirectory = CombineIfValid(dataPath, versionSuffix);
_localConfigFilename = CombineIfValid(_localConfigDirectory, UserConfigFilename);
}
}
else if (!isHttp)
{
// If we get the config from http, we do not have a roaming or local config directory,
// as it cannot be edited by the app in those cases because it does not have Full Trust.
// suffix for user config paths
string part1 = Validate(_companyName, true);
string validAppDomainName = Validate(AppDomain.CurrentDomain.FriendlyName, true);
string applicationUriLower = !String.IsNullOrEmpty(_applicationUri) ? _applicationUri.ToLower(CultureInfo.InvariantCulture) : null;
string namePrefix = !String.IsNullOrEmpty(validAppDomainName) ? validAppDomainName : Validate(_productName, true);
string hashSuffix = GetTypeAndHashSuffix(AppDomain.CurrentDomain, applicationUriLower);
string part2 = (!String.IsNullOrEmpty(namePrefix) && !String.IsNullOrEmpty(hashSuffix)) ? namePrefix + hashSuffix : null;
string part3 = Validate(_productVersion, false);
string dirSuffix = CombineIfValid(CombineIfValid(part1, part2), part3);
string roamingFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
if (Path.IsPathRooted(roamingFolderPath))
{
_roamingConfigDirectory = CombineIfValid(roamingFolderPath, dirSuffix);
_roamingConfigFilename = CombineIfValid(_roamingConfigDirectory, UserConfigFilename);
}
string localFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
if (Path.IsPathRooted(localFolderPath))
{
_localConfigDirectory = CombineIfValid(localFolderPath, dirSuffix);
_localConfigFilename = CombineIfValid(_localConfigDirectory, UserConfigFilename);
}
}
}