【问题标题】:GUID from string来自字符串的 GUID
【发布时间】:2016-04-12 01:06:25
【问题描述】:

假设我们有一个字符串

“{GUID}”

其中 GUID 是 {} 中的标准 GUID。我需要获取与给定字符串匹配的 GUID 类型的变量。它将使用 Visual C++ 完成,如果重要的话,版本非常旧(6.0)。

首先我尝试使用GUIDFromString 函数,但无法将其导入,因此了解了UuidFromString。但我真的被所有这些从 unsigned char 到 char 等的演员困住了,没有 C++ 背景,这很难。也许有人会非常好心地帮助我解决这个问题。谢谢。

【问题讨论】:

  • 虽然我对 Windows 编程几乎一无所知,但 Raymond Chen wrote about this recently.
  • 先升级你的编译器然后再回来。该编译器有缺陷,并且与线程安全的现代功能不兼容。去吧!
  • @Joel2 你真的认为我不知道新版本的编译器吗?如果升级是一种选择,我会这样做,但事实并非如此。讨论原因将是一个离题的话题,但总的来说,我正在处理一个遗留项目,我应该更改很少的东西,因此使其与当前的 VS 兼容需要大量的时间和专业知识。跨度>

标签: c++ visual-c++ guid c++98


【解决方案1】:

GUID指的是一些唯一的标识号,可以使用某种算法生成——你可以在微软的算法上找到一些描述——他们尝试将时间戳、网卡号和一个,混合成一个唯一的GUID。

我已经检查过 - 没有人阻止您创建自己的“独特”生成算法 - 但您需要以某种方式确保您的独特生成算法不会与现有算法发生冲突,这是极不可能的。此外,您的算法生成的 GUID 也不应该与您自己的 GUID 发生冲突。

在浏览互联网时,我发现了一些生成此类 guid 的方法 - 例如 - Microsoft Office:http://support.microsoft.com/kb/2186281

从字符串生成 GUID 时,您可以使用 String.GetHashCode32,甚至可以计算例如 20 字节的 sha-1 哈希值。 (第一个更容易,但第二个创建更多字节用于 GUID)。

然后根据需要开始填写 GUID。

这里有一些演示代码,让您了解这个想法:

using System;

class Program
{
    /// <summary>
    /// http://stackoverflow.com/questions/53086/can-i-depend-on-the-values-of-gethashcode-to-be-consistent
    /// 
    /// Similar to String.GetHashCode but returns the same as the x86 version of String.GetHashCode for x64 and x86 frameworks.
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static unsafe int GetHashCode32(string s)
    {
        fixed (char* str = s.ToCharArray())
        {
            char* chPtr = str;
            int num = 0x15051505;
            int num2 = num;
            int* numPtr = (int*)chPtr;
            for (int i = s.Length; i > 0; i -= 4)
            {
                num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
                if (i <= 2)
                {
                    break;
                }
                num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
                numPtr += 2;
            }
            return (num + (num2 * 0x5d588b65));
        }
    }
    /// <summary>
    /// Generates new product code for particular product / install package.
    /// </summary>
    /// <param name="productName">Logical product name for which to generate</param>
    /// <param name="productVersion">Product version in form "1.0.0"</param>
    /// <returns></returns>
    static public String GenerateProductCode( String productName, String productVersion )
    {
        String[] vparts = productVersion.Split(".".ToCharArray());
        int[] verParts = new int [3] { 1, 0, 0 };
        int i = 0; 
        foreach( String v in vparts )
        {
            Int32.TryParse(v, out verParts[i++] );
            if( i >= 3 ) break;
        }

        //
        //  "MyCompanyName", "1.0.2" will generate guid like this: {F974DC1F-0001-0000-0002-10009CD45A98}
        //                                                         ^ Hash over manufacturer name - "MyCompanyName"
        //                                                                  ^ Version - "<major>-<minor>-<build>" in hexadecimal
        //                                                                                 ^ 1 as for 64 bit.
        //                                                                                  ^000 - just reserved for future needs
        //                                                                                     ^ Hash over product name
        //
        //  See also similar generation schemes - http://support.microsoft.com/kb/2186281.
        //
        String newGuid = String.Format("{0:X8}-{1:X4}-{2:X4}-{3:X4}-1000{4:X8}", GetHashCode32("MyCompanyName"), verParts[0], verParts[1], verParts[2], GetHashCode32(productName));
        newGuid = "{" + newGuid + "}";
        return newGuid;
    }

    static void Main()
    {
        String s = GenerateProductCode("MyProduct", "1.0.2");
        Console.WriteLine(s);
    }
}

将打印出来:

{F974DC1F-0001-0000-0002-10003618D1E1}

但是以类似的方式,您也可以在 C++ 中生成 GUID - 最有可能使用 sprintf()。

这里是 .NET 兼容函数,用于将 String 转换为哈希码:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>


int GetHashCode32( const wchar_t* ps )
{
    int num = 0x15051505;
    int num2 = num;
    const wchar_t* s = ps;
    const char* chPtr=(const char*) ps;
    size_t numBuff = wcslen((wchar_t*) chPtr) * 2;
    int* numPtr = (int*)chPtr;

    for (int i = wcslen(s); i > 0; i -= 4)
    {
        num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
        if (i <= 2)
        {
            break;
        }
        num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
        numPtr += 2;
    }

    return (num + (num2 * 0x5d588b65));
}

void GetHash(const wchar_t* p)
{
    printf("'%S' = %08X", p, GetHashCode32(p));
    printf("\r\n");
}



void main(void)
{
    GetHash(L"testing");
    GetHash(L"MainClass::" __FUNCTIONW__);
    GetHash(L"1");
    GetHash(L"");

}

【讨论】:

    【解决方案2】:

    好的,问题出在 include 和 libs 中。您需要包含 &lt;Rpc.h&gt; 并链接 RPC 库:

    #pragma comment (lib, "Rpcrt4.lib")
    

    你可以使用UuidFromString 函数。请注意,您不需要在字符串表示中包含 { 和 }。

    【讨论】:

      猜你喜欢
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 2011-09-11
      • 2012-09-10
      相关资源
      最近更新 更多