Logic Issue with PowerShell - powershell

When I run this, if there is a connection, ($TRUE) the logic should go to whether the user is logged in. It moves to the Else statement which says the computer is offline? Can someone help me find the missiing link in the script? I am lost on this one. True should say online, then if user is logged in the message should be Computer in use. It is showing everyone as OFFLINE?
Function Get-RemoteLogonStatus{
ForEach ($line in Get-Content C:\ADComputers.csv)
{$Computername = $line
if(Test-Connection -ComputerName $ComputerName -Count 2 -Quiet){
If((Get-WmiObject -Class Win32_ComputerSystem -ComputerName
$ComputerName).username -eq $null)
{
Write-Output 'No user logged in. RESTART COMPUTER'
##Shutdown /r /t 0 /M \\$ComputerName
$ComputerName
}
Write-Output 'Computer in Use.'
$ComputerName
}
else{
Write-Output 'Computer OFFLINE.'
$ComputerName
}
}
}

Related

Cannot run PS1 with different credential

I have a script, which does multiple things on different servers. If I log on to a computer with my admin account, the script runs fine. However, I want to to be able to run it on my standard account by using my admin credential.
I have used invoke-command with -credential or get-credential at the beginning of my script but none has worked. I keep getting "access is denied"
Here is a part of my script.
$Computername = "Computer"
if (test-Connection -ComputerName $ComputerName -Count 1 -quiet) {Write-Host "`n$computername is ONLINE."}
else {Write-Host "`n$computername is OFFLINE."
Get-ADComputer -identity $computername
if (!$?) {Write-Host "`n$computername is not found in ActiveDir."}
Else {
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $dom.GetDirectoryEntry()
$search = [System.DirectoryServices.DirectorySearcher]$root
$search.filter = "(&(objectclass=computer)(name=$computername))"
$search.findall() | %{$_.GetDirectoryEntry() } | %{$_.DeleteObject(0)}
Write-Host "`n$computername is deleted from ActiveDir."
}}

PowerShell remote PC shutdown, single PC

