Related to PowerShell 5.1
I was playing around with XML to show how to handle conflicting namespaces. Here's the example I created:
<Employees>
<ms:Employee id='1' xmlns:ms="MicrosoftEmployees">
<FirstName>Bill</FirstName>
<LastName>Gates</LastName>
</ms:Employee>
<ms:Employee id='2' xmlns:ms="MicrosoftEmployees">
<FirstName>Paul</FirstName>
<LastName>Allen</LastName>
</ms:Employee>
<ap:Employee id='1' xmlns:ap="AppleEmployees">
<Name>Steve Jobs</Name>
</ap:Employee>
<ap:Employee id='2' xmlns:ap="AppleEmployees">
<Name>Steve Wozniak </Name>
</ap:Employee>
</Employees>
The scenario might be combining data from two different companies.
PowerShell demonstration program:
cls
$filename = "c:\XMLClass\IntroSamples\Sample05_Simpler_Namespace.xml"
[xml]$xmlDoc = Get-Content $filename
$xmlDoc.Employees.Employee[0]
$xmlDoc.Employees.Employee[1]
$xmlDoc.Employees.Employee[2]
$xmlDoc.Employees.Employee[3]
Output:
id ms FirstName LastName
-- -- --------- --------
1 MicrosoftEmployees Bill Gates
2 MicrosoftEmployees Paul Allen
1
2
Is there anyway to get a more logical output?
It seems like PowerShell locks into the first schema it sees for the Employee element, then cannot show the Name element of the Apple employees. This actually makes sense, but I was just checking to see if there is something fancier to handle this that I might be missing.
I know I could use SelectSingleNodes and XPath, but was just trying to see if and how PowerShell could handle this "out of the box".
If I reverse the code:
$xmlDoc.Employees.Employee[2]
$xmlDoc.Employees.Employee[3]
$xmlDoc.Employees.Employee[1]
$xmlDoc.Employees.Employee[0]
Then the output is:
id ap Name
-- -- ----
1 AppleEmployees Steve Jobs
2 AppleEmployees Steve Wozniak
1 ms:Employee
2 ms:Employee
Use format list to see all the properties. Format-table doesn't handle different sets of properties well.
$xmldoc.employees.employee | format-list
id : 1
ms : MicrosoftEmployees
FirstName : Bill
LastName : Gates
id : 2
ms : MicrosoftEmployees
FirstName : Paul
LastName : Allen
id : 1
ap : AppleEmployees
Name : Steve Jobs
id : 2
ap : AppleEmployees
Name : Steve Wozniak
I'm new to powershell so I had a simple question. Suppose I have the following powershell code:
$t = Get-SomeData -someParam someParamValue
$t.SomeProperty.SomeNestedField
The second command above will print the value of SomeNestedField, which is nested inside t's property called someProperty
Can I combine these two lines into one powershell command (perhaps through piping), so that the output of the second command comes from just one command overall ?
Requirement is that it should print the value, not assign it to some powershell variable ..
Perhaps something like:
Get-SomeData -someParam someParamValue | SomeProperty | SomeNestedField
Some info that might help out:
Suppose I change above code to this:
$t = Get-SomeData -someParam someParamValue
$u = $t.SomeProperty
$t.GetType()
$u.GetType()
When I execute $t.GetType(), the BaseType listed is a class, but if I do $u.GetType(), it's BaseType is listed as System.ValueType
You can use SELECT aka SELECT-OBJECT
Get-SomeData -someParam someParamValue | select -ExpandProperty SomeProperty
Or ()
(Get-SomeData -someParam someParamValue).SomeProperty.SomeNestedField
I am able to replace a single string in a SQL file using PowerShell as follows:
$newPrefix = "foo'
$dbUserMappingScriptPath = "C:\MySQL_Template.sql"
$updatedDbUserMapingScriptPath = "C:\MySQL.sql"
(gc $dbUserMappingScriptPath).Replace('DBPrefix_',$newPrefix) | sc $updatedDbUserMapingScriptPath
This is great for single scenarios, but I need to replace multiple strings. I have tried the following, but it doesn't perform the replace operation beyond replacing the first string of 'DBPrefix_' with $newPrefix. It does not perform the replacements for 'MDFDatabasePath' and 'LDFDatabasePath'.
How do I replace multiple strings given the following snippet? Note that this is wrapped in a Foreach-Object for the $.MDFDatabasePath and $.LDFDatabasePath values.
$dbUserMappingScriptPath = "C:\MySQL_Template.sql"
$updatedDbUserMapingScriptPath = "C:\MySQL.sql"
(gc $dbUserMappingScriptPath).Replace('DBPrefix_',$newPrefix).Replace('MDFDatabasePath',$_.MDFDatabasePath).Replace('LDFDatabasePath',$_.LDFDatabasePath) | sc $updatedDbUserMapingScriptPath
Here is a snippet of my SQL:
USE [master]
GO
CREATE DATABASE [DBPrefix_mydb] ON
( FILENAME = N'MDFDatabasePath\DBPrefix_mydb.MDF' ),
( FILENAME = N'LDFDatabasePath\DBPrefix_mydb.ldf' )
FOR ATTACH
GO
UPDATE: I had a mismatch in my PowerShell script in that I was running the replace on the wrong SQL script. The code above with an extra .Replace works like a charm
I'm writing a script to process a CSV file created on a non-Windows platform.
The CSV has a lot of columns, not all of which I want.
They are:
TypeName: System.Management.Automation.PSCustomObject
Name
----
Equals
GetHashCode
GetType
ToString
AVGCPUTIME
AVG_CARDS_PN
AVG_CARDS_RD
AVG_ELAPSED
AVG_IO_TIME
AVG_LINES_PRNTD
AVG_OV_MEM
AVG_OV_MEM_INT
AVG_SAV_MEM
AVG_SAV_MEM_INT
BEGINDATE
BEGINTIME
CARDS_PN
CARDS_RD
CPUTIME
DCKEYIN
ELAPSED
ENDDATE
ENDTIME
IO_TIME
JOBNAME
JOBSTATUS
JOBTYPE
LINES_PRNTD
MANUAL
MIXNUM
OV_MEM
OV_MEM_INT
PCJOB
REFNUM
RUNTIME PARAMETERS ...
SAV_MEM
SAV_MEM_INT
SCHEDDATE
SCHEDTIME
SYSTEM
TASKNUM
USERCODE
I have a problem selecting the property, RUNTIME PARAMETERS - both of the following bits of code result in me having a column with the name I expect, but every value in that column is empty (I'm using Out-GridView just now while writing the script, the final script will output data to a new file once I've filtered with Where-Object etc to pull out only the info I need - the intention is for the PowerShell script to run as an automated process when the file lands on the server).
$Inp = Import-Csv K:\LOGSTATS_ALLBATCH_20150602165021.CSV
$Inp| Select USERCODE,JOBNAME,MIXNUM,TASKNUM,BEGINDATE,BEGINTIME,ENDDATE,ENDTIME,DCKEYIN,MANUAL,JOBSTATUS,JOBTYPE,CPUTIME,IOTIME,ELAPSED,SYSTEM,"RUNTIME PARAMETERS"|OGV
$Inp = Import-Csv K:\LOGSTATS_ALLBATCH_20150602165021.CSV
$Inp| Select USERCODE,JOBNAME,MIXNUM,TASKNUM,BEGINDATE,BEGINTIME,ENDDATE,ENDTIME,DCKEYIN,MANUAL,JOBSTATUS,JOBTYPE,CPUTIME,IOTIME,ELAPSED,SYSTEM,#{Name="PARAMS";Expression={$_."RUNTIME PARAMETERS"}}|OGV
Here's a sample of the input:
"REFNUM","USERCODE","JOBNAME","MIXNUM","TASKNUM","BEGINDATE","BEGINTIME","ENDDATE","ENDTIME","SCHEDDATE","SCHEDTIME","DCKEYIN","MANUAL","PCJOB","JOBSTATUS","JOBTYPE","CPUTIME","AVGCPUTIME","IO_TIME","AVG_IO_TIME","ELAPSED","AVG_ELAPSED","SAV_MEM","AVG_SAV_MEM","OV_MEM","AVG_OV_MEM","SAV_MEM_INT","AVG_SAV_MEM_INT","OV_MEM_INT","AVG_OV_MEM_INT","LINES_PRNTD","AVG_LINES_PRNTD","CARDS_RD","AVG_CARDS_RD","CARDS_PN","AVG_CARDS_PN","SYSTEM","RUNTIME PARAMETERS"
01141730,TEST ,CONTROLCARD ,09376,00000,20150601,0106,20150601,0106,20150601,0100,N,N,N,COMPLETEDOK ,SCHEDULED ,0000000000,0000000000,0000000000,0000000000, 0:00:00, 0:00:00,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,0000000000,01234,"BETA" "INCR" "ALL"
And here's an example of the output from the 2nd piece of code, piped through Format-List:
USERCODE : TEST
JOBNAME : CONTROLCARD
MIXNUM : 09376
TASKNUM : 00000
BEGINDATE : 20150601
BEGINTIME : 0106
ENDDATE : 20150601
ENDTIME : 0106
DCKEYIN : N
MANUAL : N
JOBSTATUS : COMPLETEDOK
JOBTYPE : SCHEDULED
CPUTIME : 0000000000
IOTIME :
ELAPSED : 0:00:00
SYSTEM : 01234
PARAMS :
Any help understanding why I'm either not selecting the property with the space in it, or not seeing the values, would be greatly appreciated!
EDIT:
It seems the code was ok but there is a possible issue with the encoding of the header - adding screenshot from hex editor for #Ansgar Wiechers
It seems your input file contains null characters that mess up your field names. You can remove them like this:
$file = 'C:\path\to\your.csv'
(Get-Content $file -Raw) -replace [string][char]0 | Set-Content $file
Removing all null characters should be safe, since your file appears to be ASCII encoded (no BOM in your screenshot).
The removal operation took about a second when I tested it on a 13 MB sample file.
Warning: Do NOT use this on Unicode encoded files (UTF-8, UTF-16, ...) or you'll end up with gibberish in your files.
I am trying to get a list of security groups. (Successful - Using Get-EC2SecurityGroup)
Get a list of the specific IPPermissions associated with each security group. ( Successful - Using (Get-EC2SecurityGroup).IpPermissions )
Only return results where the FromPort = "xxx" ( Unsuccessful - Not sure how to access the FromPort property that is returned in the result list )
Ultimately what I am trying to accomplish is:
Get a list of existing security groups, and loop through each group.
While looping through each group, call the IpPermissions, and look for the specific FromPort "xxx".
If the FromPort is a match, record the other properties: (FromPort, IpProtocol, IpRanges, ToPort, UserIdGroupPairs)
Problem I am having
I am not sure how to do a loop using the amazon objects
I cant seem to access the properties even though they appear to be named and have values.
I have tried using -Filter with many different iterations, with no success.
The documentation seems self-referencing, and the examples I have run across dont get down to this level of detail.
Results returned from (Get-EC2SecurityGroup).IpPermissions
FromPort : 123
IpProtocol : tcp
IpRanges : {0.0.0.0/0}
ToPort : 123
UserIdGroupPairs : {}
Here's an example that does as you've described:
Filters security group objects by FromPort
Of the matched security groups, output IpProtocol, IpRanges, ToPort, and UserIdGroupPairs.
Code:
# Example using port 22
PS C:\> $port = 22
PS C:\> Get-EC2SecurityGroup |
? { $_.IpPermissions.FromPort -eq $port } |
% { $_.IpPermissions } |
Select -property IpProtocol, IpRanges, ToPort, UserIdGroupPairs
Output:
IpProtocol IpRanges ToPort UserIdGroupPairs
---------- -------- ------ ----------------
tcp {0.0.0.0/0} 22 {}
... ... ... ...