I am on a windows server and want to know who has ssh-ed into the server. On Linux following command works
who -s
What is its alternative on Windows 10?
With an elevated PowerShell, you can list all logged on users with:
Get-CimInstance -ClassName Win32_LogonSession | Get-CimAssociatedInstance -Association Win32_LoggedOnUser
To only get the users that are logged on via SSH, you can use the following pipeline:
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'sshd.exe'" | Get-CimAssociatedInstance -Association Win32_SessionProcess | Get-CimAssociatedInstance -Association Win32_LoggedOnUser | Where-Object {$_.Name -ne 'SYSTEM'}
Explanation:
You are looking for accounts that are logged on (via SSH). In WMI, accounts are represented by the Win32_Account class. Logon sessions are represented by the Win32_LogonSession class. If a user is logged on, a Win32_Account will be associated with a Win32_LogonSession. This association will be represented by an instance of the Win32_LoggedOnUser class.
The first pipeline from above takes all existing logon sessions and returns all user accounts that are associated with these logon sessions. In conclusion, you get a list of all logged on users.
To get a list of all users that are logged on via SSH, you can evaluate some more associations. Each process (Win32_Process) is associated with a logon session via the Win32_SessionProcess class. The second pipeline from above does the following:
It filters all processes to only get the processes of the SSH daemon.
For the SSH processes, it determines the associated logon sessions (Win32_LogonSession) via the Win32_SessionProcess association class.
It then uses these logon sessions to determine the logged on users via the Win32_LoggedOnUser association class like in the first pipeline.
In the end, it filters the result to omit the SYSTEM account.
You can get the owner of the sshd process :
Get-CimInstance Win32_Process -Filter "Name = 'sshd.exe'" | `
Invoke-CimMethod -MethodName GetOwner | Where User -ne System
Then discard the System User which is used by the service itself, other users are the connected ones
I am trying to get a list of installed programs on another computer in our domain, which requires my domain admin credentials.
$Name = Read-Host -Prompt 'Enter Computer Name'
Start-Process powershell -Credential "company\adminusername"
Get-WmiObject -ComputerName $Name -Class Win32Reg_AddRemovePrograms | Select DisplayName, Version | Sort-Object Name
I don't know if this is correct or not. But it tells me my username and password is incorrect. Which is false. I must be doing something wrong here.
When I write scripts. I literally just want to double click on them, and let them fly. I'm trying to avoid running a script just to open another script as admin.
To hold your credentials:
$cred = Get-Credential
Then use the $cred variable when you need to.
Ended up finding a great solution here that not only allows me to get credentials but store them permanently for importing later for use in other scripts as well, with option to encrypt the credential file if needed:
https://www.jaapbrasser.com/quickly-and-securely-storing-your-credentials-powershell/
I've written a small .ps1 script which automates simple commands in an attempt to fix any issues with the default printer on an end user's machine. How can I pass credentials in this script so that it always runs with elevated privileges?
net stop spooler
Remove-Item C:\Windows\System32\spool\PRINTERS\* -Force
net start spooler
This would be used across many different domains, but the admin username/password are consistent across all machines. I saw a similar question here, but the methods shown either involved saving the password as a .xml and then recalling it (which would make the password visible to the non admin), or the method simply wouldn't work for me; maybe it was my execution? Normally I wouldn't be comfortable scripting admin credentials into plain text, but the script isn't actually saved on the end users' machine, only executed in the background through RMM. Any help is appreciated.
I found the following article very helpful on how to secure credentials and use credentials stored on a text file:
http://www.adminarsenal.com/admin-arsenal-blog/secure-password-with-powershell-encrypting-credentials-part-1/
basically you would do the following:
<password> | ConverTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString | Out-File <filename>.txt
You will then have a secure string file that would store your password for use in your script. You could also use the following command in order to perform the same action without ever having to use a plain text password:
(Get-Credentail).Password | ConvertFrom-SecureString | Out-File <filename>.txt
You can then add the following code to your script in order to use the password stored, I would recommend a shared location that only the admin has access on the workstation, and use it to run the mentioned script:
$credentials = Get-Content <filename>.txt | ConvertTo-SecureString
The final step is creating an object to use the credintials:
$adminCredentails = New-Object -TypeName System.Management.Automation.PSCredentail -ArgumentList <username>, (Get-Content <filename>.txt | ConvertTo-SecureString)
I leave to your imagination how you can then use the credentials in your script.
PowerShell newcomer here, I'm writing a script which prepares newly installed PC's to be merged with my IT firms network. One task I'm having trouble with turning a local user account that I have created via PowerShell into a local administrator.
It is crucial that I use PowerShell to do this, but I haven't yet come across anything in my research. Also any help with understanding the functional aspect of the relationship between GPO's and PowerShell, or really anything that helps broaden PowerShell's capabilities which can be initiated via the command line (trying to make this script as self-sufficient and reusable as possible) would be greatly appreciated. Here's the script so far with corresponding tasks.
1.) $cn = [ADSI]"WinNT://Inquisition"
$user = $cn.Create("User","Test")
$user.SetPassword("P#ssword!")
$user.setinfo()
$user.description = "TestUser"
$user.SetInfo()
2.) Get-WmiObject -Class Win32_UserAccount -Filter "name = 'Test'" | Set-WmiInstance -Argument #{PasswordExpires = 0}
3.)?
4.) $Computername = "TEST1"
$sysinfo = Get-WmiObject Win32_ComputerSystem $sysinfo.JoinDomainOrWorkGroup("AWS-TEST")
5.) netsh advfirewall set allprofiles state off
6.) $AUSettings = (New-Object -com "Microsoft.Update.AutoUpdate").Settings
$AUSettings.NotificationLevel
$ausettings.NotificationLevel = 1
$ausettings.save()
7.) $path = 'HKCU:\Software\Microsoft\Internet Explorer\Main\'
$name = 'start page'
$value = 'http://www.blueprintcss.org/tests/parts/sample.html'
Set-Itemproperty -Path $path -Name $name -Value $value
8.)?
Add a new user account named “Test” with a password of “P#ssw0rd!”
Set the password for account “Test” to never expire
Add user “Test” to the local Administrators security group
Set the computer name to be “TEST1” and the workgroup to “AWS-TEST”
Turn the Windows Firewall Off
Turn Windows Updates off and set to never check for updates
Set company website as the default webpage in Internet Explorer
Turn off the pop-up blocker in Internet Explorer
I had a similar need once, except mine was to remove local admin rights. This was the core of what worked for me.... Since your new, make sure to predefine your variables for Domain name, Host name, and User. Hope this helps!
$AdminGroup = [ADSI]"WinNT://$HostName/Administrators,group"
$InUser = [ADSI]"WinNT://$DomainName/$User,user"
$Admingroup.Add($InUser.Path)
Here is a single liner from https://community.spiceworks.com/topic/post/3297687
([ADSI]"WinNT://<computername>/Administrators,group").Add("WinNT://<domain>/<user>")
How do I get the current username in Windows PowerShell?
I found it:
$env:UserName
There is also:
$env:UserDomain
$env:ComputerName
On Windows, you can:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
I thought it would be valuable to summarize and compare the given answers.
If you want to access the environment variable:
(easier/shorter/memorable option)
[Environment]::UserName -- #ThomasBratt
$env:username -- #Eoin
whoami -- #galaktor
If you want to access the Windows access token:
(more dependable option)
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name -- #MarkSeemann
If you want the name of the logged in user
(rather than the name of the user running the PowerShell instance)
$(Get-WMIObject -class Win32_ComputerSystem | select username).username -- #TwonOfAn on this other forum
Comparison
#Kevin Panko's comment on #Mark Seemann's answer deals with choosing one of the categories over the other:
[The Windows access token approach] is the most secure answer, because $env:USERNAME can be altered by the user, but this will not be fooled by doing that.
In short, the environment variable option is more succinct, and the Windows access token option is more dependable.
I've had to use #Mark Seemann's Windows access token approach in a PowerShell script that I was running from a C# application with impersonation.
The C# application is run with my user account, and it runs the PowerShell script as a service account. Because of a limitation of the way I'm running the PowerShell script from C#, the PowerShell instance uses my user account's environment variables, even though it is run as the service account user.
In this setup, the environment variable options return my account name, and the Windows access token option returns the service account name (which is what I wanted), and the logged in user option returns my account name.
Testing
Also, if you want to compare the options yourself, here is a script you can use to run a script as another user. You need to use the Get-Credential cmdlet to get a credential object, and then run this script with the script to run as another user as argument 1, and the credential object as argument 2.
Usage:
$cred = Get-Credential UserTo.RunAs
Run-AsUser.ps1 "whoami; pause" $cred
Run-AsUser.ps1 "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name; pause" $cred
Contents of Run-AsUser.ps1 script:
param(
[Parameter(Mandatory=$true)]
[string]$script,
[Parameter(Mandatory=$true)]
[System.Management.Automation.PsCredential]$cred
)
Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList 'noprofile','-Command',"$script"
(you may need a hyphen before noprofile, like so)
Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList '-noprofile','-Command',"$script"
$env:username is the easiest way
I'd like to throw in the whoami command, which basically is a nice alias for doing %USERDOMAIN%\%USERNAME% as proposed in other answers.
Write-Host "current user:"
Write-Host $(whoami)
[Environment]::UserName returns just the user name. E.g. bob
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name returns the user name, prefixed by its domain where appropriate. E.g. SOMEWHERENICE\bob
Now that PowerShell Core (aka v6) has been released, and people may want to write cross-platform scripts, many of the answers here will not work on anything other than Windows.
[Environment]::UserName appears to be the best way of getting the current username on all platforms supported by PowerShell Core if you don't want to add platform detection and special casing to your code.
I have used $env:username in the past, but a colleague pointed out it's an environment variable and can be changed by the user and therefore, if you really want to get the current user's username, you shouldn't trust it.
I'd upvote Mark Seemann's answer:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
But I'm not allowed to. With Mark's answer, if you need just the username, you may have to parse it out since on my system, it returns hostname\username and on domain joined machines with domain accounts it will return domain\username.
I would not use whoami.exe since it's not present on all versions of Windows, and it's a call out to another binary and may give some security teams fits.
Just building on the work of others here:
[String] ${stUserDomain},[String] ${stUserAccount} = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name.split("\")
$username=( ( Get-WMIObject -class Win32_ComputerSystem | Select-Object -ExpandProperty username ) -split '\\' )[1]
$username
The second username is for display only purposes only if you copy and paste it.
I didn't see any Add-Type based examples. Here is one using the GetUserName directly from advapi32.dll.
$sig = #'
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool GetUserName(System.Text.StringBuilder sb, ref Int32 length);
'#
Add-Type -MemberDefinition $sig -Namespace Advapi32 -Name Util
$size = 64
$str = New-Object System.Text.StringBuilder -ArgumentList $size
[Advapi32.util]::GetUserName($str, [ref]$size) |Out-Null
$str.ToString()
Sometimes the Username attribute has no data in Win32_ComputerSystem even though there's a user signed in. What works for me is to use quser and parse the output. It's not perfect, but it works. E.g.:
$quserdata = #()
$quserdata = quser
$userid = ($quserdata[1] -split ' ')[1]
$userid
Note: if this is run as the user who is logged in, quser adds '>' symbol to the output. Then you need to get rid of that symbol, but mostly this is needed for code run as system or another account than the one that is logged in.
If you're used to batch, you can call
$user=$(cmd.exe /c echo %username%)
This basically steals the output from what you would get if you had a batch file with just "echo %username%".
I find easiest to use: cd $home\Desktop\
will take you to current user desktop
In my case, I needed to retrieve the username to enable the script to change the path, ie. c:\users\%username%. I needed to start the script by changing the path to the users desktop. I was able to do this, with help from above and elsewhere, by using the get-location applet.
You may have another, or even better way to do it, but this worked for me:
$Path = Get-Location
Set-Location $Path\Desktop
In my case, I needed to retrieve the username to enable the script to change the path, ie. c:\users\%username%\. I needed to start the script by changing the path to the users desktop. I was able to do this, with help from above and elsewhere, by using the get-location applet.
You may have another, or even better way to do it, but this worked for me:
$Path = Get-Location
Set-Location $Path\Desktop