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
Related
I am trying to create a basic script that pulls a list of computer names from a text file, then pings them, and returns true or false. I then want to output the ones that returned false to a text file so I can know which ones are not responding.
the closest I have got to what I want to is below:
$workstations = Get-Content "workstation_list.txt"
$workstations | Test-NetConnection -InformationLevel Quiet -WarningAction SilentlyContinue
However whenever I try to pipe the results anywhere all I get is the true or false.
How can I pass the original names that were in the $workstations array to show for all the ones that return false?
I have tried:
$workstations = Get-Content "workstation_list.txt"
$workstations |
Test-NetConnection -InformationLevel Detailed -WarningAction SilentlyContinue |
Select-Object computername, pingsucceeded |
if(pingsucceeded -eq False){write-output} else{continue}
with the following error:
pingsucceeded : The term 'pingsucceeded' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:11 char:144
+ ... Select-Object computername, pingsucceeded | if(pingsucceeded -eq Fal ...
+ ~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (pingsucceeded:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException*
However I can't figure out how to only return the original name of the computer that is returning false when I ping it.
I then want to output it to a text file, however if I can't get it to pass the correct information to the screen It doesn't go to a file either.
Am I close or do I need to approach this a completely different way?
Thanks!
PS.this is one of my first times posting a question on stack overflow, if I need to provide information in a different way to make it easier for you to answer please provide constructive feedback so I can do better in the future.
I'd recommend using a PSCustomObject to store your results like this:
$workstations = Get-Content "workstation_list.txt"
$Result =
foreach ($ComputerName in $workstations) {
[PSCustomObject]#{
ComputerName = $ComputerName
Online = (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet)
}
}
$Result
This way you can use the variable $Result for further steps if needed. Output the successful ones for example
$Result | Where-Object -Property 'Online' -EQ -Value $true
Or filter the unsuccessful ones and output them to another file for example:
$Result |
Where-Object -Property 'Online' -EQ -Value $false |
Select-Object -ExpandProperty ComputerName |
Out-File -FilePath 'offline_workstation_list.txt'
There's some basic powershell that you need to learn. You can't pipe to an if statement for one thing, but you can to foreach-object:
$workstations = Get-Content "workstation_list.txt"
$workstations |
Test-NetConnection -InformationLevel Detailed -WarningAction SilentlyContinue |
Select-Object computername, pingsucceeded |
foreach-object { if($_.pingsucceeded -eq $False){write-output $_} else{continue} }
ComputerName PingSucceeded
------------ -------------
microsoft.com False
Trying something with the call operator and $input.
echo hi | & { if ($input -eq 'hi') { 'yes' } }
yes
When using this code:
$Prodservers = Get-ADComputer -Filter {OperatingSystem -like '*Server*'} -SearchScope Subtree -SearchBase $ProdSB -Server $DCprod -Credential $ProdCred -ErrorAction SilentlyContinue |
select -Expand DnsHostname
foreach ($P in $Prodservers) {
[PSCustomObject]#{
Hostname = $P
'Support team' = (Invoke-Command -ComputerName $P -ScriptBlock {$env:supportteam} -Credential $ProdCred)
'Local Admins' = (Invoke-Command -ComputerName $P -ScriptBlock {$ADSIComputer = [ADSI]('WinNT://localhost,computer');$lgroup = $ADSIComputer.psbase.children.find('Administrators', 'Group');$lgroup.psbase.invoke('members') | % {$_.GetType().InvokeMember('Name', 'GetProperty', $null, $_, $null)}} -Credential $ProdCred)
'Host Reachable' = [bool](Invoke-Command -ComputerName $P -ScriptBlock {1} -Credential $ProdCred)
}
}
This works, however an group membership of more than two members in the local administrators group returns similar to this:
{Administrator, Domain Admins, Prod Server Admin...
How would I expend the output to show the full membership?
Also after pointers for selecting only certain groups that match group name x or y or return True is group x is present etc.
You might be running into output display formatting issues, where the column data exceeds the displayable width in table format in PowerShell.
You can try use the Format-List cmdlet to display things in a list instead to see if your local administrators group with multiple members displays correctly. Check out the link above to see how it helps, but a basic example of using it would be:
Get-Service | Format-List
As for your filtering question, it looks like you're using reflection to invoke methods that collect that data, so it would be harder to use PS cmdlets to help there, so I would suggest getting that data as you do now, but do it separately, into a temporary variable, then filter the data there selecting your specific groups you want using something like this to match your group names, and in the if statement, put the relevant data into another variable, which you then use for your final output.
if ($item -match "groupNameX") { #Then... }
Finally worked it out.
Came across this answer.
First, found a script block that outputted the memberships as a PSObject property:
$SB = {
$members = net localgroup administrators |
where {$_ -AND $_ -notmatch "command completed successfully"} |
select -skip 4
New-Object PSObject -Property #{
Members=$members
}
}
Then modified the local admins column:
'Local Admins' = $admins.Members -join ','
The output is still truncated, however now instead of export-CSV showing the column contents as System.Object[] it now shows the full output with the separator specified in -join.
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.
Just a quick question. I am running lines of code like,
$publicIP = Get-Content (Get-AzureVM -ServiceName $servicename -Name $vmsname | Get-AzureEndpoint | Select { $._vip })
$OSDisk = Get-Content (Get-AzureVM -ServiceName $servicename -Name $vmsname | Get-AzureOSDisk)
And it does get me the IPAddress or the variables, but when trying to put the value into a csv cell, it fails. I think it is because it tries to add the extra labels, but I do not know how to get just the string and set the variable as just that. Does anyone know how to remedy this?
edit:
If the output with:
Get-AzureVM -servicename "vm1" -name "vm1" | Select DNSName | Out-String
is like this:
DNSName
-------
http://example.cloudapp.net/
How do I just put in "http://example.cloudapp.net/" as a CSV-entry? Right now it is trying to put all of the code block into the CSV which is giving me awful formatting erros.
Select is an alias for Select-Object and allows you to take one or more properties from an object and creates a new object with them.
If you want to expand a property into just the value, use the -ExpandProperty parameter:
Get-AzureVM -servicename "vm1" -name "vm1" | Select -ExpandProperty DNSName
Should give you just http://example.cloudapp.net/
Also, when you want to send data to a CSV, you can pipe objects to the cmdlet Export-CSV which will use the property names as headers and the objects in the array as rows and the properties as columns.
Example:
Get-ChildItem -File | Select Name, Size | Export-Csv c:\temp\filelist.csv
I'm sure this should be straight forward but I've been stuck on it for a while now...
I am trying to get the service names (for sql server) into an array but can't figure out how to do it. I basically want the array contents to look something like the output of this:
Get-Service -computername $server_name -name sql* | format-table -property name
I have tried things like this but the contents of $service_name are very odd:
$service_name = (Get-Service -computername $server_name -name sql* -exclude *sqlwriter | format-table -property name)
Whatever I try either errors or gives some strange message in my array. Should this be easy/possible? I'm guessing I could dump the results in a text file then use the contents of that but it's a bit messy and more overhead than seems necessary.
Not sure, but where you looking for this (with whatever variation on the pattern for -Name and/or -Exclude)?
PS> $names = (Get-Service -Name Sql* | select name)
PS> $names.GetType().IsArray
True
PS> $names.Length
3
PS> $names
Name
----
SQLBrowser
SQLSERVERAGENT
SQLWriter
Or even along the lines of the following if you really want the "Name" as a System.String array.
PS> $names = (Get-Service -Name Sql* | foreach { $_.Name -as [string]})
PS> $names[0].GetType().FullName
System.String
PS> $names
SQLBrowser
SQLSERVERAGENT
SQLWriter
But also keep the good advice in #alroc's answer in mind - maybe you want to keep the actual type of Get-Service's result (System.ServiceProcess.ServiceController) as long as possible and access/use the Name property of it as late as possible. YMMV.
You're using format-table in the pipeline. Anytime you use a format-* cmdlet, that's the end of the line for your data - it's now just a formatted bunch of text, it's no longer data that you can actually use.
Try this to get the names formatted as a table for viewing:
$service_name = (Get-Service -computername $server_name -name sql* -exclude *sqlwriter);
$service_name | format-table -property name;
That said, I ran both your version and mine above and got the same visual output - the critical difference is that mine stores data in $service_name, not just a bunch of text (as yours does).
edit:
In response to:
All I really needed was the service names in an array to then use elsewhere
$service_name = (Get-Service -computername $server_name -name sql* -exclude *sqlwriter) | select-object -expandproperty name;
or:
$service_name = (Get-Service -computername $server_name -name sql* -exclude *sqlwriter).name;
No need to invoke WMI directly.