OU=_ is a private company name. I know it's restart, this is only for testing before it goes into the real hutdown process.
function Get-LastBootUpTime {
param (
$ComputerName
)
$OperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
[Management.ManagementDateTimeConverter]::ToDateTime($OperatingSystem.LastBootUpTime)
}
$Days = -0
$ShutdownDate = (Get-Date).adddays($days)
$ComputerList = Get-ADComputer -SearchBase 'OU=TEST-OU,OU=_,DC=_,DC=_' ` -Filter '*' | Select -EXP Name
$ComputerList | foreach {
$Bootup = Get-LastBootUpTime -ComputerName $_
Write-Host "$_ last booted: $Bootup"
if ($ShutdownDate -gt $Bootup) {
Write-Host "Rebooting Computer: $_" -ForegroundColor Red
restart-Computer $Computer -Force
}
else {
Write-Host "No need to reboot: $_" -ForegroundColor Green
}
}
I'm trying to shutdown all of the PCs in my company that run longer than 2 days. The script is kind of done, but it shows an error when it comes to the point:
restart-Computer $Computer -Force
If I type instead of $Computer, $ComputerList the script shuts down every PC in that OU, even if they didnt run longer than 2 days.
So it only takes one PC to run longer than 2 days to shut down the entire company, and that's not what I want.
How can I tell the script to only turn the PCs off, when they have already run more than 2 days?
Your $Computer is not defined. You should use:
Restart-Computer $_ -Force
But the better approach would be to collect all of the computers that should restart in a variable and then restart them altogether. Would work much faster:
$toBeRestarted = $ComputerList | Where-Object { $ShutdownDate -gt (Get-LastBootUpTime -ComputerName $_) }
Restart-Computer $toBeRestarted -Force
You may add some more logging around if you like

Assistance in properly scripting a Join and Un-Join Domain script

Hello guys i have started to create a script that would basically automate the un-join and joining of a computer via a script this initially works fine right up until the point i need to start pinging for the computer to come back online. For the instance of un-joining it works fine but all the issue arise when trying to join.
Maybe fresh pair of eyes can lend me some Intel on the matter thank you.
<#
############################################################################################################
# Written by CPineda # NOTE: This only works if computer is on the wire. #
# This Script un-joins and re-joins the domain. # So its very important that we connect the devce #
# Created: 04/27/2016 # to the LAN. #
# Last revision 4/6/2016 # #
############################################################################################################
#>
# Set up your Variables
$ComputerIP = "" #Stores the Computers IP
$ComputerName = "" #Stores the Name of the computer you will be working with.
#$LocalCredentials = "" #Stores the Local Administrator credentials. (As Neeeded)
$DomainCredentials = "" #Stores the Domain Administrator credentials.
# Get information needed for the script to run.
while ($ComputerIP -eq ""){
Clear-Host #Clear the PS Console Window
$ComputerIP = Read-Host "Enter the name of the Computer IP"
}
while ($ComputerName -eq ""){
Clear-Host #Clear the PS Console Window
$ComputerName = Read-Host "Enter the name of the Computer"
}
<# while ($LocalCredentials -eq ""){
Clear-Host #Clear the PS Console Window
$LocalCredentials = Read-Host "Enter the User name of the Local User Admin Account"
}
#>
while ($DomainCredentials -eq ""){
Clear-Host #Clear the PS Console Window
$DomainCredentials = Read-Host "Enter the User name of the Domain User Admin Account"
}
# Remove the computer from the Domain.
Remove-Computer -ComputerName $ComputerName -LocalCredential $ComputerName\administrator -UnJoinDomainCredential kelsonfla\$DomainCredentials -WorkgroupName WORKGROUP -Force -Restart
Read-Host "Hit ENTER to continue"
# Ping until computer returns on the wire.
Clear-Host
Write-Host "At this time we will ping the compputer in question untill it returns back online"
Write-Host "Hit ENTER to continue"
Read-Host
Test-Connection ($ComputerIP) {
$result = Test-Connection $ComputerIP -Count 3 -Delay 10 -Quiet
if ($Result | where { $_ -match 'Reply from ' }){$true}
else {$false}
}
Write-Verbose "The computer $ComputerIP has went down for a reboot. Waiting for it to come back up..."
while (!(Test-Connection -ComputerName $ComputerIP)) {
Start-Sleep -Seconds 5
Write-Verbose "Waiting for $ComputerIP to come back online"
}
Write-Verbose "The computer $ComputerIP has come online. Waiting for OS to initialize"
$EapBefore = $ErrorActionPreference
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue
while (!(Get-WmiObject -ComputerName $ComputerIP -Class Win32_OperatingSystem -Credential $LocalCredentials)) {
Start-Sleep -Seconds 5
Write-Verbose "Waiting for OS to initialize..."
$ErrorActionPreference = $EapBefore
}
# Add computer back to the Domain.
Add-Computer -ComputerName $ComputerIP -LocalCredential $ComputerName\administrator -DomainName kelsonfla.local -Credential kelsonfla\$DomainCredentials -Restart -Force
Read-Host "Hit ENTER to continue"
# Ping until computer returns on the wire.
Clear-Host
Write-Host "At this time we will ping the compputer in question untill it returns back online"
Write-Host "Hit ENTER to continue"
Read-Host
Test-Connection ($ComputerIP) {
$result = Test-Connection $ComputerIP -Count 3 -Delay 10 -Quiet
if ($Result | where { $_ -match 'Reply from ' }){$true}
else {$false}
}
Write-Verbose "The computer $ComputerIP has went down for a reboot. Waiting for it to come back up..."
while (!(Test-Connection -ComputerName $ComputerIP)) {
Start-Sleep -Seconds 5
Write-Verbose "Waiting for $ComputerIP to come back online"
}
Write-Verbose "The computer $ComputerIP has come online. Waiting for OS to initialize"
$EapBefore = $ErrorActionPreference
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue
while (!(Get-WmiObject -ComputerName $ComputerIP -Class Win32_OperatingSystem -Credential $LocalCredentials)) {
Start-Sleep -Seconds 5
Write-Verbose "Waiting for OS to initialize..."
$ErrorActionPreference = $EapBefore
}
Clear-Host
Write-Output "If you are Reading this then you have successfully Unjoined and Re-Joined a Computer to the Network"
Start-Sleep -Seconds 3
Clear-Host
First : for the ping part, you should remove the code :
Test-Connection ($ComputerIP) {
$Result = ping $ComputerIP -n 3
if ($Result | where { $_ -match 'Reply from ' }) {
$true
} else {
$false
}
}
and simply use
!$result = $false
do {
Write-Verbose "Waiting for $ComputerIP to come back online"
$result = Test-Connection $ComputerIP -Count 2 -Delay 5 -Quiet
} while (!$result)
And then use the value of the $result boolean to see if your computer is reponding again. Test-Connection is a Cmdlet that cover the ping role.

Delete one local user account if another local adminstrator ID exist

I have few numbers of server where "tempadmin" and "Administrator" are exist as local admin user. I need to delete "tempadmin" id if "Administrator" is also exist. else "tempadmin" needs to rename as "Administrator". Could anyone help me create one PowerShell script?
cls
$strComputer = Get-Content "c:\patch\clientlist.txt"
$password = Read-Host "Enter the password : " -AsSecureString
foreach ($server in $strComputer) {
Write-Host "Working on server $server"
if (Test-Connection $server -Quiet) {
$usertest1 = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True AND Name='test1'" -ComputerName $server
if ($usertest1.name -ne 'test1') {
$user = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True AND Name='test'" -ComputerName $server
$result = $user.Rename('test1')
if ($result.name -eq 'test') {
$result
# you may just print a message here
}
Write-host "$server -> ID renamed and resetting password...."
$user1 = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True AND Name='test1'" -ComputerName $server
([adsi]("WinNT://" + $server + "$user1")).SetPassword("$password")
Write-Host "$server -> Password reset successfully"
} else {
Write-Host "$server -> Test1 ID already exist"
}
} else {
Write-Host "$server -> server is not reachable"
}
}
Here I am user "test" and "test1". I tried the above code and I can successfully rename and reset the password. But I am unable to delete if both ID's are exist.
I would try something like this:
$VerbosePreference = 'Continue'
foreach ($C in $Computer) {
if (Test-Connection $C -Quiet) {
Write-Verbose "$C > Online"
$Users = Get-WMIObject Win32_UserAccount -Filter "LocalAccount=True" -ComputerName $C
if ($Users.Name -contains 'Administrator') {
Write-Verbose "User 'Administrator' found"
if ($Users.Name -contains 'tempadmin') {
Write-Verbose "Delete user 'tempadmin'"
$ADSI = [ADSI]"WinNT://$C"
$ADSI.Delete('User','tempadmin')
}
}
else {
Write-Verbose "User 'Administrator' not found"
# Here you can rename the 'tempadmin' account or create a new 'Administrator'
}
}
else {
Write-Verbose "$C > Offline"
}
}
It's not complete but I'm sure you get the idea here. It's always better to query a client once and then loop through the collection of objects instead of querying multiple times to check for different objects in each query.
I hope this helps you out or gives you some ideas.
More info can be found on Boe Pox's excellent blog.

Powershell try/catch with test-connection

I'm trying to have offline computers recorded in a text file so that I can run them again at a later time. Doesn't seem that it is being recorded or caught in catch.
function Get-ComputerNameChange {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
[string[]]$computername,
[string]$logfile = 'C:\PowerShell\offline.txt'
)
PROCESS {
Foreach($computer in $computername) {
$continue = $true
try { Test-Connection -computername $computer -Quiet -Count 1 -ErrorAction stop
} catch [System.Net.NetworkInformation.PingException]
{
$continue = $false
$computer | Out-File $logfile
}
}
if($continue){
Get-EventLog -LogName System -ComputerName $computer | Where-Object {$_.EventID -eq 6011} |
select machinename, Time, EventID, Message }}}
try is for catching exceptions. You're using the -Quiet switch so Test-Connection returns $true or $false, and doesn't throw an exception when the connection fails.
As an alternative you can do:
if (Test-Connection -computername $computer -Quiet -Count 1) {
# succeeded do stuff
} else {
# failed, log or whatever
}
The Try/Catch block is the better way to go, especially if you plan to use a script in production. The OP's code works, we just need to remove the -Quiet parameter from Test-Connection and trap the error specified. I tested on Win10 in PowerShell 5.1 and it works well.
try {
Write-Verbose "Testing that $computer is online"
Test-Connection -ComputerName $computer -Count 1 -ErrorAction Stop | Out-Null
# any other code steps follow
catch [System.Net.NetworkInformation.PingException] {
Write-Warning "The computer $(($computer).ToUpper()) could not be contacted"
} # try/catch computer online?
I've struggled through these situations in the past. If you want to be sure you catch the right error when you need to process for it, inspect the error information that will be held in the $error variable. The last error is $error[0], start by piping it to Get-Member and drill in with dot notation from there.
Don Jones and Jeffery Hicks have a great set of books available that cover everything from the basics to advanced topics like DSC. Reading through these books has given me new direction in my function development efforts.