using powershell to gather logged on user names on remote computers? - powershell

$MachineList = Get-Content -Path "E:\ps\comp list\Test Computers.txt"; # One system name per line
foreach ($Machine in $MachineList)
{
($Machine + ": " + #(Get-WmiObject -ComputerName $Machine -Namespace root\cimv2 -Class Win32_ComputerSystem -erroraction silentlycontinue)[0].UserName);
Write-Output ($Machine + ": " + #(Get-WmiObject -ComputerName $Machine -Namespace root\cimv2 -Class Win32_ComputerSystem -erroraction silentlycontinue)[0].UserName) | Out-File "E:\ps\comp output\Test Computers.txt" -Append
}
Update: Here's the working script, thanks all for the help! :) It pulls in a list of computers prints to the screen and then also writes them to a file.
I found this powershell code and it works but I'd like it to display the machine name in front of the username when it displays. How can I get it to do that?
So like -
MachineName: Username
I'm a powershell newb... any help would be appreciated! Thanks! :)

Try this
$MachineList = Get-Content -Path c:\ListOfMachines.txt; # One system name per line
foreach ($Machine in $MachineList){
($Machine + ": " + #(Get-WmiObject -ComputerName $Machine -Namespace root\cimv2 -Class Win32_ComputerSystem)[0].UserName);
}

Try this:
Get-Content -Path c:\ListOfMachines.txt | % {
Get-WmiObject -ComputerName $_ -Namespace root\cimv2 -Class Win32_ComputerSystem -erroraction silentlycontinue | % {
"$($_.Name): $($_.username)"
}
}

Related

Powershell and TPM how to manage bitlocker?

I am trying to script a powershell function manage-bde.exe (bitlocker) to add a key protector to systems without TPM. For some reason GPO is not working. I have not had any luck getting powershell to add the protector remotely. I can log on to the endpoint and use the built in wizard to encrypt and save the key to our repository but for some reason remote automated scripting eludes me. My question is really more of guidance. Can powershell only be used, to remotely manage systems with TPM? I have bitlocker enabled and encrypted on systems without but I have had to do it manually.
Start-Transcript -Path ".\bitlockertranscript.txt" -Force
foreach ($Computer in $List) {
if (test-Connection -ComputerName $Computer -Count 1 -Quiet ) {
Get-ADComputer -Identity $Computer -Property * | Select Name,OperatingSystem
Get-WmiObject -class Win32_Tpm -namespace root\CIMV2\Security\MicrosoftTpm -computername $Computer | fl IsActivated_InitialValue, IsEnabled_InitialValue, IsOwned_InitialValue
$BitLocker = Get-WmiObject -ComputerName $Computer -Namespace Root\cimv2\Security\MicrosoftVolumeEncryption -Class Win32_EncryptableVolume
$id = $BitLocker.GetKeyProtectors(3).volumekeyprotectorid | Select -First 1
manage-bde.exe -cn $Computer -protectors -adbackup c:
manage-bde.exe -on C: -cn $Computer
Invoke-GPUpdate -Target $computer
} else
{"No Connection to $Computer"
}
}
Stop-Transcript

Powershell script in columns instead of rows

I was trying to write a script which would use a text file with hostnames and needs to generate a file with the extra data. I can only manage to get it in rows instead of columns:
Model:
Bios Version:
TPM OEM Ver:
User logged In:
I would also like to get the emailaddress from the logged on user. I was thinking to use get-aduser. Could I add another foreach after the current code, using the column with the usernames? How would I do this?
All help is greatly appreciated!
My code is:
$output = foreach ($hostname in Get-Content C:\temp\hostnames.txt)
{
$computerinfo = get-ciminstance -computername $hostname Win32_ComputerSystem
$computerBIOS = get-ciminstance -computername $hostname Win32_BIOS
$tpm = Get-ciminstance -class Win32_Tpm -namespace root\CIMV2\Security\MicrosoftTpm -ComputerName $hostname
"Hostname: " + $computerinfo.name
"Model: " + $computerinfo.Model
"Bios Version: " + $computerBIOS.smbiosbiosversion
"TPM OEM Ver: " + $tpm.ManufacturerVersion
"User logged In: " + $computerinfo.UserName
}
$output | out-file 'C:\Temp\hostnames3.txt' -append
You should use the CSV file format instead of plain text for structured data. That makes it easier to use them for further steps if needed.
$output =
foreach ($hostname in Get-Content C:\temp\hostnames.txt) {
$computerinfo = Get-CimInstance -ComputerName $hostname -ClassName Win32_ComputerSystem
$computerBIOS = Get-CimInstance -ComputerName $hostname -ClassName Win32_BIOS
$tpm = Get-CimInstance -Namespace root\CIMV2\Security\MicrosoftTpm -ComputerName $hostname -ClassName Win32_Tpm
[PSCustomObject]#{
Hostname = $computerinfo.name
Model = $computerinfo.Model
Bios_Version = $computerBIOS.smbiosbiosversion
TPM_OEM_Ver = $tpm.ManufacturerVersion
User_logged_In = $computerinfo.UserName
}
}
$output |
Export-Csv -Path 'C:\Temp\hostnames3.csv' -NoTypeInformation
In my experience the UserName property of the CIM-Class Win32_ComputerSystem is unreliable to determine the logged on user. I usually use good old quser.exe like this:
$UserQuery = ( C:\Windows\System32\quser.exe /server:$hostname 2> null)
if ($UserQuery) {
$UserQuery[1].Trim() -match "^(\S+)\s+.*((\d{2}\.){2}\d{4}\s+\d{2}:\d{2})" | Out-Null
$LoggedOnUser = $Matches[1]
$LogonTime = Get-Date -Date $Matches[2]
}
Then you can use $LoggedOnUser and $LogonTime to include it in your output object if you like.
Of course you can include a additional AD query for more information about the logged on user.

Kill Process On List Of remote Workgroup Servers

I have a list of 5 Servers and for specific reasons they are not on the domain. The credentials among them are the same.
I am trying to remotely kill any instance of a process on the machines. For this website I have change the process to notepad.exe
I am having issues trying to determine how to successfully connect to these boxes.
I am running
$StartCheck = Get-WmiObject Win32_Process -Computer $Servers |
Where-Object { $ProcessNames -contains $_.Name }
$StartCheck | FT * -a;$StartCheck | FT * -a | out-file -FilePath $logfile -Append
and Here.
(Get-WmiObject Win32_Process -Computer $Servers |
Where-Object { $ProcessNames -contains $_.Name }).Terminate() | out-null
I am faced with the following error
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
At C:\Users\first.last\Desktop\Kill All Traffic Managers.PS1:67 char:13
+ $EndCheck = Get-WmiObject Win32_Process -Computer $Servers |
+
What is the easiest way to enter the credentials?
Add this to your script and change usernname and P#ssw0rd
$account = "username"
$PASSWORD = ConvertTo-SecureString P#ssw0rd -AsPlainText -Force
$UNPASSWORD = New-Object System.Management.Automation.PsCredential $account, $PASSWORD
Also change your
Get-WmiObject Win32_Process -Computer $Servers`
for
Get-WmiObject Win32_Process -Computer $Servers -Credential $UNPASSWORD

Log output of ForEach loop

The code below gets computer info remotely. I couldn't get it send output to a log file. Also, how do I log all unqueried computers in a separate log file?
Code:
$ArrComputers = gc .\computernames.txt
Clear-Host
ForEach ($Computer in $ArrComputers)
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" -Query "Select * from Win32_ComputerSystemProduct" -computer $computer | select version
write-host "System Information for: " $computerSystem.Name -BackgroundColor DarkCyan
"-------------------------------------------------------"
"Model: " + $computerSystem.Model
"Serial Number: " + $computerBIOS.SerialNumber
"Version: " + $Version
""
"-------------------------------------------------------"
}
Logging is fairly straightforward. You just need to store output in a variable and then use Out-File cmdlet:
$ArrComputers = gc .\computernames.txt
$OutputLog = ".\output.log" # Main log
$NotRespondingLog = ".\notresponding.log" # Logging "unqueried" hosts
$ErrorActionPreference = "Stop" # Or add '-EA Stop' to Get-WmiObject queries
Clear-Host
ForEach ($Computer in $ArrComputers)
{
try
{
$computerSystem = get-wmiobject Win32_ComputerSystem -Computer $Computer
$computerBIOS = get-wmiobject Win32_BIOS -Computer $Computer
$Version = Get-WmiObject -Namespace "Root\CIMv2" `
-Query "Select * from Win32_ComputerSystemProduct" `
-computer $computer | select -ExpandProperty version
}
catch
{
$Computer | Out-File -FilePath $NotRespondingLog -Append -Encoding UTF8
continue
}
$Header = "System Information for: {0}" -f $computerSystem.Name
# Outputting and logging header.
write-host $Header -BackgroundColor DarkCyan
$Header | Out-File -FilePath $OutputLog -Append -Encoding UTF8
$Output = (#"
-------------------------------------------------------
Model: {0}
Serial Number: {1}
Version: {2}
-------------------------------------------------------
"#) -f $computerSystem.Model, $computerBIOS.SerialNumber, $Version
# Ouputting and logging WMI data
Write-Host $Output
$Output | Out-File -FilePath $OutputLog -Append -Encoding UTF8
}
In its current state, your code will give an error for each computer the Get-WmiObject command could not reach. I would consider using -ErrorAction SilentlyContinue -ErrorVariable Err at the end of the first Get-WmiObject command. This will stop the errors from coming to your screen and clogging your output. You can then condition the other two calls to Get-WmiObject to only happen if the ErrorVariable is empty. If it exists, log the name of the computer, and then output to a file.
The reason you are not able to log anything else to a file is because you are using Write-Host. I would consider using a PSObject to return information. This will allow you to see the output on the screen in an organized fashion while also allowing you to write output to a file.
Also, using the -ExpandProperty switch with Select-Object will keep you from returning a hashtable for the Version property.

How to have both write -host and html

I have written a code snippet and I have incorporated write host in it i want both write host and convert html to run for this snippet can any one help me with that.
$arrComputers = get-Content -Path "C:\Computers.txt"
foreach ($strComputer in $arrComputers)
{
$colItems = get-wmiobject -class "Win32_BIOS" -namespace "root\CIMV2" `
-computername $strComputer
foreach ($objItem in $colItems)
{
write-host "Computer Name: " $strComputer
write-host "BIOS Version: " $objItem.BIOSVersion
}
$colItems1 = get-wmiobject -class Win32_logicaldisk -Filter "DeviceID = 'C:'" -computername $strComputer
foreach ($objItem1 in $colItems1)
{
$e=$objItem1.freeSpace/1GB
write-host "Total Space: " $e
}
$colItems4 = Get-WMIObject -class Win32_PhysicalMemory -computername $strComputer
$colItems5=$colItems4 | Measure-Object -Property capacity -Sum
foreach ($objItem4 in $colItems5)
{
$e4=$colItems5.Sum/1GB
write-host "Memory : " $e4
}
}
You can use the -Fragment parameter.
$pcName = "Computer Name: $strComputer" | ConvertTo-HTML -Fragment;
$biosV = "BIOS Version: $objItem.BIOSVersion" | ConvertTo-HTML -Fragment;
ConvertTo-HTML -Body "$pcName $biosV" -Title "List of Computers" | Out-File c:\listofcomputers.html
Just create variables after the Write-Host with the same content and use the converTo-HTML at the end of the script.
This way allows you to style your HTML output too by using the param tag or even table tags to have a better layout then a clean sterile layout.