Saving Active Directory Configuration settings to a file - powershell

I'm using my machine to run a script on the Domain Controller server using Enter-PSSession. It all works except, I can't save the outputs from the script on my local machine.
I want to save the outputs from the script as objects in my local machine in a csv format (Not on the Domain Controller server).
What I'm trying to do is save results from running commands like Get-ADDomainController etc..
Can someone please help me with this?

As for this …
I can't save the outputs from the script on my local machine.
… sure you can. Just create a log file as part of your session and copy that file back to your workstation for review, or just use the *-Transcript cmdlets to that creates a file automatically that you can copy over. The transcript will record everything that happens in the sessions.
Get-Command -Name '*transcript*' | ft -a
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Start-Transcript 3.0.0.0 Microsoft.PowerShell.Host
Cmdlet Stop-Transcript 3.0.0.0 Microsoft.PowerShell.Host
# get function / cmdlet details
(Get-Command -Name Start-Transcript).Parameters
Get-help -Name Start-Transcript -Full
Get-help -Name Start-Transcript -Online
Get-help -Name Start-Transcript -Examples
Or, don't use the interactive Enter-PSSession (explicit PowerShell Remoting) that puts you directly on the DC. Use a Implicit PSRemoting session, using New-PSSession and proxy the AD cmdlets to your machine for use.
$SessionAD = New-PSSession -ComputerName ''dc01.contoso.com
Invoke-Command $SessionAD -Command {Import-Module ActiveDirectory}
Import-PSSession $SessionAD -Module ActiveDirectory | Out-Null
$ADUSers = Get-ADuser -Filter *
$var = $ADUSers | Select-Object -Property Name, SamaccountName | Out-GridView -OutputMode Single
$GroupsMember = Get-ADUser -Filter ('Name -eq "' + $var.Name + '"') -Property MemberOf |
Select -ExpandProperty MemberOf |
Get-ADGroup -Property MemberOf |
Select Name
$GroupsMember
Get-PSSession | Remove-PSSession
Then you can run ADDS cmdlets as if they are actually on your machine and results are on your machine, or if you are on Window 8 or higher, just download and install (Win 7 - 8) / enable the RSAT tools (Win 10) directly and use them.
Remoting the Implicit Way
PowerShell Implicit Remoting: Never Install a Module Again
Also, take a look and Invoke-Command for running command locally or remotely.

Related

Use PowerShell to install Windows Updates in vSphere

I have a cluster of vSphere windows clients approximately 100 that I want to remotely automate windows updates on weekly. I have listed all the windows machine out in text file on my desktop. I have run the PSWindowsUpdate module on my local windows10 machine with command:
Install-Module -Name PSWindowsUpdate and then executed the below script successful for my local machine to run windows updates.
#Import-Module PSWindowsUpdate
#Remove-Item -Path C:\Scripts\status.tx
#Start-Transcript -Path C:\Scripts\status.txt
#$Updates = "Critical Updates", "Security Updates"
#Get-WUInstall -AcceptALL- Verbose -IgnoreReboot -Category $Updates
#Write-Host "Done"
#Stop-Transcript
#Start-Sleep -s 120
#Restart-Computer -Force -Confirm:$false
-- after pc restarts run as PS As Administrator
#Get-WindowsUpdate
However, I am not a expert at PowerShell so, I do not know what to additionally script to accomplish the task of remotely updating 100 or so windows clients in vSphere.
Any suggestion would be appreciated.
You can try with the invoke-command. You can create a server list from a DC:
$Servers = Get-ADObject -Filter * -Properties Name,OperatingSystem | Where-Object OperatingSystem -like '*Server*'
And use this list with a loop like this
ForEach($_ in $Servers)
{
Invoke-Command -ScriptBlock {Get-WUInstall -AcceptALL- Verbose -IgnoreReboot -Category $Updates } -ComputerName $_.Name -ErrorAction SilentlyContinue
}

Getting list of specific attributes for all Hyper-V VMs on Windows Server

