why is no data being returned in my PowerShell script - oracle

add-type -AssemblyName System.Data.OracleClient
$username = "SYSTEM"
$password = "password"
$data_source = "production"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
try{
$statement = "SELECT SYSDATE FROM DUAL"
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
$con.Open()
$cmd = $con.CreateCommand()
$cmd.CommandText = $statement
$result = $cmd.ExecuteReader()
# Do something with the results...
Write-Host $result + "data"
If($result.HasRows) {
try {
while ($result.Read())
{
"[0] : " + $result.GetValue(0)
}
}
catch
{
#log error
}
finally
{
$con.Close()
}
}
} catch {
Write-Error (“Database Exception: {0}`n{1}” -f `
$con.ConnectionString, $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) { $con.close() }
}
I am executing SELECT SYSDATE FROM DUAL
I am expecting 21-MAY-19
However no data is returned. (no error is presented either)

As mentioned in the above comments, you've to send the content of $result to PowerShells output stream. The output stream is used to realize the pipeline feature of Powershell. If you wrap your code in e.g. "myCode.ps1" and invoke it via:
.\myCode.ps1
The content of $result is pushed in the output stream (pipeline). Since no other cmdlet is attached to the call of myCode.ps1 the Powershell host (= your command line) will receive the content. The default behavior of the host is to dump the content.
So add the following to your code:
$result = $cmd.ExecuteReader()
# Return $result to the pipeline
$result
Read more about pipelines here and more about streams here.
UPDATE1: This link describes more or less the code sample of the question. Maybe the Orcale .NET data provider is missing. Add it via:
Add-Type -Path "PathToDll\Oracle.ManagedDataAccess.dll"
Hope that helps.

Related

