Im wanting to add a printer and its port to the print server only if either that printer name and printer port isn't already taken.
I have this so far
$prnt = Import-Csv C:\scripts\printer.csv
foreach ($printer in $prnt) {
$var = Get-Printer
If (($var.name -contains $printer.Printername) -and ($var.portname -contains
$printer.IPAddress))
{
Write-Host "$printer exist!" -ForegroundColor Blue
}
else
{
Add-PrinterPort -ComputerName Printsrv01 -Name $printer.IPAddress -
PrinterHostAddress $printer.IPAddress
Add-Printer -ComputerName Printsrv01 -Name $printer.Printername -
DriverName $printer.Driver -PortName $printer.IPAddress -Location
$printer.Location
}
}
Problem is mainly with my 'if' statement. It catches the printer name but not the portnumber/ip. (The portnumber is the ip). And I also think my if statement is comparing the whole array of values from the csv file, and not just the specific value in the array like I want. Any help would be appreciated.
Csv file is setup like this
enter image description here
Try this:
$prnt = Import-Csv C:\scripts\printer.csv
$printers = (Get-Printer).Name
$ports = (Get-PrinterPort).PrinterHostAddress
foreach ($printer in $prnt)
{
If (($printers -contains $printer.Printername) -or ($ports -contains $printer.IPAddress))
{
Write-Host "$printer exist!" -ForegroundColor Blue
}
else
{
Add-PrinterPort -ComputerName Printsrv01 -Name $printer.IPAddress -PrinterHostAddress $printer.IPAddress
Add-Printer -ComputerName Printsrv01 -Name $printer.Printername -DriverName $printer.Driver -PortName $printer.IPAddress -Location $printer.Location
}
}
Related
Essentially, my script is supposed to check if each user in the administrators group is listed inside of a text file, and if it is then ignore it and move on. If it isn't, it removes the user from the administrator group. However, Get-LocalGroupMember prepends the computer name to the username. This means that the username in the txt file (ex user1), does not match the $._Name variable from the Get-LocalGroupMember command (ex desktop/user1). Here is a copy of the code
$GroupName = "Administrators"
$Exclude = "Administrator","$env:UserName"
$AuthorizedAdmins = Get-Content C:\Users\$env:UserName\admins.txt
Get-LocalGroupMember $GroupName |
ForEach-Object{
if ($_.ObjectClass -eq 'User'){
if ($AuthorizedAdmins -contains $_.Name -or $Exclude -contains $_.Name){
Continue
}
else{
Remove-LocalGroupMember -Group $GroupName -Member $_.Name -Confirm
}
}
}
I have tried several solutions. In the code, I created a new variable that removed the first $env:ComputerName+1 characters of the $._Name string. While this did work to remove the computername, powershell errors out. Here is the error code and changed script:
Get-LocalGroupMember : System error.
At users.ps1:6 char:1
+ Get-LocalGroupMember $GroupName |
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-LocalGroupMember], ContinueException
+ FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
$GroupName = "Administrators"
$Exclude = "Administrator","$env:UserName"
$AuthorizedAdmins = Get-Content C:\Users\$env:UserName\admins.txt
Get-LocalGroupMember $GroupName |
ForEach-Object{
$User = $_.Name
$length = $env:ComputerName.Length+1
$ShortUser = $User.Remove(0,$length)
if ($_.ObjectClass -eq 'User'){ #ignore groups and select only users
if ($AuthorizedAdmins -contains $ShortUser -or $Exclude -contains $ShortUser){
Continue
}
else{
Remove-LocalGroupMember -Group $GroupName -Member $_.Name -Confirm
}
}
}
The admin.txt file is formatted as follows:
user1
user2
user3
I cannot figure out how to fix this, though it is probably someting simple. Any help would be appreciated.
The real issue with your code is your use of continue in a ForEach-Object loop, see note from the docs. If you want to emulate continue in a pipeline processing function you should use return instead. So your code, with some improvements and simplifications would be:
$GroupName = "Administrators"
$exclude = #(
"Administrator"
$env:UserName
Get-Content C:\Users\$env:UserName\admins.txt
)
Get-LocalGroupMember $GroupName | ForEach-Object{
# if its not a user, skip this logic
if ($_.ObjectClass -ne 'User') {
return
}
# here we assume its a user
if ($_.Name.Split('\')[-1] -in $exclude) {
return
}
Remove-LocalGroupMember -Group $GroupName -Member $_.Name -Confirm
}
I am trying to scan computers in a specific OU in my AD to get the activation status of Windows.
I keep getting
Test-Connection : Testing connection to computer 'CN=PCNAME,OU=MY-OU' failed: No such host is known
although when i try to test the command against a single remote PC, it works fine getting the output
I tries getting all hosts using
$Hosts = Get-ADComputer -Filter \* -SearchBase "OU=MY-OU"
and then ran a for loop to test the connection of each host and using
foreach ($PC in $Hosts) {
if (Test-Connection $PC -Count 1) {
$License = Get-CimInstance SoftwareLicensingProduct -Filter "Name like 'Windows%'" -ComputerName $PC |where { $_.PartialProductKey } | select Description, LicenseStatus
$csv = [PSCustomObject]#{
License = $License
Computername = $PC
}
}
}
Write-Output $csv
Currently your $PC value is like this
$PC = "CN=server1,OU=OU1,OU=OU2,OU=OU3,DC=domain,DC=org"
in order to get computer name, split the string like below and use that value for test-connection
$CN = $PC.Split(',')[0].Split('=')[1]
$domainName = "CN=server1,OU=OU1,OU=OU2,OU=OU3,DC=domain,DC=org"
$CN = $domainName.Split(',')[0].Split('=')[1]
$CN
Edited: There are multiple properties in $Hosts, so instead of splitting distinguished name, use Select-object to get dns hostname.
I do not have an environment to test this code.. so please try yourself.
$Hosts = Get-ADComputer -Filter \* -SearchBase "OU=MY-OU" | Select-Object dnsHostName
$csv = foreach ($dnsHostName in $Hosts) {
Write-Output $dnsHostName
if (Test-Connection $dnsHostName -Count 1) {
$License = Get-CimInstance SoftwareLicensingProduct -Filter "Name like 'Windows%'" -ComputerName $dnsHostName | where { $_.PartialProductKey } | select Description, LicenseStatus
[PSCustomObject]#{
License = $License
Computername = $dnsHostName
}
}
}
$csv | Export-csv -Path C:\temp\output.csv -NoTypeInformation
i have 1 question:
i need verify 3 reg key on 20 pc and export result on csv file.
I used this string
Get-ItemProperty -Path hklm:"\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\" -Name "keyname" | Export-csv -path "csvpath"
and recive the all value for thi key but i don't need see the "PSPath, PSParentPath, PSChildName, PSDrive, PSProvider.
now i was thinking of making a script with variables to simplify it, but at this point i would like it to tell me even if the key was not found and the basic thing i can run it from the DC to all machines (about 20).
this could be a starting point
$key1 = name key 1
$key2 = name key 2
$key3 = name key 3
$hostname= hostname
$regkey= get-itemprperty -path ecc....
and now i'm seeing how you implement the verification loop and export everything to csv
thx
To verify the key existence, use Test-Path.
Computer names and Key names as arrays of strings.
No experience with remoting, I think you'll be using Invoke-Command, but this should give you an idea of looping and getting all non-PS properties:
Computer1
Computer2
Computer3
'# -split '\n'
$keyNames = #'
KeyName1
KeyName2
KeyName3
`# -split '\n'
ForEach ( $Comoputer in $Computers) {
ForEach ( $KeyName in $KeyNames ) {
If ( Test-Path $KeyName )
{
$AllProps = ($key = Get-Item $KeyName).Property
(Get-ItemProperty $key).PSobject.Properties | where name -in $AllProps | select Name , Value
<< Create output >>
}
Else
{
"$ComputerName: $KeyName not found."
}
}
} | Export-Csv "\\Path\to\CsvFile"
To probe multiple computers for 3 registry properties and output the result in a CSV file, you can use Invoke-Command like below:
$computers = 'pc01','pc02','pc03' # etc. the 20 computers you want to probe
$propertynames = 'property1','property2','property3' # you may use wildcards here
# loop over the computers
$result = foreach ($computer in $computers) {
if (!(Test-Connection -ComputerName $computer -Count 1 -Quiet)) {
Write-Warning "Computer '$computer' is not responding"
continue # skip this computer and proceed with the next
}
Invoke-Command -ComputerName $computer -ScriptBlock {
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
# create a temporary Hashtable to store the items
$hash = [ordered]#{}
# loop over the properties
foreach ($prop in $using:propertynames) {
$entry = Get-ItemProperty -Path $regPath -Name $prop -ErrorAction SilentlyContinue
if ($entry) {
$hash['ComputerName'] = $using:computer
$entry = $entry | Select-Object * -ExcludeProperty PS*
# use a loop in case you have used wildards for the property names
foreach ($item in $entry.PsObject.Properties) {
$hash[$item.Name] = $item.Value
}
}
else {
Write-Warning "Could not find property '$prop'"
}
}
if ($hash.Count) {
# output the hash converted to PSObject
[PsCustomObject]$hash
}
}
}
# remove the properties added by Invoke-Command
$result = $result | Select-Object * -ExcludeProperty PS*,RunspaceId
# output to gridview
$result | Out-GridView
# output to CSV file
$result | Export-Csv -Path 'X:\Path\To\TheResults.csv' -NoTypeInformation
I need a script that terminates all RDP sessions of an AD user.
Only the username should be given, whereupon the script terminates all RDP sessions of this user (if necessary also enforces them).
Unfortunately, the Get-RDUserSession cmdlet does not work (the ConnectionBroker cannot be found).
Unfortunately, I cannot process the result of the CMD command qwinsta in PowerShell.
Any ideas or tips?
Thank you.
You can create custom objects from qwinsta's output, filter them and use rwinsta to kill the session.
Function Get-TSSessions
{
param (
[Parameter(Mandatory = $true, Position = 0 )]
[String]$ComputerName
) # End Parameter Block
qwinsta /server:$ComputerName |
ForEach-Object{
If($_ -notmatch "SESSIONNAME")
{
New-Object -TypeName PSObject -Property `
#{
"ID" = [Int]$_.SubString(41,05).Trim()
"ComputerName" = $Computer
"User" = $_.SubString(19,22).Trim()
"State" = $_.SubString(47,08).Trim()
}
}
}
} # End Function Get-TSSessions
Get-TSSessions -ComputerName <ServerName> |
Where-Object{$_.User -eq "SomeUser"} |
ForEach{ & "rwinsta /Server:$($_.ComputerName) $($_.ID)" }
Obviously, you can improve by wrapping up the rwinsta command in its own function. At the moment I only have reporting work written around this sort of thing, so in the spirit of answering the question without writing the whole thing, this should get you through.
Also, I believe there are a number of scripts and functions available for this on the PowerShell Gallery. In fact, I think there were functions Get/Stop-TerminalSession in the PowerShell Community Extensions, which you can install as a module.
param
(
[Parameter(Mandatory = $false,
HelpMessage = 'Specifies the user name (SamAccountName).',
DontShow = $false)]
[SupportsWildcards()]
[ValidateNotNullOrEmpty()]
[ValidateScript({
Import-Module -Name 'ActiveDirectory' -Force
if (Get-ADUser -Filter "sAMAccountName -eq '$_'") {
return $true
} else {
return $false
}
})]
[string]$Username = $env:USERNAME
)
$ErrorActionPreference = 'SilentlyContinue'
Import-Module -Name 'ActiveDirectory' -Force
foreach ($system in (Get-ADComputer -Filter ("Name -ne '$env:COMPUTERNAME' -and OperatingSystem -like 'Windows Server*'"))) {
[string]$system = $system.Name
$session = ((quser /server:$system | Where-Object {
$_ -match $Username
}) -split ' +')[3]
if ($session) {
logoff $session /server:$system
}
}
Change a value in a winlogbeat.yml as it is passed to serveral remote servers. Here is the value to change > hosts: localhost:5044 and when script kicks off on remote server it is to change to >lp-index-QA.QA.com:9999
Here is the script I wrote.. no failures but does not pass the new value to remote server>>
#ExecutionPolicy
Set-ExecutionPolicy -Force Unrestricted
#DC = (facter datacenter) | Out-String
$DC = 'parpr1'
$QAhost = #("hosts: lp-index-QA.QA.com:9999", "`r`nhosts: localhost:5044")
$PRODhost = #("hosts: lp-index-PROD.PROD.com:9999", "`r`nhosts: localhost:5044")
$file = 'C:\winlogbeat-1.2.3-windows\winlogbeat.yml'
if ($DC -eq "QA")
{
Write-Host "Datacenter is $DC"
Add-Content -PassThru -Path "$file" -Value "hosts: lp-index-QA.QA.com:9999"
}
if ($DC -eq "PROD")
{
Write-Host "Datacenter is $DC"
Add-Content -PassThru -Path "$file" -Value "hosts: lp-index- PROD.PROD.com:9999"
}
# delete service if it already exists
if (Get-Service winlogbeat -ErrorAction SilentlyContinue) {
$service = Get-WmiObject -Class Win32_Service -Filter "name='winlogbeat'"
$service.StopService()
Start-Sleep -s 1
$service.delete()
}
$workdir = Split-Path $MyInvocation.MyCommand.Path
# create new service
New-Service -name winlogbeat `
-displayName winlogbeat `
-binaryPathName "`"$workdir\\winlogbeat.exe`" -c `"$workdir\\winlogbeat.yml`""
#pause 5s
Start-Sleep -s 10
#Startingserver
Start-service winlogbeat