powershell & sqlplus script in for loop - powershell

So I am quite new to powershell and I have a Oracle sql scipt I want to run inside a powershell loop
Function to read a text file to read a list of servers.
$oracleServers = "C:\Temp\oracle-servers.txt"
function Database-Servers
{
$servers = Get-Content $oracleServers
Return($servers.Trim())
}
Next I read from that list what Oracle Services are running
function Installed-Databases
$svr = $args[0]
$runningDBs = " "
$runningDBs = Get-Service -Name "OracleService*" -ComputerName $svr |
Select-Object -ExpandProperty name | Out-String | % {$_.replace("OracleService","")}
Return($runningDBs)
function ConnectString
{
$CString = " " #$args[0]
foreach ($server in Database-Servers)
{
$runningDBs = Installed-Databases $server
$rdblist = $runningDBs -split '[\n]'
foreach ( $rdb in $rdblist)
{
if(!$rdb -eq " ")
{
$CString = ' system/$rdb#$server$tnsalias$rdb'
&sqlplus $CString $scriptsql | out-file $outputfile
Write-Host $CString
Return($CString)
}
}
}
}

Related

Timestamp of finished Powershell task

I have a basic script, which will shutdown Windows services and generate a report about their shutdown processes. I also want to include two more columns into my output variable ($table), which will be timestamp values i.e. when shutdown tasks were launched and when they finished. I have no idea how to implement this into my report.
$processlist = #('SQLTELEMETRY$TESTDB', 'MSSQL$TESTDB', 'SQLWRITER')
$get = ''
$table = #{ }
$failed = 0
foreach ($proc in $processlist) {
stop-service -name $proc -force
}
#start-sleep -s 120
foreach ($proc in $processlist) {
$get = get-service $proc -Erroraction ignore
if ($get.Status -eq 'Running') {
$table += #{$proc = 'Running' }
}
else {
$table += #{$proc = 'Stopped' }
}
}
foreach ($value in $table.GetEnumerator()) {
if ($value.Value -eq 'Running') {
$failed += 1
}
}
if ($failed -gt 0) {
$err = 'FAILED'
}
else {
$err = 'SUCCESS'
}
$table.GetEnumerator() | Select-Object -Property Name, Value | export-csv appreport.csv -delimiter ";" -force -notypeinformation
(HTML part here...)
Instead of adding stuff into a Hashtable, I think it would be a lot easier to build an array of objects and write that as CSV file.
Something like this:
$serviceList = 'SQLTELEMETRY$TESTDB', 'MSSQL$TESTDB', 'SQLWRITER'
$maxAttempts = 10
# $result will become an array of PsCustomObjects you can easily pipe to Export-Csv
$result = foreach ($service in $serviceList) {
$shutStart = Get-Date
$svc = Get-Service -Name $service -ErrorAction SilentlyContinue
if ($svc) {
for ($attempt = 0; $attempt -lt $maxAttempts; $attempt++) {
$shutResult = 'Failed'
Start-Sleep -Milliseconds 100
$svc | Stop-Service -Force -ErrorAction SilentlyContinue
# test if the service has stopped. If so exit the loop
if (($svc | Get-Service).Status -eq 'Stopped') {
$shutResult = 'Success'
break
}
}
[PsCustomObject]#{
'ServiceName' = $svc.Name
'ServiceDisplayName' = $svc.DisplayName
'ShutDownStart' = $shutStart
'ShutDownEnd' = Get-Date
'Result' = $shutResult
}
}
else {
[PsCustomObject]#{
'ServiceName' = $service
'ServiceDisplayName' = ''
'ShutDownStart' = $shutStart
'ShutDownEnd' = Get-Date
'Result' = "Failed: Service '$service' could not be found."
}
}
}
# output on screen
$result
# output to CSV
$result | Export-Csv 'D:\appreport.csv' -Delimiter ";" -Force -NoTypeInformation
The output on screen will look like this:
ServiceName : SQLTELEMETRY$TESTDB
ServiceDisplayName :
ShutDownStart : 22-8-2019 16:47:40
ShutDownEnd : 22-8-2019 16:47:40
Result : Failed: Service 'SQLTELEMETRY$TESTDB' could not be found.
ServiceName : MSSQL$TESTDB
ServiceDisplayName :
ShutDownStart : 22-8-2019 16:47:40
ShutDownEnd : 22-8-2019 16:47:40
Result : Failed: Service 'MSSQL$TESTDB' could not be found.
ServiceName : SQLWRITER
ServiceDisplayName : SQL Server VSS Writer
ShutDownStart : 22-8-2019 16:47:38
ShutDownEnd : 22-8-2019 16:47:39
Result : Success
Hope that helps
I don't really know when you want to capture the time stamp for the services, but I suggest you take advantage of the below property and add it in the loop where you think its suitable.
(Get-Process -Name $proc).StartTime
Also you can use the below properties :
UserProcessorTime
TotalProcessTime
ExitTime
I hope this will help you to capture to time.

