Looking for a Powershell Script to check if Volume Shadow Copy is enabled - powershell

Sorry for asking, new in PowerShell. Looking for a Powershell Script to check if Volume Shadow Copy is enabled.
Couldn't find any useful and functional script.

Where did you look?
There are a number samples of these all over the web.
For example, using the script downloadable from here:
Get Shadow Copy Statistics
If you use Shadow Copies of Shared Folders (Previous Versions), this
script may help you keep on eye on how much history you have, the
average snapshot size, whether you are hitting storage area limits or
the 64 shadow copies per volume limit.
https://gallery.technet.microsoft.com/scriptcenter/Get-Shadow-Copy-Statistics-79e05a57
You can use it's example to get stats of such items. Meaning, if you get any results, then of course it's enabled.
#Query the local machine
.\Get-ShadowCopyStats.ps1 -ServerName .
#Query a remote machine
.\Get-ShadowCopyStats.ps1 -ServerName FS01
#Query multiple remote machines by passing an array
.\Get-ShadowCopyStats.ps1 -ServerName FS01,FS02
#Since it's the first parameter, you don't have to include -ServerName in the command:
.\Get-ShadowCopyStats.ps1 FS01,FS02
#Query multiple remote machines by passing them to the script down the pipeline
"FS01","FS02" | .\Get-ShadowCopyStats.ps1
Get-ADComputer -Filter * -SearchBase "OU=Servers,DC=company,DC=tld" | .\Get-ShadowCopyStats.ps1 -ShowAllVolumes | Tee-Object -Variable ShadowCopyStats
$ShadowCopyStats | Select * | Export-Csv -NoTypeInformation .\ShadowCopyStats.csv
Or this one...
Get Remote Shadow Volume Information With Powershell
Gather the remote shadow volume information for one or more systems
using wmi, alternate credentials, and multiple runspaces. Function
supports custom timeout parameters in case of wmi problems and returns
shadow volume information, shadow copies, their providers, and
settings.
https://gallery.technet.microsoft.com/scriptcenter/Get-Remote-Shadow-Volume-e5a72619
RemoteShadowCopyInformation -ComputerName 'Server2' -Credential $cred).ShadowCopyVolumes

when the shadowcopy is enabled, there will be a scheduled task created
$allTasks = Get-ScheduledTask
foreach ($task in $allTasks) {
if ($task.TaskName.Contains("ShadowCopyVolume")) {
#get volumeid & drive letter which shadowcopy is enabled
$allVolumes = Get-Volume
foreach ($volume in $allVolumes) {
if ($volume.ObjectId.Contains(($task.TaskName.Split("{")[1]).Split("}")[0])) {
write-host ($volume.driveletter + ":\ is enabled")
}
}
}
}

Related

Powershell Get-EventLog from computers.txt and save data

