Starting multiple Windows services if stopped - windows

I've tried the following few bits and i'm trying to create a function to insert into another powershell script
function start-OService{
Get-Service service1|?{$_.Status -eq 'Stopped'}|Start-Service
Get-Service service2|?{$_.Status -eq 'Stopped'}|Start-Service
}
And this one ...
function start-OService {
$services = 'service1', 'service1'
Get-Service | ? {
$services -contains $_.Name -and $_.Status -eq 'Stopped'
} | Start-Service
}
The first snippet doesn't seem to run correctly but i'm not getting an error. I can run each line individually but not the way I have it setup.
The 2nd one was my original attempt that was taken from another SO question. The Get-Service doesn't seem to like the $services variable having multiple services contained.

Try this:
function start-OService {
$services = 'service1', 'service1'
foreach ($service in $services)
{
if ((Get-Service $service).Status -eq "Stopped")
{
Start-Service $service
}
}
}

One liner:
"service1", "service2" | Get-Service | ?{ $_.Status -eq "Stopped" } | Start-Service

For starting all the services which was stopped at a given time, below script will be helpful
$StoppedServices=Get-Service | where {$_.Status -eq "Stopped"}
foreach ($item in $StoppedServices)
{
$Name=$item.Name
Start-Service -Name $Name
}

function start-OService {
$services = 'service1', 'service1'
$services | % {
$service = get-service -name $_;
if($service.Status -eq [System.ServiceProcess.ServiceControllerStatus]::Stopped)
{
Write-Output "Starting $_"
$service.Start()
}
}
}

Related

How to modify Get-ADGroupMember to run for multiple groups from csv, to replace nested groups with members of the said groups

Hi Im trying to write a script to replace nested groups with members of said group. I found one from https://community.spiceworks.com/topic/1816091-ad-powershell-replace-nested-groups-with-members-of-said-group
and modified as follows. Where #Parent_1 is an AD distribution group.
$TargetGroup= '#Parent_1'
ForEach ($Member in Get-ADGroupMember -Identity $TargetGroup) {
if ($Member.objectclass -eq 'group') {
ForEach ($SubMember in Get-ADGroupMember -Identity $Member -Recursive ) {
Add-ADGroupMember -Identity $TargetGroup -Members $SubMember.SamAccountName
}
Remove-ADGroupMember -Identity $TargetGroup -Members $Member -Confirm:$false
}
}
It works perfectly fine for a single group that is "#Parent_1" when used as $TargetGroup.
But I wish to run it more than one for $TargetGroup using a CSV as follows.
Instead of using $TargetGroup= '#Parent_1', I wish to have $TargetGroup =Import-Csv -Path .\xx.csv
With the following CSV.
But it won't run, just by replacing that. It just gives errors.
Did several modifications, yet casting different different errors time to time, could not make it. Not sure we need another for each loop.
Can anyone please help ? Any help would be appreciated.
PS answer for my question | Final working code
foreach($TargetGroup in Import-Csv -Path .\xx.csv)
{
ForEach ($Member in Get-ADGroupMember -Identity $TargetGroup.samaccountname)
{
if ($Member.objectclass -eq 'group')
{
ForEach ($SubMember in Get-ADGroupMember -Identity $Member -Recursive)
{
Add-ADGroupMember -Identity $TargetGroup.samaccountname -Members $SubMember.SamAccountName
}
Remove-ADGroupMember -Identity $TargetGroup.samaccountname -Members $Member -Confirm:$false
}
}
}
You just need to loop one $TargetGroup at a time
foreach($TargetGroup in Import-Csv -Path .\xx.csv)
{
ForEach ($Member in Get-ADGroupMember -Identity $TargetGroup)
{
if ($Member.objectclass -eq 'group')
{
ForEach ($SubMember in Get-ADGroupMember -Identity $Member -Recursive)
{
Add-ADGroupMember -Identity $TargetGroup -Members $SubMember.SamAccountName
}
Remove-ADGroupMember -Identity $TargetGroup -Members $Member -Confirm:$false
}
}
}
#Doug thanks.. $TargetGroup should be $TargetGroup.samaccountname for internal loops in this way.. and its works! perfect.
foreach($TargetGroup in Import-Csv -Path .\xx.csv)
{
ForEach ($Member in Get-ADGroupMember -Identity $TargetGroup.samaccountname)
{
if ($Member.objectclass -eq 'group')
{
ForEach ($SubMember in Get-ADGroupMember -Identity $Member -Recursive)
{
Add-ADGroupMember -Identity $TargetGroup.samaccountname -Members $SubMember.SamAccountName
}
Remove-ADGroupMember -Identity $TargetGroup.samaccountname -Members $Member -Confirm:$false
}
}
}

Get LastWriteTime of a particular file

