Thursday, January 12, 2023

Intune Bit-Locker Settings Not Appling

If you get this on the SETTING: Require Device Encryption STATE: Error ERROR: TYPE: 2 ERROR: CODE 65000

You could have bootable media inserted like the ISO you used to install Windows with on a VM.

You'll see this error in the event log under Applications and Services Logs > Microsoft > Windows > BitLocker-API > Management



Hope this helps

Tuesday, November 30, 2021

Use paging with Graph to change group tags on all AutoPilot devices

 Use paging with Graph to change group tags on all AutoPilot devices. Graph has a 1000 device limit and this script uses paging to get all of the devices. Once we have all of the devices we can manipulate group tags.

I would like to shout out January 2021 – TheSleepyAdmins for the assist on paging as well as Bulk Updating Autopilot enrolled devices with Graph API and assigning a Group Tag based on Purchase OrderID - Systems Management Squad (sysmansquad.com) for help with some of the other bits.


# Application (client) ID, tenant Name and secret

$clientid = Read-Host "Input your Client ID"

$clientSecret = Read-Host "Input Client Secret"

$TenantName = Read-Host "Input Tenant Name"

$resource = "https://graph.microsoft.com/"

#$grouptag = "AP-Tag1"

$ReqTokenBody = @{

    Grant_Type    = "client_credentials"

    Scope         = "https://graph.microsoft.com/.default"

    client_Id     = $clientID

    Client_Secret = $clientSecret

 

$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody

$apiUrl = 'https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/'

$Data = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $apiUrl -Method Get

$Results = @()

$Results += $Data.value

[int]$pagecount = 0


$Pages = $Data.'@odata.nextLink'

while($null -ne $Pages) {

$pagecount += 1

Write-host "Checking Page $Pagecount. Count is $($Results.count)"

$Addtional = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $Pages -Method Get


if ($Pages){

$Pages = $Addtional."@odata.nextLink"

}

$Results += $Addtional.value

}

$Results | Export-Csv -Path "c:\temp\Devices.csv" -NoTypeInformation

#Tag the devices

if($grouptag -ne $null){

$body = '{"groupTag":"'+$groupTag+'"}'

foreach ($Result in $Results) {

    $apiUrl = "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$device/UpdateDeviceProperties"

    $rest = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $apiUrl -Body $body -Method Post -ContentType 'application/json'

    Write-Host ($device + ' has been added to the ' + $grouptag)

}

 

#Sync the changes

$apiUrl2 = "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotSettings/sync"

Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $apiUrl2 -Method Post


}


Tuesday, November 9, 2021

PowerShell Code to get all AD Users and attributes.


#Get All AD Users

$Table = @()

$Arrayofmembers = Get-ADUser -filter {objectClass -eq "user"}  -searchbase "DC=LOWES,DC=com" -Properties samaccountname | Sort-Object -Descending

[int]$count = $Arrayofmembers.Count


Foreach($A in $Arrayofmembers) {

$User = Get-ADUser $A.SamAccountName -Properties * | select name,cn,mail,physicaldeliveryofficename,title,extensionattribute12,extensionattribute5,extensionattribute10,extensionAttribute7, @{n=’MemberOf’; e= { ( $_.memberof | % { (Get-ADObject $_).Name }) -join “;” }}

[int]$count = $count - 1

Write-Host "Getting $($a.samaccountname) - $count to go"

$Obj=New-Object PSObject

    $Obj | Add-Member -Name "name" -MemberType NoteProperty  -Value $User.name

    $Obj | Add-Member -Name "CN" -MemberType NoteProperty  -Value $User.cn

    $Obj | Add-Member -Name "physicaldeliveryofficename" -MemberType NoteProperty  -Value $User.physicaldeliveryofficename

    $Obj | Add-Member -Name "Title" -MemberType NoteProperty  -Value $User.title

    $Obj | Add-Member -Name "lowesEffectiveJobCode" -MemberType NoteProperty  -Value $User.extensionattribute12

    $Obj | Add-Member -Name "lowesEffectiveDeptNumber" -MemberType NoteProperty  -Value $User.extensionattribute5

    $Obj | Add-Member -Name "extensionattribute10" -MemberType NoteProperty  -Value $User.extensionattribute10

    $Obj | Add-Member -Name "lowesEffectivePhyLocationCode" -MemberType NoteProperty  -Value $User.extensionAttribute7

$Table += $obj

}

$Table | export-csv "c:\Temp\ADUsers.csv" -NoTypeInformation




Monday, November 8, 2021

 Installing and Bootstraping an SCCM task sequence during AutoPilot


log-it -message "Starting SCCM Install Script" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"

$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path

cd $ScriptDir

log-it -message "Working dir is now $ScriptDir" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"


New-Item -Path C:\ -Name "Temp" -ItemType Directory -ErrorAction SilentlyContinue

New-Item -Path C:\Temp -Name "SCCM" -ItemType Directory -ErrorAction SilentlyContinue


log-it -message "PS Policy is now $Policy" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"


Function log-it {

param( $message, $component, $path, $thread = 0, $file = 0 )


 


[string]$time = Get-Date -format "HH:mm:ss.fff+300"

[string]$date = Get-Date -Format "MM-dd-yyyy"


 


$a = "<![LOG["

$b = "]LOG]!>"

$carrot = "<"

$closecarrot = ">"

$c = "time=""$time"" date=""$date"" component=""$component"" context="""" type=""1"" thread=""$thread"" file=""$file"""

$logentry =  $a+$message+$b+$carrot+$c+$closecarrot

#Add-Content -Path c:\temp\SCCM-Install.log -Value $logentry


 


Add-Content -Path $path -Value $logmessage


 


}


log-it -message "Working directory is now $scriptdir" -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"

$dir = dir

log-it -message $dir -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"



Copy-Item .\ccmsetup.exe c:\temp\SCCM 

Copy-Item .\CMTrace.exe c:\temp




$script=@'

$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path

cd $ScriptDir


#If SCCM is installed AND the AutoPilot TS ran

if( (get-service ccmexec -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").tsname -ne $null)

{

    Disable-ScheduledTask AutoPilotCMClientInstall

}


#TS hasn't ran or didn't finish

else

{

    #Checks if the user is logged in and in an active session

    function Query-User

    {

        $users = (((quser) -ireplace '\s{2,}',',' | ConvertFrom-Csv).username).replace(">","")

        if($users -eq "defaultuser0")

        {

            return $false

        }


        else

        {

            return $true

        }

    }

       

    

    #Checks to make sure machine is connected to VPN

    function Check-VPN

    {

        if ((Test-Connection $localServer -Count 1 -Quiet) -eq $false)

        {

            return $false

        }


        else

        {

            return $true

        }

    }



    $isOnline = Check-VPN

    $isUserLoggedIn = Query-User


    While(($isOnline -eq $false) -or ($isUserLoggedIn -eq $false))

    {

        $isOnline = Check-VPN

        $isUserLoggedIn = Query-User

    

        sleep -Seconds 5


    }


    

    #If TSManager.exe is not running then the TS is not actively running. Okay to install SCCM

    if((ps TSManager -ErrorAction SilentlyContinue) -eq $null)

    {

        Start-Process c:\temp\SCCM\ccmsetup.exe -argumentlist  "/noCRLCheck /mp:CompanyCMG.CLOUDAPP.NET CCMHOSTNAME=CompanyCMG.CLOUDAPP.NET/CCM_Proxy_MutualAuth/72057594037958338 SMSSiteCode=XXX PROVISIONTS=C0220AC4 /forceinstall" 

    }



    sleep -Seconds 600


    #If SCCM is installed AND the AutoPilot TS ran

    if( (get-service ccmexec -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").tsname -ne $null)

    {

        Disable-ScheduledTask AutoPilotCMClientInstall

    }


}


'@


log-it -message "Creating C:\Temp\SCCM\AutoPilotCMClientInstall.ps1 script." -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"

Add-Content C:\Temp\SCCM\AutoPilotCMClientInstall.ps1 -Value $script



#Checks if SCCM is already installed. If it is, it will not create the scheduled task.

$isInstalled = gwmi win32_product | ? {$_.Name -eq "Configuration Manager Client"}


if($isInstalled -eq $null)

{

    log-it -message "Creating Scheduled Task." -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"

    

    $A = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-Ex Bypass -file C:\Temp\SCCM\AutoPilotCMClientInstall.ps1"

    #$T = New-ScheduledTaskTrigger -AtLogOn


    $T = @(

    $(New-ScheduledTaskTrigger -AtLogOn),

    $(New-ScheduledTaskTrigger -Once -At (get-date) -RepetitionInterval (New-TimeSpan -Minutes 1) )

    )


    $P =  New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest

    $S = New-ScheduledTaskSettingsSet –AllowStartIfOnBatteries –DontStopIfGoingOnBatteries -DontStopOnIdleEnd

    $D = New-ScheduledTask -Action $A -Principal $P -Trigger $T -Settings $S

    Register-ScheduledTask AutoPilotCMClientInstall -InputObject $D

}



#Enables UAC visibility through MSRA / Quick Assist

Set-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name PromptOnSecureDesktop -Value 0 -ErrorAction SilentlyContinue







#Detects if script was successful

$task = (Get-ScheduledTask AutoPilotCMClientInstall -ErrorAction SilentlyContinue).state


if ( ($task -eq "Ready") -or ($task -eq "Running") -or (test-path C:\Windows\CCM\CcmExec.exe) )

{

    log-it -message "SCCM is either detected or the installation TS is enabled and will install it." -component "AP" -path "C:\Temp\" -logname "Company_AP.log"

}


else

{

    log-it -message "Didn't detect task!" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"


}


 

Script to get the current user's AD details.

<#
Script will get the currently logged in user and then search for their AD attributes via ADSI.
The attributes are written to a csv file in c:\temp to be used later. They cannot be directly written to TS variables since this step has to be ran as a user account and it would have its own variable store.
#>

#Step needs to run as an AD account to pull info. Currently runs as _sccmsvc1


$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment

#Get logged in user
$user = (Get-WmiObject -Class Win32_Process -Filter 'Name="explorer.exe"').GetOwner().User

#Get AD User attributes
$searcher = [adsisearcher]"(samaccountname=$user)"
$userTitle = $searcher.FindOne().Properties.title
$userDeptNum = $searcher.FindOne().Properties.extensionattribute5
$userDeptName = $searcher.FindOne().Properties.department
$userLocation = $searcher.FindOne().Properties.extensionattribute7


$userObject = New-Object psobject -Property @{
"currentUserADID" = "$user"
"currentUserTitle" = "$userTitle"
"currentUserDeptNum" = "$userDeptNum"
"currentUserDeptName" = "$userDeptName"
"currentUserLocation" = "$userLocation"
}

$userObject | export-csv c:\temp\userAttributes.csv -NoTypeInformation

 Detect OOBE - Script to see if an AutoPilot device is in OOBE


$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path -ErrorAction Ignore
cd $ScriptDir -ErrorAction Ignore


$LoggedOnUser = Get-WmiObject win32_computersystem | select Username -ErrorAction Ignore
$user = $LoggedOnUser.Username

$count = 0
while($user -like "")
{
$LoggedOnUser = Get-WmiObject win32_computersystem | select Username -ErrorAction Ignore
$user = $LoggedOnUser.Username
$count++
sleep -Seconds 5

}


If($LoggedOnUser.Username -like "*defaultuser0")
{

Write-Output "OOBE"
exit 0

}


else
{

exit 12345

}

Thursday, October 28, 2021

PowerShell Code to add a PC to an Azure Group



<#
.Synopsis
Add Computers to Azure AD Group
.DESCRIPTION
Add Computers to Azure AD Group.
.EXAMPLE
Create a txt file with the netbios names of devices you want to add. The script invokes a file picker to allow you to choose the file.
.INPUTS
Inputs to this cmdlet (if any) None
.OUTPUTS
Output from this cmdlet (if any) Console
.NOTES
General notes
.COMPONENT
AzureAD#>
###################################################################################
# Adjust these variables accordingly... #
###################################################################################
$azgroup = "BitLocker Settings Assignment Group"

####################################################################################lets check to see if we have the Azure AD module installed...

if (Get-Module -ListAvailable -Name Azuread) {
Write-Host "AzureAD Module exists, loading"
Import-Module Azuread
}


else {
#no module, does user hae admin rights?
Write-Host "AzureAD Module does not exist please install`r`n with install-module azuread" -ForegroundColor Red
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
[Security.Principal.WindowsBuiltInRole] "Administrator")) {
Write-Host "Insufficient permissions to install module. Please run as an administrator and try again." -ForegroundColor DarkYellow
return(0)
}
else {
Write-Host "Attempting to install Azure AD module" -ForegroundColor Cyan
Install-Module AzureAD -Confirm:$False -Force
}
}# OK, lets pick the file..
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
InitialDirectory = [Environment]::GetFolderPath('Desktop')
Filter = 'Documents (*.txt)|*.txt|TextFile (*.txt)|*.txt'
}
$null = $FileBrowser.ShowDialog()
$machines = get-content $FileBrowser.FileName
#ok, if we got here, we must have the Azure AD module installed, lets connect...
Connect-AzureAD
write-host "Getting Object ID of group.." -ForegroundColor Green
$objid = (get-azureadgroup -Filter "DisplayName eq '$azgroup'" ).objectid
write-host "Getting group members (We dont want duplicates!).." -ForegroundColor Cyan
$members = Get-AzureADGroupMember -ObjectId $objid -all $true | select displayname
foreach ($machine in $machines) {
$refid = Get-AzureADDevice -Filter "DisplayName eq '$machine'"
Write-host "Adding " $refid.displayname -ForegroundColor Cyan
Add-AzureADGroupMember -ObjectId $objid -RefObjectId $refid.objectid
}