8

我已经安装了 .NET 应用程序。它的配置位置是

%AppData%\[CompanyName]\[ExeName]_Url_[hash]\[version]\user.config.

我需要[hash]从另一个应用程序中获得价值。

根据MSDNuser.config路径模板是

[c:\Documents and Settings]\[username]\[Local Settings]\Application Data\[companyname]\[appdomainname]_[eid]_[hash]\[version]

[hash]证据的 SHA1 哈希值在哪里(在我的例子中是 eid=Url)。

我注意到以下几点:

  • [hash]随着应用程序安装路径的改变而改变。
  • [hash]总是 32 个字符长,所以它不是 SHA1 的十六进制表示,它长 40 个字符。看起来[hash]=base32(sha1([install path]))

我尝试了不同的值[install path]

c:\Program Files...
file:///c:\Program Files..
file:///c:\Program%20Files...等

[hash]总是错的。

4

2 回答 2

5

在经历了尝试计算程序user.config(本地)路径的相同问题之后,我决定用代码片段补充@Gerard Sexton 的答案。以下方法是在假设[eid]等于"Url"[appdomainname]是可执行文件名的情况下完成的。

public string GetExeLocalAppDataUserConfigPath(string fullExePath)
{
    //E.g.: fullExePath = @"C:\Program Files (x86)\MyExeFolder\MyProgram.exe"
    var localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);

    var versionInfo = FileVersionInfo.GetVersionInfo(fullExePath);
    var companyName = versionInfo.CompanyName;
    var exeName = versionInfo.OriginalFilename;// or 'AppDomain.CurrentDomain.FriendlyName'

    var assemblyName = AssemblyName.GetAssemblyName(fullExePath);
    var version = assemblyName.Version.ToString();

    var uri = "file:///" + fullExePath; //or 'assemblyName.CodeBase' if vshost (you can check the 'FriendlyName')
    uri = uri.ToUpperInvariant();

    var ms = new MemoryStream();
    var bSer = new BinaryFormatter();
    bSer.Serialize(ms, uri);
    ms.Position = 0;
    var sha1 = new SHA1CryptoServiceProvider();
    var hash = sha1.ComputeHash(ms);
    var hashstring = ToBase32StringSuitableForDirName(hash);

    //<AppData Local User Path> + <Company Name> + <[ExeName]_[eid]_[Hash]> + <Version> + user.config
    var userConfigLocalAppDataPath = Path.Combine(localAppDataPath, companyName, exeName+"_Url_"+hashstring, version, "user.config");

    return userConfigLocalAppDataPath;
}

这是ToBase32StringSuitableForDirName在 Gerard 的链接中找到的实现!

static Char[] s_Base32Char = {
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 
            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
            'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
            'y', 'z', '0', '1', '2', '3', '4', '5'};

private static string ToBase32StringSuitableForDirName(byte[] buff)
{
    StringBuilder sb = new StringBuilder();
    byte b0, b1, b2, b3, b4;
    int l, i;

    l = buff.Length;
    i = 0;

    // Create l chars using the last 5 bits of each byte.  
    // Consume 3 MSB bits 5 bytes at a time.

    do
    {
        b0 = (i < l) ? buff[i++] : (byte)0;
        b1 = (i < l) ? buff[i++] : (byte)0;
        b2 = (i < l) ? buff[i++] : (byte)0;
        b3 = (i < l) ? buff[i++] : (byte)0;
        b4 = (i < l) ? buff[i++] : (byte)0;

        // Consume the 5 Least significant bits of each byte
        sb.Append(s_Base32Char[b0 & 0x1F]);
        sb.Append(s_Base32Char[b1 & 0x1F]);
        sb.Append(s_Base32Char[b2 & 0x1F]);
        sb.Append(s_Base32Char[b3 & 0x1F]);
        sb.Append(s_Base32Char[b4 & 0x1F]);

        // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4
        sb.Append(s_Base32Char[(
            ((b0 & 0xE0) >> 5) |
            ((b3 & 0x60) >> 2))]);

        sb.Append(s_Base32Char[(
            ((b1 & 0xE0) >> 5) |
            ((b4 & 0x60) >> 2))]);

        // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4

        b2 >>= 5;

        if ((b3 & 0x80) != 0)
            b2 |= 0x08;
        if ((b4 & 0x80) != 0)
            b2 |= 0x10;

        sb.Append(s_Base32Char[b2]);

    } while (i < l);

    return sb.ToString();
}
于 2017-07-14T22:42:18.673 回答
2

The advice for writing to a custom location is to provide your own SettingsProvider. The default settings provider is LocalFileSettingsProvider. So starting in LocalFileSettingsProvider, then following the code to ConfigurationManagerInternalFactory then ConfigurationManagerInternal then finally in ClientConfigPaths. In ClientConfigPaths:412 you can see how the hash is determined from the current AppDomain's evidence.

Basically, for Uri type, it takes the Uri in the form

file:///c:\app\app.exe

This uri is then converted to upper case (invariant), then SHA-1 hashed, then the hash is encoded in base32. I don't know if the base32 used in the referenced source is a standard base32 implementation or not (if one exists).

于 2017-03-28T03:12:49.490 回答