File does not exist (but it's there) and Multiple ambiguous overloads found for "AddPicture" and the argument count: "2"

I'm trying to add an image to an excel worksheet with powershell 5. and VSCode.
I get these errors:
C:\CC_SnapViews\EndToEnd_view\path is correct\file.bmp
does not exist (but it's there)
Multiple ambiguous overloads found for "AddPicture" and the argument
count: "2"
When I search the internet, this error isn't coming up in the search. I was following these examples:
addPicture
addPicture github
This is my code:
$xlsx = $result | Export-Excel -Path $outFilePath -WorksheetName $errCode -Autosize -AutoFilter -FreezeTopRow -BoldTopRow -PassThru # -ClearSheet can't ClearSheet every time or it clears previous data ###left off
$ws = $xlsx.Workbook.Worksheets[$errCode]
for ($row = 2 ;( $row -le $tempRowCount ); $row++)
{
#Write-Host $($ws.Dimension.Rows)
#Write-Host $($row)
$ws.Row($row).Height
$ws.Row($row).Height = 150
$ws.Row($row)[3]
$result.GetValue($row) #$ws.Row($row)[3]
$pictureName=$result[$row].PictureID
$pictureNamePath=$result[$row].ImageFileName
#place the image in spreadsheet
#https://github.com/dfinke/ImportExcel/issues/1041 https://github.com/dfinke/ImportExcel/issues/993
$drawingName = "$($pictureName)_Col3_$($row)" #Name_ColumnIndex_RowIndex
#Write-Host $image
Write-Host $drawingName
####
if($null -ne $pictureNamePath)
{
$image = Get-Image -imageFileName $pictureNamePath ###error pictureNamePath does not exist but it does
}
else
{
Write-Host "Did not find an image file for $pictureName in $pictureNamePath"
}
$picture = $ws.Drawings.AddPicture($pictureNamePath,$image) ###error message here
}
Any ideas why powershell thinks the image file doesn't exist?
Update:
I added some debug in the foreach for the rows:
for ($row = 2 ;( $row -le $tempRowCount ); $row++)
{
#Write-Host $($ws.Dimension.Rows)
#Write-Host $($row)
$ws.Row($row).Height
$ws.Row($row).Height = 150
$ws.Row($row)[3]
$result.GetValue($row) #prints entire row info
$pictureName=$result[$row].PictureID
$pictureNamePath=$result[$row].ImageFileName
if(Test-Path $pictureNamePath)
{
Write-Host "$($pictureNamePath) exists" ##prints ...filenamepath... exists (looks good)
}
Write-Host "pic path = $pictureNamePath" ##prints pic path = ..file name path... (looks good)
...
Update2:
Adding the Get-Image function:
Function Get-Image{
[cmdletbinding()]
Param ([string]$imageFileName)
Process
{
#find image file name to look for
if($imageFileName.Exists) #if($imageFile2.Exists)
{
[System.Drawing.Image] $image = [System.Drawing.Image]::FromFile($imageFileName) #may not need this step
#need to figure out which is correct if there's multiple images
return $image
}
else {
Write-Host "$($imageFileName) does not exist"
return $null
}
} #end Process
}# End of Function
I changed my function to use Test-Path instead and it sets the image now.
Function Get-Image{
[cmdletbinding()]
Param ([string]$imageFileName)
Process
{
#find image file name to look for
if(Test-Path $imageFileName) ###instead of Exists
{
[System.Drawing.Image] $image = [System.Drawing.Image]::FromFile($imageFileName) #may not need this step
#need to figure out which is correct if there's multiple images
return $image
}
else {
Write-Host "$($imageFileName) does not exist"
return $null
}
} #end Process
}# End of Function

PowerShell Scipt for adding new Credentials

I'm trying to make script to automaticly assign credidentials based on the group that was chose. I'm getting a lot of syntax errors. Can you help?
Function Add-OSCCredential
{
$target = Read-Host "Group number"
If($target)
{
If($target -eq 1)
{[string]$result = cmdkey /add:Group1 /user:Group1 /pass:Pass1}
[ElseIf($target -eq 2)
{[string]$result = cmdkey /add:Group2 /user:Group2 /pass:Pass2}]
{
[ElseIf($target -eq 3)
{[string]$result = cmdkey /add:Group3 /user:Group3 /pass:Pass3}]
{
If($result -match "The command line parameters are incorrect")
{Write-Error "Failed to add Windows Credential to Windows vault."}
ElseIf($result -match "CMDKEY: Credential added successfully")
{Write-Host "Credential added successfully."}
}
Else
{
Write-Error "Internet(network address) or username can not be empty,please try again."
Add-OSCCredential
}
}
Add-OSCCredential
I'd suggest you use a proper editor such as vscode which will give you lots of hints concerning bad syntax.
In your case there are a lot of [] and {} parenthesis that do not make sense.
Only considering the syntax of that function, the following should 'work':
Function Add-OSCCredential {
$target = Read-Host "Group number"
If ($target) {
If ($target -eq 1) {
[string]$result = cmdkey /add:Group1 /user:Group1 /pass:Pass1
}
ElseIf ($target -eq 2) {
[string]$result = cmdkey /add:Group2 /user:Group2 /pass:Pass2
}
ElseIf ($target -eq 3) {
[string]$result = cmdkey /add:Group3 /user:Group3 /pass:Pass3
}
If ($result -match "The command line parameters are incorrect") {
Write-Error "Failed to add Windows Credential to Windows vault."
}
ElseIf ($result -match "CMDKEY: Credential added successfully") {
Write-Host "Credential added successfully."
}
}
Else {
Write-Error "Internet(network address) or username can not be empty,please try again."
Add-OSCCredential
}
}
edit:
you'd most likely want to look into a ready-to-use PowerShell Module such as CredentialManager, this way you wouldn't have to fiddle with cmdkey.exe yourself.
The returned value for Read-Host is always a string, but you treat it like an integer in your tests.
For better readability, I suggest using a switch rather that yet another set of if..elseif..else statements.
Something like this:
function Add-OSCCredential {
$target = Read-Host "Enter Group number (1-3)"
if ($target -match '1|2|3') {
switch ([int]$target) {
1 {[string]$result = cmdkey /add:Group1 /user:Group1 /pass:Pass1}
2 {[string]$result = cmdkey /add:Group2 /user:Group2 /pass:Pass2}
3 {[string]$result = cmdkey /add:Group3 /user:Group3 /pass:Pass3}
}
if($result -match "The command line parameters are incorrect") {
Write-Error "Failed to add Windows Credential to Windows vault."
}
elseif ($result -match "Credential added successfully") {
Write-Host "Credential added successfully."
}
else {
Write-Warning $result
}
}
else {
Write-Warning "Group number must be either 1, 2 or 3. Please try again."
Add-OSCCredential
}
}
Add-OSCCredential

Powershell Connection to Oracle Database

I'm having trouble connecting to an Oracle database from Powershell using the Oracle.ManagedDataAccess.dll.
I followed this tutorial on Technet and ended up with this code:
add-type -path "C:\oracle\product\12.1.0\client_1\ODP.NET\managed\common\Oracle.ManagedDataAccess.dll"
$username = "XXXX"
$password = "XXXX"
$data_source = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX)(PORT=XXXX))(CONNECT_DATA = (SERVER=dedicated)(SERVICE_NAME=XXXX)))"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
try{
$con = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($connection_string)
$con.Open()
} catch {
Write-Error (“Can’t open connection: {0}`n{1}” -f `
$con.ConnectionString, $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) { $con.close() }
}
Unfortunately I'm getting this error:
C:\Users\XXXX\Desktop\oracle_test.ps1 : Can’t open connection: User Id=XXXX;Password=XXXX;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX)(PORT=XXXX))(CONNECT_DATA =
(SERVER=dedicated)(SERVICE_NAME=XXXX)))
System.Management.Automation.MethodInvocationException: Exception calling "Open" with "0" argument(s): "The type initializer for 'Oracle.ManagedDataAccess.Types.TimeStamp' threw an exception." --->
System.TypeInitializationException: The type initializer for 'Oracle.ManagedDataAccess.Types.TimeStamp' threw an exception. ---> System.Runtime.Serialization.SerializationException: Unable to find assembly
'Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=XXXX'.
at OracleInternal.Common.OracleTimeZone.GetInstance()
at Oracle.ManagedDataAccess.Types.TimeStamp..cctor()
--- End of inner exception stack trace ---
at OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, String instanceName)
at OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
at OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
at OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword)
at Oracle.ManagedDataAccess.Client.OracleConnection.Open()
at CallSite.Target(Closure , CallSite , Object )
--- End of inner exception stack trace ---
at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,oracle_test.ps1
I have checked, that the connection string is correct (it works for tnsping)
The Username and password are correct as well
I replaced anything that shouldn't be disclosed with XXXX
The database version is: Oracle Database 12c Release 12.1.0.1.0
The error is the same for the 32-Bit and 64-Bit Powershell instances
Before the first run the Oracle.ManagedDataAccess.dll isn't loaded, after the run it stays loaded until I close that shell
Unfortunately I'm neither an Oracle nor a Powershell Expert (I prefer MySQL and Python), therefore I would really appreciate any ideas and/or insights you might have.
Im not sure if this is technically a solution - I'd classify it more as a workaround, but it worked for me.
After doing some more research I found a suitable alternative to the Oracle.ManagedDataAccess.dll. I found the System.Data.OracleClient class of the .Net Framework. (It requires an installed Oracle Client, which the machine fortunately has)
Here's an outline of the solution that worked for me:
add-type -AssemblyName System.Data.OracleClient
$username = "XXXX"
$password = "XXXX"
$data_source = "XXXX"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
$statement = "select level, level + 1 as Test from dual CONNECT BY LEVEL <= 10"
try{
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
$con.Open()
$cmd = $con.CreateCommand()
$cmd.CommandText = $statement
$result = $cmd.ExecuteReader()
# Do something with the results...
} catch {
Write-Error (“Database Exception: {0}`n{1}” -f `
$con.ConnectionString, $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) { $con.close() }
}
Use the server:port/service syntax.
$dataSource="server.network:1522/service1.x.y.z"
Here is my (Powershell, but you can adapt to C#) code to do this with ODP.NET managed data access.... which I load directly using the Powershell Add-Type but in C# would be a using/reference...
create a connection, using the connection builder class to ensure the resulting connection string is exactly as desired. Of course you can simplify but this is self-documenting:
function New - OracleConnection { <
#
.SYNOPSIS# generate a well - formed connection string with individual properties
Create and open a new Oracle connection using optional connectionstring argument
.DESCRIPTION
Create and open a new Oracle connection using optional connectionstring argument
.EXAMPLE
New - OracleConnection
New - OracleConnect - connectionString "My well-formed Oracle connections string"
.NOTES
Connection is opened here by
default# > #Add - Type - Path ".\Oracle.ManagedDataAccess.dll" [OutputType([Oracle.ManagedDataAccess.Client.OracleConnection])]
Param(
[Parameter(Mandatory = $false)]
[string] $theConnectionString, [Parameter(Mandatory = $false)]
[string] $openOnCreate = "1"#
means true - open the connection...
)[Oracle.ManagedDataAccess.Client.OracleConnection] $con = New - Object - TypeName Oracle.ManagedDataAccess.Client.OracleConnection;
if ([string]::IsNullOrEmpty($theConnectionString)) {#
$dataSource = "*********:1521/******;"
$conStringBuilder = New - Object Oracle.ManagedDataAccess.Client.OracleConnectionStringBuilder;
$conStringBuilder["Data Source"] = $dataSource;
$conStringBuilder["User ID"] = "*******";
$conStringBuilder["Password"] = "*******";
$conStringBuilder["Persist Security Info"] = $True;
$conStringBuilder["Connection Lifetime"] = 180;
$conStringBuilder["Connection Timeout"] = 10;
$conStringBuilder["Pooling"] = $true;
$conStringBuilder["Min Pool Size"] = 10;
$conStringBuilder["Max Pool Size"] = 20;
$conStringBuilder["Incr Pool Size"] = 5;
$conStringBuilder["Decr Pool Size"] = 2;
$conStringBuilder["Statement Cache Size"] = 200;
$conStringBuilder["Statement Cache Purge"] = $false;#
default
$con.ConnectionString = $conStringBuilder.ConnectionString;
} else {
$con.ConnectionString = $theConnectionString;
}
if (Get - IsTrue - yesNoArg $openOnCreate) {
if (-not(Get - ConnectionStateIsOpen($con))) {#
attempt open, ignore error
if already open.State is normally open after successful create
try {
$con.Open();
} catch {
$null;
}
}
}
Write - Output - NoEnumerate $con;
}
get a connection:
$con = New - OracleConnection;
open / close as necessary(it defaults to open...)
...
...
if ($con.State - ne[System.Data.ConnectionState]::Open) {
$con.Open();#
no arguments that I know of ...
}
use it and then close/dispose...
$sql = "SELECT * FROM YOUR_TABLE t WHERE t.SOMETHING = :the_parm";
[Oracle.ManagedDataAccess.Client.OracleCommand]$cmd = New-Object -TypeName Oracle.ManagedDataAccess.Client.OracleCommand;
$cmd.Connection = Get-OracleConnection;
$cmd.CommandText = $sql;
$cmd.BindByName = $true;
$dbType = ([Oracle.ManagedDataAccess.Client.OracleDbType]::VarChar2);
$cmd.Parameters.Add(( New-Param -name "the_parm" -type $dbType -size 15 )).Value = $the_criteria_value ;
Write-Output -NoEnumerate ($cmd.ExecuteScalar());
$cmd.Connection.Close();
$cmd.Dispose();
It could very well be an issue with oracle 12.2.x
I had to add the following lines to the sqlnet.ora file on the database server to allow connections from older oracle clients:
SQLNET.ALLOWED_LOGON_VERSION_CLIENT=8
SQLNET.ALLOWED_LOGON_VERSION_SERVER=8
Once added I could login with oracle 10g and 11g clients
I had the exact same issue and I switched from ODAC version 12.2.0.1.0 to version 11.2.0.3 and it worked like a charm to Open connection and read data. Hope this helps.
Thanks,
SK

Adding a deployment step to call a http endpoint in Octopus Deploy

I am trying to create a new Octopus deploy step, which will call a http endpoint.
I have found the following step type that seems promising, but can get any documentation on it:
"Http Json Value Check
Gets json from http endpoint, looks-up a value by key and checks that it matches a predefined value. If value matches then script exists with a success code, if value does not match then script exists with a failure code."
I am not sure what to enter for the:
"Json Key" and the "Expected Value"
Has anyone done this? have an example or suggest a different method to achieve what I am trying?
Here is a PowerShell script I use to get the JSON from an endpoint and check for a valid Value. If I could remember where I got the code base before I modified it a little I would give credit to the original author. It will work with either a string or a regex.
#-------------------------------------------------------------------------
# Warmup.ps1
#-------------------------------------------------------------------------
[int]$returnme = 0
[int]$SleepTime = 5
[string]$regex = '[>"]?[aA]vailable["<]?'
[string]$strContains = $regex
# [string]$strContains = "log in"
[string]$hostName = hostname
[string]$domainName = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName .).DNSDomain
[string]$warmMeUp = "http://$hostName.$domainName/endpoint"
[string]$html = "Will Be Set Later"
#-------------------------------------------------------------------------
# Get-WebPage
#-------------------------------------------------------------------------
function Get-WebPage([string]$url)
{
try
{
$wc = new-object net.webclient;
$wc.credentials = [System.Net.CredentialCache]::DefaultCredentials;
[string]$pageContents = $wc.DownloadString($url);
$wc.Dispose();
}
catch
{
Write-Host "First Try Failed. Second Try in $SleepTime Seconds."
try
{
Start-Sleep -s $SleepTime
$wc = new-object net.webclient;
$wc.credentials = [System.Net.CredentialCache]::DefaultCredentials;
$pageContents = $wc.DownloadString($url);
$wc.Dispose();
}
catch
{
$pageContents = GetWebSiteStatusCode($url)
}
}
return $pageContents;
}
#-------------------------------------------------------------------------
# GetWebSiteStatusCode
#-------------------------------------------------------------------------
function GetWebSiteStatusCode
{
param (
[string] $testUri,
[int] $maximumRedirection = 5
)
$request = $null
try {
$request = Invoke-WebRequest -Uri $testUri -MaximumRedirection $maximumRedirection -ErrorAction SilentlyContinue
}
catch [System.Net.WebException] {
$request = $_.ErrorDetails.Message
}
catch {
Write-Error $_.Exception
return $null
}
return $request
}
#-------------------------------------------------------------------------
# Main Application Logic
#-------------------------------------------------------------------------
"Warming up '{0}'..." -F $warmMeUp;
$html = Get-WebPage -url $warmMeUp;
Write-Host "Looking for Pattern $strContains"
if ($html.ToLower().Contains("unavailable") -or !($html -match $strContains))
{
$returnme = -1
Write-Host "Warm Up Failed. html returned:`n" + $html
}
exit $returnme

