Repository moved to Forgejo
Usable scripts migrated to https://forgejo.oskamp.info/ivooskamp/Autopilot.git This Gitea copy is emptied and kept only as a redirect.
This commit is contained in:
parent
8ec0b8c791
commit
08a00bf63e
@ -1,96 +0,0 @@
|
||||
# Configuration
|
||||
$csvPath = "$env:TEMP\AutopilotHash.csv"
|
||||
$autopilotScript = "$env:TEMP\Get-WindowsAutopilotInfo.ps1"
|
||||
|
||||
# Microsoft 365 OAuth Configuration
|
||||
$tenantId = "YOUR_TENANT_ID"
|
||||
$clientId = "YOUR_CLIENT_ID"
|
||||
$clientSecret = "YOUR_CLIENT_SECRET" # Store securely!
|
||||
$fromEmail = "sender@example.com"
|
||||
$toEmail = "recipient@example.com"
|
||||
|
||||
# Retrieve the device serial number
|
||||
$serialNumber = (Get-WmiObject -Class Win32_BIOS).SerialNumber
|
||||
if (-not $serialNumber) {
|
||||
$serialNumber = "Unknown_SerialNumber"
|
||||
}
|
||||
|
||||
# Email subject including the serial number
|
||||
$subject = "Autopilot Hash Export - $serialNumber"
|
||||
$body = "See the attached CSV file containing the Autopilot Hash for device $serialNumber."
|
||||
|
||||
# Download Get-WindowsAutopilotInfo.ps1 from a trusted source
|
||||
Write-Host "Downloading Get-WindowsAutopilotInfo.ps1..."
|
||||
$downloadUrl = "https://gitea.oskamp.info/ivooskamp/Autopilot/raw/branch/main/Get-WindowsAutoPilotInfo.ps1"
|
||||
|
||||
Try {
|
||||
Invoke-WebRequest -Uri $downloadUrl -OutFile $autopilotScript -UseBasicParsing -ErrorAction Stop
|
||||
} Catch {
|
||||
Write-Host "Error: Failed to download Get-WindowsAutopilotInfo.ps1."
|
||||
Exit 1
|
||||
}
|
||||
|
||||
# Verify if the script was downloaded correctly
|
||||
if (-not (Test-Path $autopilotScript)) {
|
||||
Write-Host "Error: Get-WindowsAutopilotInfo.ps1 does not exist after download."
|
||||
Exit 1
|
||||
}
|
||||
|
||||
# Execute the script to collect the Autopilot hash
|
||||
Write-Host "Collecting the Autopilot hash..."
|
||||
Try {
|
||||
& PowerShell -ExecutionPolicy Bypass -File $autopilotScript -OutputFile $csvPath -ErrorAction Stop
|
||||
} Catch {
|
||||
Write-Host "Error retrieving the Autopilot hash: $_"
|
||||
Exit 1
|
||||
}
|
||||
|
||||
# Check if the CSV file was created
|
||||
if (-not (Test-Path $csvPath)) {
|
||||
Write-Host "Error: CSV file was not created."
|
||||
Exit 1
|
||||
}
|
||||
|
||||
# Obtain Microsoft 365 OAuth Token
|
||||
Write-Host "Retrieving Microsoft 365 OAuth token..."
|
||||
$tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
|
||||
$tokenBody = @{
|
||||
client_id = $clientId
|
||||
scope = "https://graph.microsoft.com/.default"
|
||||
grant_type = "client_credentials"
|
||||
client_secret = $clientSecret
|
||||
}
|
||||
|
||||
$tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl -ContentType "application/x-www-form-urlencoded" -Body $tokenBody
|
||||
$accessToken = $tokenResponse.access_token
|
||||
|
||||
# Send email via Microsoft Graph API
|
||||
$graphUrl = "https://graph.microsoft.com/v1.0/users/$fromEmail/sendMail"
|
||||
|
||||
$emailJson = @{
|
||||
message = @{
|
||||
subject = $subject
|
||||
body = @{
|
||||
contentType = "Text"
|
||||
content = $body
|
||||
}
|
||||
toRecipients = @(@{ emailAddress = @{ address = $toEmail } })
|
||||
attachments = @(@{
|
||||
"@odata.type" = "#microsoft.graph.fileAttachment"
|
||||
name = "AutopilotHash_$serialNumber.csv"
|
||||
contentType = "text/csv"
|
||||
contentBytes = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($csvPath))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
$emailJson = $emailJson | ConvertTo-Json -Depth 10
|
||||
|
||||
Write-Host "Sending email..."
|
||||
Invoke-RestMethod -Uri $graphUrl -Headers @{Authorization = "Bearer $accessToken"; "Content-Type" = "application/json"} -Method Post -Body $emailJson
|
||||
|
||||
Write-Host "Email sent to $toEmail"
|
||||
|
||||
# Cleanup
|
||||
Remove-Item -Path $csvPath -Force
|
||||
Remove-Item -Path $autopilotScript -Force
|
||||
@ -1,173 +0,0 @@
|
||||
param(
|
||||
[string]$AssignedUser = "",
|
||||
[switch]$Online
|
||||
)
|
||||
|
||||
# ── Execution Policy ────────────────────────────────────────────────────────
|
||||
$OriginalPolicy = Get-ExecutionPolicy -Scope Process
|
||||
$RestrictedPolicies = @("Restricted", "AllSigned")
|
||||
|
||||
if ($OriginalPolicy -in $RestrictedPolicies) {
|
||||
Write-Host ""
|
||||
Write-Host "De huidige execution policy is: $OriginalPolicy" -ForegroundColor Yellow
|
||||
Write-Host "Dit script heeft minimaal 'RemoteSigned' nodig om te kunnen draaien."
|
||||
Write-Host ""
|
||||
$Confirm = Read-Host "Wil je de execution policy tijdelijk aanpassen? (j/n)"
|
||||
|
||||
if ($Confirm -notmatch '^[jJyY]') {
|
||||
Write-Host "Geannuleerd. Execution policy is niet gewijzigd." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
Write-Host "Execution policy tijdelijk ingesteld op Unrestricted." -ForegroundColor Cyan
|
||||
$PolicyChanged = $true
|
||||
} else {
|
||||
$PolicyChanged = $false
|
||||
}
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Fixed settings to make the script idiot-proof
|
||||
$GroupTag = "Medewerker"
|
||||
$DateStamp = Get-Date -Format "yyyy-MM-dd"
|
||||
|
||||
# Prefer the script/USB location for output
|
||||
if ($PSScriptRoot) {
|
||||
$BasePath = $PSScriptRoot
|
||||
} else {
|
||||
$BasePath = (Get-Location).Path
|
||||
}
|
||||
|
||||
$OutputFile = Join-Path $BasePath ("AutoPilotHashes-{0}.csv" -f $DateStamp)
|
||||
|
||||
function Write-Info {
|
||||
param([string]$Message)
|
||||
Write-Host $Message
|
||||
}
|
||||
|
||||
function Test-InternetConnection {
|
||||
try {
|
||||
$null = Test-NetConnection -ComputerName "graph.microsoft.com" -Port 443 -InformationLevel Quiet -WarningAction SilentlyContinue
|
||||
return [bool]$?
|
||||
} catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Get-AutopilotHardwareHash {
|
||||
try {
|
||||
$hash = (Get-CimInstance -Namespace "root/cimv2/mdm/dmmap" -ClassName "MDM_DevDetail_Ext01" -Filter "InstanceID='Ext' AND ParentID='./DevDetail'").DeviceHardwareData
|
||||
if ([string]::IsNullOrWhiteSpace($hash)) {
|
||||
throw "DeviceHardwareData is empty."
|
||||
}
|
||||
return $hash
|
||||
} catch {
|
||||
throw "Unable to read the Autopilot hardware hash from WMI. Run this script in full Windows OOBE or Windows with the MDM Bridge WMI provider available. Details: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-DeviceSerialNumber {
|
||||
try {
|
||||
$serial = (Get-CimInstance -ClassName Win32_BIOS).SerialNumber
|
||||
if ([string]::IsNullOrWhiteSpace($serial)) {
|
||||
throw "Serial number is empty."
|
||||
}
|
||||
return $serial.Trim()
|
||||
} catch {
|
||||
throw "Unable to read the device serial number. Details: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
function Ensure-CsvHeader {
|
||||
param([string]$Path)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path)) {
|
||||
'"Device Serial Number","Windows Product ID","Hardware Hash","Group Tag","Assigned User"' | Out-File -LiteralPath $Path -Encoding utf8
|
||||
}
|
||||
}
|
||||
|
||||
function Add-AutopilotCsvRow {
|
||||
param(
|
||||
[string]$Path,
|
||||
[string]$SerialNumber,
|
||||
[string]$HardwareHash,
|
||||
[string]$GroupTagValue,
|
||||
[string]$AssignedUserValue
|
||||
)
|
||||
|
||||
Ensure-CsvHeader -Path $Path
|
||||
|
||||
$row = [pscustomobject]@{
|
||||
'Device Serial Number' = $SerialNumber
|
||||
'Windows Product ID' = ''
|
||||
'Hardware Hash' = $HardwareHash
|
||||
'Group Tag' = $GroupTagValue
|
||||
'Assigned User' = $AssignedUserValue
|
||||
}
|
||||
|
||||
$row | Export-Csv -LiteralPath $Path -NoTypeInformation -Append -Encoding utf8
|
||||
}
|
||||
|
||||
function Upload-ToIntune {
|
||||
param([string]$CsvPath)
|
||||
|
||||
if (-not $Online) {
|
||||
return
|
||||
}
|
||||
|
||||
if (-not (Test-InternetConnection)) {
|
||||
Write-Info "No internet connection detected. Skipping online upload. The CSV fallback has been saved to: $CsvPath"
|
||||
return
|
||||
}
|
||||
|
||||
$moduleName = "WindowsAutoPilotIntune"
|
||||
|
||||
try {
|
||||
if (-not (Get-Module -ListAvailable -Name $moduleName)) {
|
||||
Write-Info "WindowsAutoPilotIntune module not found. Installing module..."
|
||||
Install-Module -Name $moduleName -Force -Scope CurrentUser -AllowClobber
|
||||
}
|
||||
|
||||
Import-Module $moduleName -Force
|
||||
|
||||
if (-not (Get-Command -Name Get-AutopilotDevice -ErrorAction SilentlyContinue)) {
|
||||
throw "The WindowsAutoPilotIntune module was loaded, but the expected commands are not available."
|
||||
}
|
||||
|
||||
Write-Info "Connecting to Microsoft Graph..."
|
||||
Connect-MSGraph | Out-Null
|
||||
|
||||
Write-Info "Uploading CSV to Intune..."
|
||||
Import-AutoPilotCSV -csvFile $CsvPath
|
||||
|
||||
Write-Info "Upload finished."
|
||||
} catch {
|
||||
Write-Info "Online upload failed. The CSV fallback is still available at: $CsvPath"
|
||||
Write-Info ("Upload error: " + $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Write-Info "Collecting Autopilot device information..."
|
||||
Write-Info ("Group Tag is fixed to: " + $GroupTag)
|
||||
Write-Info ("Output file: " + $OutputFile)
|
||||
|
||||
$serialNumber = Get-DeviceSerialNumber
|
||||
$hardwareHash = Get-AutopilotHardwareHash
|
||||
|
||||
Add-AutopilotCsvRow -Path $OutputFile -SerialNumber $serialNumber -HardwareHash $hardwareHash -GroupTagValue $GroupTag -AssignedUserValue $AssignedUser
|
||||
|
||||
Write-Info "Hardware hash saved successfully."
|
||||
Upload-ToIntune -CsvPath $OutputFile
|
||||
Write-Info "Done."
|
||||
} catch {
|
||||
Write-Error $_.Exception.Message
|
||||
exit 1
|
||||
} finally {
|
||||
if ($PolicyChanged) {
|
||||
Set-ExecutionPolicy -ExecutionPolicy $OriginalPolicy -Scope Process -Force
|
||||
Write-Host "Execution policy teruggezet naar: $OriginalPolicy" -ForegroundColor Cyan
|
||||
}
|
||||
}
|
||||
@ -1,190 +0,0 @@
|
||||
<#PSScriptInfo
|
||||
|
||||
.VERSION 1.3
|
||||
|
||||
.GUID ebf446a3-3362-4774-83c0-b7299410b63f
|
||||
|
||||
.AUTHOR Michael Niehaus
|
||||
|
||||
.COMPANYNAME Microsoft
|
||||
|
||||
.COPYRIGHT
|
||||
|
||||
.TAGS Windows AutoPilot
|
||||
|
||||
.LICENSEURI
|
||||
|
||||
.PROJECTURI
|
||||
|
||||
.ICONURI
|
||||
|
||||
.EXTERNALMODULEDEPENDENCIES
|
||||
|
||||
.REQUIREDSCRIPTS
|
||||
|
||||
.EXTERNALSCRIPTDEPENDENCIES
|
||||
|
||||
.RELEASENOTES
|
||||
Version 1.0: Original published version.
|
||||
Version 1.1: Added -Append switch.
|
||||
Version 1.2: Added -Credential switch.
|
||||
Version 1.3: Added -Partner switch.
|
||||
|
||||
#>
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Retrieves the Windows AutoPilot deployment details from one or more computers
|
||||
.DESCRIPTION
|
||||
This script uses WMI to retrieve properties needed by the Microsoft Store for Business to support Windows AutoPilot deployment.
|
||||
.PARAMETER Name
|
||||
The names of the computers. These can be provided via the pipeline (property name Name or one of the available aliases, DNSHostName, ComputerName, and Computer).
|
||||
.PARAMETER OutputFile
|
||||
The name of the CSV file to be created with the details for the computers. If not specified, the details will be returned to the PowerShell
|
||||
pipeline.
|
||||
.PARAMETER Append
|
||||
Switch to specify that new computer details should be appended to the specified output file, instead of overwriting the existing file.
|
||||
.PARAMETER Credential
|
||||
Credentials that should be used when connecting to a remote computer (not supported when gathering details from the local computer).
|
||||
.PARAMETER Partner
|
||||
Switch to specify that the created CSV file should use the schema for Partner Center (using serial number, make, and model).
|
||||
.EXAMPLE
|
||||
.\Get-WindowsAutoPilotInfo.ps1 -ComputerName MYCOMPUTER -OutputFile .\MyComputer.csv
|
||||
.EXAMPLE
|
||||
.\Get-WindowsAutoPilotInfo.ps1 -ComputerName MYCOMPUTER -OutputFile .\MyComputer.csv -Append
|
||||
.EXAMPLE
|
||||
.\Get-WindowsAutoPilotInfo.ps1 -ComputerName MYCOMPUTER1,MYCOMPUTER2 -OutputFile .\MyComputers.csv
|
||||
.EXAMPLE
|
||||
Get-ADComputer -Filter * | .\GetWindowsAutoPilotInfo.ps1 -OutputFile .\MyComputers.csv
|
||||
.EXAMPLE
|
||||
Get-CMCollectionMember -CollectionName "All Systems" | .\GetWindowsAutoPilotInfo.ps1 -OutputFile .\MyComputers.csv
|
||||
.EXAMPLE
|
||||
.\Get-WindowsAutoPilotInfo.ps1 -ComputerName MYCOMPUTER1,MYCOMPUTER2 -OutputFile .\MyComputers.csv -Partner
|
||||
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True,Position=0)][alias("DNSHostName","ComputerName","Computer")] [String[]] $Name = @($env:ComputerName),
|
||||
[Parameter(Mandatory=$False)] [String] $OutputFile = "",
|
||||
[Parameter(Mandatory=$False)] [Switch] $Append = $false,
|
||||
[Parameter(Mandatory=$False)] [System.Management.Automation.PSCredential] $Credential = $null,
|
||||
[Parameter(Mandatory=$False)] [Switch] $Partner = $false,
|
||||
[Parameter(Mandatory=$False)] [Switch] $Force = $false
|
||||
)
|
||||
|
||||
Begin
|
||||
{
|
||||
# Initialize empty list
|
||||
$computers = @()
|
||||
}
|
||||
|
||||
Process
|
||||
{
|
||||
foreach ($comp in $Name)
|
||||
{
|
||||
$bad = $false
|
||||
|
||||
# Get the common properties.
|
||||
Write-Verbose "Checking $comp"
|
||||
$serial = (Get-WmiObject -ComputerName $comp -Credential $Credential -Class Win32_BIOS).SerialNumber
|
||||
|
||||
# Get the hash (if available)
|
||||
$devDetail = (Get-WMIObject -ComputerName $comp -Credential $Credential -Namespace root/cimv2/mdm/dmmap -Class MDM_DevDetail_Ext01 -Filter "InstanceID='Ext' AND ParentID='./DevDetail'")
|
||||
if ($devDetail -and (-not $Force))
|
||||
{
|
||||
$hash = $devDetail.DeviceHardwareData
|
||||
}
|
||||
else
|
||||
{
|
||||
$bad = $true
|
||||
$hash = ""
|
||||
}
|
||||
|
||||
# If the hash isn't available, get the make and model
|
||||
if ($bad -or $Force)
|
||||
{
|
||||
$cs = Get-WmiObject -ComputerName $comp -Credential $Credential -Class Win32_ComputerSystem
|
||||
$make = $cs.Manufacturer.Trim()
|
||||
$model = $cs.Model.Trim()
|
||||
if ($Partner)
|
||||
{
|
||||
$bad = $false
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$make = ""
|
||||
$model = ""
|
||||
}
|
||||
|
||||
# Getting the PKID is generally problematic for anyone other than OEMs, so let's skip it here
|
||||
$product = ""
|
||||
|
||||
# Depending on the format requested, create the necessary object
|
||||
if ($Partner)
|
||||
{
|
||||
# Create a pipeline object
|
||||
$c = New-Object psobject -Property @{
|
||||
"Device Serial Number" = $serial
|
||||
"Windows Product ID" = $product
|
||||
"Hardware Hash" = $hash
|
||||
"Manufacturer name" = $make
|
||||
"Device model" = $model
|
||||
}
|
||||
# From spec:
|
||||
# "Manufacturer Name" = $make
|
||||
# "Device Name" = $model
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
# Create a pipeline object
|
||||
$c = New-Object psobject -Property @{
|
||||
"Device Serial Number" = $serial
|
||||
"Windows Product ID" = $product
|
||||
"Hardware Hash" = $hash
|
||||
}
|
||||
}
|
||||
|
||||
# Write the object to the pipeline or array
|
||||
if ($bad)
|
||||
{
|
||||
# Report an error when the hash isn't available
|
||||
Write-Error -Message "Unable to retrieve device hardware data (hash) from computer $comp" -Category DeviceError
|
||||
}
|
||||
elseif ($OutputFile -eq "")
|
||||
{
|
||||
$c
|
||||
}
|
||||
else
|
||||
{
|
||||
$computers += $c
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
End
|
||||
{
|
||||
if ($OutputFile -ne "")
|
||||
{
|
||||
if ($Append)
|
||||
{
|
||||
if (Test-Path $OutputFile)
|
||||
{
|
||||
$computers += Import-CSV -Path $OutputFile
|
||||
}
|
||||
}
|
||||
if ($Partner)
|
||||
{
|
||||
$computers | Select "Device Serial Number", "Windows Product ID", "Hardware Hash", "Manufacturer name", "Device model" | ConvertTo-CSV -NoTypeInformation | % {$_ -replace '"',''} | Out-File $OutputFile
|
||||
# From spec:
|
||||
# $computers | Select "Device Serial Number", "Windows Product ID", "Hardware Hash", "Manufacturer Name", "Device Name" | ConvertTo-CSV -NoTypeInformation | % {$_ -replace '"',''} | Out-File $OutputFile
|
||||
}
|
||||
else
|
||||
{
|
||||
$computers | Select "Device Serial Number", "Windows Product ID", "Hardware Hash" | ConvertTo-CSV -NoTypeInformation | % {$_ -replace '"',''} | Out-File $OutputFile
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
@ECHO OFF
|
||||
echo Enabling WinRM
|
||||
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command Enable-PSRemoting -SkipNetworkProfileCheck -Force
|
||||
echo Gathering AutoPilot Hash
|
||||
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command %~dp0Get-WindowsAutoPilotInfo.ps1 -ComputerName $env:computername -OutputFile %~dp0compHash.csv -append
|
||||
echo Done!
|
||||
pause
|
||||
@ -1,9 +0,0 @@
|
||||
@ECHO OFF
|
||||
echo Enabling WinRM
|
||||
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command Enable-PSRemoting -SkipNetworkProfileCheck -Force
|
||||
echo Gathering AutoPilot Hash
|
||||
PowerShell -NoProfile -ExecutionPolicy Unrestricted -Command %~dp0Get-WindowsAutoPilotInfo.ps1 -ComputerName $env:computername -OutputFile %~dp0compHash.csv -append
|
||||
echo Done!
|
||||
dir
|
||||
pause
|
||||
shutdown.exe -s -t 0
|
||||
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Autopilot — moved
|
||||
|
||||
This repository has **moved to Forgejo** and is no longer maintained here.
|
||||
|
||||
➡️ **New location:** https://forgejo.oskamp.info/ivooskamp/Autopilot.git
|
||||
|
||||
Only the current, usable scripts were migrated:
|
||||
|
||||
- `Get-WindowsAutoPilotInfo-IdiotProof-v4.ps1` — modern, self-contained hash
|
||||
collection (Get-CimInstance, handles execution policy, optional Intune upload).
|
||||
- `start.bat` — launcher for the v4 script.
|
||||
|
||||
The obsolete Microsoft v1.3 script, the `GetAutoPilot*.CMD` launchers and the
|
||||
email-export script were intentionally left behind and not migrated.
|
||||
|
||||
Please update your remotes:
|
||||
|
||||
```bash
|
||||
git remote set-url origin https://forgejo.oskamp.info/ivooskamp/Autopilot.git
|
||||
```
|
||||
|
||||
This Gitea copy has been emptied intentionally and is kept only as a redirect.
|
||||
Reference in New Issue
Block a user