Let's start off on the right foot. I'm not looking for someone to write the script discussed below for us. What I'd like is a pointer or pointers that can quickly get me up to speed on just the PowerShell parts I need in order to accomplish this task without first becoming an expert in PowerShell and then in use of Get-VM. That said, please read on.
We are attempting to do a virtual machine inventory on several VM hosts in a network of computers. To that end, we would like to write a script that writes a .CSV file containing the host name, and specific attributes for each VM defined on that host. So, for example:
HostName, VMName, ComputerName, ID, Maximum memory, Minimum meomry, ...
VMH1, VM1, DATACENTER1, 54324ebe-f167-..., 1099511627776, 536870912, ...
and so on, for each VM under this host... and we'd run the command on each of our hosts to get the inventory into files we could merge for an enterprise view.
Where I need help, is with PowerShell scripting. I'm highly skilled with KornShell and many other scripting languages, but I've avoided PS all these years. Now the piper is at my door.
Trying to understand how to tie these two things together:
I can get a list of VMs with the
Get-VM | ft Name
Given a VM, I can get the details I want with
Get-VM <vmname> |
Select-Object Name, etc...
I believe I'd need to pipe the command into the command, but that's not working for me. And then once that's done, need to manipulate the output so that %COMPUTERNAME% is at the front of the output, so a simple Export-Csv won't work for us either.
Again, I don't want this to be a "here's my homework - do it for me" entry; just looking for pointers.
THanks for your time.
All of what you are after are in the examples in the PowerShell Help Files for that cmdlet.
# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-VM).Parameters
(Get-Command -Name Get-VM).Parameters.Keys
Get-help -Name Get-VM -Examples
# Results
<#
Get-VM -ComputerName Server1 |
Where-Object {$_.State -eq 'Running'}
Get-ClusterGroup |
Where {$PSItem.GroupType -eq 'VirtualMachine' } |
Get-VM
#>
Get-help -Name Get-VM -Full
Get-help -Name Get-VM -Online
As for your code in the comment section, this ...
Get-VM |
ForEach-Object Get-VM |
Select-Object *
and/or this ...
Get-VM |
ft Name|
ForEach-Object Get-VM |
Select-Object *
... both are syntactically wrong. If you use the PowerShell_ISE or VSCode editor they would immediately flag these as errors. If you are prone to staying in the console host, then use the Invoke-ScriptAnalyzer cmdlet to check your code and Trace-Command to see all it is doing. See the help file for details.
(Get-Command -Name Invoke-ScriptAnalyzer).Parameters
(Get-Command -Name Invoke-ScriptAnalyzer).Parameters.Keys
Get-help -Name Invoke-ScriptAnalyzer -Examples
Get-help -Name Invoke-ScriptAnalyzer -Full
Get-help -Name Invoke-ScriptAnalyzer -Online
(Get-Command -Name Trace-Command).Parameters
(Get-Command -Name Trace-Command).Parameters.Keys
Get-help -Name Trace-Command -Examples
Get-help -Name Trace-Command -Full
Get-help -Name Trace-Command -Online
Thus should be this
Get-VM |
ForEach-Object {
$PSItem |
Select-Object -Property '*'
}
Never do '*' for all properties, unless that is what you really want. Always select only what you need.
To see all the properties of on the first VM, just to this
(Get-VM)[0] |
Select-Object -Property '*'
To see all the properties of all the VM's, just remove the [0].
You easily leverage the Out-GtidView cmdlet for selecting VM and viewing details.
(Get-VM)[0] |
Select-Object -Property '*' |
Out-GridView -Title 'Showing Virtual Machines'
see:
https://mcpmag.com/articles/2016/02/17/creating-a-gui-using-out-gridview.aspx
https://spiderzebra.com/2020/05/26/utilizing-powershell-out-gridview-as-a-gui-alternative
https://mikefrobbins.com/2014/09/11/creating-a-simplistic-gui-interface-with-out-gridview
Lastly, you are also saying, you want a list of VMHosts, that you are then trying to get the VM Guest off those hosts. That is not what Get-VM is for.
If your VMHosts are Windows Servers, joined to your domain, you'd use Get-ADComputer to get a list of VMHost names (however you have them named), then pass that to Get-VM to get the guests.
Example:
Get-ADComputer -Identity 'VMHost*' |
ForEach-Object {Get-VM -ComputerName $PSitem}
If they are not windows machines, use your chosen method to get that hostname, then pass that to Get-VM.
Doing this on my local Hyper-V machine
$env:COMPUTERNAME, 'Localhost' |
ForEach {
Get-VM -ComputerName $PSItem |
Select-Object -Property Name, State, Status, Version
}
# Results
<#
Name State Status Version
---- ----- ------ -------
WS2K16 Off Operating normally 9.0
...
#>
$env:COMPUTERNAME, 'Localhost' |
ForEach-Object {
$VMHostName = $PSItem
Get-VM -ComputerName $VMHostName |
Select-Object -Property #{
Name = 'VMHost'
Expression = {$VMHostName }
}, Name, State, Status, Version |
Export-Csv -Path 'D:\Temp\VMGuestReport.Csv' -Append
}
Import-Csv -Path 'D:\Temp\VMGuestReport.Csv' |
Format-Table -AutoSize
# Results
<#
VMHost Name State Status Version
------ ---- ----- ------ -------
SRV1 WS2K16 Off Operating normally 9.0
...
Localhost WS2K16 Off Operating normally 9.0
...
#>

Exporting mailadressen to CSV

