PowerShell webdeploy - powershell

I'm trying to use PowerShell with web deployment based on this
article
This is how my script looks like
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Deployment")
function Sync-Provider($provider, $sourceLocation, $destLocation)
{
$destBaseOptions = new-object Microsoft.Web.Deployment.DeploymentBaseOptions
$syncOptions = new-object Microsoft.Web.Deployment.DeploymentSyncOptions
Try
{
$deploymentObject = [Microsoft.Web.Deployment.DeploymentManager]::CreateObject($provider, $sourceLocation)
$deploymentObject.SyncTo($provider,$destLocation,$destBaseOptions,$syncOptions)
}
Catch
{
echo "EXCEPTION THROWN::[ $_ ] "
#throw $_
}
}
Sync-Provider ("apphostConfig","D:\NerdDinner_2.0\NerdDinner","c:\inetpub\wwwroot")
Running this gives the following exception
EXCEPTION THROWN::[ Cannot convert argument "0", with value: "System.Object[]",
for "CreateObject" to type "Microsoft.Web.Deployment.DeploymentWellKnownProvid
er": "Cannot convert value "apphostConfig,D:\NerdDinner_2.0\Ne
rdDinner,c:\inetpub\wwwroot" to type "Microsoft.Web.Deployment.DeploymentWellKn
ownProvider" due to invalid enumeration values. Specify one of the following en
umeration values and try again. The possible enumeration values are "Unknown, A
ppHostConfig, AppHostSchema, AppPoolConfig, ArchiveDir, Auto, Cert, ComObject32
, ComObject64, ContentPath, CreateApp, DirPath, DBFullSql, DBMySql, FilePath, G
acAssembly, IisApp, MachineConfig32, MachineConfig64, Manifest, MetaKey, Packag
e, RecycleApp, RegKey, RegValue, RootWebConfig32, RootWebConfig64, RunCommand,
SetAcl, WebServer, WebServer60"." ]
Could you give me some hints on this, please?

Try to enclose the first parameter [Microsoft.Web.Deployment]::DeploymentWellKnownProvider.AppHostConfig with a pair of extra parenthesis: ([Microsoft.Web.Deployment]::DeploymentWellKnownProvider.AppHostConfig).

In my case I had the same problem, just opened the powershell console as Administrator and it worked.

Related

Pester doesn't catch the thrown error