I have some problems getting EventLog and save data. I am able to get my EventLogs but not logs from network computers.
Here is the code I am running:
$logFileName = "Application"
$path = $MyInvocation.MyCommand.Path +"\Output\"
$path = $PSScriptRoot+"\Output\"
new-item $path -ItemType directory
$array = ("System", "Security")
$file = $PSScriptRoot +"\computers.txt"
$users = ForEach ($machine in $(Get-Content $file)) {
$pathMachine = $path+$machine
new-item $pathMachine -ItemType directory
ForEach ($logFileName in $array){
# do not edit
$logFileName
$exportFileName = (get-date -f yyyyMMdd) + "_" + $logFileName + ".evt"
$logFile = Get-WmiObject Win32_NTEventlogFile -ComputerName $machine | Where-Object {$_.logfilename -eq $logFileName}
$logFile
$exportFileName
$pathMachine
$temp = $pathMachine + "\"+ $exportFileName
$temp
$fff = $logFile.BackupEventLog($temp)
}
}
This could e considered a duplicate of this.
Reading event log remotely with Get-EventLog in Powershell
# swapped from this command
get-eventlog -LogName System -computername <ServerName>
# to this
invoke-command {get-eventlog -LogName System} -ComputerName <ServerName>
Don't struggle with writing this from scratch. Well, unless it's a learning exercise. There are pre-built script for you to leverage as is and or tweak as needed.
Running commands on Remote host require using the Invoke cmdlet, and or an established PSRemoting session to that host.
Get Remote Event Logs With Powershell
Gather the remote event log information for one or more systems using wmi, alternate credentials, and multiple runspaces. Function supports custom timeout parameters in case of wmi problems and returns Event Log information for the specified number of past hours.
Download: Get-RemoteEventLogs.ps1
The script is too long (it's 100+ lines) to post here, but here in the Synopsis of it.
Function Get-RemoteEventLogs
{
<#
.SYNOPSIS
Retrieves event logs via WMI in multiple runspaces.
.DESCRIPTION
Retrieves event logs via WMI and, if needed, alternate credentials. This function utilizes multiple runspaces.
.PARAMETER ComputerName
Specifies the target computer or comptuers for data query.
.PARAMETER Hours
Gather event logs from the last number of hourse specified here.
.PARAMETER ThrottleLimit
Specifies the maximum number of systems to inventory simultaneously
.PARAMETER Timeout
Specifies the maximum time in second command can run in background before terminating this thread.
.PARAMETER ShowProgress
Show progress bar information
.EXAMPLE
PS > (Get-RemoteEventLogs).EventLogs
Description
-----------
Lists all of the event logs found on the localhost in the last 24 hours.
.NOTES
Author: Zachary Loeber
Site: http://www.the-little-things.net/
Requires: Powershell 2.0
Version History
1.0.0 - 08/28/2013
- Initial release
#>
Or this one.
PowerShell To Get Event Log of local or Remote Computers in .csv file
This script is handy when you want to extract the eventlog from remote or local machine. It has multiple filters which will help to filter the data. You can filter by logname,event type, source etc. This also have facility to get the data based on date range. You can change th
Download : eventLogFromRemoteSystem.ps1
Again, too big to post here because the length is like the other one.
I am working on some assumptions but maybe this will help.
When I Ran your Code I got
Get-Content : Cannot find path 'C:\computers.txt' because it does not exist.
I had to make the C:\computers.txt file, then I ran your code again and got this error.
Get-Content : Cannot find path 'C:\Output\computers.txt' because it does not exist.
I made that file in that location, then I ran your code again and I got the event log file. Maybe try creating these two missing files with a command like
Get-WmiObject Win32_NTEventlogFile -ComputerName $machine
mkdir C:\Output\$machine
$env:computername | Out-File -FilePath c:\Output\Computers.txt
You may also want to setup a Network share and output to that location so you can access the event logs from a single computer. Once the share is setup and the permissions just drop the unc path in.

Net view - get Just ' Share Name'

I need to get all of the shares name in some storage's.
Im using Net view $StorageName and it's show The result in a Table format :
Share name Type Used as Comment
----------------------------------------------------------------------------
Backups Disk
CallRecordings Disk
Download Disk System default share
home Disk Home
homes Disk System default share
Installs Disk
Justin Disk Copy of files from Justin laptop
michael Disk
Multimedia Disk System default share
Network Recycle Bin 1 Disk [RAID5 Disk Volume: Drive 1 2 3 4]
Public Disk System default share
Qsync Disk Qsync
Recordings Disk System default share
Sales Disk Sales Documents
SalesMechanix Disk
Server2012 Disk Windows Server 2012 Install Media
Usb Disk System default share
VMWareTemplates Disk
Web Disk System default share
The command completed successfully.
Thats good, but I need Just the Share Name.
I need Help please.
Thanke You!
Here is one way you could do it with the net view output:
(net view $StorageName | Where-Object { $_ -match '\sDisk\s' }) -replace '\s\s+', ',' | ForEach-Object{ ($_ -split ',')[0] }
Basically that is saying find the lines that have Disk surrounded by whitespace just in case something else might have Disk in the name. Then replace multiple spaces with a comma. Then, for each of those lines, split again by the comma and take the first value which would be the share name.
If you are on a Windows 8/2012 or newer system (and attempting to enumerate shares on other Windows systems), you could use a CIM session along with Get-SmbShare instead of net view which would return the results as objects and allow you to select the fields you want in the native PowerShell way.
For example:
$cimSession = New-CimSession $StorageName
Get-SmbShare -CimSession $cimSession | Select Name
Name
----
Admin
ADMIN$
C$
IPC$
J$
print$
Public
Software
Another option for parsing the net view output that relies on positioning rather than regular expression matching. personally I feel it's a bit easier to read and just as reliable.
function get-shares {
param($server)
$rawShares = net view \\$server
$shares = $rawShares[7..($s.Count - 3)]
$shares | . {process{$_.substring(0,($_.indexof(" ")))}}
}

Powershell: Re-create RDS Remote Apps by Looping?

I'm stumped. I can usually take the output of one powershell command and use it as the input to another powershell command. For example:
Get-Mailbox | Set-Mailbox -MaxSendSize 40MB
This will loop through every mailbox and then set the maximum send size to 40 MB in Exchange 2007.
...but the same doesn't work with get-rdremoteapp and new-rdremoteapp.
Get-RDRemoteApp | new-rdremoteapp -collectionname APPSNEW -connectionbroker edge-1.mydom.local
The goal of this command is that we are preparing to Migrate from a Windows 2012 RDS environment on virtual servers to a Windows 2012 R2 environment on physical servers.
On the virtual 'edge' server, I should be able to get all the RD Remote Apps, loop through them, and then use the 'new-rdremoteapp' command to create them on the new 'edge-1' server.
What actually happens is the command runs and creates the 1st remote app, then exits without an error. It doesn't process the apps in the list.
I think I need to use foreach-object, but after reading the docs and playing around, I can't seem to get it to work.
I couldn't find an easy out. I had to specify a bunch of parameters like so:
Get-RDRemoteApp | foreach-object -process {new-rdremoteapp -collectionname APPSNEW -connectionbroker edge-1.mydom.local -displayname $_.displayname -filepath $_.filepath -alias $_.alias -commandlinesetting $_.commandlinesetting -usergroups $_.usergroups}
Time to find a job that has more bash scripting... ;)

How to determine storage type (SAN/NAS/local disk) remotely, using PowerShell?

I have to collect the attached storage types of each server in our environment: Several hundreds of W2K3/W2K8 servers.
A script would be very useful to determine if the attached storage is SAN / SAN mirrored / NAS / local or combination of these. The problem is that I haven't really found any good solution.
I was thinking about a script, and the best I could figure out would do something like the following:
If the server uses SAN, Veritas Storage Foundation is always installed, so I would search for it with gwmi win32_product. This is really slow, and this doesn't provide the information if the storage is SAN, or SAN mirrored.
If the attached storage is NAS, there must be an ISCSI target ip, and I would search for that somehow.
I really don't think these methods are acceptable though. Could you please help me find a better way to determine the attached storage types somehow?
Thank you very much
I found an article about accessing the VDS service in powershell. Getting More Information About You Cluster LUN’s
Massaged the code a bit to get type. Works even on 2003.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Storage.Vds") | Out-Null
$oVdsServiceLoader = New-Object Microsoft.Storage.Vds.ServiceLoader
$oVdsService = $oVdsServiceLoader.LoadService($null)
$oVdsService.WaitForServiceReady()
$oVdsService.Reenumerate()
$cDisks = ($oVdsService.Providers |% {$_.Packs}) |% {$_.Disks}
$cPacks = $oVdsService.Providers |% {$_.Packs}
foreach($oPack in $cPacks)
{
If($oPack.Status -eq "Online")
{
foreach($oDisk in $oPack.Disks)
{
Write-Host "$($oDisk.FriendlyName) ( $($oDisk.BusType) )"
}
foreach($oVolume in $oPack.Volumes)
{
Write-Host "`t$($oVolume.AccessPaths) ( $($oVolume.Label) )"
}
}
}
You could probably find the info in one of the following WMI classes:
Win32_LogicalDisk
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394173(v=vs.85).aspx
Win32_Volume
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394515(v=vs.85).aspx
Win32_DiskDrive
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394132(v=vs.85).aspx
Then... do something like:
Get-AdComputer Server* | Foreach-Object { Get-WmiObject -Class Win32_DiskDrive -ComputerName $_.Name }

Powershell Remoting Speeding up a Foreach Loop Hosted Exchange

I have a CSV of email adddresses and Departments that I need to set on Live#edu. The command I currently have looks something like this:
Import-CSV departments.csv | ForEach-Object { Set-User $_.EmailAddress $_.Department }`
The problem is, this operation takes FOREVER.
My first thought is that it would be great to have the ForEach-Object command actually be forwarded over to the remote machine, so that it will only need to create the one pipeline between the two machines, but when I go into the PSSession, there doesn't seem to be any foreach-object available. For reference, How I Import the PSSession is:
Import-PSSession(New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri 'https://ps.outlook.com/powershell' `
-Credential (Get-Credential) `
-Authentication Basic -AllowRedirection)
Is there a better way that I can import the session to allow ForEach-Object to be remote, or to import an aliased version of the remote foreach-object, perhaps as ForEach-Object-Remote, or perhaps does anybody have something better to suggest to streamline this process?
UPDATE:
A Couple Things I've tried:
Using the -AsJob switch on the implicitly remoted command.
Import-CSV departments.csv | ForEach-Object { Set-User $_.EmailAddress $_.Department -AsJob }
This, unfortunately, doesn't work because there are throttling limits in place that don't allow the additional connections. Worse than that, I don't even know that anything went wrong until I check the results, and find that very few of them actually got changed.
Importing the ForEach-Object under a different name.
Turns out that adding a prefix is easy as putting -Prefix RS in the Import-PSSession Command to have things like the ForEach-Object from the Remote Session become ForEach-RSObject in the local session. Unfortunately, this won't work for me, because the server I'm connecting to does not does not have the Microsoft.Powershell ConfigurationName available to me.
UPDATE 2: The Set-User cmdlet seems to be Microsoft provided for Live#edu administration. Its purpose is to set User attributes. It is not a script or cmdlet that I am able to debug. It doesn't take pipeline input, unfortunately, so that would not be able to fix the issue.
As Far as I can tell, the problem is that it has to construct and tear down a pipeline to the remote machine every time this command runs, rather than being able to reuse it. The remote ForEach idea would have allowed me to offload that loop to avoid having to create all those remote pipelines, while the -asJob would have allowed them to all run in parallel. However, it also caused errors to fail silently, and only a few of the records actually get properly updated.
I suspect at this point that I will not be able to speed up this command, but will have to do whatever I can to limit the amount of data that needs to be changed in a particular run by keeping better track of what I have done before (keeping differential snapshots). Makes the job a bit harder.
EDIT: Start-Automate left a very useful help, unfortunately, neither of them work. It is my feeling at this point that I won't find a way to speed this up until my provider gives access to more powershell cmdlets, or the exchange cmdlets are modified to allow multiple pipelines, neither of which I expect to happen any time soon. I am marking his answer as correct, despite the ultimate result that nothing helps significantly. Thanks, Start-Automate.
You can speed up your script and also avoid trying to make two connections to the server by the use of the foreach statement, instead of Foreach-Object.
$departments = #(import-csv .\departments.csv)
foreach ($user in $departments) {
Set-User $user.EmailAddress $user.Department
}
If you need to batch, you could use the for statement, moving forward in each batch
for ($i =0; $i -lt $departments.Count; $i+=3) {
$jobs = #()
$jobs+= Invoke-Command { Set-User $departments[$i].EmailAddress $departments[$i].Department } -AsJob
$jobs+= Invoke-Command { Set-User $departments[$i + 1].EmailAddress $departments[$i + 1].Department } -AsJob
$jobs+= Invoke-Command { Set-User $departments[$i + 2].EmailAddress $departments[$i + 2].Department } -AsJob
$jobs | Wait-job | Receive-job
}
Hope this helps