I want our Marketing deparment to extract all mailadressen from our users to CSV.
I created and Constrained Endpoint by using a configuration file, but i keep getting errors
First i created the config file:
New-PSSessionConfigurationFile -Path 'c:\marketing.pssc' -SessionType 'RestrictedRemoteServer' -LanguageMode FullLanguage -ModulesToImport ActiveDirectory -VisibleCmdlets ('Get-ADUser', 'Get-ADGroupMember', 'Export-Csv', 'Select-Object')
Register-PSSessionConfiguration –Name ‘Marketing’ -ShowSecurityDescriptorUI –Path ‘c:\marketing.pssc’
Im trying to run this code:
Set-ExecutionPolicy remotesigned -Scope Process -Force
$session = New-PSSession -ComputerName name -ConfigurationName 'marketing'
Invoke-Command -Session $session -Scriptblock {
Get-ADGroupMember -Identity "groupname" -Recursive | Get-ADUser -Properties Mail | where {$_.mail -ne $null} | Select Name,Mail | Export-CSV -Path "\\somepathto\file.csv" -NoTypeInformation
}
Remove-PSSession $session
i Expect an CSV file with name and email adressen.
The script works when running as a domain admin, currently i get this error:
The term 'where.exe' is not recognized as the name of a cmdlet, function, script file, or operable program....
According to the get-aduser commandlet, you should provide at least a required input param. Currently, it is stating the one you provide(-properties) is not approved by the validateset of the input param set.
https://learn.microsoft.com/en-us/powershell/module/addsadministration/get-aduser?view=win10-ps
This will help you out:
Get-ADUser -LDAPFilter '(mail=*marketing)' | select-object Name,Mail
https://ss64.com/ps/get-aduser.html

How do I check in PowerShell if a service has read access to a certain folder?

So far, I know to do the following:
Determine the service logon account - (Get-WmiObject -Query "SELECT StartName FROM win32_service where name = 'mssqlserver'").StartName
Get accounts that have read access to the folder - accesschk -q -d $env:TEMP
But this leads me nowhere:
PS C:\> (Get-WmiObject -Query "SELECT StartName FROM win32_service where name = 'mssqlserver'").StartName
LocalSystem
PS C:\> accesschk -q -d $env:TEMP
c:\Users\MKHARI~1\AppData\Local\Temp
RW NT AUTHORITY\SYSTEM
RW BUILTIN\Administrators
RW DAYFORCE\mkharitonov
PS C:\> accesschk LocalSystem -q -d $env:TEMP
Accesschk v5.2 - Reports effective permissions for securable objects
Copyright (C) 2006-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
Error looking up account: LocalSystem:
The operation completed successfully.
PS C:\> accesschk "DAYFORCE\mkharitonov" -q -d $env:TEMP
RW c:\Users\MKHARI~1\AppData\Local\Temp
PS C:\>
The AccessChk does not seem to recognize LocalSystem. Also, if I run it with an account belonging to the BUILTIN\Administrators, it does not seem to acknowledge the access.
Does it mean AccessChk is not suitable for this or am I using it wrong? Is there a way to do it at all without actually trying to access the folder under the account in question?
When PowerShell is running not as administrator:
PS C:\> $service = Get-WmiObject -EnableAllPrivileges Win32_Service | Where-Object {$_.Name -eq "MSSQLSERVER"}
PS C:\> '{0:x}' -f $service.GetSecurityDescriptor().ReturnValue
80070522
PS C:\>
Which corresponds to A required privilege is not held by the client. The command works OK when the PowerShell is running as administrator. Ideally, I would like a solution that does not require elevation.
localsystem uses the token of nt authority\System, so this command line will work (you will need to map the localsystem to system in code):
accesschk.exe system -q -d $env:temp
I have created a snippet to fetch the proper name and pass it to accesschk (tested in PowerShell v5 and requires elevated access):
$service = Get-WmiObject -EnableAllPrivileges Win32_Service | Where-Object {$_.Name -eq "wlidsvc"}
$desc = (($service.GetSecurityDescriptor()).Descriptor).owner
$desc.Domain + "\"+$desc.name | %{.\accesschk.exe $_ -q -d $env:temp}
$desc.Domain + "\"+$desc.name will return NT AUTHORITY\SYSTEM instead of localsystem
PS: The script can be optimized
$account = 'whatever you like'
$acl = Get-Acl 'folder'
$acl.access | where { $_.IdentityReference -like "*$account*"}).FileSystemRights
I am not sure this will work with PowerShell v.2, but it will work for PowerShell v.3 and later.

powershell Get-Process with ComputerName is missing Path

I want to get a list of processes under specific folder on some remote machine and kill them. However, if I add -ComputerName, Get-Process does not return Path as desired, thus I cannot Where with Path. Is there a way to Get-Process / Stop-Process on remote machine under a specific path?
// Paths are filled
PS C:\> Get-Process | Format-Table Name, Path
Name Path
---- ----
firefox C:\Program Files (x86)\Mozilla Firefox\firefox.exe
// Paths are empty
PS C:\> Get-Process -ComputerName localhost | Format-Table Name, Path
Name Path
---- ----
firefox
You could use Invoke-Command if Remoting is enabled on the remote server, and perform your action in the scriptblock of the command:
Invoke-Command -ComputerName remoteComputer -Script { param($pathFilter) Get-Process | ?{$_.Path -like $pathFilter} | Format-Table Name, Path } -Args "somefilter*"
I had a similar case that I resolved by using x64 version of powershell.