Get device serial number with PowerShell
PowerShell Version: >2
Modules: none
This will print the serial number of your device:
(gwmi win32_bios | select SerialNumber).serialNumber
or
gwmi win32_bios | Select –ExpandProperty SerialNumber
PowerShell Version: >2
Modules: none
This will print the serial number of your device:
(gwmi win32_bios | select SerialNumber).serialNumber
or
gwmi win32_bios | Select –ExpandProperty SerialNumber
Today I had an interesting issue with DFS shares. I created a new user which was not able to access the DFS share via FQDN (\\domain\dfsspace\sharename) but was able to access the UNC path (\\servername\sharename).
After some research I found out that the DFS cache sometimes creates this issue and needs to be wiped before proceeding. There are two ways to handle this:
Enter this in an elevated command prompt on the client and reboot:
reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Csc\Parameters /v FormatDatabase /t REG_DWORD /d 1 /f
Or as an alternative create a new .reg file containing this, execute on the client and reboot:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\CSC\Parameters] "FormatDatabase"=dword:00000001
PowerShell Version: >2
Modules: none
New-ItemProperty "hklm:\SOFTWARE\Microsoft\..." -Name "testkey" -Value 1 -PropertyType "DWord"
-Name is the RegKey Name
-Value is the Value in hexadecimal
-PropertyType defines that we want a DWORD
PowerShell Version: >2
Modules: none
Today I am documenting a little script I worked on that needed some workarounds and tweaks to function. Basically, we have a GPO that acts on shutdown (to save users a restart after hotfix installation) and should be applied for the whole domain. Some users in this domain use RDP and need these specific hotfixes so I had to find a way to apply a machine based GPO with a script to a group of users. Also, the RDC 8.1 hotfixes need to be applied in a specific order (KB2574819, KB2830477, KB2857650, KB2913751, KB3036965, KB2862019), which is why I can not work with foreach here.
#receive username from logon script $user = Get-Content 'C:\tmp\$variables.txt' | select -index 0 $os = (Get-WMIObject Win32_OperatingSystem).name $wusa = "C:\windows\system32\wusa.exe" $userGroups = ([Security.Principal.WindowsIdentity]"$($user)").Groups.Translate([System.Security.Principal.NTAccount]) $LogPath = "c:\tmp\hotfixes.log" $date = Get-Date -Format "dd.MM.yyyy hh:mm" Start-Transcript -Path $LogPath # Windows 7 Client hotfixes if ($os -like "*Windows 7*") { # Remotedesktop hotfixes if ($userGroups -like "*main_rdp_group") { "##########################################################" "# $date" "##########################################################" "User: $user" "Hostname: $env:COMPUTERNAME" "##########################################################" # https://support.microsoft.com/en-us/kb/2830477 # Remote Desktop Connection (RDC) 8.1 "Installing Windows6.1-KB2574819-v2-x64.msu..." & $wusa \\path_to_ad_share\Windows6.1-KB2574819-v2-x64.msu /quiet /norestart "Installing Windows6.1-KB2830477-x64.msu..." & $wusa \\path_to_ad_share\Windows6.1-KB2830477-x64.msu /quiet /norestart "Installing Windows6.1-KB2857650-x64.msu..." & $wusa \\hpath_to_ad_share\Windows6.1-KB2857650-x64.msu /quiet /norestart "Installing Windows6.1-KB2913751-x64.msu..." & $wusa \\path_to_ad_share\Windows6.1-KB2913751-x64.msu /quiet /norestart # https://support.microsoft.com/en-us/kb/3036965 # Printing preferences window appears behind a RemoteApp window in Windows "Installing Windows6.1-KB3036965-x6.msu..." & $wusa \\path_to_ad_share\Windows6.1-KB3036965-x64.msu /quiet /norestart # https://support.microsoft.com/en-us/kb/2862019 # A RemoteApp application main window takes the focus after the applications windows are maximized in Windows "Installing Windows6.1-KB2862019-x64.msu..." & $wusa \\path_to_ad_share\Windows6.1-KB2862019-x64.msu /quiet /norestart } } Stop-Transcript
As the computer based GPO would use the computername$ as the username when running, I had to find a way to get the actual username for my group-filter:
$user = Get-Content 'C:\tmp\$variables.txt' | select -index 0
I simply added some lines at the end of the existing logon script:
# check if c:\tmp exists... $path_to_c_tmp = Test-Path c:\tmp if ($path_to_c_tmp -eq $true) { # Gather variables for further scripts $env:USERNAME | Out-File 'C:\tmp\$variables.txt' $env:COMPUTERNAME | Out-File 'C:\tmp\$variables.txt'-Append $PSVersionTable.PSVersion.Major | Out-File 'C:\tmp\$variables.txt'-Append } else { # if c:\tmp does not exist create it and continue with gathering variables for further scripts "c:\tmp does not exist, creating...." New-Item c:\tmp -type directory # check if creation was successfull if ($? -eq $true) { "Success!" # Gather variables for further scripts $env:USERNAME | Out-File 'C:\tmp\$variables.txt' $env:COMPUTERNAME | Out-File 'C:\tmp\$variables.txt'-Append $PSVersionTable.PSVersion.Major | Out-File 'C:\tmp\$variables.txt'-Append } else { "Something went wrong..." } }
In this example we would only use the $env:USERNAME but I added computername and psversion also for further projects. I can now call every line of the C:\tmp\$variables.txt file with | select -index number_of_line and use this to make the if ($userGroups -like “*main_rdp_group”) work. (If c:\tmp does not exist it will create it and gather the information again.)
I will continue working on this script to enable results in the logs and more filter options for other hotfixes. The goal here is to have one script to apply all hotfixes in the environment to the assigned target group.
I pretty often filter through AD user groups and this way even works with PowerShell 1.0:
([Security.Principal.WindowsIdentity]"$($env:USERNAME)").Groups.Translate([System.Security.Principal.NTAccount])
PowerShell Version: 1
Modules: none
If you need the name of the operation system for any kind of filter use this:
(Get-WMIObject Win32_OperatingSystem).name
Result:
Microsoft Windows 7 Enterprise |C:\Windows|\Device\Harddisk0\Partition1
Possible filter for any kind of script:
$os = (Get-WMIObject Win32_OperatingSystem).name if ($os -like "*Windows 7*") { }
PowerShell Version: 4
Modules: none
If you want to get your major PowerShell version run the following:
$PSVersionTable.PSVersion.Major
Result:
4
PowerShell Version: 4
Modules: none
If you have installed the “ActiveDirectory Module for Windows PowerShell” you can pretty easily handle every AD operation with PowerShell, like removing deactivated accounts for example:
Check for disabled users:
$users = Get-ADUser -Filter * | where {($_.enabled -eq $false)}
You can either measure
echo "COUNT:" ($users | measure).Count
or echo these users.
$user.UserPrincipalName
If you know want to remove those:
foreach ($user in $users) { Remove-ADUser -Identity $user.SAMAccountName $disabled = $user.UserPrincipalName "$disabled disabled." }
And the whole script:
$users = Get-ADUser -Filter * | where {($_.enabled -eq $false)} echo "COUNT:" ($users | measure).Count foreach ($user in $users) { Remove-ADUser -Identity $user.SAMAccountName $disabled = $user.UserPrincipalName "$disabled disabled." }
Update:
Since PowerShell 4 you can achieve this in one line:
Search-ADAccount -AccountDisabled | where {$_.ObjectClass -eq 'user'} | Remove-ADUser
PowerShell Version: 4
Modules: ActiveDirectory Module for Windows PowerShell
If you want to remove Desktop items with PowerShell, this script will get the local Desktop folder from the registry and look for the item mentioned in line 5 to remove it (old shortcuts for example).
$desktopfolder = (Get-ItemProperty "hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders").Desktop $shortcuts = Get-Childitem $desktopfolder foreach ($item in $shortcuts) { if ($item -match "example.lnk") { Remove-Item $item.fullname echo "#########################################################################" echo $date echo "$item from User $env:USERNAME at $env:COMPUTERNAME in $desktopfolder removed." } }
PowerShell Version: 4
Modules: none
If the Test-Connection is just not enough you can also add a port check to your PowerShell scripts:
$ErrorActionPreference = 'SilentlyContinue' # we do not want to see any errors here $hostip = "127.0.0.1" $port = "4441" Test-Connection $hostip -Count 2 | out-null if ([int]$? -eq 0) { echo "$hostip is offline!" } else { echo "$hostip is online!" $Socket = New-Object Net.Sockets.TcpClient $Socket.Connect($hostip, $port) $ErrorActionPreference = 'Continue' if ($Socket.Connected) { echo "-> $port is open!" $Socket.Close() } else { echo "-> $port is closed or filtered!" } } #resetting the variable between iterations is necessary. $Socket = $null
Line 14 to 28 is where the magic happens:
$hostip = "127.0.0.1" $port = "4441"
$Socket = New-Object Net.Sockets.TcpClient $Socket.Connect($hostip, $port) $ErrorActionPreference = 'Continue' if ($Socket.Connected) { echo "-> $port is open!" $Socket.Close() } else { echo "-> $port is closed or filtered!" } } #resetting the variable between iterations is necessary. $Socket = $null
Result:
127.0.0.1 is online!
-> 4441 is open!
PowerShell Version: 4
Modules: none