How can I get powershell exception descriptions into a string? - exception

I want to have access to the same message that Powershell prints when you send an error record to the output stream
Example:
This is the exception message At
C:\Documents and
Settings\BillBillington\Desktop\psTest\exThrower.ps1:1
char:6
+ throw <<<< (New-Object ArgumentException("This is the
exception"));
+ CategoryInfo : OperationStopped: (:) [],
ArgumentException
+ FullyQualifiedErrorId : This is the exception
I when a get the last ErrorRecord by doing $Error[0] I can't seem to figure out how to get this information in a simple way
I found this 'Resolve-Error' function from the community extensions here which does roughly what I want but it prints a huge semi-formatted list of stuff I don't need that I have to then strip
Is there way of accessing the message that Powershell uses or failing that a simpler way of getting hash of the values I care about so I can put them into a string in a format of my choosing?

How about:
$x = ($error[0] | out-string)
Is that what you wanted?

If you want a bit shorter message (more user friendly sometimes?) than #tomasr suggests this will do:
$error[0].ToString() + $error[0].InvocationInfo.PositionMessage
You will get something like:
Cannot find path 'C:\TEMP\_100804_135716\missing' because it does not exist.
At C:\TEMP\_100804_135716\test.ps1:5 char:15
+ Get-ChildItem <<<< missing
This technical info will be excluded:
+ CategoryInfo : ObjectNotFound: (C:\TEMP\_100804_135716\missing:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

I took it a bit further because I didn't like the multilines from $error[0].InvocationInfo.PositionMessage.
Function FriendlyErrorString ($thisError) {
[string] $Return = $thisError.Exception
$Return += "`r`n"
$Return += "At line:" + $thisError.InvocationInfo.ScriptLineNumber
$Return += " char:" + $thisError.InvocationInfo.OffsetInLine
$Return += " For: " + $thisError.InvocationInfo.Line
Return $Return
}
[string] $ErrorString = FriendlyErrorString $Error[0]
$ErrorString
You can look at what else is availible to construct your own String via:
$Error | Get-Member
$Error[0].InvocationInfo | Get-Member

Foreach ($Errors in $Error){
#Log Eintrag wird zusammengesetzt und in errorlog.txt geschrieben
"[$Date] $($Errors.CategoryInfo.Category) $($Errors.CategoryInfo.Activity) $($Errors.CategoryInfo.Reason) $($Errors.CategoryInfo.TargetName) $($Errors.CategoryInfo.TargetType) $($Errors.Exception.Message)" |Add-Content $Path\errorlog.txt -Encoding UTF8
}
You can also do this and you will get all Informations about the Error

Similar to #tomasr, but shorter:
$($error[0])
For all errors in a script:
$($error)

Related

Issues with calling json file using powershell

I am trying to run simple power-shell command to call json file to deploy some resources on Azure but it give me the same errors each time I try to run the file.The error message I am getting is -
New-AzDeployment : Cannot retrieve the dynamic parameters for the cmdlet. Invalid property identifier character: �. Path '', line 2, position 0.
At line:1 char:1
+ New-AzDeployment -Name $DeploymentName -Location uksouth -TemplateUri ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [New-AzDeployment], ParameterBindingException
+ FullyQualifiedErrorId : GetDynamicParametersException,Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.NewAzureDeploymentCmdlet
below is the powershell, I am trying to run -
$DeploymentSubscription = "Visual Studio Enterprise with MSDN"
$DeploymentRSG = "xyz"
$DeploymentName = "vvv"
$ParameterRoute = "D:\xyz\json\VM\"
$ParameterFile = $ParameterRoute + "Build.json"
$TemplateFileRoute = "D:\xyz\VM\"
$TemplateFileName = "Deploy_RG_Resources.json"
$TemplateFile = $TemplateFileRoute + $TemplateFileName
$TemplateFileURi = $TemplateFileRoute + $TemplateFileName
New-AzResourceGroupDeployment -Name $DeploymentName -ResourceGroupName $DeploymentRSG -DeploymentDebugLogLevel All -Verbose -TemplateUri $TemplateFileURi -TemplateParameterFile $ParameterFile
Thanks
That error is very specific.
What you are passing is valid. The help files for the cmdlet shows this command in action.
New-Az​Resource​Group​Deployment
$newAzResourceGroupDeploymentSplat = #{
TemplateParameterFile = "D:\Azure\Templates\EngSiteParams.json"
TemplateObject = $TemplateObject
ResourceGroupName = "ContosoEngineering"
}
New-AzResourceGroupDeployment #newAzResourceGroupDeploymentSplat
Note the fully qualified UNC to the .json file.
But you are doing this..
$ParameterFile = $ParameterRoute + "Build.json"
... and based on your post, that is not the path to your .json file.
Try using -TemplateFile as parameter instead of -TemplateUri if your Template file in on local machine.
This is resolved now .Issue was with the JSON template syntax.Quite weird though I have validate the template many times

How to let JsonTextReader ignore current record and continue to next one?

I'm trying to use powershell to invoke the namespace Newtonsoft.Json to deal with large size of Json files. Each file contains millions of json records and not all of them are in correct format. I'm using Newtonsoft.Json.JsonTextReader since it reads one json record each time other than read the whole file into memory. But when it read to a record which contains some format problem, it will fail and i have no idea how to ignore current one.
Is there any way to let it ignore current record and continue the next one?
$file="C:\logtest\log-3.json"
add-type -path "C:\logtest\Newtonsoft.Json.dll"
$sr=new-object system.IO.StreamReader($file)
$reader=new-object Newtonsoft.Json.JsonTextReader($sr)
$analyzer=New-Object Newtonsoft.Json.JsonSerializer
$analyzer.ReferenceLoopHandling=[Newtonsoft.Json.ReferenceLoopHandling]::Ignore
$i=0
$n=0
while($reader.read()){
if($n -gt 2){
if($reader.TokenType.ToString() -eq "StartObject"){
$single=$null
$single=$analyzer.Deserialize($reader)
# Deal with the json record...
$i++
}
}
$n++
}
$reader.Close()
And here is the exception when it facing format issue:
Exception calling "Deserialize" with "1" argument(s): "After parsing a value an unexpected character was encountered: ". Path 'records[46796].properties.userAgent', line 374378, position 634."
At line:6 char:13
+ $single=$analyzer.Deserialize($reader)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : JsonReaderException
Exception calling "Read" with "0" argument(s): "After parsing a value an unexpected character was encountered: ". Path 'records[46796].properties.userAgent', line 374378, position 634."
At line:1 char:7
+ while($reader.read()){
+ ~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : JsonReaderException
Here is an example json file, as you can see there is format issue for the property "P2" of the 3rd record.
{
"Record":
[
{
"P1":"data",
"P2":"data",
"P3":"data"
}
,
{
"P1":"data2",
"P2":"data2",
"P3":"data2"
}
,
{
"P1":"data3",
"P2":"data3"",
"P3":"data3"
}
,
{
"P1":"data4",
"P2":"data4",
"P3":"data4"
}
]
}
What about a Try Catch statement?
try {
$single=$analyzer.Deserialize($reader)
# Deal with the json record...
$i++ }
catch {
LogWrite ("Caught the exception")
LogWrite ($Error[0].Exception)
$i++
}
}

Issue with get shortcut function not loading in separate script

So I have the following script I am trying to run which keeps erroring out
. .\stshortcut.ps1 |
Get-Shortcut . |
Where Target -eq "cmd.exe" |
%{$myPath, $myNewName = $null;
Write-Warning "Processing $($_.Link)";
If (-Not (Test-Path .\BadShortcuts -PathType Container)) {New-Item -
WhatIf -ItemType Directory BadShortcuts | Out-Null};
[string]$myPath = $_.Arguments.Split()[-1] -replace '"';
[string]$myNewName = $_.Link -replace "\.lnk$";
Rename-Item -WhatIf -Force -Path $myPath -NewName $myNewName;
(Get-Item -Force $myNewName).Attributes = '';
Move-Item -WhatIf $_.LinkPath .\BadShortcuts;}`
the error I get is as follows
The term 'Get-Shortcut' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try
again.
At C:\Shared\APPS\FixShortcutX2.ps1:1 Char 13
+ Get Shortcut <<<<< . |
+ CategoryInfor : ObjectNotFound: (Get-Shortcut:String)[],
CommandNotFoundException
+ FullyQualifiedErrorID : CommandNotFoundException
the stshortcut.ps1 script has the get-shortcut and set-shortcut functions and are called to do such - I got this script from
https://www.reddit.com/r/PowerShell/comments/4su2jg/zeroday_malware_renamed_folders_on_a_shared_drive/
which is an answer script to fix a macro virus from a word doc attachment - sent from a spoofed email address -
Any assistance is GREATLY appreciated
EDITx2 after some further helpful advice and editing I now am receiving the following
Where-Object : Cannot bind parameter 'FilterScript' . Cannot convert the "Target" value of type "System.String" to type "System.Management.Automation.ScriptBlock".
At C:\Shared\Apps\FixShortcutX2.ps1:3 char:6
+ Where <<<<< Target -eq "cmd.exe" |
+CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand
You need to dot-source stshortcut.ps1 before you can use Get-Shortcut.
Change the first line:
.\stshortcut.ps1 |
To
. .\stshortcut.ps1

New-ADUser is not working properly when bulk loading via .csv file

I'm running into an error where this is not picking up the password field at all... I ran the import command manually to make sure it was grabbing all of the correct data, but it errors out on the password and group info...
$Users = Import-Csv -Path "C:\NewUsers.csv"
foreach ($User in $Users)
{
$Displayname = $User.'Firstname' + " " + $User.'Lastname'
$UserFirstname = $User.'Firstname'
$UserLastname = $User.'Lastname'
$OU = $User.'OU'
$SAM = $User.'SAM'
$UPN = $User.'Firstname' + "." + $User.'Lastname' + "#" + $User.'Maildomain'
$Password = $User.'Password'
$Description = $User.'Description'
$Group = $User.'Group'
$Account = New-ADUser -Name "$Displayname" -DisplayName "$Displayname" -SamAccountName $SAM -UserPrincipalName $UPN -GivenName "$UserFirstname" -Surname "$UserLastname" -Description "$Description" -AccountPassword (ConvertTo-SecureString $Password -AsPlainText -Force) -Enabled $true -Path "$OU" -ChangePasswordAtLogon $false -PasswordNeverExpires $true -server esg.intl -PassThru
Add-ADGroupMember -Identity $Group -Members $Account
}
And here are the errors I'm getting even though I know the passwords are ok:
New-ADUser : The password does not meet the length, complexity, or history requirement of the domain.
At C:\Users\A-Shane.Johnson\Desktop\Bulk Add Domain Users.ps1:24 char:13
+ ... $Account = New-ADUser -Name "$Displayname" -DisplayName "$Displaynam ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (CN=ESGAP PMOInt...,DC=esg,DC=intl:String) [New-ADUser], ADPasswordComplexi
tyException
+ FullyQualifiedErrorId : ActiveDirectoryServer:1325,Microsoft.ActiveDirectory.Management.Commands.NewADUser
Add-ADGroupMember : Cannot validate argument on parameter 'Members'. The argument is null or empty. Provide an
argument that is not null or empty, and then try the command again.
At C:\Users\A-Shane.Johnson\Desktop\Bulk Add Domain Users.ps1:26 char:46
+ Add-ADGroupMember -Identity $Group -Members $Account
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-ADGroupMember], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.AddADGrou
pMember
Depending on how that CSV is generated you might try double checking that there isn't an extra space in the Password column header? i.e. 'Password '. Sometimes that trips me up because it doesn't show in the excel or cmd line view easily.
I found the problem and answer. Apparently our domain has an issue when part of the username is in the password. I misunderstood that error thinking that the conversion is what was causing the issue...
I fixed the passwords and now the script runs beautifully!

PowerShell hash-table return values

I have a simple script to return values from a hash table:
param
(
[Parameter(Mandatory = $true)]
[string]$Name
)
function getvalues ($Name) {
$nameList= #{"CFT"=#{"name1"="text1"; "name2"="text2"}}
#return $nameList[$Name]
return ,$nameList
}
$Values = getvalues($Name)
Write-Debug "DEBUG: Name1 = "$Values["name1"]
Write-Debug "DEBUG: Name2 = "$Values["name2"]
When I run it, I get the following error:
Write-Debug : A positional parameter cannot be found that accepts argument '$null'.
At C:\MSFT\add-test.ps1:21 char:2
+ write-Debug "DEBUG: Name1 = "$Values["name1"]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Debug], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WriteDebugCommand
Write-Debug : A positional parameter cannot be found that accepts argument '$null'.
At C:\MSFT\add-test.ps1:22 char:2
+ write-Debug "DEBUG: Name2 = "$Values["name2"]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Write-Debug], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WriteDebugCommand
You're terminating your strings and then using the $Values lookup. Either use a + or embed it into the string, or use the -f operator:
write-Debug ("DEBUG: Name1 = " + $Values["name1"])
write-Debug "DEBUG: Name2 = $($Values["name2"])"
write-Debug ("DEBUG: Name3 = {0}" -f $Values["name3"])
Note forms 1 and 3 need parentheses ( ).
Regarding your comment that there are no more errors and no output:
Are you sure your debug preference is set such that you can see the output? The point of Write-Debug and Write-Verbose is that you only see the output when the preference is set as such (and you shouldn't add DEBUG: in your string, it will be added for you). I suspect Write-Verbose is more appropriate for what you're doing.
To test quickly whether it will work, you can actually add -Debug or -Verbose as appropriate.
So for example:
Write-Verbose "Name2 = $($Values["name2"])" -Verbose