So I'm trying to find the SID for a user that's logged onto a system before. Our system has a split of non-administrative users (without a # at the start) and administrative users (with a #). My PowerShell script so far is this:
$CurrentDomainUser = wmic computersystem get username
$Separator = "\"
$CurrentDomainUserSplit = $CurrentDomainUser.split($Separator)
$DomainUser= $CurrentDomainUserSplit[3]
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_Users
$UserSID = ls 'hklm:software/microsoft/windows nt/currentversion/profilelist' | ? {
$_.getvalue('profileimagepath') -match '$DomainUser' -and
$_.getvalue('profileimagepath') -notmatch '#'
} | % pschildname
This script doesn't work if I have use the '$DomainUser' in the final $UserSID = ... line above. It does work if I put in the actual value that I'm searching for.
I'm guessing this is a simple PowerShell syntax problem.
Using Get-WmiObject instead of wmic
$DomainUser = (Get-WmiObject Win32_ComputerSystem).Username -replace '^.+\\'
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_Users
$UserSID = Get-ChildItem 'HKLM:/software/microsoft/windows nt/currentversion/profilelist' |
Where-Object { $_.getvalue('profileimagepath') -match $DomainUser -and $_.getvalue('profileimagepath') -notmatch '#'} |
ForEach-Object pschildname
Using NTAccount.Translate
Windows already knows how to translate names to security identifiers. We might use use this method of getting to a SID.
$userName = (Get-WmiObject Win32_ComputerSystem).Username
$ntAccount = New-Object System.Security.Principal.NTAccount($userName)
$sid = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])
... -match '$DomainUser' ...
PowerShell expands Variables only in double-quoted strings, not in single-quoted strings. Replace the single quotes with double qoutes or remove the quotes entirely.
Related
So, I'm trying to remotely remove some manually added printer from a separate machine. Problem is, I don't want to remove all of the printers, only ones that have "HJK" or "LSG" anywhere in the name.
So, to get the list of names, I do:
Invoke-Command AaronsComputer -ScriptBlock {get-printer | select name -expandproperty name}
and to delete the printer, I would do:
Invoke-Command AaronsComputer -ScriptBlock {Remove-Printer -Name "Full Printer Name Here"}
I know I can export the results of get-printer as a CSV to work with it better but I'd rather not do that and have it all happen in Powershell.
I thought something along these lines would work but I don't think PowerShell intelligently sees each line as a variable.
$PrinterResults = Invoke-Command $Computer -ScriptBlock {get-printer | select name -expandproperty name}
foreach $PrinterResults
if ($PrinterResults -contains "HJK") {
Invoke-Command $Computer -ScriptBlock {Remove-Printer -Name "$PrinterResults"}
}
if ($PrinterResults -contains "LSG") {
Invoke-Command $Computer -ScriptBlock {Remove-Printer -Name "$PrinterResults"}
}
The end goal is that I can delete all printers that match the criteria in one go.
Managed to get this done in the end with the below:
Invoke-Command $Computer -ScriptBlock {
$Printers = get-printer | Where-Object {($_.name -like '*HJK*') -or ($_.name -like '*LSG*')} | Select Name -expandproperty name
foreach ($PrinterName in $Printers)
{
printui.exe /dl /n $PrinterName
}
}
in many scripts i have the problem, that it always shows me the complete name like domain\user.
for example like that
Invoke-command -computer computername {Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI -Name LastLoggedOnUser | select -ExpandProperty LastLoggedOnUser}
how can i cut off the domain and just have the user name?
i have tried that for example.
Invoke-command -computer computername{Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI -Name LastLoggedOnUser | select -ExpandProperty LastLoggedOnUser #{N="LastLoggedOnUser";E={$_.LastLoggedOnUser -replace ".+\"}}}
You can go with :
Invoke-command -computer computername {Get-ItemProperty `
HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI `
-Name LastLoggedOnUser | select -ExpandProperty LastLoggedOnUser} | `
%{ $_ -replace "^[^\\]*\\","" }
Backslash is a special regex character that would need to be escaped to be taken literally.
'stackoverflow\joe' -replace '.*\\'
joe
here is yet another way to get the no-domain-name last logged on user from that registry key [grin] ...
what it does ...
sets the reg key to use
sets the prop of that key to get the value from
grabs that value
splits on the \
takes the last item from that split result
assigns it to a $Var
displays the value therein
the code ...
$LogonUiRegKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI'
$TargetPropName = 'LastLoggedOnUser'
$LastLoggedOnUser = (Get-ItemPropertyValue -Path $RegKey -Name $TargetPropName).Split('\')[-1]
$LastLoggedOnUser
output = MyUserName
I am trying to add a Guid which I have obtained from AD on to a number of remote users. I have got the Guid and the SID from Profilelist within the registry but each time I try and complete it I get the incorrect path and I cannot find a way to word this to Google it better.
I have the following in Powershell:
$user = Read-Host -Prompt 'Input the user name'
$guid = Get-ADUser $user -Properties * | Select ObjectGUID
$sid = (New-Object System.Security.Principal.NTAccount($user)).Translate([System.Security.Principal.SecurityIdentifier]).value
$regpath = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\'
$profilepath = $sid
$fullpath = $regpath + $profilepath
$credential = Get-Credential -Credential doman\admin.account
Enter-PSSession -ComputerName laptopnumber -Credential $credential
New-Item -Path $path3 -Name Test -Value '14'
When I Write-Output for $fullpath I get the exact path I would expect. However, when I run the script I get the following error:
New-Item : Could not find a part of the path 'C:\Users\nameofaccountIamusing\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\S-1-5-21-1810327472-1994124132-3348413286-12785\Test'.
At line:9 char:1
+ New-Item -Path $fullpath -Name Test -Value '14'
I cannot work this out. Any advice hugely appreciated. I don't see why it is adding in the C:\Users\nameofaccountIamusing
The main problem here is that you forgot to add the registry provider in front of the path and without that, the system will try and find a path on the disk.
Instead of
$regpath = 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\'
use
$regpath = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
or (*)
$regpath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
I would also advise to use the Join-Path cmdlet for concatenating parts to create a full path.
Because Get-ADUser by default returns objects with these properties: DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName, there is no need to first fetch the ObjectGUID and from that figure out the users SID.
Just do $adUser = Get-ADUser -Filter "SamAccountName -eq '$user'" -ErrorAction SilentlyContinue and if that returns an object, you can get the SID like this: $adUser.SID
(*)
When using PowerShell < 7, the Set-ItemProperty cmdlet to create a new registry value cannot handle the -Type parameter when using the short HKLM: provider path..
This does however work when using Registry::HKEY_LOCAL_MACHINE
First Post here. First off, I really have little experience with scripting, so thank you for your kindness.
I have a script I found that can somewhat get the drive letters that have shares on it
Push-Location
Set-Location 'HKLM:\SYSTEM\CurrentControlSet\services\LanmanServer\Shares'
Get-Item . |
Select-Object -ExpandProperty property |
ForEach-Object {
New-Object psobject -Property #{"property"=$_;"Value" = (Get-ItemProperty -Path . -Name $_).$_}
} |
Format-Table property, value -AutoSize
Pop-Location
The "value" results are long:
{CSCFlags=0, MaxUses=4294967295, Path=C:\location, Permissions=x...}
Ideally, all I need is the drive letter. Then I would like to use the drive letter found to see if Volume Shadow Copy is enabled on said drive.
The following will create an array of all drive letters on a target server and then check each using wmi to see if volume shadow storage is present.
# Specify host to check
$serverName = "localhost"
# Create an empty array to hold our drive letters
$driveLetterArray = #()
# Use wmi to get all share paths
(get-wmiobject win32_share -computername $serverName).path | foreach {
# Get just the drive letter of the share path
$driveLetter = $_.split(":")[0]
# Send drive letter to array if it doesn't already exist in that array
if (($driveLetter) -and ($driveLetterArray -notcontains $driveLetter)) {
$driveLetterArray += $driveLetter
}
}
# Check if that drive letter has shadowstorage
foreach ($letter in $driveLetterArray) {
# Clean up the letter variable so it will be able to match results from gwmi win32_volume
$letter = $letter + ":\"
$deviceID = (gwmi win32_volume -computername $serverName | Where-Object {$_.Name -eq $letter}).deviceID
# Clean up the deviceID variable so it will be able to match results from gwmi win32_shadowstorage
$deviceID = $deviceID.TrimStart("\\?\")
$deviceID = "Win32_Volume.DeviceID=`"\\\\?\\" + $deviceID + "\`""
$shadowQuery = gwmi win32_shadowstorage -computername $serverName | Where-Object {$_.Volume -eq $deviceID}
# Report findings to the user
if ($shadowQuery) {
"Volume shadow enabled on drive $letter"
} else {
"Volume shadow NOT enabled on drive $letter"
}
}
This is pretty horrible, and I'm sure there's a better way to address your problem, but the below effectively looks at your public shares, finds the drive letter, looks up the VolumeID for that drive letter and then checks to see if the VolumeID is present in the shadow copy config:
$paths = $(gwmi win32_share | ? {$_.name -notmatch '.*\$$' } | select -expandproperty path) -replace '([A-Z]:).*', '$1'
foreach($p in $($paths | sort-object -Unique)) {
$deviceId = gwmi win32_volume | ? { $_.driveletter -eq $p } | select -expandproperty deviceid
if( $(gwmi win32_shadowcopy | ? {$_.volumename -eq $deviceId }) ) {
Write-Host "$($p) Volume Shadow Copy enabled"
}
else {
Write-Host "$($p) No Volume Shadow Copy"
}
}
I've got a command that can list all app pools on a machine:
Get-WmiObject -namespace "root/MicrosoftIISv2" -class IIsApplicationPool |Select-Object -property #{N="Name";E={$name = $_.Name; $name.Split("/")[2] }} | Format-Table
I want to set the managedpipeline of every app pool on the box. I've tried this:
Get-WmiObject -namespace "root/MicrosoftIISv2" -class IIsApplicationPool |Select-Object -property #{N="Name";E={$name = $_.Name; $name.Split("/")[2] }} | ForEach-Object {cmd /c "c:\windows\system32\inetsvr\appcmd.exe set apppool $name /managedPipleineMode:"Classic"'}
This is giving me a "cannot find the path specified" error. Any ideas how I can this to work?
In order to set the Managed Pipeline mode (or any property of the AppPool), you need to use Set-ItemProperty. But it gets more fun than that:
Set-ItemProperty takes a Path as its input. Get-ChildItem will
return you a collection of ConfigurationElement objects, not Path
strings.
ManagedPipelineMode is internally stored as an integer, so
you have to know the correct "magic" number to pass in.
Fortunately, that is documented here, in the "Remarks" section.
This did the trick for me:
Import-Module WebAdministration
Get-ChildItem IIS:\AppPools |
Select-Object -ExpandProperty PSPath |
ForEach-Object { Set-ItemProperty $_ ManagedPipelineMode 1 }
following the documentation :
$iisAppPoolName = "MyPool"
$appPool = New-WebAppPool -Name $iisAppPoolName
$appPool.managedPipelineMode = "Classic"
$appPool |Set-Item
I tested, IIS 8.0, Windows server 2012, and it works.
If you're on Powershell V2 I would use the WebAdministration module e.g. from an elevated prompt:
Import-Module WebAdministration
Get-ChildItem IIS:\AppPools | Foreach {$_.ManagedPipelineMode = 'Classic'}