Powershell Error: missing '=' operator after key in hash literal - powershell

I needed to create a script that checks to see if an IIS App Pool for a specific site and its child App Pools are started. (I have a separate script to start "stopped" App Pools as I just want to check if they are stopped) I was able to create the script however when I modified it to format the output better I keep getting this error,
At E:\iis\scripts\svc_pl_fm_app_pool_status.ps1:12 char:6
+ App Pool = $item.Name;
+ ~
Missing '=' operator after key in hash literal.
At E:\iis\scripts\svc_pl_fm_app_pool_status.ps1:7 char:29
+ foreach ($item in $results) {
+ ~
Missing closing '}' in statement block.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : MissingEqualsInHashLiteral
I checked here and Microsoft but I left more confused about the error then when I first saw it. I saw this Missing closing '}' in statement block. so i assumed I was in fact missing one but I checked and I am not. I am not sure if it is a spacing/ indentation issue but I do not know enough about this error message. Here is my script below.
$results = $item = $appPool = $status = $NULL
$status = "1"
import-module WebAdministration
$AppPoolList = #()
$results = Get-ChildItem IIS:\AppPools\* | Where-Object { ($_.Name -like "someAppPool*" -and $_.Name -like "someChildAppPool*" )}
foreach ($item in $results) {
if ($item.State -ne "Started") {$status = "0"}
$AppPoolList += [PSCustomObject]#{
App Pool = $item.Name;
Status = $item.State;
}
}
$AppPoolList | Format-List

Related

Powershell Throw Causing Variables to Clear?

My PowerShell script just checks multiple servers to make sure the input* and output* directories are clear of any files.
I'm simply trying to output to console the results of a GCI call prior to throwing an error message. However, when I uncomment the "throw" line, the $inputFiles and $outputFiles no longer output to the console. Below is the code:
$allServers = #(
"server1.com",
"server2.com")
foreach ($server in $allServers) {
$inputFiles = Get-ChildItem -Path "\\$server\C$\jobs\statements\input*\" -Recurse | Where-Object {! $_.PSIsContainer } | Select FullName
$outputFiles = Get-ChildItem -Path "\\$server\C$\jobs\statements\output*\" -Recurse | Where-Object {! $_.PSIsContainer } | Select FullName
if ($inputFiles -eq $NULL -and $outputFiles -eq $NULL) {
Write-Host "Environment is ready for statement processing."
}
else {
Write-Host "Environment is NOT ready for statement processing."
Write-Host "The following files exist in input/output: `n"
$inputFiles
$outputFiles
#Throw "Files exist in input/output. See above for details."
}
}
Below is the console output:
Environment is NOT ready for statement processing.
The following files exist in input/output:
Environment is NOT ready for statement processing.
The following files exist in input/output:
FullName
--------
\\server1.com\C$\jobs\statements\input\asdasd.txt
\\server1.com\C$\jobs\statements\input_254\asdasd.txt
\\server1.com\C$\jobs\statements\input_test\asdasd.txt
\\server2.com\C$\jobs\statements\input\CUSSTAT10302021.245
\\server2.com\C$\jobs\statements\input\CUSSTAT11312021
\\server2.com\C$\jobs\statements\input\CUSSTAT11312021.zip
And below is the console output when I uncomment the "throw" line:
Environment is NOT ready for statement processing.
The following files exist in input/output:
Files exist in input/output. See above for details.
At C:\jobs\statements\bin\Statements-EnvironmentCheck.ps1:47 char:9
+ Throw "Files exist in input/output. See above for details."
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Files exist in ...ve for details.:String) [], RuntimeException
+ FullyQualifiedErrorId : Files exist in input/output. See above for details.
I know I have some error output cleanup to perform in order to include all the servers that might have files present, but please ignore that for now.
What you're experiencing is explained in this answer and this answer, basically you need to implement Out-Host \ Out-Default:
$inputFiles, $outputFiles | Out-Host # Should fix the problem
# possibly `throw` might require this too
throw "Files exist in input/output. See above for details." | Out-Host
However, I feel is worth showing you a better way to approach your code, returning a unified array of objects which you can filter, sort and export.
$allServers = #(
"server1.com"
"server2.com"
)
$result = foreach ($server in $allServers) {
# use `-File` instead of `! $_.PSIsContainer`
$out = #{
in = Get-ChildItem "\\$server\C$\jobs\statements\input*\" -Recurse -File
out = Get-ChildItem "\\$server\C$\jobs\statements\output*\" -Recurse -File
}
# if $out['in'] and $out['out'] are `$null`, Ready is `$true`
[pscustomobject]#{
Ready = -not($out['in'] -or $out['out'])
Server = $server
Files = $out
}
}
Now, if you want to see which servers are Ready (no files in input and output):
$result.where{ $_.Ready }
And if you want to see which servers are not Ready, and have a list of the files:
$result.where{ -not $_.Ready }.foreach{
foreach($file in $_.Files.PSBase.Values.FullName) {
[pscustomobject]#{
Server = $_.Server
Files = $file
}
}
}

