Hi all, I have a strange behavior on a script. I’m trying to replicate my current VBS logon script in PS. The script mainly does 3 things:
1 - map network drives by reading from a text file
2 - Synchronize the time with the DC
3 - launch chrome.
If I launch the script from PS ISe or with a simple double click everything works perfectly, but if I use it as a logon script on AD, only time synchronization and chrome launch are performed. I also tried using the GPO as logon script but the result is the same…
The script is locaded in the \SYSVOL\ folder, where the current VBS logon script is located.
Do you have any indication for me? Thank you
Since the script seems to start at least the issue might be caused by the code you use to map the network drives. Please show at least this (sanitized) part of the script (formatted as code please).
Here it is
Thanx Olaf
$rid = "S-1-5-21-1935876511-693123410-1237804090-"
# Add PresentationFramework for user alert
Add-Type -AssemblyName PresentationFramework
$AlternativeI = [System.Collections.ArrayList] @("Q", "R", "P", "T")
$EccezioniGruppi = [System.Collections.ArrayList] @("L", "V")
#2 - Rimuovi netdrive (comprese le mappature statiche)
$DriveList = Get-WMIObject Win32_LogicalDisk ` | Where-Object { $_.DriveType -eq 4 }
Foreach ($drive in $DriveList.DeviceID) {
$psDrive = $drive -replace ":"
Remove-SmbMapping -LocalPath $drive -Force -UpdateProfile
If ((Get-PSDrive -Name $psDrive) 2>$Null) {
Remove-PSDrive -Name $psDrive -Force
}
}
#4 - Definisco l'utente in LDAP e il primarygroupID
$user = $env:username
$userAD = (New-Object System.DirectoryServices.DirectorySearcher("(&(objectCategory=User)(samAccountName=$($user)))")).FindOne().GetDirectoryEntry()
$userGroups = $userAD.memberOf -replace '^CN=([^,]+).+$', '$1'
$pgID = $userAD.primaryGroupId
$homeDrive = ($userAD.homeDrive -replace ":", "" | Out-String).Trim()
$homeDirectory = ($userAD.homeDirectory | Out-String).Trim()
$rid = "S-1-5-21-1935876511-693123410-1237804090-"
$userPrimaryGroup = (New-Object System.DirectoryServices.DirectorySearcher("(objectSID=$($rid + $pgID))")).FindOne().GetDirectoryEntry().name
# sort group by name
$userGroups = $userGroups | Sort-Object
$mappedDrive = [System.Collections.ArrayList] (Get-WMIObject Win32_LogicalDisk | Select-Object -ExpandProperty "DeviceID" | ForEach-Object { $_ -replace ":", "" })
# Mappa W
if ($null -ne $homeDrive -and $homeDrive -ne '' -and $null -ne $homeDirectory -and $homeDirectory -ne '') {
Set-NetworkDrive $homeDrive $homeDirectory $mappedDrive $true
}
$otherI = [System.Collections.ArrayList]::new()
$otherEccezioniGruppi = [System.Collections.ArrayList]::new()
#16 - Crea le Mappature in funzione dell'utente (legge il file SHARES.INI)
$lines = Get-Content -Path @("d:\drive\shares.ini")
foreach ($line in $lines) {
If ($line -ne "" -and $line.StartsWith("[") -ne $True) {
$cols = $line -split (',')
$iniPrimaryGP = $cols[0]
$iniUnit = $cols[1]
$iniShare = $cols[2]
if ($iniPrimaryGP -eq "TUTTI" -or $iniPrimaryGP -eq $user -or $iniPrimaryGP -eq $userPrimaryGroup ) {
Set-NetworkDrive $iniUnit $iniShare $mappedDrive $true
}
elseif ( $iniUnit -eq "I" -and $userGroups -contains $iniPrimaryGP ) {
$otherI.Add($line) > $null
}
elseif ( $EccezioniGruppi -contains $iniUnit -and $userGroups -contains $iniPrimaryGP ) {
$otherEccezioniGruppi.Add($line) > $null
}
}
}
#$otherI = $otherI | Sort-Object
foreach ( $line in $otherI ) {
$cols = $line -split (',')
$iniPrimaryGP = $cols[0]
$iniUnit = $cols[1]
$iniShare = $cols[2]
if ( $AlternativeI.count -gt 0) {
Set-NetworkDrive $AlternativeI[0] $iniShare $mappedDrive $false
$AlternativeI.Remove($AlternativeI[0])
}
}
foreach ( $line in $otherEccezioniGruppi ) {
$cols = $line -split (',')
$iniPrimaryGP = $cols[0]
$iniUnit = $cols[1]
$iniShare = $cols[2]
Set-NetworkDrive $iniUnit $iniShare $mappedDrive $false
}
function Set-NetworkDrive {
Param (
[Parameter(Mandatory = $true, Position = 0)]
[string] $letter,
[Parameter(Mandatory = $true, Position = 1)]
[string] $path,
[Parameter(Mandatory = $true, Position = 2)]
[System.Collections.ArrayList] $mappedDrive,
[Parameter(Mandatory = $true, Position = 3)]
[bool] $alert
)
if ($letter -ne $null -and $letter -ne '' -and $path -ne $null -and $path -ne '') {
if ( $mappedDrive.Contains($letter) ) {
if ( $alert ) {
[System.Windows.MessageBox]::Show("Il disco " + $letter + " non può essere mappato perchè esiste già.`nApri una chiamata al Callcenter dal link sul tuo desktop e verrai ricontattato al più presto.`nGrazie.", "Errore")
}
}
else {
New-PSDrive -Name $letter -Root $path -Persist -PSProvider "FileSystem" -Scope Global > $null
$mappedDrive.Add($letter) > $null
}
}
}
WOW … that’s a very very big chunk of code to digest … especially for such a simply job like to map some network drives. Without digging too deep into it I would recommend to make it way less complex and reduce it to the absolut necessary minimum.
If I’m not wrong your issue comes from using a function before you define it. You use Set-NetworkDrive
twice before it is actually defined.
I strongly recommend NOT doing logon scripts. These ultimately cause more problems than they solve.
The first issue is remote work. They won’t run for people who are already logged into their laptops using cached credentials, but not yet connected by VPN.
When on the network in the office, they can create long logon times. The more complex the logon script, the further from the DC and/or resources such as the file server with the shares to be mapped, the LONGER logons will take.
Next, mapping drives. It only seems a nice thing to do for users, but ultimately, it’s not. The much better solution is for the users to learn the share paths, not the mapped drive letter. As well as learning how to search for shares. There are only so many letters in the alphabet, which is more an issue in a large company than a smaller one, but large doesn’t have to be that large. Ran into this problem with a company with only about 5,000 employees at its peak.
No need to sync time in a logon script. The Domain controller holding the PDC emulator role should be pointed to a reliable internet time source, and then all member computers (PCs, Server) synce to the PDC emulator. If someone is remote, but connects to the VPN, as long as the laptop can resolve the DC, it will update.
If someone doesn’t regularly connect to the network either by being in the office or over VPN, the script won’t help because it won’t run on that device until they do connect to the network prior to the user logging in. but if you are home, using a VPN, that will never happen.
Launching an application, if a user can’t launch the application, they probably are not qualified for their job.
I stopped using logon scripts a long time ago, as have other AD admins I know. But I know of some that still cling to them, and it is causing problems.
I don’t want to discourage you from going through the process just to see if it can be done and using it as a PS learning tool. But in terms of a modern production environment, I would discourage their use.
Their day, in my opinion is has come and gone.
I also have left login scripts and software installation GPOs behind for the same reason, line of sight during boot up/login. If I need software installed (outside of SCCM environments) or a script ran I often use a scheduled task via GPO. It will still apply over the vpn eventually. Also many RMM platforms give good options.