We are trying to find from which machine a user has taken rdp .
Using "quser" utility we are able to get all the information about logged in user except client name.
Following is the command
function Get-LoggedOnUser
{
param([String[]]$ComputerName = $env:COMPUTERNAME)
$ComputerName | ForEach-Object {
(quser /SERVER:$_) -replace '\s{2,}', ',' |
ConvertFrom-CSV |
Add-Member -MemberType NoteProperty -Name ComputerName -Value $_ -PassThru
}
}
It displays all the information which can be provided in Windows task manager except client Name .
How to get client Name using powershell?
I doubt if WMI has a way to do this. You can check the PSTerminal Services module and it has a Get-TSSession cmdlet which does the same job you are looking for.
http://archive.msdn.microsoft.com/PSTerminalServices
This module uses binary Cassia namespace.
You can use this:
http://gallery.technet.microsoft.com/scriptcenter/0e43993a-895a-4afe-a2b2-045a5146048a
and look for the logged on user with a logon type of RemoteInteractive
You can read that information from the Security eventlog (look for logon type 10):
$username = '...'
$eventID = 4624 # 526 on Server 2003 and earlier
$date = (Get-Date).Date
$pattern = 'logon type:\s+10[\s\S]+source network address:\s+(\S+)'
Get-EventLog Security -InstanceId $eventID -EntryType SuccessAudit `
-After $date -Message '*$username*' `
| ? { $_.Message -match $pattern } `
| % { $matches[1] } `
| select -Unique
Note that on Server 2003 and earlier you need to check for event ID 528 instead of 4624.
References:
http://technet.microsoft.com/en-us/library/cc787567
http://support.microsoft.com/kb/977519
Related
Hi I hope someone can help me, I'm not great at scripting and my issue is...
I have a medium estate of around 15,000 users which is in a bit of a mess. There are around 3000 user accounts which are disabled. Some user accounts are disabled due to the user being on long term sick, maternity, or suspended, these 'known' accounts are not to be touched so I cannot do a broad "find accounts that are disabled and just delete them" script.
Currently I have a script which exports all disabled accounts to a csv, I then manually manipulate that data within the csv to tag known accounts that cannot be deleted. I then take that file and run this script...
Import-Module ActiveDirectory
$list = Import-CSV C:\temp\deleteuser.csv
forEach ($item in $list) {
$samAccountName = $item.samAccountName
#Get DistinguishedName from SamAccountName
$DN = Get-ADuser -Identity $Samaccountname -Properties DistinguishedName |
Select-Object -ExpandProperty DistinguishedName
try{
#Remove object using DN
Remove-ADObject -Identity $DN -Confirm:$false
"Remove successful for $SamAccountName" | Out-File 'C:\temp\Account Delete Success.txt' -Append }
Catch{
"Remove failed for $SamAccountName" | Out-File 'C:\temp\Account Delete Failed.txt' -Append
}
}
While this is great, I'd love to be able to check the user account is still disabled before the Remove-ADObject command is run and for it to skip the account and output the name of the skipped account to a txt file. Is that possible or am I over complicating things?
simply test 'Enabled' property before deleting user like this :
Import-Module ActiveDirectory
$list = Import-CSV C:\temp\deleteuser.csv
forEach ($item in $list) {
$samAccountName = $item.samAccountName
#Get DistinguishedName from SamAccountName
$DN = Get-ADuser -Identity $Samaccountname -Properties DistinguishedName, Enabled |
Select-Object -ExpandProperty DistinguishedName
try{
#Remove object using DN
if (!$DN.Enabled){
Remove-ADObject -Identity $DN -Confirm:$false
"Remove successful for $SamAccountName" | Out-File 'C:\temp\Account Delete Success.txt' -Append }
else {
"Remove aborted for $SamAccountName" | Out-File 'C:\temp\Account Delete aborted.txt' -Append }
}
}
Catch{
"Remove failed for $SamAccountName" | Out-File 'C:\temp\Account Delete Failed.txt' -Append
}
}
I have created a tsv file to list Servers and Services as follows:
TSV File as follows:
Hostname Services
=========================
Server01 SP4AdminV4,SPTraceV4,SPWriterV4,WAS,W3SVC
Server02 SP4AdminV4,SPTraceV4,SPWriterV4,WAS,W3SVC,SPSearchHostController, OSearch16
PowerShell command
Import-csv C:\ServerServerList.tsv
$Services = $_.Services -Split ','
Start-Service -Computer 'Server01' -Name $Services
I then get the following error:
Start-Service: Cannot Bind Argument to parameter 'Name' because it is an empty string.
At Line:3 char:43
+ Start-Service -Computer $_.Hostname -Name **$Services**
+
+categoryinfo: InvalidData (:) [Start-Service], ParameterBindingValidationException
+FullyQualifiedErrorId: ParameterArgumentValidationErrorEmptyStringNotAllowed,
Microsoft.Powershell.Commands.StartServiceCommand
There are a couple of problems I can spot at a glance. First you don't seem to be assigning $Services correctly. 2nd you Start-Service doesn't have a -ComputerName parameter.
To get around that you can use the use Get-Service in conjunction with Set-Service implicitly using the -InputObject parameter via the pipeline.
Import-csv C:\ServerServerList.tsv -Delimiter "`t" |
ForEach-Object{
$Services = $_.Services -Split ','
Get-Service -Computer $_.HostName -Name $Services
} |
Start-Service
I'm assuming this is a Tab separated file as you described. Also assuming the services are listed in such a way to make the split proper.
The loop sends [System.ServiceProcess.ServiceController] objects down the pipeline. Those are bound to the -InputObject parameter. Internally Start-Service uses the .MachineName property to make the change on the remote system.
Warning: Get/Set-Service doesn't always report errors properly in this kind of scenario. The primary obstacle I've encountered is misleading errors and/or silent failures in cases where the operator account doesn't have access to the remote system.
I'm sure there's easier ways to go about this but, here's what I got:
# import csv and save to variable.
$CSV = Import-Csv -Path 'C:\ServerServerList.tsv'
# Use a foreach loop to iterate throw csv
# one row at a time - assigning the current iteration to $Row.
foreach ($Row in $CSV) {
# Split services into an array
$Services = ($Row.Services -split ',').Trim()
# Invoke the start-service call due to it not
# having it's own -ComputerName parameter to work with.+
Invoke-Command -ScriptBlock {
# Start the service using the newly created array of $Services.
# Note: we must use a *Remote Variable* to pass over our local variable
# by specifying the $using: keyword.
Start-Service -Name $using:Services -PassThru -WhatIf
} -ComputerName $Row.Hostname
}
- This is untested -
I have windows powershell 5.1 script block like the following that successfully retrieves appRoles and oauth2permissions.
import-module -name AzureAD
if ($null -eq $mycredentials) { $mycredentials = Get-Credential }
$azConnectionContext = Connect-AzureAD -Credential $mycredentials
# $svp = Get-AzureADServicePrincipal -Filter "DisplayName -eq 'Microsoft Graph' } # not working, why ???
$svp = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq 'Microsoft Graph }
$appRoles = $svp.AppRoles; $oauth2permissions = $svp.Oauth2Permissions
I'm trying to convert to powershell core 7 script block like the following and i'm unable to retrive appRoles and oauth2permissions because the PSADServicePrincipal type doesn't expose those properties.
import-module -name Az.Accounts
$azConnectionContext = Connect-AzAccount
$svp = Get-AzADServicePrincipal -DisplayName 'Microsoft Graph' }
$appRoles = $svp.AppRoles; $oauth2permissions = $svp.Oauth2Permissions # both of these fail
Question - anyone know how i get at azure ad service principal appRoles and oauth2permissions using powershell core 7.0.3 apis and types?
Instead of:
$svp.AppRoles;
Use:
$svp.AppRole;
$svp.Oauth2Permissions should work. Type should be Microsoft.Azure.PowerShell.Cmdlets.Resources.Models.Api16.OAuth2Permission.
To your last question, remove-module only removes a module for the current session. You need to run Uninstall-Module instead.
There is an Uninstall-AzModule function here that might help you: https://learn.microsoft.com/en-us/powershell/azure/uninstall-az-ps?view=azps-4.6.1
I am having trouble getting an array passed to a scriptblock in Start-Job. Can you tell me what I might be doing wrong?
$bounceBlock = {
param(
[string[]]$list,
[System.Management.Automation.PSCredential]$cred
)
Add-PSSnapin VMware.VimAutomation.Core | Out-Null
Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope User -InvalidCertificateAction Ignore -Confirm:$false | Out-Null
Connect-VIServer -Server servername -Credential $cred -AllLinked
Get-VM -Name $list
}
if ($targets) {
$activeTargets = $targets | Get-Random -Count $prodTargets.Count
$counter = [pscustomobject] #{Value = 0}
$groupSize = 50
$groups = $activeTargets | Group-Object -Property {[math]::Floor($counter.Value++ / $groupSize)}
$connection = Connect-VIServer -Server servername -Credential $cred -AllLinked
if ($connection -match "servername") {
foreach ($group in $groups) {
while ((Get-Job -State Running).Count -ge 5) {
Start-Sleep -Seconds 5
}
Start-Job -ScriptBlock $bounceBlock -ArgumentList (,$group.Group.ServerName),$cred
}
Disconnect-VIServer * -Force -Confirm:$false
}
}
I basically split an array into chunks of 50 (working) then try to run them as jobs. The error I get looks like it's trying to run Get-VM for a single server, named all 50 values appended together.
I am certainly no expert with PS, but first to address how you're passing in the appended list of servers; I do something similar with Azure VMs using Get-AzureVM and I pass in my list of VM names in a System.Array to functions or cmdlets such as a variable such as $theVMs= "MyServer1","MyServer2","MyServer3"
and then I execute a foreach loop over ($vm in $theVMs) and then perform the actions such as Get-VM sequentially. I do this sequentially since PS has some much lower limits, 5 per my experience, doing this via a parallel for loop.
A typical way I interact with the VMs remotely and create a PS Job per each is to use
$uri = Get-AzureWinRMUri -ServiceName $svc -Name $vmname
Invoke-Command -ConnectionUri $uri -Credential $creds **-JobName
$jobname**
-ArgumentList $vmname -ScriptBlock {
param([string]$thevm) ...
}
This requires the InstallWinRMCertAzureVM.ps1 script which is discussed and available at http://blogs.technet.com . I use this for between 30 servers regularly.
Just wanted everyone to know in case they run into a similar problem, this is an issue with running Get-VM, and it exists whether running it in a job or workflow. VMWare is aware of this issue.
param(
[string]$UserName
)
$DCs = Get-ADGroupMember "Domain Controllers"
foreach ($DC in $DCs)
{
Write-Host $DC.name
}
$EventList = Get-Eventlog –ComputerName $ComputerName -LogName Security -InstanceID 4740 -UserName *Username* -After "07/20/2014"
$EventList | Format-List -Property TimeGenerated,Message
I'm writing a script to figure out lockout events for specific users within all the domains.
I'm trying to figure out how to the computername variable from the $DC.name, I know at some point i'll have to move the $Eventlist = Get-Eventlog line within the loop.Then would I just delete the write-host $DC.name?
Get-EventLog can take an array of computernames. You don't even need the foreach loop. So what you could do is this:
$DCs = Get-ADGroupMember "Domain Controllers"
$EventList = Get-Eventlog –ComputerName $DCs.Name -LogName Security -InstanceID 4740 -UserName *Username* -After "07/20/2014"
$EventList | Format-List -Property TimeGenerated,Message
Note that you should only use Format-List if you do not intend to use the information for anything other than displaying in the console. If you want to use the object for anything, don't use Format-List or Format-Table.