PowerShell - Use Dynamically Created Variable Name Within a Variable Name

So I have a powershell script that I am trying to get up and running. Most of it works but what I am trying to do to make it as easy as possible to run periodically is to have it reference a list of numbers (IPs) in a text file, and then create a new variable for each line of the text file. This part does work using the following.
$iplist = get-content c:\powershell\ips.txt | where-object { $_.Trim() -ne '' }
$startnum = 0
foreach($line in $iplist){
$startnum++
new-variable -name "ip$startnum" -Value $line -Force
}
This is great, but later on in the script it has to use the number stored in each of those dynamically created variables in two other parts of the script. One part is where is reverses the IP address and then stores its reversed variant in another variable, and on another part it uses that reversed IP address as part of a lookup using [System.Net.DNS].
So basically, using that first snippet of code the script does the following, using a text file called ips.txt with 1.2.3.4 on the first line and 5.6.7.8 on the second line
$ip1 = 1.2.3.4
$ip2 = 5.6.7.8
Then I want to take those $ip1 and $ip2 values and reverse them. I know the reverse part works cause it works with a static input, but when i try it with variables it doesn't work, below is a snippet of the code i'm trying to do this with. Its basically an updated version of the code snippet from above.
$iplist = get-content c:\powershell\ips.txt | where-object { $_.Trim() -ne '' }
$startnum = 0
foreach($line in $iplist){
$startnum++
new-variable -name "ip$startnum" -Value $line -Force
new-variable -name "ipParts$startnum" -Value "$ip$startnum".Split('.')
[array]::Reverse($ipParts$startnum)
$ipparts$startnum = [string]::join('.',$ipParts$startnum)
}
When I run that though I get the following errors
At line:8 char:30
+ [array]::Reverse($ipParts$startnum)
+ ~
Missing ')' in method call.
At line:8 char:30
+ [array]::Reverse($ipParts$startnum)
+ ~~~~~~~~~
Unexpected token '$startnum' in expression or statement.
At line:4 char:26
+ foreach($line in $iplist){
+ ~
Missing closing '}' in statement block or type definition.
At line:8 char:39
+ [array]::Reverse($ipParts$startnum)
+ ~
Unexpected token ')' in expression or statement.
At line:9 char:53
+ $ipparts.$startnum = [string]::join('.',$ipParts$startnum)
+ ~
Missing ')' in method call.
At line:9 char:53
+ $ipparts.$startnum = [string]::join('.',$ipParts$startnum)
+ ~~~~~~~~~
Unexpected token '$startnum' in expression or statement.
At line:9 char:62
+ $ipparts.$startnum = [string]::join('.',$ipParts$startnum)
+ ~
Unexpected token ')' in expression or statement.
At line:10 char:1
+ }
+ ~
Unexpected token '}' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
There are two parts to this, but i'm hoping if I can figure out this first part then the second part when I use the final value that is supposed to be stored in $ipParts$startnum to do the lookups will be easier.
EDIT
So I had an idea and change the script to this
$iplist = get-content c:\powershell\ips.txt | where-object { $_.Trim() -ne '' }
$startnum = 0
foreach($line in $iplist){
$startnum++
new-variable -name "ip$startnum" -Value $line -Force -ErrorAction SilentlyContinue
new-variable -name "ipParts$startnum" -Value "$ip$startnum".Split('.')
$iptemp = get-variable -name "ipparts$startnum"
[array]::Reverse("$iptemp")
$iptemp = [string]::join('.',"$iptemp")
set-variable -name "ipParts$startnum" -Value "$iptemp"
}
write-host "iplist is $iplist......ip1 is $ip1....ip2 is $ip2....ipparts1 is $ipparts1.......ipparts2 is $ipparts2....iptemp value is $iptemp"
Basically use set-variable to modify it as a string with other variable names in it, kind of works, but when i did write-host on the last part to make sure its actually writing the proper values to the variables, on $ipparts1, $ipparts2, and $iptemp, i have the following value
"System.Management.Automation.PSVariable"
I'm not entirely sure what that means.