I'm using Windows 10 Enterprise 1709 and PowerShell ISE v5. I am trying to get the last write time to the file deployment.properties by checking to see if the testpath holds the file and if it does, write the LastWriteTime of that file. I'm not sure I'm doing this the correct way. Any help showing me how to make this work would be appreciated. I've tried several options but this is the only one that doesn't produce an error. However, the code runs, completes without error but doesn't produce and output. My code is listed below first and then the output I see on the PowerShell ISE screen.
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $javauser.FullName $DeplPath
if (Test-Path $folderFile) {
$testResult = Get-ChildItem | select -Property fullName, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
}
$dateTime
Below is the output I get which returns no information.
PS C:\WINDOWS\system32> Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$filelist = Join-Path $User.FullName $file
if (Test-Path $filelist) {
$testResult = Get-ChildItem $dateTime | select -Property fullName, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
}
$dateTime
PS C:\WINDOWS\system32>
Newly modified code below
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $User.FullName $DeplPath
if (Test-Path $folderFile) {
$testResult = Get-ChildItem | select -Property fullName, $DeplPath.LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
[PSCustomObject]#{
"Computer Name" = $env:COMPUTERNAME
"Java User True/False" = $TestResult
"Users" = $user.Name
"Last Write Time" = $testResult.LastWriteTime
}
}
$dateTime
Try this out. Your property select for the get-childitem were mislabeled.
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $User.FullName $DeplPath
$test = Test-Path $folderFile
if ($test -eq $True) {
$testResult = Get-ChildItem $folderfile | select -Property Name, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
[PSCustomObject]#{
"Computer Name" = $env:COMPUTERNAME
"Java User True/False" = $TestResult
"Users" = $user.Name
"Last Write Time" = $testResult.LastWriteTime
}
}
$dateTime

Get the domain name of the user of ADSI object?

In the following script, it will print all the users of the groups. However, the domain name is missing (Some users are in different Windows domain)?
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | ? {
$_.psbase.schemaClassName -eq 'group'
} | % {
$gn = $_.name.ToString()
write-host $gn
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | % {
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
}
Try fetching the SID instead of the name and translate that back to a username:
$computer.psbase.children | ? {
$_.psbase.schemaClassName -eq 'group'
} | % {
$gn = $_.name.ToString()
write-host $gn
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | % {
$bytes = $_.GetType().InvokeMember('objectSid', 'GetProperty', $null, $_, $null)
$sid = New-Object Security.Principal.SecurityIdentifier ($bytes, 0)
$sid.Translate([Security.Principal.NTAccount])
}
}
The result should include the computer or domain name.
We have a similar issue where there are accounts from different domains on the computers and we need the domain back. Unfortunately the SID fetch doesn't work I think for local accounts and the domains the computer used to be joined to in some cases, so it didn't return all results.
This was the best solution I found for us:
Admin = $_.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $_, $null)
will return results like
WinNT://#domain#/#account#
or WinNT://#domain of computer#/#computer-name#/#account#
for local accounts
$servers= get-content 'C:\temp\work\localadmins\serverlist_in.txt'
$output = 'C:\temp\work\localadmins\serverlist_out.csv'
$results = #()
foreach($server in $servers)
{
$admins = #()
$group =[ADSI]"WinNT://$server/Administrators"
$members = #($group.psbase.Invoke("Members"))
$members | foreach {
$obj = new-object psobject -Property #{
Server = $Server
Admin = $_.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $_, $null)
}
$admins += $obj
}
$results += $admins
}
$results | Export-csv $Output -NoTypeInformation

How can I create log for ADD-Adgroupmember results

Simple really, I have a PS script ready to go but I would like to pipe the results of adding 1000 names to an AD security group with Add-ADGroupMember. Problem is ADD-Adgroupmember doesn't return any results. What would be the best way to do this?
You can wrap the call in a try/catch block:
$Group = Get-ADGroup "myGroup"
$Users = "habanagold","habanasilver","mrceo"
foreach($User in $Users){
try {
Add-ADGroupMember -Identity $Group -Members $User -ErrorAction Stop
"$User added to $Group" | Out-File C:\path\to\output.log -Append
} catch {
"Failed to add $User to $Group" | Out-File C:\path\to\output.log -Append
}
}

Users and Local Groups Report using Powershell?

Is there a simple way using powershell to show all Local Windows Groups that are active on a machine and the users that are part of those groups? A second part of this question would be if it can be extended to look at more than one machine at a time.
In fact you can with the ADSI type shortcut and the WinNT moniker. Here's an example to list groups and members from your own machine:
$server="."
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | foreach {
write-host $_.name
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
write-host
}
Powershell does not have any inherent support for such a feature. However it's easy to wrap the "net localgroup" command with a couple of powershell functions and thus enable it in the pipeline.
Get Local Groups
function Get-LocalGroups() {
net localgroup | ?{ $_ -match "^\*.*" } | %{ $_.SubString(1) };
}
Get Local Group members
function Get-LocalGroupMembers() {
param ([string]$groupName = $(throw "Need a name") )
$lines = net localgroup $groupName
$found = $false
for ($i = 0; $i -lt $lines.Length; $i++ ) {
if ( $found ) {
if ( -not $lines[$i].StartsWith("The command completed")) {
$lines[$i]
}
} elseif ( $lines[$i] -match "^----" ) {
$found = $true;
}
}
}
Below is an improved version of Shay Levy's script which works for local groups with "orphaned" accounts which SIDs can't be resolved.
$server = "$env:COMPUTERNAME"
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | foreach {
write-host $_.name
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | foreach {$_."GetType".Invoke().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
write-host
}
Jay Levy's answer turned into a function :)
Function Get-LocalGroupMembers
{
Param(
[string]
$server = "."
)
Try
{
$computer = [ADSI]"WinNT://$( $Server ),computer"
$computer.psbase.children |
where {
$_.psbase.schemaClassName -eq 'group'
} |
ForEach {
$GroupName = $_.Name.ToString()
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") |
foreach {
$memberName = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) -replace "WinNT:", ""
$props = #{
"LocalGroup" = $GroupName
"MemberName" = $memberName
}
$obj = New-Object -TypeName psobject -Property $props
Write-Output $obj
} # foreach members
} # foreach group
}
Catch
{
Throw
}
}
To get the local group members
Get-LocalGroupMembers
To get the local group members for another machine
Get-LocalGroupMembers -Server $Computer

Resources