How to Retrieve EC2 Windows Instance ID in Batch Script for Program Arguments


2 views

When working with AWS EC2 Windows instances, you often need to access instance-specific metadata like the instance ID. The simplest approach is using the instance metadata service available at http://169.254.169.254. Here's how to implement this in a batch script:

@echo off
for /f "tokens=*" %%a in ('powershell -command "(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id').Content"') do set INSTANCE_ID=%%a
myprogram.exe /instanceID=%INSTANCE_ID%

For older Windows systems without PowerShell 3.0+ (which includes Invoke-WebRequest), you can use these alternatives:

:: Using bitsadmin (Windows XP/2003 and later)
bitsadmin /transfer GetInstanceID /download /priority normal http://169.254.169.254/latest/meta-data/instance-id %TEMP%\instance-id.txt
set /p INSTANCE_ID=<%TEMP%\instance-id.txt
myprogram.exe /instanceID=%INSTANCE_ID%

:: Using certutil (Windows 7/2008 R2 and later)
certutil -urlcache -split -f http://169.254.169.254/latest/meta-data/instance-id %TEMP%\instance-id.txt
set /p INSTANCE_ID=<%TEMP%\instance-id.txt
myprogram.exe /instanceID=%INSTANCE_ID%

In production environments, you should add error handling and retry logic:

@echo off
set RETRY_COUNT=3
set RETRY_DELAY=5

:RETRY
for /f "tokens=*" %%a in ('powershell -command "$ErrorActionPreference='Stop'; try {(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id' -TimeoutSec 10).Content} catch { exit 1 }"') do (
    set INSTANCE_ID=%%a
    goto HAVE_ID
)

set /a RETRY_COUNT-=1
if %RETRY_COUNT% GTR 0 (
    timeout %RETRY_DELAY%
    goto RETRY
)

echo Failed to retrieve instance ID after multiple attempts
exit /b 1

:HAVE_ID
myprogram.exe /instanceID=%INSTANCE_ID%

If you're using CloudFormation or Auto Scaling, consider passing the instance ID as a user data parameter:

@echo off
for /f "tokens=*" %%a in ('powershell -command "(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/user-data').Content"') do set USER_DATA=%%a
for /f "tokens=2 delims==" %%b in ('echo %USER_DATA% ^| findstr /i "INSTANCE_ID="') do set INSTANCE_ID=%%b
myprogram.exe /instanceID=%INSTANCE_ID%

Remember these security best practices:

  • The metadata service is only accessible from within the instance
  • For sensitive data, use AWS Systems Manager Parameter Store instead
  • Consider rate limiting your metadata requests
  • Use IMDSv2 for enhanced security with token-based access

When working with AWS EC2 Windows instances, you often need to access instance metadata like the instance ID. This becomes particularly important when you need to pass this information as a parameter to another program during startup.

AWS provides a simple HTTP endpoint for retrieving instance metadata:

http://169.254.169.254/latest/meta-data/instance-id

This endpoint is only accessible from within the EC2 instance and returns the instance ID as plain text.

Here are several approaches to retrieve the instance ID in a Windows batch script:

Method 1: Using PowerShell

The most reliable way is to use PowerShell within your batch script:

@echo off
for /f %%i in ('powershell -command "(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id').Content"') do set INSTANCE_ID=%%i
myprogram.exe /instanceID=%INSTANCE_ID%

Method 2: Using cURL

If you have cURL installed:

@echo off
for /f %%i in ('curl http://169.254.169.254/latest/meta-data/instance-id') do set INSTANCE_ID=%%i
myprogram.exe /instanceID=%INSTANCE_ID%

Method 3: Using bitsadmin (Older Windows)

For systems without PowerShell or cURL:

@echo off
bitsadmin /transfer getid /download /priority normal http://169.254.169.254/latest/meta-data/instance-id %TEMP%\instance-id.txt
set /p INSTANCE_ID=<%TEMP%\instance-id.txt
myprogram.exe /instanceID=%INSTANCE_ID%

It's good practice to add error handling:

@echo off
setlocal enabledelayedexpansion
set INSTANCE_ID=unknown

for /f %%i in ('powershell -command "try {(Invoke-WebRequest -Uri 'http://169.254.169.254/latest/meta-data/instance-id').Content} catch { 'unknown' }"') do (
    set INSTANCE_ID=%%i
)

if "!INSTANCE_ID!" == "unknown" (
    echo Failed to retrieve instance ID
    exit /b 1
)

myprogram.exe /instanceID=!INSTANCE_ID!

If you're launching the instance yourself, you can pass the instance ID through user data:

@echo off
for /f "tokens=2 delims==" %%i in ('wmic os get localdatetime /value') do set datetime=%%i
set INSTANCE_ID=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%_%datetime:~8,6%
myprogram.exe /instanceID=%INSTANCE_ID%

The metadata service is generally fast, but if your script runs frequently, you might want to cache the instance ID:

@echo off
if exist "C:\instance-id.txt" (
    set /p INSTANCE_ID=C:\instance-id.txt
    )
)
myprogram.exe /instanceID=%INSTANCE_ID%

Remember that instance metadata is sensitive information. Always:

  • Limit access to the script containing the instance ID
  • Never log the instance ID unnecessarily
  • Consider using IAM roles instead of hardcoding credentials