PowerShell SQL scripting USPs and Users - sql-server

I have put together the below PowerShell script which scripts out all the USPs on a server.
Is there an option to split the output into individual files (instead of saving as one whole/large file)?
Get-ChildItem -Path SQLSERVER:\SQL\myserver\Default\Databases\mydb\StoredProcedures\ | %{$_.script() | out-file -Filepath "myfilelocation.sql"}

Try the following; it should append the procedure name to the file.
Get-ChildItem -Path SQLSERVER:\SQL\myserver\Default\Databases\mydb\StoredProcedures\ |
%{
#Deal with invalid chars in Procedure name i.e. [Customers\Remove]
$SProc = "$($_.name -replace '\\', '_')"
# $Sproc | Out-Host # Uncomment this to check the procedure names...
$_.script() |
out-file -Filepath "myfilelocation_$SProc.sql"
}
This should make the file name unique per database and not have the file over-written each time. That is what is currently happening with your script.

Related

Search multiple text files for string and copy line by appending it to summary_[date].log

I'm trying to search through a number of log files with different filenames. I want search for a hostname in each log and when a match is found have it copy that entire line to summary_[date].log and keep appending matching lines to it. So something I've started with is:
$captured = Get-ChildItem -recurse -Path \\nas1\share1 -Include *.log |
where { ($_.Name | Select-String -pattern ('PC1','PC2','PC3') -SimpleMatch) }
Now copy the line from each log file which contains the pattern and append it to a file with today's date stamp, so each week I'll have a file like \\nas1\share1\summary_03-07-2020.log
But this is not quite what I want as this will capture the filenames and append them to the $captured variable. It's also missing the code to copy any matching lines to a date stamped summary_[date].log
Each text file will contain, among other lines that start with a time stamp, something like this:
03-07-2020_14-36-17 - Backup of computer [PC1] is successfully
created.
So what I want is to search several text files on a share for several hostnames. If a text file contains the hostname have it append the line which contains the hostname to summary_[date].log. Lastly, since the matching lines will all start with a date/time stamp I need to keep the contents of summary_[date].log file sorted from newest date to oldest.
Essentially I should end up with a summary_[date].log every week that will look similar to this:
03-07-2020_14-36-17 - Backup of computer [PC1] is successfully created.
03-07-2020_13-21-12 - Backup of computer [PC3] is successfully created.
03-07-2020_11-36-29 - Backup of computer [PC2] is successfully created.
By doing this I get a summary of all log files from that day in a single file which I will then automatically email to a specific email address.
How do I accomplish this?
Your current code selects a string from the file name, not the content.
To do what you are after, you can use simething like this:
$logFolder = '\\nas1\share1'
$outFile = Join-Path -Path $logFolder -ChildPath ('summary_{0:dd-MM-yyyy}.log' -f (Get-Date))
$captured = Get-ChildItem -Recurse -Path $logFolder -Include *.log | ForEach-Object {
($_ | Select-String -Pattern 'PC1','PC2','PC3' -SimpleMatch).Line
} | Sort-Object # sorting is optional of course
#output on screen
$captured
# output to new log file
$captured | Set-Content -Path $outFile
Next send this file as attachment like:
# use splatting for cmdlets that take a lot of parameters
$params = #{
SmtpServer = 'yourmailserver'
From = 'logtester#yourcompany.com'
To = 'someone#yourcompany.com'
Subject = 'Summary'
Body = 'Hi, in the attachment a summary of the backup logs'
Attachments = $outFile
# etc.
}
Send-Mailmessage #params
How big are your log files?
This will work but it loads the entire content of all files into memory and maybe inefficient with large file and/or a large number of files.
If there is a large number of files or large files you could do some nested foreach loops and loop through each computer name for each file.
This also uses match rather than like in where-object, you can use. like if you get false positives.
$FileContent = Get-Content -Path "\\nas1\share1\*.log"
$ComputerArray = 'PC1','PC2','PC3'
$DateStamp = get-date -Format dd-MM-yyyy
$OutFile = 'summary_' + $DateStamp + '.log'
foreach ($ComputerName in $ComputerArray)
{
$FileContent | Where {$_ -match $ComputerName} | Add-Content -Path $OutFile
}

PowerShell SQL Server Cannot Find Path

I have 2x mini scripts which are fairly similar.
The first backs up our SQL Jobs and runs fine:
Import-Module "SQLPS" Get-ChildItem -Path SQLSERVER:\SQL\MYSERVERNAME\Default\JobServer\Jobs\ | %{$_.script()} | out-file -Filepath "MYFILEPATH_$(get-date -f yyyyMMdd).sql"
The second is meant to back up our SQL Stored Procedures, and does not produce results in the output file:
Import-Module "SQLPS" Get-ChildItem -Path SQLSERVER:\SQL\MYSERVERNAME\Default\Databases\MYDBNAME\StoredProcedures\ | %{$_.script()} | out-file -Filepath "MYFILEPATH_$(get-date -f yyyyMMdd).sql"
This problematic second script gives the below error:
Get-ChildItem : Cannot find path 'SQLSERVER:\SQL\MYSERVERNAME\Default\Databases\MYDBNAME\StoredProcedures\' because it does not exist.
It used to run successfully until around the time I upgraded to Windows10. Any suggestions on how to correct this second script?

Search a literal in a zip file

