> ## Documentation Index
> Fetch the complete documentation index at: https://help.gorelo.io/llms.txt
> Use this file to discover all available pages before exploring further.

# الكتابة إلى حقل أصل مخصص بالنصوص البرمجية

> استخدم نصوص Gorelo البرمجية لكتابة قيم مثل مفاتيح استرداد BitLocker وكلمات مرور المسؤول المحلي المُدوَّرة ومعرفات UID لجهات خارجية إلى حقول الأصول المخصصة تلقائيًا.

مفاتيح BitLocker، تدوير كلمة مرور المسؤول المحلي، معرف UID لجهة خارجية، إلخ.

يمكنك الكتابة إلى حقل أصل مخصص عبر النصوص البرمجية. هذا مفيد لأشياء مثل مفاتيح BitLocker، وتدوير كلمات مرور المسؤول المحلي، ومعرفات UID لجهات خارجية.

<Steps>
  <Step title="إنشاء حقل أصل مخصص">
    1. انتقل إلى **Settings** > **Assets** > **Custom Fields**.
    2. أضف حقلًا مخصصًا بالتفاصيل التالية:

    <Tabs>
      <Tab title="BitLocker">
        * **Name**: BitLocker Recovery Key
        * **Variable**: bitlockerRecoveryKey

        <Frame>
          <img src="https://mintcdn.com/gorelo/hTBX2qpHbjxDttw-/images/image-116.png?fit=max&auto=format&n=hTBX2qpHbjxDttw-&q=85&s=2319913d92820567f3479e8016569176" alt="صورة" width="778" height="619" data-path="images/image-116.png" />
        </Frame>
      </Tab>

      <Tab title="Windows Install Date">
        * **Name**: Windows Install Date
        * **Variable**: windowsInstallDate

        <Frame>
          <img src="https://mintcdn.com/gorelo/hTBX2qpHbjxDttw-/images/image-110.png?fit=max&auto=format&n=hTBX2qpHbjxDttw-&q=85&s=10e3f1f3314306dba75c38d4701feb7c" alt="صورة" width="787" height="606" data-path="images/image-110.png" />
        </Frame>
      </Tab>

      <Tab title="Windows Product Key">
        * **Name**: Windows Product Key
        * **Variable**: windowsProductKey

        <Frame>
          <img src="https://mintcdn.com/gorelo/vUQ8OM8P3jBMi8Dq/images/image-118.png?fit=max&auto=format&n=vUQ8OM8P3jBMi8Dq&q=85&s=1dfb76668303d54756404bee5f0fbf4d" alt="صورة" width="781" height="603" data-path="images/image-118.png" />
        </Frame>
      </Tab>

      <Tab title="MAC Address">
        * **Name**: MAC Address
        * **Variable**: macAddress

        <Frame>
          <img src="https://mintcdn.com/gorelo/fI4EZlX_4VIJ5gmy/images/image-119.png?fit=max&auto=format&n=fI4EZlX_4VIJ5gmy&q=85&s=5515c35750de344cd60cb7c3d62b4ee1" alt="صورة" width="793" height="630" data-path="images/image-119.png" />
        </Frame>
      </Tab>

      <Tab title="RAM Slots Used">
        * **Name**: RAM Slots Used
        * **Variable**: ramSlotsUsed

        <Frame>
          <img src="https://mintcdn.com/gorelo/l3kfLaTp3Zy4uEi2/images/image-121.png?fit=max&auto=format&n=l3kfLaTp3Zy4uEi2&q=85&s=eb10f33b94faeaa1bf5b8441ff39ce97" alt="صورة" width="786" height="602" data-path="images/image-121.png" />
        </Frame>
      </Tab>
    </Tabs>
  </Step>

  <Step title="إنشاء النص البرمجي">
    1. انتقل إلى **Scripts**.
    2. أنشئ نصًا برمجيًا بالتفاصيل التالية:

    <Tabs>
      <Tab title="BitLocker">
        * **Name**: 🗝️Store-BitlockerRecoveryKey
        * **Content**:

        ```powershell theme={null}
        $ErrorActionPreference = 'SilentlyContinue' 

        # Get drives where BitLocker is "On" 
        $BitlockerDrives = Get-BitLockerVolume | Where-Object ProtectionStatus -EQ "On" -ErrorAction SilentlyContinue

        #Get FileSystem drives 
        $Drives = Get-PSDrive -PSProvider FileSystem

        #Create array of Drive Names with ":" added
        $DrivesName = @()
        $Drives |  foreach {$DrivesName += $_.name + ':' }

        #If any Bitlockered drives exist
        if($BitlockerDrives){

            #Foreach Drive
            Foreach ($DriveName in $DrivesName) {

                #Confirm is drive is bitlockered
                $BitlockerDrive = $BitlockerDrives | where { $DriveName -contains $_ }

                #If specific drive is bitlockered
                if ($BitlockerDrive){

                    #Get RecoveryKey 
                    $RecoveryKey = $BitlockerDrive.KeyProtector | Where-Object RecoveryPassword -NE "" | Select-Object -ExpandProperty RecoveryPassword -ErrorAction SilentlyContinue
              
                    #Join if multiple with ; delimiter 
                    $RecoveryKey = $RecoveryKey -join ";"

                    #Add the drive letter to the output
                    $RecoveryKey = "$($BitlockerDrive.mountpoint)$RecoveryKey"

                    #Add to other drive keys (If exist)
                    $RecoveryKeys += " $RecoveryKey "

                } else { $RecoveryKeys += $DriveName + "Not Enabled" }   
                
            }

            GoreloAction -SetCustomField -Name 'asset.bitlockerRecoveryKey' -Value $RecoveryKeys

        #If no bitlockered drives found
        }else { 
            
            Foreach ($DriveName in $DrivesName) { 
                
                $RecoveryKeys += $DriveName + "Not Enabled " 
                
            } 
            
            GoreloAction -SetCustomField -Name 'asset.bitlockerRecoveryKey' -Value $RecoveryKeys 
            
        }
        ```
      </Tab>

      <Tab title="Windows Install Date">
        * **Name**: 🗝️Store-WindowsInstallDate
        * **Content**:

        ```powershell theme={null}
        # Initialize array to store all valid dates
        $allDates = @()

        # Method 1: Win32_OperatingSystem class
        $osInfo = Get-WmiObject Win32_OperatingSystem
        $installDate = $osInfo.ConvertToDateTime($osInfo.InstallDate)
        $allDates += $installDate
        Write-Host "OS Installation Date (from Win32_OperatingSystem): $($installDate.ToString('MM/dd/yyyy'))" -ForegroundColor White

        # Method 2: Registry installation date
        $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
        $registryInstallDate = Get-ItemProperty -Path $registryPath | Select-Object -ExpandProperty InstallDate
        $registryInstallDateTime = (Get-Date "1970-01-01 00:00:00.000Z").AddSeconds($registryInstallDate)
        $allDates += $registryInstallDateTime
        Write-Host "Registry Installation Date: $($registryInstallDateTime.ToString('MM/dd/yyyy'))" -ForegroundColor White

        # Method 3: Earliest system restore point (with proper date parsing)
        try {
            $restorePoints = Get-ComputerRestorePoint | Sort-Object -Property CreationTime
            if ($restorePoints) {
                $earliestRestorePoint = [datetime]::ParseExact($restorePoints[0].CreationTime.ToString(), "yyyyMMddHHmmss.ffffff-000", $null)
                $allDates += $earliestRestorePoint
                Write-Host "Earliest System Restore Point: $($earliestRestorePoint.ToString('MM/dd/yyyy'))" -ForegroundColor White
            }
        }
        catch {
            Write-Host "Unable to retrieve or parse system restore points." -ForegroundColor Yellow
        }

        # Method 4: Windows.old folder date (if exists)
        $windowsOldPath = "$env:SystemDrive\Windows.old"
        if (Test-Path $windowsOldPath) {
            $windowsOldDate = (Get-Item $windowsOldPath).CreationTime
            $allDates += $windowsOldDate
            Write-Host "Windows.old Folder Creation Date: $($windowsOldDate.ToString('MM/dd/yyyy'))" -ForegroundColor White
        }

        # Filter out any null dates and find the oldest
        $validDates = $allDates | Where-Object { $_ -ne $null }
        $oldestDate = $validDates | Sort-Object | Select-Object -First 1

        Write-Host "`nOldest detected date (likely original deployment): $($oldestDate.ToString('MM/dd/yyyy'))" -ForegroundColor Green

        # Format date for Gorelo (date only)
        $goreloDateString = Get-Date $oldestDate -Format "yyyy-MM-dd"

        # Set Gorelo custom field with the oldest date
        try {
            GoreloAction -SetCustomField -Name '$gorelo:asset.windowsInstallDate' -Value $goreloDateString
            Write-Host "Successfully updated Gorelo custom field" -ForegroundColor Green
        } catch {
            Write-Host "Error updating Gorelo custom field: $($_.Exception.Message)" -ForegroundColor Red
        }

        # Display difference between oldest and newest dates for verification
        $newestDate = $validDates | Sort-Object | Select-Object -Last 1
        $dateDifference = New-TimeSpan -Start $oldestDate -End $newestDate
        Write-Host "`nDate range span: $($dateDifference.Days) days" -ForegroundColor Cyan
        Write-Host "Newest date found: $($newestDate.ToString('MM/dd/yyyy'))" -ForegroundColor Cyan
        ```
      </Tab>

      <Tab title="Windows Product Key">
        * **Name**: 🗝️Store-WindowsProductKey
        * **Content**:

        ```powershell theme={null}
        # Get Windows Product Key and update Gorelo custom field
        try {
            # Get Windows Product Key using WMI
            $productKey = (Get-WmiObject -query 'select * from SoftwareLicensingService').OA3xOriginalProductKey

            if ([string]::IsNullOrEmpty($productKey)) {
                # If OA3xOriginalProductKey is empty, try getting it from registry
                $regPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform'
                $regValue = 'BackupProductKeyDefault'
                $productKey = (Get-ItemProperty -Path $regPath -Name $regValue -ErrorAction SilentlyContinue).$regValue
            }

            if ([string]::IsNullOrEmpty($productKey)) {
                # If still empty, try another registry method
                $regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId"
                $digitalId = (Get-ItemProperty -Path $regPath).DigitalProductId
                
                # Convert Digital Product ID to Product Key
                $keyOffset = 52
                $isWin8 = ([math]::Floor($digitalId[66] / 6) -band 1)
                $productKey = ""
                $chars = "BCDFGHJKMPQRSTVWXY2346789"

                for ($i = 24; $i -ge 0; $i--) {
                    $r = 0
                    for ($j = 14; $j -ge 0; $j--) {
                        $r = ($r * 256) -bxor $digitalId[$j + $keyOffset]
                        $digitalId[$j + $keyOffset] = [math]::Floor($r / 24)
                        $r = $r % 24
                    }
                    $productKey = $chars[$r] + $productKey
                    if (($i % 5) -eq 0 -and $i -ne 0) {
                        $productKey = "-" + $productKey
                    }
                }
            }

            if (![string]::IsNullOrEmpty($productKey)) {
                # Update Gorelo RMM custom field
                GoreloAction -SetCustomField -Name '$gorelo:asset.WindowsProductKey' -Value $productKey
                Write-Output "Successfully updated Windows Product Key in Gorelo"
            } else {
                Write-Error "Could not retrieve Windows Product Key"
                exit 1
            }
        } catch {
            Write-Error "Error: $($_.Exception.Message)"
            exit 1
        }
        ```
      </Tab>

      <Tab title="MAC Address">
        * **Name**: MAC Address for Ethernet
        * **Content**:

        ```powershell theme={null}
        # Get Ethernet adapter MAC address only
        $MacAddress = (Get-NetAdapter | Where-Object {$_.Name -like "*Ethernet*" -and $_.Status -eq "Up"} | Select-Object -First 1 -ExpandProperty MacAddress)

        if ($MacAddress) {
            GoreloAction -SetCustomField -Name 'asset.macAddress' -Value $MacAddress
            Write-Host "Ethernet MAC Address set to: $MacAddress"
        } else {
            Write-Host "No active Ethernet adapter found"
        }
        ```
      </Tab>

      <Tab title="RAM Slots Used">
        * **Name**: 🗝️Store-ramSlotsUsed
        * **Content**:

        ```powershell theme={null}
        $totalSlots = (Get-CimInstance -ClassName Win32_PhysicalMemoryArray).MemoryDevices
        $usedSlots = (Get-CimInstance -ClassName Win32_PhysicalMemory).Count
        $emptySlots = $totalSlots - $usedSlots
        $totalRAM = [math]::Round((Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory/1GB, 2)

        $ramInfo = "RAM: $totalRAM GB installed | Slots: $usedSlots/$totalSlots used ($emptySlots empty)"

        # Set Gorelo RMM custom field
        GoreloAction -SetCustomField -Name 'asset.ramSlotsUsed' -Value $ramInfo

        Write-Host "Set Gorelo field 'asset.ramSlotsUsed' to: $ramInfo"
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="نشر النص البرمجي عبر سياسة.">
    1. انتقل إلى **[Policies](https://app.gorelo.io/Asset/policy-management).**
    2. عدّل سياسة موجودة تغطي الأصول التي تريد تخزين المفاتيح أو العناوين لها.
    3. أضف النص البرمجي وعيّنه ليتكرر يوميًا في الوقت المفضل لديك.
    4. **احفظ** ووزّع السياسة.
  </Step>
</Steps>