run and handle output from ps1 script

The goal : get all logged in / logged out users from the system.
Those users who logged in / logged out by using remote desktop connection.
My script :
Param(
[array]$ServersToQuery = (hostname),
[datetime]$StartTime = "January 1, 1970"
)
foreach ($Server in $ServersToQuery) {
$LogFilter = #{
LogName = 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'
ID = 21, 23, 24, 25
StartTime = $StartTime
}
$AllEntries = Get-WinEvent -FilterHashtable $LogFilter -ComputerName $Server
$AllEntries | Foreach {
$entry = [xml]$_.ToXml()
[array]$Output += New-Object PSObject -Property #{
TimeCreated = $_.TimeCreated
User = $entry.Event.UserData.EventXML.User
IPAddress = $entry.Event.UserData.EventXML.Address
EventID = $entry.Event.System.EventID
ServerName = $Server
}
}
}
$FilteredOutput += $Output | Select TimeCreated, User, ServerName, IPAddress, #{Name='Action';Expression={
if ($_.EventID -eq '21'){"logon"}
if ($_.EventID -eq '22'){"Shell start"}
if ($_.EventID -eq '23'){"logoff"}
if ($_.EventID -eq '24'){"disconnected"}
if ($_.EventID -eq '25'){"reconnection"}
}
}
$Date = (Get-Date -Format s) -replace ":", "."
$FilePath = "$env:USERPROFILE\Desktop\$Date`_RDP_Report.csv"
$FilteredOutput | Sort TimeCreated | Export-Csv $FilePath -NoTypeInformation
Write-host "Writing File: $FilePath" -ForegroundColor Cyan
Write-host "Done!" -ForegroundColor Cyan
#End
I really do not understand ps1 scripts. I've found this script but i want to use it for my purposes.
When i try to execute it with c# :
Scenario 1 :
string scriptText = "C:\\MyPath\\script.ps1";
try
{
Runspace runspace = RunspaceFactory.CreateRunspace();
// open it
runspace.Open();
// create a pipeline and feed it the script text
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
Collection<PSObject> results = pipeline.Invoke();
It throws an error :
ps1 is not digitally signed.
Second scenario :
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript(str_Path);
Collection<PSObject> PSOutput = PowerShellInstance.Invoke();
if (PowerShellInstance.Streams.Error.Count > 0)
{
// error records were written to the error stream.
// do something with the items found.
}
}
Streams are always empty. Actually it always count 0 rows.
Any idea/suggestion how to get this done ?
I used Write-Output instead of Write-Host into the end of the script without generating csv file. Credits to this.

Powershell workflow/parallel citrix sessions

Edit - I should preface this by saying I'm very new to powershell. This is one of the first "complicated" scripts i've tried to write.
I'm trying to use workflow/parallel to run a script against two lists simultaneously. after I get it working, the goal will be to add multiple lists, to cut down on the time it takes to process each one.
The script by itself works great. Adding the workflow returns nothing. :/
$Global:ctxsession = Read-Host -Prompt 'Input the Username'
$serverlist1 = get-content .\serverlist1.txt
$serverlist2 = get-content .\serverlist2.txt
function citrixlist {
#([string]$Servers)
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$servers
)
foreach ($server in $servers) {
#ping first
if (Test-Connection -count 1 -computer $server -quiet) {
#temporary write-host to see where it hangs (might leave in permanently)
Write-Host $server
#check for sessions
$sessions = qwinsta /server $server| ?{ $_ -notmatch '^ SESSIONNAME' } | %{
#separating into objects
$item = "" | Select "Active", "SessionName", "Username", "Id", "State", "Type", "Device"
$item.Active = $_.Substring(0,1) -match '>'
$item.SessionName = $_.Substring(1,18).Trim()
$item.Username = $_.Substring(19,20).Trim()
$item.Id = $_.Substring(39,9).Trim()
$item.State = $_.Substring(48,8).Trim()
$item.Type = $_.Substring(56,12).Trim()
$item.Device = $_.Substring(68).Trim()
$item
}
foreach ($session in $sessions){
#match for session name entered
if ($session.Username -match $ctxsession){
Write-Host 'Found' $session.Username 'on' $server 'with Session ID' $session.Id $session.State
#Kill session with ID and Server, with verbose switch
#rwinsta $session.Id /server:$server /v
}
}
}
}
}
workflow get-citrixlist1 {
citrixlist -servers $serverlist1
}
workflow get-citrixlist2 {
citrixlist -servers $serverlist2
}
workflow get-citrixkill {
parallel {
get-citrixlist1
get-citrixlist2
}
}