I have a folder with oracle bi publisher reports
Folder/Usage Trend Report.xdmz
Folder/Usage Summary Report.xdmz
Folder/Charge Trend Report.xdmz
Folder/Consolidation Reports.xdmz
Folder/Charge Summary Report.xdmz
Each report is like zip file and contains some files
_datamodel.xdm
~metadata.meta
security.xml
I want to make a batch file, searches all the _datamodel.xdm file in order to find a literal (eg INVOICE_NBR or invoice_nbr)
The output will be something like
Report Name Literal Usages
Consolidation Reports.xdmz INVOICE_NBR 1
Is there anyone to help me do it ?
Thanks
In the future, please show what you've tried to solve the problem on your own, and where you're getting stuck. For this time, I found the challenge interesting, so I whipped up a beginning for you. It's a Batch + PowerShell hybrid script. Save it with a .bat extension and salt to taste. Be advised that the regexp object that performs a count of strings uses case-sensitive matching; so "INVOICE_NBR" would not increment the count when searching for "invoice_nbr".
<# : batch portion
#echo off & setlocal
set "outerfile=*.xdmz"
set "innerfile=_datamodel.xdm"
set "search=invoice_nbr"
rem // re-launch self with PowerShell interpreter
powershell "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell hybrid chimera #>
add-type -as System.IO.Compression.FileSystem
# // encapsulate loop into a collection for select | format-table
&{ foreach ($archive in (gci $env:outerfile)) {
# // create a temporary directory within %temp%
$tempdir = New-Item -path $env:temp -name ([Guid]::NewGuid()) -type dir
[IO.Compression.ZipFile]::ExtractToDirectory($archive, $tempdir)
# // For each innerfile found within the zip archive...
gci -path $tempdir -filter $env:innerfile -recurse | %{
new-object PSObject -property #{
"Report Name" = $archive.Name
"Usages" = ([regex]::Matches((gc $_.FullName | out-string), $env:search)).count
"Literal" = $env:search
}
}
Remove-Item $tempdir -recurse -force
} } | select "Report Name",Literal,Usages | format-table -auto
Example output:
Report Name Literal Usages
----------- ------- ------
Usage Summary Report.xdmz invoice_nbr 2
Usage Trend Report.xdmz invoice_nbr 2
If you want case-insensitive matching, add the following as a third argument to the [regex]::Matches() function:
[Text.RegularExpressions.RegexOptions]::IgnoreCase

Output overwrites previous entry in file

If I get rid of the last line Out-File "HDDresults.txt" then the output shows on the screen in the correct format, just a long list of all the computers and their serial numbers. If I try to output to a file, each computer entry overwrites the previous entry, so when the script finishes executing there is only the last entry in the file. How do I get the file output to look exactly like the console output?
I don't know how to script. I just copied and pasted from multiple sources until I got something that works.
Import-Module ActiveDirectory
Get-ADComputer -filter * | Foreach-Object {
Get-WmiObject Win32_PhysicalMedia -computer $_.name |
Format-Table __server, Tag, SerialNumber |
Out-File "HDDresults.txt"
}
You simply need to set the -Append flag:
Out-File "HDDresults.txt" -Append
By default, Out-File overwrites the content of the file for each write operation. This will cause it to add text to the end of the file instead.
While adding the -Append argument makes the script function, I think a better fix to this is to move the Select statement and all that follows it outside of the ForEach loop so that the file is written once with all of the information once it is processed, and not having to open the file, write to it, close it, open it again, write to it, close it again, for each system.
Import-Module ActiveDirectory
Get-ADComputer -filter * |
Foreach-Object { Get-WmiObject Win32_PhysicalMedia -computer $_.name } |
Format-Table __server, Tag, SerialNumber |
Out-File "HDDresults.txt"

Read entries from text file into a variable in PowerShell

I hope someone can help me. I am pretty new to PowerShell and can't really script it myself with the exception of looking at existing code and modifying it.
I have found a PowerShell script that reports file share permissions for a specific share and recurses through the subfolders returning their permissions as well.
My problem is I need to do this with a lot of shares so would like to be able to provide the script with a text file containing the share names. I know I need to do a for each loop and read the names of the shares in a text file into an array but I don't know how to do this. I guess it's pretty simple for someone with more experience.
This is the script i have used with single entry.
http://mywinsysadm.wordpress.com/2011/08/17/powershell-reporting-ntfs-permissions-of-windows-file-shares/
#Set variables
$path = Read-Host "Enter the path you wish to check"
$filename = Read-Host "Enter Output File Name"
$date = Get-Date
#Place Headers on out-put file
$list = "Permissions for directories in: $Path"
$list | format-table | Out-File "C:\scripts\$filename"
$datelist = "Report Run Time: $date"
$datelist | format-table | Out-File -append "C:\scripts\$filename"
$spacelist = " "
$spacelist | format-table | Out-File -append "C:\scripts\$filename"
#Populate Folders & Files Array
[Array] $files = Get-ChildItem -path $path -force -recurse
#Process data in array
ForEach ($file in [Array] $files)
{
#Convert Powershell Provider Folder Path to standard folder path
$PSPath = (Convert-Path $file.pspath)
$list = ("Path: $PSPath")
$list | format-table | Out-File -append "C:\scripts\$filename"
Get-Acl -path $PSPath | Format-List -property AccessToString | Out-File -append "C:\scripts\$filename"
} #end ForEach
Sorry for the noob question. I plan to learn more when I have a bit more time but any help now would be massively appreciated.
Thanks in advance.
If you have a share name on each line within your text file can put all the shares into an array like this:
$path = "C:\ShareNames.txt"
$shareArray = gc $path
To access the first share you can use this syntax:
$shareArray[0]

Resources