I can't get this code to work:
Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach- Object {Get-ItemProperty $.pspath} |
Where-Object { $.DisplayName -Eq 'Microsoft Lync 2013'} | Select-Object DisplayVersion
What am i doing wrong?
This one works fine, both of them are in regedit, I am aware that this example is not en wow6432node, could that be the problem?
Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $.pspath} |
Where-Object { $.DisplayName -Eq 'Microsoft Security Client'} | Select-Object DisplayVersion
You had several syntax errors. In such cases, I try to resolve the one-liner into multiple steps and write a .ps1 file to spot the error(s). Copy this into a file of your choice:
$a = Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall
$b = $a | ForEach-Object { Get-ItemProperty $_.pspath}
$c = $b | Where-Object { $_.DisplayName -Eq 'Microsoft Lync 2013'}
$d = $c | Select-Object DisplayVersion
write-host `$d.length $d.length
write-host content of `$d
$d
write-host
write-host intermediate results were:
write-host `$c.length $c.length
write-host `$b.length $b.length
write-host `$a.length $a.length
pause
I get no results left after step $c in my case, because I do not have Microsoft Lync 2013 installed:
PS> .\test.ps1
$d.length 0
content of $d
intermediate results were:
$c.length 0
$b.length 976
$a.length 992
Drücken Sie die Eingabetaste, um den Vorgang fortzusetzen...:
Related
This script that iam working on used to work perfectly fine, but now the part that should give the ports of the running services isnt giving me an output for some reason and as iam pretty new to powershell i cant figure out why?
#Laufende Dienste
$Service = Get-Service | where{$_.Status -eq "Running"}
Write-Host "Laufende Services:" -ForegroundColor Red
foreach($x in $Service){
Write-Host $x.ServiceName
}
# Standard Dienste importen
$csvfile = Import-CSV -Path "K:\Example\Example.csv"
Foreach ($x in $csvfile) {
Write-Host $x.Name
}
#Vergleichen der Liste und laufenden Dienst
Compare-Object -ReferenceObject (get-service|where{$_.Status -eq "Running"}).servicename -DifferenceObject (import-csv K:\Example\Example.csv ).name -IncludeEqual
Write-Host "Nur in Laufenden Diensten(<=) | In Laufenden Diensten und der Liste(=) | Nur in der Liste(=>)(WICHTIG) " -ForegroundColor Green
#Ports finden
Get-CimInstance Win32_Service -Filter "State='Running'" | ForEach {
$service = $_
# TCP first
Get-NetTCPConnection -OwningProcess $_.ProcessId -ErrorAction SilentlyContinue |
Select #{l="ServiceName";e={$service.Name}}, LocalPort}
I have 2 scripts as follows that gets websites for IIS.
IIS 6 -
$website = Get-WmiObject -Class IIsWebServerSetting -Namespace "root\microsoftiisv2" | Select ServerComment | Format-Table -HideTableHeaders | out-file c:\website.txt
$b = Get-Content -Path C:\website.txt
$b | ForEach {$_.TrimEnd()} | ? {$_.trim() -ne '' } > C:\website.txt
$b = Get-Content -Path C:\website.txt
#(ForEach ($a in $b) {$a.Replace(' ', '')}) > C:\website.txt
Get-Content C:\website.txt
IIS 7+
Import-Module webadministration
$a = Get-Website | Select-Object Name
$a | ForEach-Object {
$_.name = $_.name.replace(" ","")
}
$a | Format-Table -HideTableHeaders | Out-File $DeviceDrive\Apps\NetprobeNT\Auto-monitor\Website.txt
$b = Get-Content -Path $DeviceDrive\Apps\NetprobeNT\Auto-monitor\Website.txt
$b | ForEach {$_.TrimEnd()} | ? {$_.trim() -ne '' } > $DeviceDrive\Apps\NetprobeNT\Auto-monitor\Website.txt
$b = Get-Content -Path $DeviceDrive\Apps\NetprobeNT\Auto-monitor\Website.txt
#(ForEach ($a in $b) {$a.Replace(' ', '')}) > $DeviceDrive\Apps\NetprobeNT\Auto-monitor\Website.txt
I have a different script for IIS 6 (Windows 2003 hosts) because webadministration module is not available for II6.
I need to add an if statement that will add logic to run the correct code dependent on the host operating system and if W3SVC service (World Wide Web Publishing Service) is present (running or stopped). Something along the lines
IF W3SVC is present
Check host operating system
IF operating system = Windows 2003
Run II6 code
Else
Run II7+ code
I don't know where to begin with this script. PowerShell and scripting is new to me and this is part of my first script I am creating. Any help will be greatly appreciated.
I can get the host operating system but confused on how I would put logic into it to get the results I need.
(Get-WmiObject Win32_OperatingSystem).Name
Use Caption rather than Name. Other than that you simply plug the routine into your pseudocode:
if ((Get-WmiObject Win32_OperatingSystem).Caption -eq 'Windows 2003') {
# Run II6 code
} else {
# Run II7+ code
}
For the service you can use the Get-Service cmdlet:
if (Get-Service -Name w3svc -ErrorAction SilentlyContinue) {
...
}
or Get-WmiObject on the Win32_Service class if the Get-Service cmdlet isn't available in PowerShell v2 (not sure about that):
if (Get-WmiObject Win32_Service -Filter "Name='w3svc'") {
...
}
I have a problem with this code. It prints "x86 operating system", even though the write-host, $OSArchitecture, states the architecture is 64-bit.
$OSArchitecture = (Get-WmiObject -Class Win32_OperatingSystem | Select-Object OSArchitecture -ErrorAction Stop).OSArchitecture
write-host = $OSArchitecture
if ($OSArchitecture -eq '*64*')
{
Write-Host "x64 operating system"
$Version = Get-ChildItem hklm:\software\wow6432node\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath} | Where-Object {
$_.DisplayName -Eq 'Microsoft Lync 2013'} | Select-Object DisplayVersion
}
else
{
Write-Host "x86 operating system"
$Version = Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath} | Where-Object {
$_.DisplayName -Eq 'Microsoft Lync 2013'} | Select-Object DisplayVersion
}
Update:
I get this error: Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Int32".
On x64 system [Environment]::Is64BitOperatingSystem gives $true. Therefore, you could do this:
if ([Environment]::Is64BitOperatingSystem)
{
Write-Host "x64 operating system"
$Version = Get-ChildItem hklm:\software\wow6432node\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath} | Where-Object {
$_.DisplayName -Eq 'Microsoft Lync 2013'} | Select-Object DisplayVersion
}
else
{
Write-Host "x86 operating system"
$Version = Get-ChildItem hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object {Get-ItemProperty $_.pspath} | Where-Object {
$_.DisplayName -Eq 'Microsoft Lync 2013'} | Select-Object DisplayVersion
}
Corrected code.
$OSArchitecture=Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop | Select-Object -ExpandProperty OSArchitecture
if ($OSArchitecture -eq "64-bit") {
Write-Output "x64 operating system"
$Path="HKLM:\software\wow6432node\microsoft\windows\currentversion\uninstall"
}
else {
Write-Output "x86 operating system"
$Path="HKLM:\software\microsoft\windows\currentversion\uninstall"
}
$Version=Get-ChildItem -Path "HKLM:\software\wow6432node\microsoft\windows\currentversion\uninstall" | ForEach-Object { Get-ItemProperty $_.pspath } | Where-Object { $_.DisplayName -eq 'Microsoft Lync 2013'} | Select-Object -ExpandProperty DisplayVersion
You can use this for this job
if ([System.IntPtr]::Size -eq 4) { "32-bit" } else { "64-bit" }
or change in your code
if ($OSArchitecture -match '64')
I'm trying to find the next available computer name in out domain. Our computers use a naming format
departmentName001
departmentName003
departmentName004
...
departmentName999
I can find the existing computer accounts and add 1 but I can't work out for to get it to start looking at 001, I'm aware of the use of "{0:d3}" -f but I'm not using it correctly. Can anyone help?
function GetComputerList($ComputerName)
{
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = “LDAP://dc=domain,dc=local”
$objSearcher.Filter = ("(&(objectCategory=computer)(name=$ComputerName))")
$colProplist = "name"
$objSearcher.PageSize = 1000
foreach ($i in $colPropList){[void]$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{$objComputer = $objResult.Properties; $objComputer.name}
}
$HostName = Finance
$unit="{0:d3}" -f $_
$num = GetComputerList("$HostName*") | Foreach {[int]($_.Name)} | Sort-Object | Select-Object -Last 1
$name = $HostName+($unit+($num+1))
Try this, it gets all computer with name starting with 'departmentName', strips all a-z characters, leaving just the numbers, converts the numbers to integers and sorting them to find the largest one:
$searcher = [ADSISearcher]'(&(objectCategory=computer)(name=departmentName*))'
$searcher.PageSize = 1000
$last = $searcher.FindAll() | Foreach-Object { [int]($_.Properties.name -replace '\D').Trim() } | Sort-Object | Select-Object -Last 1
$digitLength = "$last".Length
$NewComputerName = "{0}{1:D$digitLength}" -f 'departmentName',($last+1)
$NewComputerName
EDIT:
# get next available number in a range of numbers. returns 5 for 1,2,3,4,6,7,9
$number = $searcher.FindAll() | Foreach-Object { [int]($_.Properties.name -replace '\D').Trim() } | Sort-Object
for($i=0; $i -lt $number.length; $i++) {if( $number[$i+1]-$number[$i] -gt 1) {$number[$i]+1; break} }
try this:
$searcher = [ADSISearcher]'(&(objectCategory=computer)(name=Finance*))'
$searcher.PageSize = 1000
$last = $searcher.FindAll() | Foreach-Object {
[string]($_.Properties.name -replace '\D') } | Sort-Object
$i = 0
$last | % { if ($i -ne [int]$_ ) { $new = $i.tostring().padleft(3,'0'); break }
else
{ $i++ }}
$newComputerName = "finance" + $new
based on the information in this post I have made a few changes and tweaks to the code for my environment to check more than just AD.. and also fixed it not filling in blanks at the start of a range.. I have blogged it here: AutoGeneratingServer Names
copy of the code here too, and I know it can be refactored lots!
[CmdletBinding()]
param()
# ********************************************************
$startOfName = "xxxYYYZZWEB"
# ********************************************************
# VMWare Details
$ADVIServers = #("vsphere1.blah.local","vsphere2.blah.local","vsphere3.blah.local","vsphere4.blah.local")
$StandAloneHosts = #()
# DNS Details
$DNSServer = "xxxxxx.blah.local"
# SCCM 2012 Details
$SCCM2012SiteServer = "sccm2012.blah.local"
$SCCM2012SiteCode = 'SiteCode'
# SCCM 2007 Details
$SCCM2007SiteServer = "sccm2007.blah.local"
$SCCM2007SiteCode = 'SiteCode2'
# SCOM 2007 Details
$SCOMServer = "scom.blah.local"
# Create Empty Arrays
$VMNumbers = #()
$ADnumbers = #()
$DNSNumbers = #()
$SCCM2012Numbers = #()
$SCCM2007Numbers = #()
$SCOM2007Numbers = #()
# VMWare
Write-Verbose "Processing VMware"
Add-PSSnapin vmware.vimautomation.core -ErrorAction SilentlyContinue
# Set options for certificates and connecting to multiple enviroments
$null = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$False
$null = Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope User -Confirm:$False
# Connect to each AD Authenticated viServer
foreach ($VIServer in $ADVIServers){$null = Connect-VIServer $VIServer -verbose:$false}
# Connect to standalone host
foreach ($Host in $StandAloneHosts){$null = Connect-VIServer $Host -User 'usernamehere' -Password 'passwordhere' -verbose:$false}
# get next available number in a range of numbers.
$VMNames = Get-VM -Name "$($startOfName)*" -verbose:$false |select Name
$VMNames |select Name | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
$VMNumbers = $VMNames |select Name | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
Write-Verbose "$($VMNumbers.Count) Matching entries found"
# Active Directory
Write-Verbose "Processing Active Directory"
# Issue Query
$searcher = [ADSISearcher]"(&(objectCategory=computer)(name=$($StartOfName)*))"
$searcher.PageSize = 1000
# get next available number in a range of numbers. returns 5 for 1,2,3,4,6,7,9 From AD
$ADNames = $searcher.FindAll() | Foreach-Object {[string]$_.Properties.name} | Sort-Object
$ADNames | Foreach-Object {Write-Verbose $_} | Sort-Object
$ADnumbers = $ADNames | Foreach-Object {[int]($_ -replace '\D').Trim() } | Sort-Object
Write-Verbose "$($ADnumbers.Count) Matching entries found"
# Search DNS
Write-Verbose "Processing DNS"
# Import DNS module
Import-Module dnsShell -Verbose:$false
$DNSNames = get-dnsRecord -server $DNSServer -RecordType A -Zone blah.local | select Name |where {$_.Name -like "$($startOfName)*"}
$DNSNames | Foreach-Object {Write-Verbose $_.Name} | Sort-Object -Unique
$DNSNumbers = $DNSNames | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object -Unique
Write-Verbose "$($DNSNumbers.Count) Matching entries found"
# Search SCCM
Write-Verbose "Processing SCCM 2012"
# Query SCCM2012 Env
$SCCM2012Members = Get-WmiObject -ComputerName $SCCM2012SiteServer -Namespace "ROOT\SMS\site_$SCCM2012SiteCode" -Query "SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID='SMS00001' AND Name LIKE '$($startOfName)%' order by name" | select Name -Unique
$SCCM2012Members |select Name | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
$SCCM2012Numbers = $SCCM2012Members |select Name | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
Write-Verbose "$($SCCM2012Numbers.Count) Matching entries found"
Write-Verbose "Processing SCCM 2007"
# Query SCCM2007 Env
$SCCM2007Names = Get-WMIObject -ComputerName $SCCM2007SiteServer -Namespace "root\sms\site_$SCCM2007SiteCode" -class "SMS_R_System" -filter "Name LIKE `"$startOfName%`"" |select Name | Sort-Object -Property Name -Unique
$SCCM2007Names |select Name | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
$SCCM2007Numbers = $SCCM2007Names |select Name | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
Write-Verbose "$($SCCM2007Numbers.Count) Matching entries found"
# Search Production SCOM 2007
Write-Verbose "Processing SCOM 2007"
#Initialize SCOM SnapIn
Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client -ErrorAction SilentlyContinue -verbose:$false
#Connect to Production SCOM 2007 Env.
$null = New-ManagementGroupConnection -ConnectionString $SCOMServer
#Connect to SCOM Provider
Push-Location 'OperationsManagerMonitoring::'
# Get Agents Matching Name
$SCOM2007Names = Get-ManagementServer |Get-Agent |Where {$_.Name -like "$($startOfName)*"}
$SCOM2007Names | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
$SCOM2007Numbers = $SCOM2007Names | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
Write-Verbose "$($SCOM2007Numbers.Count) Matching entries found"
# Return to previous location
Pop-Location
# Merge arrays adding a zero so we allways start issuing numbers from the beginning (ie 001)
$list = #(0) + $VMNumbers + $ADnumbers + $DNSNumbers + $SCCM2012Numbers + $SCCM2007Numbers + $SCOM2007Numbers
# Remove Duplicates numbers from the array and sort into numerical order
$list = $list | Sort-Object -Unique
Write-Verbose "Used numbers after sorting: $($list)"
# Determine if next server name is a gap in the sequence in the array
for($i=0; $i -lt $list.length; $i++) {
if( $list[$i+1]-$list[$i] -gt 1) {
# The gap between the current server number and the next element in the array is greater than 1
# So we have an available number we can use.
# TODO: - Add support for consecutive numbers IE build 6 servers with consecutive numbers.
$num = "{0:000}" -f ($list[$i]+1)
break
}
}
# If no gap found in the sequence then use the next number from the sequence in the array
if ($num -eq $null) {
$num = "{0:000}" -f (($list[-1]+1))
}
# Construct new name
$NewComputerName = "{0}{1}" -f $startOfName,$num
# Create DNS Record to 'reserve / mark the name as in use'
Write-Verbose "Creating DNS Reservation"
New-DnsRecord -Name $NewComputerName -IPAddress "127.0.0.1" -Zone blah.local -Type A -Server $DNSServer
write-output $NewComputerName
How do I properly use $_ in out-file? Here's my code:
get-content computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach { Get-Hotfix -computername $_ } |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
I'm trying to execute a get-hotfix for all the computers listed in the text file then I want them to be exported to CSV with the computer name as the filename.
You need one pipeline to process the computers.txt files, and a nested one inside the foreach to process the list of hotfixes for each computer:
get-content .\computers.txt |
Where {$_ -AND (Test-Connection $_ -Quiet)} |
foreach {
Get-Hotfix -computername $_ |
Select CSName,Description,HotFixID,InstalledBy,InstalledOn |
convertto-csv | out-file "C:\$_.csv"
}
Edit: Changed computers.txt to .\computers.txt, as this is required for local paths in powershell
i can see with this:
get-content .\computers.txt | Where {$_ -AND (Test-Connection $_ -Quiet)} | foreach{ Get-Hotfix -id KB4012212 -computername $_ | Select CSName,Description,HotFixID,InstalledBy,InstalledOn | convertto-csv | out-file "C:\$_.csv" }
i can see only in which PC is the fix (KB4012212) installed.
it's possible to see the following
CSNAME Fix(Inst/NotInst)
PC1 FIxInstalled
PC2 FixNotinstalled
PC3 FixnotInstalled
..
..
etc
I monkeyed with this for a while and nothing I found on-line worked until I used this combo.
I used the method is this thread but it was SO slow and I wanted to learn more about using jobs so this is what ended up working for me on Windows 7 PS Ver 4.
All other options were either too slow or did not return data from the remote system.
$VMs = get-content C:\WinVms.txt #Generate your hostnames list however you deem best.
foreach ($vm in $vms)
{
Write-Host "Attempting to get hotfixes on:" $vm
invoke-command -computername $vm -ScriptBlock {start-job -scriptblock {(get-hotfix | sort installedon)[-1]} | wait-job | receive-job} -AsJob
}
start-sleep 60 # give it a minute to complete
get-job | ? { $_.state -eq "Completed"} | receive-job -keep | export-csv c:\temp\win-patch.csv
you can check your failures too like this:
get-job | ? { $_.state -eq "Failed"}