在 Exchange Online 中将 Exchange 2003 邮箱转换为已启用邮件的用户

完成暂存迁移后,将本地邮箱转换为已启用邮件的用户,以便本地用户可以自动连接到其云邮箱。

为什么要将邮箱转换为启用邮件的用户?

需要将迁移的本地邮箱转换为) (MEU 启用邮件的用户,以便可以使用 Active Directory 管理本地组织中的基于云的用户。

本文包括从基于云的邮箱收集信息的 PowerShell 脚本,以及将 Exchange 2003 邮箱转换为 MEU 的 Visual Basic (VB) 脚本。 运行此脚本时,来自基于云的邮箱的代理地址会复制到 MEU,MEU 驻留在 Active Directory 中。 MEU 的属性使目录同步能够将 MEU 与其相应的云邮箱进行匹配。

建议将本地邮箱转换为 MEU 以用于迁移批处理。 分阶段 Exchange 迁移批处理完成后,你已验证该批中的所有邮箱已成功迁移,并且邮箱项目到云的初始同步已完成,将迁移批处理中的邮箱转换为 MEU。

从云邮箱收集数据的 PowerShell 脚本

使用本部分中的脚本收集有关基于云的邮箱的信息,并将 Exchange 2003 邮箱转换为 MEU。

PowerShell 脚本从云邮箱收集信息并将其保存到 CSV 文件中。 先运行该脚本。

将脚本复制到记事本,并将文件另存为ExportO365UserInfo.ps1。

注意

在运行脚本之前,需要安装 Exchange Online PowerShell 模块。 有关说明,请参阅安装和维护 Exchange Online PowerShell 模块。 该模块使用新式身份验证。

  • 通常情况下,如果组织是 Microsoft 365 或 Microsoft 365 GCC,则可按原样使用该脚本。 如果组织是 Office 365 德国、Microsoft 365 GCC 高或 Microsoft 365 DoD,则需编辑脚本中的 Connect-ExchangeOnline 行。 具体而言,你需要使用 ExchangeEnvironmentName 参数和组织的相应值。 有关更多信息,请参阅连接到 Exchange Online PowerShell中的示例。
Param($migrationCSVFileName = "migration.csv")
function O365Logon
{
    #Check for current open O365 sessions and allow the admin to either use the existing session or create a new one
    $session = Get-PSSession | ?{$_.ConfigurationName -eq 'Microsoft.Exchange'}
    if($session -ne $null)
    {
        $a = Read-Host "An open session to Exchange Online PowerShell already exists. Do you want to use this session?  Enter y to use the open session, anything else to close and open a fresh session."
        if($a.ToLower() -eq 'y')
        {
            Write-Host "Using existing Exchange Online Powershell Session." -ForeGroundColor Green
            return
        }
        Disconnect-ExchangeOnline -Confirm:$false
    }
    Import-Module ExchangeOnlineManagement
    Connect-ExchangeOnline
}
function Main
{
    #Verify the migration CSV file exists
    if(!(Test-Path $migrationCSVFileName))
    {
        Write-Host "File $migrationCSVFileName does not exist." -ForegroundColor Red
        Exit
    }
    #Import user list from migration.csv file
    $MigrationCSV = Import-Csv $migrationCSVFileName
    #Get mailbox list based on email addresses from CSV file
    $MailBoxList = $MigrationCSV | %{$_.EmailAddress} | Get-Mailbox
    $Users = @()
    #Get LegacyDN, Tenant, and On-Premises Email addresses for the users
    foreach($user in $MailBoxList)
    {
        $UserInfo = New-Object System.Object
        $CloudEmailAddress = $user.EmailAddresses | ?{($_ -match 'onmicrosoft') -and ($_ -cmatch 'smtp:')}
        if ($CloudEmailAddress.Count -gt 1)
        {
            $CloudEmailAddress = $CloudEmailAddress[0].ToString().ToLower().Replace('smtp:', '')
            Write-Host "$user returned more than one cloud email address. Using $CloudEmailAddress" -ForegroundColor Yellow
        }
        else
        {
            $CloudEmailAddress = $CloudEmailAddress.ToString().ToLower().Replace('smtp:', '')
        }
        $UserInfo | Add-Member -Type NoteProperty -Name LegacyExchangeDN -Value $user.LegacyExchangeDN
        $UserInfo | Add-Member -Type NoteProperty -Name CloudEmailAddress -Value $CloudEmailAddress
        $UserInfo | Add-Member -Type NoteProperty -Name OnPremiseEmailAddress -Value $user.PrimarySMTPAddress.ToString()
        $Users += $UserInfo
    }
    #Check for existing csv file and overwrite if needed
    if(Test-Path ".\cloud.csv")
    {
        $delete = Read-Host "The file cloud.csv already exists in the current directory. Do you want to delete it?  Enter y to delete, anything else to exit this script."
        if($delete.ToString().ToLower() -eq 'y')
        {
            Write-Host "Deleting existing cloud.csv file" -ForeGroundColor Red
            Remove-Item ".\cloud.csv"
        }
        else
        {
            Write-Host "Will NOT delete current cloud.csv file. Exiting script." -ForeGroundColor Green
            Exit
        }
    }
    $Users | Export-CSV -Path ".\cloud.csv" -notype
    (Get-Content ".\cloud.csv") | %{$_ -replace '"', ''} | Set-Content ".\cloud.csv" -Encoding Unicode
    Write-Host "CSV File Successfully Exported to cloud.csv" -ForeGroundColor Green
}
O365Logon
Main

Visual Basic 脚本将本地 Exchange 2003 邮箱转换为 MEU。 运行 PowerShell 脚本以从云邮箱收集信息后运行此脚本。

将脚本复制到记事本,并将文件另存为Exchange2003MBtoMEU.vbs。

'Globals/Constants
Const ADS_PROPERTY_APPEND = 3
Dim UserDN
Dim remoteSMTPAddress
Dim remoteLegacyDN
Dim domainController
Dim csvMode
csvMode = FALSE
Dim csvFileName
Dim lastADLookupFailed
Class UserInfo
    public OnPremiseEmailAddress
    public CloudEmailAddress
    public CloudLegacyDN
    public LegacyDN
    public ProxyAddresses
    public Mail
    public MailboxGUID
    public DistinguishedName
    Public Sub Class_Initialize()
        Set ProxyAddresses = CreateObject("Scripting.Dictionary")
    End Sub
End Class
'Command Line Parameters
If WScript.Arguments.Count = 0 Then
    'No parameters passed
    WScript.Echo("No parameters were passed.")
    ShowHelp()
ElseIf StrComp(WScript.Arguments(0), "-c", vbTextCompare) = 0 And WScript.Arguments.Count = 2 Then
    WScript.Echo("Missing DC Name.")
    ShowHelp()
ElseIf StrComp(WScript.Arguments(0), "-c", vbTextCompare) = 0 Then
    'CSV Mode
    csvFileName = WScript.Arguments(1)
    domainController = WScript.Arguments(2)
    csvMode = TRUE
    WScript.Echo("CSV mode detected. Filename: " & WScript.Arguments(1) & vbCrLf)
ElseIf wscript.Arguments.Count <> 4 Then
    'Invalid Arguments
    WScript.Echo WScript.Arguments.Count
    Call ShowHelp()
Else
    'Manual Mode
    UserDN = wscript.Arguments(0)
    remoteSMTPAddress = wscript.Arguments(1)
    remoteLegacyDN = wscript.Arguments(2)
    domainController = wscript.Arguments(3)
End If
Main()
'Main entry point
Sub Main
    'Check for CSV Mode
    If csvMode = TRUE Then
        UserInfoArray = GetUserInfoFromCSVFile()
    Else
        WScript.Echo "Manual Mode Detected" & vbCrLf
        Set info = New UserInfo
        info.CloudEmailAddress = remoteSMTPAddress
        info.DistinguishedName = UserDN
        info.CloudLegacyDN = remoteLegacyDN
        ProcessSingleUser(info)
    End If
End Sub
'Process a single user (manual mode)
Sub ProcessSingleUser(ByRef UserInfo)
    userADSIPath = "LDAP://" & domainController & "/" & UserInfo.DistinguishedName
    WScript.Echo "Processing user " & userADSIPath
    Set MyUser = GetObject(userADSIPath)
    proxyCounter = 1
    For Each address in MyUser.Get("proxyAddresses")
        UserInfo.ProxyAddresses.Add proxyCounter, address
        proxyCounter = proxyCounter + 1
    Next
    UserInfo.OnPremiseEmailAddress = GetPrimarySMTPAddress(UserInfo.ProxyAddresses)
    UserInfo.Mail = MyUser.Get("mail")
    UserInfo.MailboxGUID = MyUser.Get("msExchMailboxGUID")
    UserInfo.LegacyDN = MyUser.Get("legacyExchangeDN")
    ProcessMailbox(UserInfo)
End Sub
'Populate user info from CSV data
Function GetUserInfoFromCSVFile()
    CSVInfo = ReadCSVFile()
    For i = 0 To (UBound(CSVInfo)-1)
        lastADLookupFailed = false
        Set info = New UserInfo
        info.CloudLegacyDN = Split(CSVInfo(i+1), ",")(0)
        info.CloudEmailAddress = Split(CSVInfo(i+1), ",")(1)
        info.OnPremiseEmailAddress = Split(CSVInfo(i+1), ",")(2)
        WScript.Echo "Processing user " & info.OnPremiseEmailAddress
        WScript.Echo "Calling LookupADInformationFromSMTPAddress"
        LookupADInformationFromSMTPAddress(info)
        If lastADLookupFailed = false Then
            WScript.Echo "Calling ProcessMailbox"
            ProcessMailbox(info)
        End If
        set info = nothing
    Next
End Function
'Populate user info from AD
Sub LookupADInformationFromSMTPAddress(ByRef info)
    'Lookup the rest of the info in AD using the SMTP address
    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDomain = objRootDSE.Get("DefaultNamingContext")
    Set objRootDSE = nothing
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    Set objCommand = CreateObject("ADODB.Command")
    BaseDN = "<LDAP://" & domainController & "/" & strDomain & ">"
    adFilter = "(&(proxyAddresses=SMTP:" & info.OnPremiseEmailAddress & "))"
    Attributes = "distinguishedName,msExchMailboxGUID,mail,proxyAddresses,legacyExchangeDN"
    Query = BaseDN & ";" & adFilter & ";" & Attributes & ";subtree"
    objCommand.CommandText = Query
    Set objCommand.ActiveConnection = objConnection
    On Error Resume Next
    Set objRecordSet = objCommand.Execute
    'Handle any errors that result from the query
    If Err.Number <> 0 Then
        WScript.Echo "Error encountered on query " & Query & ". Skipping user."
        lastADLookupFailed = true
        return
    End If
    'Handle zero or ambiguous search results
    If objRecordSet.RecordCount = 0 Then
        WScript.Echo "No users found for address " & info.OnPremiseEmailAddress
        lastADLookupFailed = true
        return
    ElseIf objRecordSet.RecordCount > 1 Then
        WScript.Echo "Ambiguous search results for email address " & info.OnPremiseEmailAddress
        lastADLookupFailed = true
        return
    ElseIf Not objRecordSet.EOF Then
        info.LegacyDN = objRecordSet.Fields("legacyExchangeDN").Value
        info.Mail = objRecordSet.Fields("mail").Value
        info.MailboxGUID = objRecordSet.Fields("msExchMailboxGUID").Value
        proxyCounter = 1
        For Each address in objRecordSet.Fields("proxyAddresses").Value
            info.ProxyAddresses.Add proxyCounter, address
            proxyCounter = proxyCounter + 1
        Next
        info.DistinguishedName = objRecordSet.Fields("distinguishedName").Value
        objRecordSet.MoveNext
    End If
    objConnection = nothing
    objCommand = nothing
    objRecordSet = nothing
    On Error Goto 0
End Sub
'Populate data from the CSV file
Function ReadCSVFile()
    'Open file
    Set objFS = CreateObject("Scripting.FileSystemObject")
    Set objTextFile = objFS.OpenTextFile(csvFileName, 1, false, -1)
    'Loop through each line, putting each line of the CSV file into an array to be returned to the caller
    counter = 0
    Dim CSVArray()
    Do While NOT objTextFile.AtEndOfStream
        ReDim Preserve CSVArray(counter)
        CSVArray(counter) = objTextFile.ReadLine
        counter = counter + 1
    Loop
    'Close and return
    objTextFile.Close
    Set objTextFile = nothing
    Set objFS = nothing
    ReadCSVFile = CSVArray
End Function
'Process the migration
Sub ProcessMailbox(User)
    'Get user properties
    userADSIPath = "LDAP://" & domainController & "/" & User.DistinguishedName
    Set MyUser = GetObject(userADSIPath)
    'Add x.500 address to list of existing proxies
    existingLegDnFound = FALSE
    newLegDnFound = FALSE
    'Loop through each address in User.ProxyAddresses
    For i = 1 To User.ProxyAddresses.Count
        If StrComp(address, "x500:" & User.LegacyDN, vbTextCompare) = 0 Then
            WScript.Echo "x500 proxy " & User.LegacyDN & " already exists"
            existingLegDNFound = true
        End If
        If StrComp(address, "x500:" & User.CloudLegacyDN, vbTextCompare) = 0 Then
            WScript.Echo "x500 proxy " & User.CloudLegacyDN & " already exists"
            newLegDnFound = true
        End If
    Next
    'Add existing leg DN to proxy list
    If existingLegDnFound = FALSE Then
        WScript.Echo "Adding existing legacy DN " & User.LegacyDN & " to proxy addresses"
        User.ProxyAddresses.Add (User.ProxyAddresses.Count+1),("x500:" & User.LegacyDN)
    End If
    'Add new leg DN to proxy list
    If newLegDnFound = FALSE Then
        'Add new leg DN to proxy addresses
        WScript.Echo "Adding new legacy DN " & User.CloudLegacyDN & " to existing proxy addresses"
        User.ProxyAddresses.Add (User.ProxyAddresses.Count+1),("x500:" & User.CloudLegacyDN)
    End If
    'Dump out new list of addresses
    WScript.Echo "Original proxy addresses updated count: " & User.ProxyAddresses.Count
    For i = 1 to User.ProxyAddresses.Count
        WScript.Echo " proxyAddress " & i & ": " & User.ProxyAddresses(i)
    Next
    'Delete the Mailbox
    WScript.Echo "Opening " & userADSIPath & " as CDOEXM::IMailboxStore object"
    Set Mailbox = MyUser
    Wscript.Echo "Deleting Mailbox"
    On Error Resume Next
    Mailbox.DeleteMailbox
    'Handle any errors deleting the mailbox
    If Err.Number <> 0 Then
        WScript.Echo "Error " & Err.number & ". Skipping User." & vbCrLf & "Description: " & Err.Description & vbCrLf
        Exit Sub
    End If
    On Error Goto 0
    'Save and continue
    WScript.Echo "Saving Changes"
    MyUser.SetInfo
    WScript.Echo "Refeshing ADSI Cache"
    MyUser.GetInfo
    Set Mailbox = nothing
    'Mail Enable the User
    WScript.Echo "Opening " & userADSIPath & " as CDOEXM::IMailRecipient"
    Set MailUser = MyUser
    WScript.Echo "Mail Enabling user using targetAddress " & User.CloudEmailAddress
    MailUser.MailEnable User.CloudEmailAddress
    WScript.Echo "Disabling Recipient Update Service for user"
    MyUser.PutEx ADS_PROPERTY_APPEND, "msExchPoliciesExcluded", Array("{26491CFC-9E50-4857-861B-0CB8DF22B5D7}")
    WScript.Echo "Saving Changes"
    MyUser.SetInfo
    WScript.Echo "Refreshing ADSI Cache"
    MyUser.GetInfo
    'Add Legacy DN back on to the user
    WScript.Echo "Writing legacyExchangeDN as " & User.LegacyDN
    MyUser.Put "legacyExchangeDN", User.LegacyDN
    'Add old proxies list back on to the MEU
    WScript.Echo "Writing proxyAddresses back to the user"
    For j=1 To User.ProxyAddresses.Count
        MyUser.PutEx ADS_PROPERTY_APPEND, "proxyAddresses", Array(User.ProxyAddresses(j))
        MyUser.SetInfo
        MyUser.GetInfo
    Next
    'Add mail attribute back on to the MEU
    WScript.Echo "Writing mail attribute as " & User.Mail
    MyUser.Put "mail", User.Mail
    'Add msExchMailboxGUID back on to the MEU
    WScript.Echo "Converting mailbox GUID to writable format"
    Dim mbxGUIDByteArray
    Call ConvertHexStringToByteArray(OctetToHexString(User.MailboxGUID), mbxGUIDByteArray)
    WScript.Echo "Writing property msExchMailboxGUID to user object with value " & OctetToHexString(User.MailboxGUID)
    MyUser.Put "msExchMailboxGUID", mbxGUIDByteArray
    WScript.Echo "Saving Changes"
    MyUser.SetInfo
    WScript.Echo "Migration Complete!" & vbCrLf
End Sub
'Returns the primary SMTP address of a user
Function GetPrimarySMTPAddress(Addresses)
    For Each address in Addresses
        If Left(address, 4) = "SMTP" Then GetPrimarySMTPAddress = address
    Next
End Function
'Converts Hex string to byte array for writing to AD
Sub ConvertHexStringToByteArray(ByVal strHexString, ByRef pByteArray)
    Set FSO = CreateObject("Scripting.FileSystemObject")
    Set Stream = CreateObject("ADODB.Stream")
    Temp = FSO.GetTempName()
    Set TS = FSO.CreateTextFile(Temp)
    For i = 1 To (Len (strHexString) -1) Step 2
        TS.Write Chr("&h" & Mid (strHexString, i, 2))
    Next
    TS.Close
    Stream.Type = 1
    Stream.Open
    Stream.LoadFromFile Temp
    pByteArray = Stream.Read
    Stream.Close
    FSO.DeleteFile Temp
    Set Stream = nothing
    Set FSO = Nothing
End Sub
'Converts raw bytes from AD GUID to readable string
Function OctetToHexString (arrbytOctet)
    OctetToHexStr = ""
    For k = 1 To Lenb (arrbytOctet)
        OctetToHexString = OctetToHexString & Right("0" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
    Next
End Function
Sub ShowHelp()
    WScript.Echo("This script runs in two modes, CSV Mode and Manual Mode." & vbCrLf & "CSV Mode allows you to specify a CSV file from which to pull usernames." & vbCrLf& "Manual mode allows you to run the script against a single user.")
    WSCript.Echo("Both modes require you to specify the name of a DC to use in the local domain." & vbCrLf & "To run the script in CSV Mode, use the following syntax:")
    WScript.Echo("  cscript Exchange2003MBtoMEU.vbs -c x:\csv\csvfilename.csv dc.domain.com")
    WScript.Echo("To run the script in Manual Mode, you must specify the users AD Distinguished Name, Remote SMTP Address, Remote Legacy Exchange DN, and Domain Controller Name.")
    WSCript.Echo("  cscript Exchange2003MBtoMEU.vbs " & chr(34) & "CN=UserName,CN=Users,DC=domain,DC=com" & chr(34) & " " & chr(34) & "user@cloudaddress.com" & chr(34) & " " & chr(34) & "/o=Cloud Org/ou=Cloud Site/ou=Recipients/cn=CloudUser" & chr(34) & " dc.domain.com")
    WScript.Quit
End Sub

脚本的用途是什么?

ExportO365UserInfo.ps1

ExportO365UserInfo.ps1是在基于云的组织中运行的 PowerShell 脚本,用于收集有关在分阶段 Exchange 迁移期间迁移的云邮箱的信息。 它使用 CSV 文件来设定用户批的范围。 建议使用用于迁移一批用户的相同迁移 CSV 文件。

运行 ExportO365UserInfo 脚本时,将执行以下操作:

  • 从云邮箱中为输入 CSV 文件中列出的用户收集以下属性:
    • 主 SMTP 地址。
    • 相应本地邮箱的主 SMTP 地址。
    • 云邮箱的其他代理地址。
    • LegacyExchangeDN
  • 收集的属性被保存到名为 Cloud.csv 的 CSV 文件。

Exchange2003MBtoMEU.vbs

Exchange2003MBtoMEU.vbs是在本地 Exchange 2003 组织中运行的 VB 脚本,用于将邮箱转换为 MEU。 它使用 ExportO365UserInfo.ps1 PowerShell 脚本生成的 Cloud.csv 文件。

运行 Exchange2003MBtoMEU.vbs 脚本时,将针对输入 CSV 文件中列出的每个邮箱执行以下操作:

  • 从输入 CSV 文件和本地邮箱收集信息。
  • 从本地和云邮箱创建代理地址列表,以添加到 MEU。
  • 删除本地邮箱。
  • 创建具有以下属性的 MEU:
    • legacyExchangeDN:来自本地邮箱的值。

    • mail:云邮箱的主 SMTP。

    • msExchMailboxGuid:来自本地邮箱的值。

    • proxyAddresses:来自本地邮箱和云邮箱的值。

    • targetAddress:从本地邮箱读取;值是云邮箱的主 SMTP。

      重要

      若要启用从Exchange Online退到 Exchange 2003 的退出,需要将 MEU 上的 msExchMailboxGuid 属性值替换为基于云的邮箱中的 GUID。 若要获取基于云的邮箱的 GUID 值并将其保存到 CSV 文件,请运行以下Exchange Online PowerShell 命令:

      Get-Mailbox | Select PrimarySmtpAddress,Guid | Export-csv -Path .\guid.csv
      

      此命令将所有云邮箱的主 SMTP 地址和 Guid 提取到 guid.csv 文件中,然后将该文件保存到当前目录。

可以在手动模式下运行 Exchange2003MBtoMEU.vbs 脚本一次转换一个邮箱,而不是使用输入 CSV 文件成批转换邮箱。 如果选择此方法,则需要提供以下输入参数:

  • 本地邮箱的可分辨名称 (DN)。
  • 云邮箱的主 SMTP 地址。
  • 云邮箱的 Exchange 旧版 DN。
  • Exchange 2003 组织中的域控制器名称。

将本地邮箱转换为 MEU 的步骤

  1. 在Exchange Online组织中运行ExportO365UserInfo.ps1。 将迁移批处理的 CSV 文件作为输入文件使用。 该脚本将创建名为 Cloud.csv 的 CSV 文件。

    cd <location of the script>
    
    .\ExportO365UserInfo.ps1 <CSV input file>
    

    例如:

    cd c:\data\scripts
    
    .\ExportO365UserInfo.ps1 .\MigrationBatch1.csv
    
  2. 将 Exchange2003MBtoMEU.vbs 和 Cloud.csv 复制到本地组织的同一目录中。

  3. 在本地组织中运行以下命令:

    cscript Exchange2003MBtoMEU.vbs -c .\Cloud.csv <FQDN of on-premises domain controller>
    

    例如:

    cscript Exchange2003MBtoMEU.vbs -c .\Cloud.csv DC1.contoso.com
    

    若要在手动模式下运行该脚本,请输入以下命令。 在每个值之间使用空格。

    cscript Exchange2003MBtoMEU.vbs "<DN of on-premises mailbox>" "<Primary SMTP of cloud mailbox>" "<ExchangeLegacyDN of cloud mailbox>" <FQDN of on-premises domain controller>
    

    例如:

    cscript Exchange2003MBtoMEU.vbs "CN=Ann Beebe,CN=Users,DC=contoso,DC=com" "annb@contoso.onmicrosoft.com" "/o=First Organization/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=d808d014cec5411ea6de1f70cc116e7b-annb" DC1.contoso.com
    
  4. 验证是否已创建新的 MEU。 在 Active Directory 用户和计算机 中,执行以下步骤:

    1. 单击“ 操作>查找”。

    2. 单击" Exchange 选项卡"。

    3. 选择" 仅显示 Exchange 收件人",然后选择" 具有外部电子邮件地址的用户"。

    4. 单击" 立即查找"。

      " 搜索结果"下列出已转换为 MEU 的邮箱。

  5. 使用 Active Directory 用户和计算机ASI 编辑Ldp.exe验证以下 MEU 属性是否填充了正确的信息:

    • legacyExchangeDN
    • mail
    • msExchMailboxGuid*
    • proxyAddresses
    • targetAddress

    * 如上文所述,Exchange2003MBtoMEU.vbs 脚本保留来自本地邮箱的 msExchMailboxGuid 值。 若要启用从 Microsoft 365 或 Office 365到 Exchange 2003 的退出,需要将 MEU 上的 msExchMailboxGuid 属性值替换为基于云的邮箱中的 GUID。