unable to fetch system.int64 registry datavalue in powershell

Below powershell code is for exporting the complete registry hive to CSV file. But it gives error for exporting REG_Binary type data whose value is big as shown in the attached registry screenshot. Though I tried to convert it to string but no luck. Please suggest on how to fetch the REG_Binary data or how to convert it to string.
Function Get_Reg_Keys ($reg_key) {
$actualKey = Get-Item -Path Registry::$reg_key
#Write-Host $actualKey
ForEach ($name in $actualKey.GetValueNames()) {
# Write-Host $name
$name.Property | foreach {
$type = $actualKey.GetValue($name).GetType()
#Write-Host $type
Write-Host $actualKey.Name " | " $name " | " $actualKey.GetValue($name) " | " $type
If ( $type -eq [System.Byte[]] -Or $type -eq [System.Int64[]]) {
$a = [System.BitConverter]::ToString($actualKey.GetValue($name))
( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $a) |
Out-File "C:\Temp\Automation\HKCU.csv" -append -Encoding ascii -erroraction SilentlyContinue
}
Else {
( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $actualKey.GetValue($name)) |
Out-File "C:\Temp\Automation\HKCU.csv" -append -Encoding ascii -erroraction SilentlyContinue
}
}
}
$keyinfo = Get-ChildItem Registry::$reg_key
if ($keyinfo.count -gt 0) {
ForEach ($keyitem in $keyinfo) { Get_Reg_Keys ($keyitem) }
}
}
Then running: Get_Reg_Keys ("HKEY_CURRENT_USER\")
Gives the error:
Cannot convert argument "index", with value: "MRUListEx", for "GetValue" to type "System.Int64": "Cannot convert value "MRUListEx" to type "System.Int64". Error: "Input string was
not in a correct format.""
At C:\Temp\Automation\HKCUregistrynew.ps1:27 char:21
+ ( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $act ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Registry Key details:
To be honest, I'm having a tough time following your function. I'm not even sure how you're iterating over values in a key with that $name.properties | foreach... loop.
But, generally, this is pretty straight forward. For example, I've got a registry key HKCU:\Environment. I've created a property in that key named "thing", and I've stuffed it with some random binary data.
I'll take the guts of that property and output it to a file:
$reg_key = 'HKCU:\Environment'
$key_properties = Get-Item -Path $reg_key
[System.BitConverter]::ToString($key_properties.GetValue('thing')) | Out-File -FilePath .\Test.txt
cat .\Test.txt
Just to show there is nothing up my sleeve:
Good luck.
After making below changes I am able to export a registry hive to CSV file:
$actualKey = Get-Item -LiteralPath Registry::$reg_key
$keyinfo = Get-ChildItem -LiteralPath Registry::$reg_key

running a PowerShell command sp 2010

I am trying to create a site map with a PowerShell command from this example:
http://blogs.msdn.com/b/opal/archive/2010/04/13/generate-sharepoint-2010-sitemap-with-windows-powershell.aspx
My actions: I copied the code into a file named New-SPSiteMap
I opened the PowerShell and wrote
New-SPSiteMap –Url http://centerportal –SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
The error I get is:
The term 'New-SPSiteMap' 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 line:1 char:14
+ New-SPSiteMap <<<< -Url http://mossdev2010 -SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
+ CategoryInfo : ObjectNotFound: (New-SPSiteMap:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
In order to have the New-SPSiteMap function available you have to execute the script containing the function:
& .\New-SPSiteMap.ps1
New-SPSiteMap –Url http://centerportal –SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
Alliteratively, you could turn the PowerShell script into a "function" that is callable like this:
.\New-SPSiteMap.ps1 -Url http://centerportal –SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
All you have to do is remove the function declaration function New-SPSiteMap:
param($SavePath="C:\inetpub\wwwroot\wss\VirtualDirectories\80\SiteMap.xml", $Url="http://sharepoint")
function New-Xml
{
param($RootTag="urlset",$ItemTag="url", $ChildItems="*", $SavePath="C:\SiteMap.xml")
Begin {
$xml="<?xml version=""1.0"" encoding=""UTF-8""?>
<urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9"">"
}
Process {
$xml += " <$ItemTag>"
foreach ($child in $_){
$Name = $child
$xml += " <$ChildItems>$url/$child</$ChildItems>"
}
$xml += " </$ItemTag>"
}
End {
$xml += "</$RootTag>"
$xmltext=[xml]$xml
$xmltext.Save($SavePath)
}
}
$web = Get-SPWeb $url
$list = $web.Lists | ForEach-Object -Process {$_.Items} | ForEach-Object -Process {$_.url.Replace(" ","%20")}
# excludes directories you don’t want in sitemap. you can put multiple lines here:
$list = $list | ? {$_ -notmatch "_catalogs"}
$list = $list | ? {$_ -notmatch "Reporting%20Templates"}
$list = $list | ? {$_ -notmatch "Reporting%20Metadata"}
$list | New-Xml -RootTag urlset -ItemTag url -ChildItems loc -SavePath $SavePath

Powershell WMI Query failing when executed from Task Scheduler

i have a strange problem...
i have the following code, which takes the output from Sysinternals Disk Usage tool (link below)
Disk Usage - Sys Internals
so first i get the physical drives into array $Disks, then i enumerate these through the foreach and mess about with them.
my problem lies in this line $Dir = du.exe -q -v $d.DeviceID
$PC = get-content env:COMPUTERNAME
$Disk = gwmi win32_logicaldisk -filter "drivetype=3"
foreach ($d in $Disk)
{
$Dir = du.exe -q -v $d.DeviceID
$Dir[8..($Dir.length-8)] | foreach {
$Size = $_.substring(0,10).replace(",","")/1024
$Path = $_.substring(10)
}
}
$d.DeviceID should be the drive letter (i.e. C:)
then i populate $Dir with the output from DU.exe, but $d.DeviceID is not acting how it is supposed to, running this from a task has this following result (added a line that says $d.DeviceID, to show the output):
B:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
C:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
D:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
running it from the ISE or just from the Shell has no issues, running it on other servers from all methods works.
i do believe the population of the $Dir vairable is the problem, as the du.exe has trouble with the $d.DeviceID
i dont understand why it is just this server/task sheduler that has the issue. i have tried the following:
redefined the array element to $i = $d.deviceID to fix it down - nothing
exported the job from other server (both DCs) an imported - nothing
restarted the winmgmt service - nothing
i think its a permissions issue, but im running this on an AD as THE Dom Admin with top privilages.
please can you guys help on this one, really am stuck...
cheers
Lee
Yet another update based on comment below:
Try:
$cmd = "du.exe `-q `-v $($d.DeviceID)"
$dir = Invoke-Expression $cmd
Updating as per the comment below.
Take this example. This can get the size of every folder and display size and full path to the folder.
Function Get-FolderSize {
Param ($folderPath)
$colItems = (Get-ChildItem $folderPath -recurse | Measure-Object -property length -sum)
return $colItems.sum/1MB
}
$folders = Get-ChildItem -Recurse C:\Scripts
$folders | % {
if ($_.PSIsContainer) {
$size = Get-FolderSize $_.FullName
Write-Host $size
Write-Host $_.FullName
}
}
You can use WMI to get the drive letter and pass it to the script. For example:
$disks = gwmi win32_logicaldisk -filter "drivetype=3"
$disks | % {
$items = Get-ChildItem -Recurse $_.DeviceID -Force
$items | % {
if ($_.PSIsContainer) {
$size = Get-FolderSize $_.FullName
Write-Host $size
Write-Host $_.FullName
}
}
}
So, with this, you dont need DU.exe. You can run this as a script.
--------------OLD ANSWER _-------------------
First thing I would suspect is the path to DU.exe. What is the working directory set on the scheduled task? Is it the place where DU.exe is available?
BTW, what is the goal of this script? Are you just looking at the disk drive size? What are you capturing into $path? I did not have the patience to test your code. But, I feel that this can be easily achieved using just WMI and no other external tools.