When I run the following pester test I expect it to catch the expected error but it doesn't. But when I run the test with a different function with a different throw statement it works.
Pester Test:
Describe "Remove-GenericCredential Function Tests" {
$InternetOrNetworkAddress = 'https://PesterTestUser#PesterTestURl.com'
Context "Test: Remove-GenericCredential -InternetOrNetworkAddress '$InternetOrNetworkAddress' (Credential does not exist)" {
It "This Command threw an error. The credential does not exist." { { (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false) } | should throw "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found" }
}
}
Error that isn't caught:
Remove-GenericCredential : Credential https://PesterTestUser#PesterTestURl.com not found
At C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\Remove-GenericCredential.Tests.ps1:30 char:76
+ ... xist." { { (Remove-GenericCredential -InternetOrNetworkAddress $Inter ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-GenericCredential
[-] This Command threw an error. The credential does not exist. 44ms
Expected: the expression to throw an exception with message {Remove-GenericCredential : Credential https://PesterTestUser#PesterTestURl.com not found}, an exception was not raised, message was {}
from C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\New-GitHubCredential.Tests.ps1:59 char:176
+ ... e $UserName -Token 'NotAGitHubTokenSpecialCharacters!##$%^&*') } | sh ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
at <ScriptBlock>, C:\Users\klocke7\Documents\WindowsPowerShell\Modules\Ford_CredentialManager\Tests\Remove-GenericCredential.Tests.ps1: line 30
30: It "This Command threw an error. The credential does not exist." { { (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false) } | should throw 'Remove-GenericCredential : Credential https://PesterTestUser#PesterTestURl.com not found' }
Per the other answer, the function is throwing a non-terminating error and as such its not being considered to match the test of Should Throw, which is checking for terminating errors.
There are two ways you could address this:
You could change it so that it throws a terminating error by changing your Write-Error to Throw.
You could change the test to force the function to throw a terminating error even when non-terminating ones occur by using -ErrorAction Stop when you invoke it (I can see you're using -Confirm, I assume you have used [cmdletbinding()] in the function to add the common parameters like -ErrorAction).
Here's an example of the second solution (I've simulated the function at the top so that I could test this, but you don't need to include that in your test script):
Function Remove-GenericCredential {
[cmdletbinding(supportsshouldprocess)]
Param(
$InternetOrNetworkAddress
)
Write-Error "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found"
}
Describe "Remove-GenericCredential Function Tests" {
$InternetOrNetworkAddress = 'https://PesterTestUser#PesterTestURl.com'
Context "Test: Remove-GenericCredential -InternetOrNetworkAddress '$InternetOrNetworkAddress' (Credential does not exist)" {
It "This Command threw an error. The credential does not exist." {
{ (Remove-GenericCredential -InternetOrNetworkAddress $InternetOrNetworkAddress -Confirm:$false -ErrorAction Stop) } | should throw "Remove-GenericCredential : Credential $InternetOrNetworkAddress not found" }
}
}
From help Write-Error:
The Write-Error cmdlet declares a non-terminating error. By default,
errors are sent in the error stream to the host program to be
displayed, along with output.
To write a non-terminating error, enter an error message string, an ErrorRecord object, or an Exception object. Use the other parameters of Write-Error to populate the error record.
Non-terminating errors write an error to the error stream, but they do not stop command processing. If a non-terminating error is declared on one item in a collection of input items, the command continues to process the other items in the collection.
To declare a terminating error, use the Throw keyword. For more information, see about_Throw
(http://go.microsoft.com/fwlink/?LinkID=145153).
This is probably because the cmdlet is throwing a non-terminating error because Pester only asserts against terminating errors. In this case need to rewrite the test as follows (using old Pester v3 synatax as per your example):
It "Test a non-terminating error gets thrown" {
$errorThrown = $false;
try
{
Invoke-CmdletThatThrowsNonTerminatingError -ErrorAction Stop
}
catch
{
$errorThrown = $true
}
$errorThrown | Should Be $true
}
In the catch block you can also get exception details such as message or exception type on the $_ ob

PowerShell - InvalidCastException when returning Boolean to explicitly declared variable [duplicate]

This question already has answers here:
Function return value in PowerShell
(10 answers)
Closed 5 years ago.
I've written a PowerShell script to perform some pre-installation setup for a series of patches I'm deploying to client computers across our estate and I'm hitting a bit of an odd issue that I can't wrap my head around.
The setup patch checks the 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe.config' file due to a "feature" of PowerShell 2.0 whereby the application uses .NET Framework 2.0.0 by default instead of 4.5.2, preventing certain functions from being executed. If the file doesn't exist or the evaluated values don't match a specification, I add the XML file and provide the necessary values.
The command I run is as follows:
$psConfigDir = "C:\Windows\System32\WindowsPowerShell\v1.0"
$psConfigFileName = "powershell.exe.config"
[boolean]$psExeXml = Set-PSRuntimeConfigs -FilePath ( [String]::Format("{0}\{1}", $psConfigDir, $psConfigFileName) ) -CLRVersions #("v4.0.30319", "v2.0.50727")
...and the Set-PSRuntimeConfigs method is found in a PowerShell Module I created with the code below:
Function Set-PSRuntimeConfigs {
[CmdletBinding()]
Param(
[String]$FilePath,
[System.Collections.ArrayList]$CLRVersions
)
Try {
$xmlWriter = New-Object System.Xml.XmlTextWriter($FilePath, $null)
$xmlWriter.Formatting = "Indented"
$xmlWriter.Indentation = 4
$xmlWriter.WriteStartDocument()
$xmlWriter.WriteStartElement("configuration")
$xmlWriter.WriteStartElement("startup")
$xmlWriter.WriteAttributeString("useLegacyV2RuntimeActivationPolicy", $true)
$CLRVersions | ForEach-Object {
$xmlWriter.WriteStartElement("supportedRuntime")
$xmlWriter.WriteAttributeString("version", $_)
$xmlWriter.WriteEndElement()
}
$xmlWriter.WriteEndElement()
$xmlWriter.WriteEndElement()
$xmlWriter.WriteEndDocument()
$xmlWriter.Close()
$xmlWriter.Dispose()
return $true
} Catch {
echo "ERROR: Exception occurred during XML write process!"
echo "ERROR: Exception message: $($_.Exception.Message)"
return $false
}
}
However, the function is returning an InvalidCastException when trying to assign the result of the function to the $psExeXml variable. Oddly, PowerShell returns with an error stating that [System.Object()] cannot be converted to type [Boolean] despite the fact that only $true or $false is returned from the function.
My first thought is that an exception was being thrown by the function due to a code issue but the function is written to report the error in the prompt and just return $false in that case... Regardless, I'm stuck and can't figure out where to proceed with this...
If the function produces any output then the result will be an array containing the strings that were output and then the final element will be your boolean.
So for this code:
echo "ERROR: Exception occurred during XML write process!"
echo "ERROR: Exception message: $($_.Exception.Message)"
return $false
the function returns an array of two strings and a boolean.

Powershell dsacls on success or fail

I have PowerShell script which delegates powers of security group for the selected OU via dsacls.
All works fine but i want to output a JSON response for success delegation (without all dsacls access list and object info) and for error just information.
How i run dcals:
dsacls "OU=Organization,DC=domain,DC=tld" /I:S /G GroupName:RPWP;sn;user
How to check now is dsacls run correct delegate and return via ConvertTo-Json method?
Is there another option than checking response string of dsacls?
Thanks.
maybe something like this:
$res = dsacls "OU=Organization,DC=domain,DC=tld" /I:S /G GroupName:RPWP;sn;user
#{ success = $?
error = if (!$?) { [string]$res } else { "" }
} | ConvertTo-Json
the $? variable contains the success status of the last executed command (true or false)

Throw an exception in powershell with nesting original error

I'm a C# developer who is trying to build something useful using PowerShell. That's why I'm keep trying to use well-known idioms from .NET world in PowerShell.
I'm writing a script that has different layer of abstractions: database operations, file manipulation etc. At some point I would like to catch an error and wrap it into something more meaningful for the end user. This is a common pattern for C#/Java/C++ code:
Function LowLevelFunction($arg)
{
# Doing something very useful here!
# but this operation could throw
if (!$arg) {throw "Ooops! Can't do this!"}
}
Now, I would like to call this function and wrap an error:
Function HighLevelFunction
{
Try
{
LowLevelFunction
}
Catch
{
throw "HighLevelFunction failed with an error!`nPlease check inner exception for more details!`n$_"
}
}
This approach is almost what I need, because HighLevelFunction will throw new error and the root cause of the original error would be lost!
In C# code I always can throw new exception and provide original exception as an inner exception. In this case HighLevelFunction would be able to communicate their errors in a form more meaningful for their clients but still will provide inner details for diagnostic purposes.
The only way to print original exception in PowerShell is to use $Error variable that stores all the exceptions. This is OK, but the user of my script (myself for now) should do more things that I would like.
So the question is: Is there any way to raise an exception in PowerShell and provide original error as an inner error?
You can throw a new exception in your catch block and specify the base exception:
# Function that will throw a System.IO.FileNotFoundExceptiopn
function Fail-Read {
[System.IO.File]::ReadAllLines( 'C:\nonexistant' )
}
# Try to run the function
try {
Fail-Read
} catch {
# Throw a new exception, specifying the inner exception
throw ( New-Object System.Exception( "New Exception", $_.Exception ) )
}
# Check the exception here, using getBaseException()
$error[0].Exception.getBaseException().GetType().ToString()
Unfortunately when throwing a new exception from the catch block as described by this answer, the script stack trace (ErrorRecord.ScriptStackTrace) will be reset to the location of the throw. This means the root origin of the inner exception will be lost, making debugging of complex code much harder.
There is an alternative solution that uses ErrorRecord.ErrorDetails to define a high-level message and $PSCmdlet.WriteError() to preserve the script stack trace. It requires that the code is written as an advanced function cmdlet. The solution doesn't use nested exceptions, but still fulfills the requirement "to catch an error and wrap it into something more meaningful for the end user".
#------ High-level function ----------------------------------------------
function Start-Foo {
[CmdletBinding()] param()
try {
# Some internal code that throws an exception
Get-ChildItem ~foo~ -ErrorAction Stop
}
catch {
# Define a more user-friendly error message.
# This sets ErrorRecord.ErrorDetails.Message
$_.ErrorDetails = 'Could not start the Foo'
# Rethrows (if $ErrorActionPreference is 'Stop') or reports the error normally,
# preserving $_.ScriptStackTrace.
$PSCmdlet.WriteError( $_ )
}
}
#------ Code that uses the high-level function ---------------------------
$DebugPreference = 'Continue' # Enable the stack trace output
try {
Start-Foo -ErrorAction Stop
}
catch {
$ErrorView = 'NormalView' # to see the original exception info
Write-Error -ErrorRecord $_
''
Write-Debug "`n--- Script Stack Trace ---`n$($_.ScriptStackTrace)" -Debug
}
Output:
D:\my_temp\ErrorDetailDemo.ps1 : Could not start the Foo
+ CategoryInfo : ObjectNotFound: (D:\my_temp\~foo~:String) [Write-Error], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,ErrorDetailDemo.ps1
DEBUG:
--- Script Stack Trace ---
at Start-Foo, C:\test\ErrorDetailDemo.ps1: line 5
at , C:\test\ErrorDetailDemo.ps1: line 14
Our high-level error message 'Could not start the Foo' hides the error message of the underlying exception, but no information is lost (you could access the original error message through $_.Exception.Message from within the catch handler).
Note: There is also a field ErrorDetails.RecommendedAction which you could set as you see fit. For simplicity I didn't use it in the sample code, but you could set it like this $_.ErrorDetails.RecommendedAction = 'Install the Foo'.

Hash entry sometime is $NULL (error), and sometimes isn't?

I have my little 3-sided socket-server. Each server has its own hash with its key-values.
The very first is:
$Local = #{ID="Local"; ...}
$RemtA = #{ID="RemtA"; ...}
$RemtB = #{ID="RemtB"; ...}
I start for all of the the listeners - no problem.
If now a client wants to connect, I want to add the ID to $ProgressHead, which is defined like this:
$ProgressHead = "Value-Broadcast, Connected: "
and used in my function to accept a client called with its hash as $h:
if ( !$h.Connected ) {
#Write-Host "$($h.ID) not connected, pending: $($h.listener.Pending())"
if ( $h.listener.Pending()) {
$h.client = $h.listener.AcceptTcpClient() # will block here until connection
$h.stream = $h.client.GetStream();
$h.writer = New-Object System.IO.StreamWriter $h.stream
$h.writer.AutoFlush = $true
$h.Connected = $true
Write-Host $Global:ProgressHead # fails - empty ??
Write-Host $h.ID # prints oh depit it is marked as error
if ( !$Global:ProgressHead.Contains( $h.ID ) ) { # <= HERE IS THE ERROR ????
$Global:ProgressHead= "$($Global:ProgressHead)$($h.ID) "
}
}
}
The Error message says:
Can't call a method for an expression which is NULL and $h.ID is underlined
BUT I DO NOT get any error if I start this either in the cmd-console when running powershell -file ThreeServer.ps1 or within the ISE in debug mode. The ID is written correctly to $ProgressHead!
Only if I start this in the Powershell console (PS C:\...> ./ThreeServer.ps1) I get this error, but all the other keys in the lines above are valid ONLY $h.ID on ONLY the PS-console throws this error?