Is it possible in PowerShell to add a parameter on a cmdlet call ONLY if there is a variable to pass?
E.g.
Send-MailMessage -To $recipients (if($copy -ne "") -cc $copy) ....
Not the way you've written above but you can splat the parameters, building the hash with conditions, so you only have one call to send-mailmessage. An example from a script I wrote a few months ago:
#Set up default/standard/common parameters
$MailParams = #{
"Subject"="This is my subject";
"BodyAsHtml" = $true;
"From" = $MailFrom;
"To" = $MailTo;
"SmtpServer" = $SMTPServer;
};
#On the last day of the month, attach a logfile.
if ((Get-Date).AddDays(1).Day -eq 1) {
$attachment = $LogFilePath;
$ReportContent = "Full log for the the preceding month is attached.<br><br>" + $ReportContent;
$MailParams.Add("Attachments",$attachment);
}
send-mailmessage #MailParms
So in your case, it would be:
$MailParams = #{
"Subject"="This is my subject";
"From" = $MailFrom;
"To" = $recipients;
"SmtpServer" = $SMTPServer;
};
if (($copy -ne [string]::empty) -and ($copy -ne $null)) {
$MailParms.Add("CC",$copy);
}
send-mailmessage #MailParms
Related
I have a string like
$query = "date=20.10.2007&amount=400+date=11.02.2008&amount=1400+date=12.03.2008&amount=1500";
there are two variables named date and amount containing a value e.g date= 20.10.2007 and amount=400 and these two variables repeat itself with different values and each set (date & amount) are separated by '+' sign. Now i want to display this string like this:
Date Amount
20.10.2007 400
11.02.2008 1400
12.02.2008 1500
Need help
We can make judicious use of explode and preg_split here to get the output you want:
$query = "date=20.10.2007&amount=400+date=11.02.2008&amount=1400+date=12.03.2008&amount=1500";
$array = explode("+", $query);
$counter = 0;
echo "Date Amount\n";
foreach($array as $item) {
if ($counter > 0) echo "\n";
$parts = explode("&", $item);
echo preg_split("/=/", $parts[0])[1] . " ";
echo preg_split("/=/", $parts[1])[1];
$counter = $counter + 1;
}
This prints:
Date Amount
20.10.2007 400
11.02.2008 1400
12.03.2008 1500
The logic here is that we first split the query string on + to obtain components looking like:
date=20.10.2007&amount=400
Then, inside the loop over all such components, we split again by & to obtain the date and amount terms. Finally, each of these are split again on = to get the actual values.
Thanks a lot Tim Biegeleisen for your kind guidance. From your help i did it with this code below:
$str = "date=20.10.2007&amount=400+date=11.02.2008&amount=1400+date=12.03.2008&amount=1500"; $array = explode("+",$str);
$i = 0;
echo nl2br("Date Amount \n");
foreach($array as $item[$i])
{
parse_str($item[$i]);
echo $date;
echo $amount."<br>";
$i++;
}
I'm trying to write a powershell script that will output the contents of a column inside a spreadsheet to a txt file. I don't know powershell but I found and figured out how to get a cell, now I need the whole column. The spreadsheet in question has 8K+ rows. Here is what I have so far:
$SMTPApprovedXLS = "c:\temp\SMTP\SMTPAPPLIST.XLS"
$SheetName = "Active"
$objExcel = New-Object -ComObject Excel.Application
$objExcel.Visible = $False
$Workbook = $objExcel.Workbooks.open($SMTPApprovedXLS)
$Worksheet = $Workbook.sheets.item($SheetName)
$startRow = 4
[pscustomobject][ordered]#{
ApprovedIPs = $Worksheet.Cells.Item(4,$startRow).Value()
}
The column is "D" and should start at row 4.
Thanks in advance.
All you have to do is use a loop to run through all the entries and capture the data. Try this:
$SMTPApprovedXLS = "c:\temp\SMTP\SMTPAPPLIST.XLS"
$SheetName = "Active"
$objExcel = New-Object -ComObject Excel.Application
$objExcel.Visible = $False
$Workbook = $objExcel.Workbooks.open($SMTPApprovedXLS)
$Worksheet = $Workbook.sheets.item($SheetName)
$startRow = 4
$ApprovedIPs = #()
$count = $Worksheet.Cells.Item(65536,4).End(-4162)
for($startRow=4; $startRow -le $count.row; $startRow++)
{
$ApprovedIPs += $Worksheet.Cells.Item($startRow, 4).Value()
}
$ApprovedIPs | Out-File C:\ApprovedIPs.txt
Note that the last line is what creates the txt file with the desired data, where C:\ is the directory and ApprovedIPs is the file name. You can just substitute them for your desired location and name of the file.
Consider that CSV file:
Node Name,Client Name,Job Directory,Policy Name
server1,test.domain.com,"vmware:/?filter= VMHostName AnyOf "server2.domain.com", "server3.domain.com"",TEST
My code:
$events = Import-Csv "C:\file.csv" | foreach {
New-Object PSObject -prop #{
Server = $_.{Node Name};
Client = $_.{Client Name};
{JobDirectory/Script} = $_.{Job Directory};
Policy = $_.{Policy Name};
}
}
I have some problems when I try to parse the third field. I am not sure if its because the comma, or the double quote.
This is the object I would like to have:
Node Name : server1
Client Name : test.domain.com
JobDirectory/Script : vmware:/?filter= VMHostName AnyOf "server2.domain.com", "server3.domain.com"
Policy Name : TEST
Can someone help me?
Ok, so the easiest way to approach this is to read the file in with Get-Content and then split each line where the commas are not inside quotes. I borrowed the regex from this solution for this.
Using your current input data I would do something like this
$filedata = Get-Content C:\temp\test.csv
$asObject = ForEach($singlerow in ($filedata | Select-Object -Skip 1)){
$props = #{}
$singlerow = $singlerow -split ',(?=(?:[^"]*"[^"]*")*[^"]*$)'
[pscustomobject][ordered]#{
Server = $singlerow[0]
Client = $singlerow[1]
"JobDirectory/Script" = $singlerow[2]
Policy = $singlerow[3]
}
}
Sample Output from $asObject | Format-List
Server : server1
Client : test.domain.com
JobDirectory/Script : "vmware:/?filter= VMHostName AnyOf "server2.domain.com", "server3.domain.com""
Policy : TEST
Another way using your starting code
$obj = gc c:\temp\test.csv |
% { $_ -replace '"(\b[^"]*\b)"','$1' } |
convertfrom-csv | % { [pscustomobject][ordered] #{
Server = $_.{Node Name}
Client = $_.{Client Name}
{JobDirectory/Script} = $_.{Job Directory}
Policy = $_.{Policy Name} }
}
I'm trying to figure out how to get the page name from a facebook page and although I've figured out how to get it from the http://www.facebook.com/pagename version, I can't figure out how to test and get it from the longer version that looks like this http://www.facebook.com/pages/pagename/433425324544. How can I test to see if the path starts with /pages and how can I extract the pagename from it all using one function. Here's what I use to get the page name in the standard form.
function get_facebook_username( $facebook_url ) {
$url = $facebook_url;
$result = preg_match("/(https|http)?:\/\/(www\.)?facebook\.com\/?([^\/]*)/", $url, $matches);
$fb_username = 'default value';
if($result == 1){
$fb_username = $matches[3];
} else {
return;
}
echo "$fb_username";
}
I found a better way to do this I think except it cuts the last letter off the username if the url is in it's shortened version. For example.
//---short
$url = http://www.facebook.com/pagename
//---long
$url = http://www.facebook.com/pages/pagename/7532527927346
<?php
$url = $facebook_username;
$path = parse_url($url, PHP_URL_PATH);
$pathTrimmed = trim($path, 'pages/../0123456789');
echo $pathTrimmed;
?>
//---short
pagenam
//---long
pagename
Why is the short version missing the last letter?
The way I would go about this is to use explode to place the url into an array using the below code:
$url = "http://www.facebook.com/pages/pagename/7532527927346";
$result = explode("/", $url);
You get the following array:
array(6) {
[0]=>
string(5) "http:"
[1]=>
string(0) ""
[2]=>
string(16) "www.facebook.com"
[3]=>
string(5) "pages"
[4]=>
string(8) "pagename"
[5]=>
string(13) "7532527927346"
}
Then a simple if $result[3] == "pages" will allow you to check if the url contains pages.
Ninja Edit
In place of explode, you can also use the preg_split which will return no empty array elements:
$result = preg_split("~/~", $url, -1, PREG_SPLIT_NO_EMPTY);
I am parsing text output from a disk array that lists information about LUN snapshots in a predictable format. After trying every other way to get this data out of the array in a useable manner, the only thing I can do is generate this text file and parse it. The output looks like this:
SnapView logical unit name: deleted_for_security_reasons
SnapView logical unit ID: 60:06:01:60:52:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
Target Logical Unit: 291
State: Inactive
This repeats all through the file with one line break between each group. I want to identify a group, parse each of the four lines, create a new PSObject, add the value for each line as a new NoteProperty, and then add the new object to a collection.
What I can figure out is, once I identify the first line in the block of four lines, how to then process the text from lines two, three, and four. I'm looping through each line, finding the start of a block, and then processing it. Here's what I have so far, with comments where the magic goes:
$snaps = get-content C:\powershell\snaplist.txt
$snapObjects = #()
foreach ($line in $snaps)
{
if ([regex]::ismatch($line,"SnapView logical unit name"))
{
$snapObject = new-object system.Management.Automation.PSObject
$snapObject | add-member -membertype noteproperty -name "SnapName" -value $line.replace("SnapView logical unit name: ","")
#Go to the next line and add the UID
#Go to the next line and add the TLU
#Go to the next line and add the State
$snapObjects += $snapObject
}
}
I have scoured the Google and StackOverflow attempting to figure out how I can reference the line number of the object I'm iterating through, and I can't figure it out. I may rely on foreach loops too much and so that's affecting my thinking, I don't know.
As you say, I think you're thinking too much foreach when you should be thinking for. The below modification should be more along the lines of what you're looking for:
$snaps = get-content C:\powershell\snaplist.txt
$snapObjects = #()
for ($i = 0; $i -lt $snaps.length; $i++)
{
if ([regex]::ismatch($snaps[$i],"SnapView logical unit name"))
{
$snapObject = new-object system.Management.Automation.PSObject
$snapObject | add-member -membertype noteproperty -name "SnapName" -value ($snaps[$i]).replace("SnapView logical unit name: ","")
# $snaps[$i+1] Go to the next line and add the UID
# $snaps[$i+2] Go to the next line and add the TLU
# $snaps[$i+3] Go to the next line and add the State
$snapObjects += $snapObject
}
}
A while loop may be even cleaner because then you can increment $i by 4 instead of 1 when you hit this case, but since the other 3 lines won't trigger the "if" statement... there's no danger, just a few wasted cycles.
Another possibility
function Get-Data {
$foreach.MoveNext() | Out-Null
$null, $returnValue = $foreach.Current.Split(":")
$returnValue
}
foreach($line in (Get-Content "C:\test.dat")) {
if($line -match "SnapView logical unit name") {
$null, $Name = $line.Split(":")
$ID = Get-Data
$Unit = Get-Data
$State = Get-Data
New-Object PSObject -Property #{
Name = $Name.Trim()
ID = ($ID -join ":").Trim()
Unit = $Unit.Trim()
State = $State.Trim()
}
}
}
Name ID Unit State
---- -- ---- -----
deleted_for_security_reasons 60:06:01:60:52:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX 291 Inactive
switch -regex -file C:\powershell\snaplist.txt {
'^.+me:\s+(\S*)' {$SnapName = $Matches[1]}
'^.+ID:\s+(\S*)' {$UID = $Matches[1]}
'^.+it:\s+(\S*)' {$TLU = $Matches[1]}
'^.+te:\s+(\S*)' {
New-Object PSObject -Property #{
SnapName = $SnapName
UID = $UID
TLU = $TLU
State = $Matches[1]
}
}
}
try this
Get-Content "c:\temp\test.txt" | ConvertFrom-String -Delimiter ": " -PropertyNames Intitule, Value
if you have multiple packet try this
$template=#"
{Data:SnapView logical unit name: {UnitName:reasons}
SnapView logical unit ID: {UnitId:12:3456:Zz}
Target Logical Unit: {Target:123456789}
State: {State:A State}}
"#
Get-Content "c:\temp\test.txt" | ConvertFrom-String -TemplateContent $template | % {
[pscustomobject]#{
UnitName=$_.Data.UnitName
UnitId=$_.Data.UnitId
Target=$_.Data.Target
State=$_.Data.State
}
}