Retrieve the Windows Identity of the AppPool running a WCF Service

I need to verify that the underlying server-side account running my WCF Service has correct ACL permissions to various points on the local file system. If I can get the underlying Windows Identity, I can take it from there. This folds into a larger Powershell script used after deployment.
Below is my powershell snippet, that get the ApplicationPoolSid, how do you map this to the AppPool's Windows Identity?
$mywcfsrv = Get-Item IIS:\AppPools\<MyWCFServiceName>;
Updated below to include Keith's snippet
For completeness, here's the solution:
Function Get-WebAppPoolAccount
{
param ( [Parameter(Mandatory = $true, Position = 0)]
[string]
$AppPoolName )
# Make sure WebAdmin module is loaded.
$module = (Get-Module -ListAvailable) | ForEach-Object { if ($_.Name -like 'WebAdministration') { $_ } };
if ($module -eq $null)
{
throw "WebAdministration PSSnapin module is not available. This module is required in order to interact with WCF Services.";
}
Import-Module $module;
# Get the service account.
try
{
$mywcfsrv = Get-Item (Join-Path "IIS:\AppPools" $AppPoolName);
}
catch [System.Exception]
{
throw "Unable to locate $AppPoolName in IIS. Verify it is installed and running.";
}
$accountType = $mywcfsrv.processModel.identityType;
$account = $null;
if ($accountType -eq 'LocalSystem')
{
$account = 'NT AUTHORITY\SYSTEM';
}
elseif ($accountType -eq 'LocalService')
{
$account = 'NT AUTHORITY\LOCAL SERVICE';
}
elseif ($accountType -eq 'NetworkService')
{
$account = 'NT AUTHORITY\NETWORK SERVICE';
}
elseif ($accountType -eq 'SpecificUser')
{
$account = $mywcfsrv.processModel.userName;
}
return $account;
}
Like so:
$mywcfsrv = Get-Item IIS:\AppPools\<MyWCFServiceName>
$mywcfsrv.processModel.identityType

Resources