IoT Hub: Quick setup ... with help from AI
iot powershell dotnetcore iothub azure iot-core
A set of scripts for creating an Azure IoT Hub and 10 devices. A simulator is generated for each device and runs locally. Cleanup scripts are included. The scripts were generated with help from GitHub Copilot. They are designed to run from a VS Code terminal on Windows. Azure IoT Explorer is used to verify the devices are created and running. The scripts are idempotent, so they can be rerun without error.
Tip: avoid hardcoded hub names by setting an environment variable once in PowerShell:
$IOTHUB_NAME = 'my-iot-hub-137'
Update 2026-07-11
The newer C# simulator scripts support a reusable environment variable (IOTHUB_NAME) so the hub name no longer has to be hardcoded in every script call.
.\1_QuickSetup\set_iothub_env.ps1 -HubName $IOTHUB_NAME -Scope User
After that, scripts can be run without -HubName, for example:
1_QuickSetup/7_create_resource_group_and_iot_hub_b1.ps1
Repository
Azure IoT Hub Fast Setup on GitHub: djaus2/iothub-fast-setup
Scripts
The scripts as per sections (from section 7) from this post are on GitHub at djaus2/iothub-fast-setup/1_QuickSetup
Index of scripts from this post
- 7_create_resource_group_and_iot_hub_b1.ps1 — Create resource group and IoT Hub (B1 SKU) with example settings.
- 7_verify_iot_hub.ps1 — Verify IoT Hub exists and show basic properties.
- 8_create_10_devices.ps1 — Create 10 device identities in the IoT Hub.
- 8_create_10_devices_idempotent.ps1 — Idempotent device-creation version (safe to re-run).
- 8_verify_devices.ps1 — Verify device identities in the hub.
- 9_get_device_connection_strings.ps1 — Retrieve device connection strings for each device.
- 10_get_iothub_connection_string_for_explorer.ps1 — Get IoT Hub connection string for Azure IoT Explorer (service policy).
- 12_get_emulator_job_status.ps1 — Query status of local emulator jobs started as PowerShell background jobs.
- 12_start_10_local_device_emulators.ps1 — Start 10 local device emulators (multi-line job version).
- 12_start_10_local_device_emulators_copy_safe_oneliner.ps1 — Copy-safe one-line start command for 10 emulators.
- 12_stop_all_simulators.ps1 — Stop and remove emulator jobs started by the scripts.
- 15_delete_all_resources.ps1 — Delete all Azure resources created for this lab (resource group delete).
About
Have previously created Powershell scripts to simplify creation of an IoT Hub and related devices.
See blog category iot/
This is a set of scripts authored with help from GitHub Copilot. The scripts are designed to run from a VS Code terminal on Windows. They create a resource group, an IoT Hub, and 10 devices. They then run 10 local device emulators and open the IoT Hub in Azure IoT Explorer.
Azure IoT Hub End-to-End Setup in VS Code (Windows)
This guide shows how to do the full workflow in VS Code terminal:
- Create Resource Group: $IOT_RG
- Create IoT Hub: $IOTHUB_NAME
- Create 10 devices: device1 to device10
- Run 10 local device emulators
- Open and verify in Azure IoT Explorer
It also includes extension upgrade/repair steps for the issue you hit.
1. Prerequisites
- Install VS Code.
- Install Azure CLI (az).
- Sign in to Azure from terminal.
- Make sure you have an active subscription with permission to create resources.
- Install Azure IoT Explorer desktop app.
Notes:
- You do not need a VS Code IoT extension for this workflow.
- You do need the Azure CLI extension named azure-iot.
2. Open VS Code Terminal
In VS Code:
- Open your project folder.
- Open Terminal > New Terminal.
- Use PowerShell terminal on Windows.
3. Verify Azure CLI
Run:
az version
Expected:
- azure-cli is installed
- extensions may or may not include azure-iot yet
If Azure CLI is missing, install it first from Microsoft docs.
4. Sign In and Select Subscription
Run:
az login --use-device-code
If you have multiple tenants:
az login --tenant <tenant-id> --use-device-code
Set active subscription:
az account set --subscription <subscription-id>
az account show --query "{user:user.name, subscription:id, name:name}" -o json
5. Install Required Azure IoT CLI Extension
Install:
az extension add --name azure-iot --upgrade
Verify:
az extension list --query "[?name=='azure-iot'].{name:name,version:version}" -o table
6. Names and Azure Naming Rules
Requested names:
- Resource Group: My-IoT-Grp-137
- IoT Hub: My-IoT-Hub-137
- Devices: device1 to device10
Important:
- IoT Hub name must be globally unique.
- IoT Hub name must be lowercase.
So use this hub name in commands:
my-iot-hub-137
If already taken globally, append a suffix, for example:
my-iot-hub-137-01
7. Create Resource Group and IoT Hub (S1)
Choose location (example: australiaeast), then run:
az group create -n $IOT_RG -l australiaeast
az iot hub create -g $IOT_RG -n $IOTHUB_NAME --sku S1 --partition-count 2
Verify hub:
az iot hub show -n $IOTHUB_NAME --query "{name:name,sku:sku.name,state:properties.state,hostname:properties.hostName}" -o json
8. Create 10 Devices
PowerShell loop:
for ($i=1; $i -le 10; $i++) {
az iot hub device-identity create -n $IOTHUB_NAME -d ("device" + $i)
}
Idempotent version (safe if rerun):
for ($i=1; $i -le 10; $i++) {
$d = "device$i"
az iot hub device-identity show -n $IOTHUB_NAME -d $d --query deviceId -o tsv 1>$null 2>$null
if ($LASTEXITCODE -ne 0) {
az iot hub device-identity create -n $IOTHUB_NAME -d $d | Out-Null
}
}
Verify:
az iot hub device-identity list -n $IOTHUB_NAME --query "[].deviceId" -o table
9. Get Device Connection Strings
PowerShell loop:
for ($i=1; $i -le 10; $i++) {
$d = "device$i"
$cs = az iot hub device-identity connection-string show -n $IOTHUB_NAME -d $d --query connectionString -o tsv
Write-Output "$d`t$cs"
}
10. Get IoT Hub Connection String for IoT Explorer
Use service policy connection string (for hub management in IoT Explorer):
az iot hub connection-string show -n $IOTHUB_NAME --policy-name iothubowner --key primary --query connectionString -o tsv
11. Open in Azure IoT Explorer
- Open Azure IoT Explorer desktop app.
- Select Add connection.
- Choose IoT Hub.
- Paste the IoT Hub connection string from step 10.
- Connect.
- Open Devices and confirm Device-1 to Device-10 are visible.
- Open Devices and confirm device1 to device10 are visible.
12. Run 10 Local Device Emulators from VS Code
Start all 10 simulators as background PowerShell jobs:
Important: Keep line breaks, or add ; separators if pasting as one line.
$hub=$IOTHUB_NAME; 1..10 | ForEach-Object { $d = "device$_"; Start-Job -Name "iot-$d" -ScriptBlock { param($h,$device) az iot device simulate -n $h -d $device --msg-count 1000000 --msg-interval 5 --data "Ping from $device" --only-show-errors } -ArgumentList $hub,$d | Out-Null }; Get-Job -Name 'iot-device*' | Select-Object Name,State,PSBeginTime
Get-Job -Name 'iot-device*' | Select-Object Name,State,PSBeginTime
Copy-safe one-line version:
$hub=$IOTHUB_NAME; 1..10 | ForEach-Object { $d = "device$_"; Start-Job -Name "iot-$d" -ScriptBlock { param($h,$device) az iot device simulate -n $h -d $device --msg-count 1000000 --msg-interval 5 --data "Ping from $device" --only-show-errors } -ArgumentList $hub,$d | Out-Null }; Get-Job -Name 'iot-device*' | Select-Object Name,State,PSBeginTime
Stop all simulators:
$jobs = Get-Job | Where-Object { $_.Name -like 'iot-device*' }
if ($jobs) {
$jobs | Stop-Job -ErrorAction SilentlyContinue
$jobs | Remove-Job -Force -ErrorAction SilentlyContinue
'Stopped/removed jobs: ' + ($jobs.Name -join ', ')
} else {
'No matching iot emulator jobs found.'
}
13. Troubleshooting (Upgrade/Extension Issues)
Problem: azure-iot commands fail and mention extension update/copy errors
Symptoms can include:
- FileExistsError in cliextensions\azure-iot
- Access denied deleting old extension folders
- Dynamic install repeatedly trying to upgrade and failing
Fix (Windows PowerShell):
az config set extension.use_dynamic_install=no
az extension remove --name azure-iot
$extPath = Join-Path $HOME ".azure\\cliextensions\\azure-iot"
if (Test-Path $extPath) {
attrib -r "$extPath\\*" /s /d | Out-Null
Remove-Item -LiteralPath $extPath -Recurse -Force -ErrorAction SilentlyContinue
}
az extension add --name azure-iot --upgrade
az extension show --name azure-iot --query "{name:name,version:version}" -o json
After repair, retry device commands.
Problem: Stop-Job says “A positional parameter cannot be found that accepts argument ‘Get-Job’”
Cause:
- Two pipelines were typed on one line without a separator, so PowerShell treated
Get-Jobas an argument toStop-Job.
Correct examples:
Get-Job -Name 'iot-device*' | Stop-Job; Get-Job -Name 'iot-device*' | Remove-Job
or
Get-Job -Name 'iot-device*' | Stop-Job
Get-Job -Name 'iot-device*' | Remove-Job
14. Common Gotchas
- IoT Hub name must be lowercase and globally unique.
- Device IDs are case-sensitive.
- IoT Explorer uses IoT Hub service connection string, not device connection strings.
- If login says no subscriptions found, verify tenant and subscription selection.
- If operations are denied, check RBAC permissions on the subscription/resource group.
15. Optional Cleanup
Delete only emulator jobs:
$jobs = Get-Job | Where-Object { $_.Name -like 'iot-device*' }
if ($jobs) {
$jobs | Stop-Job -ErrorAction SilentlyContinue
$jobs | Remove-Job -Force -ErrorAction SilentlyContinue
}
What it does:
- Stops the running emulator jobs.
- Removes those jobs from your PowerShell session.
What it does not do:
- It does not uninstall Azure CLI or the azure-iot extension.
- It does not delete IoT Hub device identities in Azure.
Quick check:
Get-Job -Name iot-device*
Delete all Azure resources in this lab:
az group delete -n $IOT_RG --yes --no-wait
Azure IoT Hub Explorer
Use Azure IoT Explorer to confirm your hub is reachable and your devices exist.
Install Azure IoT Explorer
- Download Azure IoT Explorer from the official Microsoft GitHub releases page: Azure-iot-explorer/releases
- Install it using the Windows installer.
- Launch Azure IoT Explorer from the Start menu.
Add Your IoT Hub
- In Azure IoT Explorer, select Add connection.
- Select IoT Hub.
- Get the IoT Hub service connection string as per Section 10 above.
- Paste the IoT Hub service connection string
- Select Connect.
Check Devices
- Open the Devices tab in Azure IoT Explorer.
- Confirm device1 through device10 are listed.
- Select one device and check status fields (for example, connection state and last activity time).
- If your simulators are running, refresh and confirm activity updates.
If Devices Are Missing
Run this command in VS Code terminal to verify device identities in the hub:
az iot hub device-identity list -n $IOTHUB_NAME --query "[].deviceId" -o table
16. Quick Command Checklist
Run in order:
# Need environment variables for hub name and resource group
# Run 1_QuickSetup\set_iothub_env.ps1 with a unique name for your IoT Hub.
# Resource Group gets generated from that.
if ([string]::IsNullOrWhiteSpace($IOTHUB_NAME) -or [string]::IsNullOrWhiteSpace($IOT_RG)) {
throw "Required variables missing. Set non-empty values for IOTHUB_NAME and IOT_RG before running this checklist."
}
az version
az login --use-device-code
az account set --subscription <subscription-id>
az extension add --name azure-iot --upgrade
az group create -n $IOT_RG -l australiaeast
az iot hub create -g $IOT_RG -n $IOTHUB_NAME --sku B1 --partition-count 2
for ($i=1; $i -le 10; $i++) { az iot hub device-identity create -n $IOTHUB_NAME -d ("device" + $i) }
az iot hub connection-string show -n $IOTHUB_NAME --policy-name iothubowner --key primary --query connectionString -o tsv
Addendum: Terminal Scoping for Get-Job in VS Code
If this command returns nothing:
Get-Job -Name 'iot-device*' | Select-Object Name,State,PSBeginTime
it usually means the jobs were started in a different PowerShell session.
Key point:
Get-Jobis session-scoped (per terminal process), not system-wide.- In VS Code, each terminal tab can be a separate PowerShell process.
- So one terminal can have zero jobs, while simulators still run from another terminal.
Check jobs in the same terminal tab that started them:
Get-Job | Select-Object Id,Name,State,PSBeginTime,PSEndTime
Check simulator processes system-wide (ps-style view):
Get-CimInstance Win32_Process |
Where-Object { $_.CommandLine -match 'az iot device simulate|azure.cli|az\.cmd' } |
Select-Object ProcessId,Name,CreationDate,CommandLine
If the original job session is open, stop cleanly from that session:
Get-Job -Name 'iot-device*' | Stop-Job
Get-Job -Name 'iot-device*' | Remove-Job
If the original session is gone, stop by process match (system-wide):
Get-CimInstance Win32_Process |
Where-Object { $_.CommandLine -match 'az iot device simulate|azure.cli' } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force }
Tip:
- To avoid this confusion, keep emulator jobs and job management commands in one dedicated terminal tab.
Next: Some device code
| Topic | Subtopic | |
| Next: > | IoT Hub | Device Twin vs Device Update for IoT Hub |
| < Prev: | GitHub | Creating Releases |
| This Category Links | ||
| Category: | IoT Index: | IoT |