Citrix Application list with assigned groups

The following script gives me the list I want but I need to save the output to a file:
asnp citrix*
$apps = Get-BrokerApplication -MaxRecordCount 10000 -AdminAddress khonemdc75ddc01;
$apps | ForEach-Object {
$array = $_.AssociatedDesktopGroupUids
foreach ($element in $array) {
$policy = Get-BrokerAccessPolicyRule –DesktopGroupUid $element -AllowedConnections NotViaAG
write-host "Application: " $_.ApplicationName
if ($_.AssociatedUserNames)
{
write-host "Users configured using Visibility:" $_.AssociatedUserNames
write-host '--------------------'
}
else
{
write-host "Users with access inherited from DG:"
$policy.IncludedUsers;
write-host '--------------------'
}
}
}
If you use the Write-Hostcmdlet, you won't be able to pipe the output to a file - just write the string to the pipeline. To save the output, you can use the Out-File cmdlet:
asnp citrix*
$apps = Get-BrokerApplication -MaxRecordCount 10000 -AdminAddress khonemdc75ddc01;
$apps | ForEach-Object {
$array = $_.AssociatedDesktopGroupUids
foreach ($element in $array) {
$policy = Get-BrokerAccessPolicyRule –DesktopGroupUid $element -AllowedConnections NotViaAG
"Application: $_.ApplicationName"
if ($_.AssociatedUserNames)
{
"Users configured using Visibility: $_.AssociatedUserNames"
'--------------------'
}
else
{
"Users with access inherited from DG: $policy.IncludedUsers;"
'--------------------'
}
}
} | Out-File -FilePath 'your_file.txt'
Use write-ouput instead out write-host and at the end just pipe it at the end > c:\test.txt

sql failed jobs export to csv with powershell

I am battling with a PowerShell script that captures all SQL Failed jobs for the past day and exports it to .CSV
Please view code below.
param (
#[string]$serverInstance = '03RNB-VSQLPRD4\SQLPRD04
)
begin {
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
}
process {
try {
Write-Verbose "List failed SQL Server jobs using SMO..."
$serverInstance = Get-Content "C:\MountSpaceCollector\SQLJobFailures\servers2.txt";
$server = new-object Microsoft.SqlServer.Management.Smo.server $serverInstance
$results = #()
$reasons = #()
$jobs = $server.jobserver.jobs | where-object {$_.isenabled}
# Process all SQL Agent Jobs looking for failed jobs based on the last run outcome
foreach ($job in $jobs) {
[int]$outcome = 0
[string]$reason = ""
# Did the job fail completely?
if ($job.LastRunOutcome -eq "Failed") {
$outcome++
$reasons += "Job failed: " + $job.name + " Result: " + $job.LastRunOutcome
# Did any of the steps fail?
foreach ($jobStep in $job.jobsteps) {
if ($jobStep.LastRunOutcome -ne "Succeeded") {
$outcome++
$reasons += "Step failed: " + $jobStep.name + " Result: " + $jobStep.LastRunOutcome
}
}
}
if ($outcome -gt 0) {
$jobFailure = New-Object -TypeName PSObject -Property #{
Name = $job.name
LastRunDate = $job.lastrundate
LastRunOutcome = $reasons
}
$results += $jobFailure
}
}
Write-Output $results | Export-CSV -Path 'C:\MountSpaceCollector\SQLJobFailures\SQLJobFailures.csv' -Delimiter '|'
}
catch [Exception] {
Write-Error $Error[0]
$err = $_.Exception
while ( $err.InnerException ) {
$err = $err.InnerException
Write-Output $err.Message
Write-Output $results
}
}
}
But It Exports all except the last field (LastRunOutcome). It only displays "System.Object[]"?
Can anyone please assist with this as I do not know what I am doing wrong?
It's because $Reasons is an object, more specifically an array. You need to format the reasons differently, as a string for instance, to be able to have it appear in the CSV normally.
Perhaps you meant to use the string $Reason that you declare, but don't use?