Saturday, 2 October 2021

Detect autopilot session

 

Ensuring that some apps only install during autopilot is not easily accomplished, you can use the below powershell script as a requirement rule in Intune for the application.This ensure it'll only proceed when the PC is going through autopilot.

 

$username = "defaultuser0"
$currentuser = (Get-Process -IncludeUserName -Name explorer | Select-Object -ExpandProperty UserName).Split('\')[1]

if ($currentuser -eq $username)
{
    Write-Output 1
    Exit 0
}
else {
    exit 1
}

Friday, 1 October 2021

Code42 proactive remediation - Check for last successful backup

There is no easy way to script a check on code42 being active and working on windows PCs. One way is to use the logs to read if Code42 is backing up recently.

 
#By tausif for FICO

###############
if ((Get-Service Code42Service).Status -eq "Running")
{
    #get code42 logged in user
    if (Test-Path "$env:ALLUSERSPROFILE\CrashPlan\.identity")
    {
        $c42currentuser  = (Get-Content $env:ALLUSERSPROFILE\CrashPlan\.identity) | Select-String -Pattern "username"
        #Get last backup date
        ##################################################################################
        $todaysdate = Get-Date -UFormat "%m/%d/%y"
        $dt = [DateTIme]$todaysdate
        $todayminus60 = $dt.AddDays(-60)
        $logdatepattern = "\d{2}/\d{2}/\d{2}"
        if (Test-Path "$env:ALLUSERSPROFILE\CrashPLan\Log\history.log.0") 
        {
            $lastlinedateonhistorylog = (Get-Content $env:ALLUSERSPROFILE\CrashPLan\Log\history.log.0)[-1] | Select-String -Pattern $logdatepattern | foreach {$_.Matches.Groups[0].Value}

            $patcompletedbackuptoprecloud = "Completed backup to PROe Cloud"
            $backupcompleteline = (Get-Content $env:ALLUSERSPROFILE\CrashPlan\Log\history.log.0 | Select-String -Pattern $patcompletedbackuptoprecloud )[-1]
            $backuppaths = (Get-Content $env:ALLUSERSPROFILE\CrashPLan\Log\app.log)|  Select-String -pattern  "backupPaths  "
            $lastbackupdate = [string]$backupcompleteline | Select-String -Pattern $logdatepattern | foreach {$_.Matches.Groups[0].Value}
            $ndt = [DateTIme]$lastbackupdate
            $dayssincelastbackup = (New-TimeSpan -Start $ndt -End $dt).TotalDays

            ######

            If ($dayssincelastbackup -ge "30")
            {
               
                Write-Output "More than $dayssincelastbackup since last backup, Last back up date: $lastbackupdate, C42 logged on $c42currentuser, $backuppaths"
    
                exit 1
            }
            else
            {
                Write-Output "Days since last backup $dayssincelastbackup, Last back up date: $lastbackupdate, C42 logged on $c42currentuser, $backuppaths"
                exit 0
            }
        }
        else
        {
            Write-Output "No history of successful backup"
            exit 1
        }


    }
    else
    {
        Write-Output "No User logged in"
        exit 1
    }
}
else
{
    Write-Output "Code42 Service not running"
    exit 1
}

Remove Box tools-per user install


Tuesday, 5 December 2017

SCCM - Install dell drivers dynamically during OSD

The below script may be used in an SCCM task to download Dell drivers from :
"http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment" to a PC being imaged.

Create a Dell group in the task sequence
Run the Powershell Script to filter dell systems with the WMI query as shown below.


The next step should run the powershell script shown below


Add another step to install dell drivers as using dism




The powershell script is shown below:

#By Tausif for FICO
#download dell drivers directly and install during the SCCM task sequence.

#Logging function borrowed from Mikael Nystrom 
Function Import-SMSTSENV
{
 try
 {
  $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
  Write-Output "$ScriptName - tsenv is $tsenv "
  $MDTIntegration = "YES"
  
  #$tsenv.GetVariables() | % { Write-Output "$ScriptName - $_ = $($tsenv.Value($_))" }
 }
 catch
 {
  Write-Output "$ScriptName - Unable to load Microsoft.SMS.TSEnvironment"
  Write-Output "$ScriptName - Running in standalonemode"
  $MDTIntegration = "NO"
 }
 Finally
 {
  if ($MDTIntegration -eq "YES")
  {
   $Logpath = $tsenv.Value("LogPath")
   $LogFile = $Logpath + "\" + "$ScriptName.log"
   
  }
  Else
  {
   $Logpath = $env:TEMP
   $LogFile = $Logpath + "\" + "$ScriptName.txt"
  }
 }
}
Function Start-Logging
{
 start-transcript -path $LogFile -Force
}
Function Stop-Logging
{
 Stop-Transcript
}

# Set Vars
$SCRIPTDIR = split-path -parent $MyInvocation.MyCommand.Path
$SCRIPTNAME = split-path -leaf $MyInvocation.MyCommand.Path
$SOURCEROOT = "$SCRIPTDIR\Source"
$LANG = (Get-Culture).Name
$OSV = $Null
$ARCHITECTURE = $env:PROCESSOR_ARCHITECTURE

#Try to Import SMSTSEnv
. Import-SMSTSENV

#Start Transcript Logging
. Start-Logging


#Output base info
Write-Output ""
Write-Output "$ScriptName - ScriptDir: $ScriptDir"
Write-Output "$ScriptName - SourceRoot: $SOURCEROOT"
Write-Output "$ScriptName - ScriptName: $ScriptName"
Write-Output "$ScriptName - Log: $LogFile"



Function Set-RegistryKey
{
 [CmdletBinding()]
 Param(
 [Parameter(Mandatory=$True,HelpMessage="Please Enter Registry Item Path",Position=1)]
 $Path,
 [Parameter(Mandatory=$True,HelpMessage="Please Enter Registry Item Name",Position=2)]
 $Name,
 [Parameter(Mandatory=$True,HelpMessage="Please Enter Registry Property Item Value",Position=3)]
 $Value,
 [Parameter(Mandatory=$False,HelpMessage="Please Enter Registry Property Type",Position=4)]
 $PropertyType = "DWORD"
 )
 
 # If path does not exist, create it
 If( (Test-Path $Path) -eq $False ) {
 
 $newItem = New-Item -Path $Path -Force
 
 } 
 
 # Update registry value, create it if does not exist (DWORD is default)
 $itemProperty = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue
 If($itemProperty -ne $null) {
 $itemProperty = Set-ItemProperty -Path $Path -Name $Name -Value $Value
 } Else {
 
 $itemProperty = New-ItemProperty -Path $Path -Name $Name -Value $Value -PropertyType $PropertyType
 }
 
}





 Function Get-OSVersion() {
# Version numbers as per http://www.gaijin.at/en/lstwinver.php
$osVersion = "Version not listed"
$os = (Get-WmiObject -class Win32_OperatingSystem)
Switch (($os.Version).Substring(0,3)) {
    "5.1" { $osVersion = "XP" }
    "5.2" { $osVersion = "2003" }
    "6.0" { If ($os.ProductType -eq 1) { $osVersion = "Vista" } Else { $osVersion = "2008" } }
    "6.1" { If ($os.ProductType -eq 1) { $osVersion = "Windows 7" } Else { $osVersion = "2008R2" } }
    "6.2" { If ($os.ProductType -eq 1) { $osVersion = "Windows 8" } Else { $osVersion = "2012" } }
    # 8.1/2012R2 version detection can be broken, and show up as "6.2", as per http://www.sapien.com/blog/2014/04/02/microsoft-windows-8-1-breaks-version-api/
    "6.3" { If ($os.ProductType -eq 1) { $osVersion = "Windows 8.1" } Else { $osVersion = "2012R2" } }
    "10." { If ($os.ProductType -eq 1) { $osVersion = "Windows 10" } Else { $osVersion = "2016" } }
}
return $osVersion
}

$osversion = Get-OSVersion
Write-Output "$osversion - Log: $LogFile"
$Model = (Get-WmiObject Win32_ComputerSystem).Model
Write-Output "$Model - Log: $LogFile"

### Disable IE First Run Wizard and RSS Feeds this is needed to Invoke-Webrequest will work without running IE for the first time.
Set-RegistryKey -Path "HKLM:\SOFTWARE\Policies\Microsoft\Internet Explorer\Main" -Name "DisableFirstRunCustomize" -Value 1


# Remove the "E" prefix character from Latitude models due to some dodgy Dell URLs...
If ($Model.ToCharArray()[0] -eq "E" -and $Model -notmatch "Embedded")
{
 $Model = $Model.Replace("E", "")
 Write-Output "Model name set to $Model - Log: $LogFile"
}

# Find the specific wiki page for the model from the main wiki page
$URI = "http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment"
Write-Output "URI set to $URI - Log: $LogFile"
$html = Invoke-WebRequest $URI -ErrorAction Stop -TimeoutSec 1800
Write-Output "$URL queried successfully - Log: $LogFile"
$Href = $HTML.AllElements | Where {$_.innerText -match ("$Model" + " W") -and $_.innerText -match "Windows 10" -and $_.innerText -match "Driver" -and $_.tagName -eq "A"} | Select -ExpandProperty href
If (!$Href)
{
 Write-Output "No Wiki page found for $Model and $OperatingSystem.- Log: $LogFile"
    Return
}
Write-Output "Wiki page found for $Model and $OperatingSystem. - $Href - Log: $LogFile"
# Find the download URL from the model
$URI = "http://en.community.dell.com/$Href"

Write-Output "URI updated to $URI - Log: $LogFile"
Try
{
    $HTML = Invoke-WebRequest -Uri $URI -ErrorAction Stop
    $CabDownloadLink = $HTML.AllElements | Where {$_.innerHTML -match "Download Now" -and $_.tagName -eq "A"} | Select -ExpandProperty href
 #Return $CabDownloadLink
 Write-Output "Cab download link set to $CabDownloadLink - Log: $LogFile"
}
Catch
{
 $_
 Write-Output "Cab download not found- Log: $LogFile"
    Return
}

$CABfilename = $CabDownloadLink.Substring($CabDownloadLink.LastIndexOf("/") + 1)
Write-Output "Cab file name is $CABfilename - Log: $LogFile"
$drivedownloaddirectory = "C:\Temp"

if(!(Test-Path -Path $drivedownloaddirectory )){
 New-Item -ItemType directory -Path $drivedownloaddirectory
 Write-Output "$drivedownloaddirectory created - Log: $LogFile"
}

$CABDestinationpath = "$drivedownloaddirectory\$CABfilename"
Write-Output "The CAB will be downloaded to $CABDestinationpath - Log: $LogFile"
Try
{
    # Begin the download
    $WebClient = New-Object System.Net.WebClient
    $WebClient.DownloadFile($CabDownloadLink, $CABDestinationpath)
}
Catch
{
 $Stopwatch.Stop()
 Write-Output "Failed to download file - Log: $LogFile"
    $_
    Return

}




$DriverSourceCab = (Get-ChildItem $drivedownloaddirectory).FullName
$DriverExtractDest = "$drivedownloaddirectory\Extracted"


if(!(Test-Path -Path $DriverExtractDest )){
 New-Item -ItemType directory -Path $DriverExtractDest
 Write-Output "Created the $DriverExtractDest directory - Log: $LogFile"
}

Expand "$DriverSourceCab" -F:* "$DriverExtractDest"
<#
#Copy-Item "C:\Windows\System32\pnputil.exe" "X:\Windows\System32"
$driverinfs = get-childitem -path $DriverExtractDest -recurse -filter *.inf
foreach ($inf in $driverinfs)
 
{
    Write-Host "Injecting driver $inf"
    #pnputil -i -a $inf.FullName
}

#this part does not work because for some reason it throws a memory error, will replace this with:

DISM.exe /Image:%OSDTargetSystemDrive%\ /Add-Driver /Driver:c:\Temp\Extracted /Recurse /logpath:%_SMSTSLogPath%\dism.log
#>
. Stop-Logging




This script logs to SMSTS.log directly and the dism step can log to wherever you'd like it to.
Add another step to delete the Extracted drivers and downloaded drivers as needed.




Tuesday, 2 May 2017

Powershell - Download and install Java using powershell

I got tired of updating the JRE package for our windows task sequences and used powershell to scrape for web-links from https://www.java.com/en/download/manual.jsp and install it silently.


Saturday, 4 March 2017

Delete DEPROVISIONED okta users using API

Okta tombstones its users and does not delete them automatically when they are deactivated in AD. I use the below script to run on schedule with an okta API token to delete users:
You'll need the okta powershell module install and be a super user on okta :
https://github.com/okta/oktasdk-csharp/tree/master/Okta.Core.Automation/


#Import module okta
Import-Module Okta.Core.Automation
 
#COnnect to okta  using token and domain
Connect-Okta -Token alphanumerictoken -FullDomain "https://domain.okta.com"
 
 
###################Logging function
$Logfile = "$env:ProgramData\InstallLogs\DeleteOktaUsers_$(get-date -format `"yyyyMMdd_hhmmsstt`").log"
Function LogWrite($string, $color)
{
   if ($Color -eq $null) {$color = "white"}
   write-host $string -foregroundcolor $color
   $string | out-file -Filepath $Logfile -append
}
 
if ((Test-Path -path C:\ProgramData\InstallLogs\) -ne $True)
{
New-Item C:\ProgramData\InstallLogs\ -type directory
}
 
########################################
 
 
#get a list of all DEPROVISIONED users
$AllUsers = Get-OktaUser -Filter 'status eq "DEPROVISIONED"'


#list neatly in a csv file located in C:\programdata\InstallLogs
$AllUsers | Select @{L="FirstName";E={$_.profile.firstName}},`
@{L="LastName";E={$_.profile.lastName}},`
@{L="UserName";E={$_.profile.login}},`
@{L="ID";E={$_.id}},@{L="UserStatus";E={$_.Status}} | FT | Out-File "$env:ProgramData\InstallLogs\deprovisionedusers_$(get-date -format `"yyyyMMdd_hhmmsstt`").csv"
 
 
#loop through the list of deprovisioned users and delete log deletions to the logfile
foreach($user in $AllUsers){
   
    Delete-OktaUser $user.Profile.Login
    If($? -eq "True") {
     LogWrite "Successfully deleted user $user" green
     }
}

Friday, 3 February 2017

Office for mac autodicover error with okta -

You see the following error when signing into Office for mac 2016 with okta SSO enabled for office 365:



Update Outlook for mac 2016 to version 15.30 and above
Run the following command on your terminal and hit enter:

defaults write com.microsoft.Outlook DisableModernAuth -bool YES

Then check if the following location is updated ~/Library/Group Containers/UBF8T346G9.Office/Outlook/Outlook 15 Profiles/Main Profile/Caches/

You might need to remove and re-add your exchange account on outlook.


Detect autopilot session

  Ensuring that some apps only install during autopilot is not easily accomplished, you can use the below powershell script as a requiremen...