Special characters in PowerShell - powershell

I am trying to work with PowerShell and have it output the copyright character into a Microsoft Word document. For example, the code listed below is what I am trying to use and it is not working.
$SummaryPara.Range.Text = "© "
$SummaryPara.Range.Text = "Get-Date -Format yyyy"
$SummaryPara.Range.Text = " - Name of Org Here "
$SummaryPara.Range.InsertParagraphAfter()
Do I need to use the Alt + 0169 sequence somehow?
I am not sure what I am doing wrong since the following code seems to work:
$selection.TypeParagraph()
$selection.TypeText("© ")
$selection.TypeText((Get-Date -Format yyyy))
$selection.TypeText(" - Name of Org Here ")
$selection.TypeParagraph()
How can I make this work for both the copyright character and other similar special characters?

There are a few problems here. I'll list those and address each:
You can get any character you need by casting the Unicode representation to a char. In this case
[char]0x00A9
You assign a new value to $SummaryPara.Range.Text three times. So, you are overwriting the previous value each time, instead of concatenating ('+' operator), which I think is what you were trying to do.
You are trying to use the cmdlet Get-Date, but since you have quoted it, you will end up with the literal string "Get-Date -Format yyyy", instead of the result of the cmdlet.
Putting it all together, I think you want something like this:
$word = New-Object -ComObject Word.Application
$doc = $word.Documents.Add()
$SummaryPara = $doc.Content.Paragraphs.Add()
$SummaryPara.Range.Text = [char]0x00A9 + ($date = Get-Date -Format yyyy) + " - Name of Org Here "
$word.Visible = $true

Related

How to use the .AddMonths method of Get-Date in Powershell

I am writing a simple script that gets the date, gets the date 6 months from now, and copies both of those dates to the clipboard. When run, the script is supposed to copy:
Terminated MM/dd/yy - Delete from AD on MM/dd/yyyy
But it only copies
Terminated MM/dd/yyyy - Delete from AD on
$currentDate = Get-Date -Format "MM/dd/yyyy"
$futureDate = Get-Date.AddMonths(6) -Format "MM/dd/yyyy"
$copyThisText = "Terminated " + $currentDate + " - Delete from AD on " + $futureDate
$copyThisText | clip
The reason it failed is because once you format a date using -Format "MM/dd/yyyy" it converts that variable to a type of string rather than datetime which then means that the normal datetime methods are no longer available.
For demonstration purposes I have tried to change as little as possible. What I have done below is set the $currentDate and $futureDate without implicitly converting them to strings. I then format them the way you want when you are concatenating the strings in $copyThisText.
This will do what you want.
$currentDate = Get-Date
$futureDate = (Get-Date).AddMonths(6)
$copyThisText = "Terminated " + $currentDate.tostring("MM/dd/yyyy") + " - Delete from AD on " + $futureDate.tostring("MM/dd/yyyy")
$copyThisText | clip
Furthermore there are multiple ways to format the strings that could aid in readability of the code. Thanks #Santiago Squarzon for the suggestion -
"Terminated {0:MM/dd/yyyy} - Delete from AD on {1:MM/dd/yyyy}" -f $currentDate, $futureDate

Is there a way to replace the first two occurrences of a value in a string?

I am going to be as clear with my question as I can.
I might be missing something very obvious here but I just don't know how to find a solution...
I have a string and I would like to replace the first two occurrences of ":" with "/":
String:
$string = 2020:10:07 08:45:49
Desired String:
2020/10/07 08:45:49
I have tried using .Replace as seen below:
$string = $string.Replace([regex]":","/",2)
But I am given this error every time:
Cannot find an overload for "replace" and the argument count: "3".
I have seen others use .Replace in this way before so I'm not sure what is so different about my usage. Can anyone point me in the right direction?
PowerShell is .net-based language.
String does not have overload method Replace with anything like count argument in .Net, but Python's string does.
You can use this:
$string = '2020:10:07 08:45:49'
#Replace 2+ spaces you have in source with single space
$string = $string -replace '\s+', ' '
# Variant 0 - Best - ALWAYS use proper types. There is DateTime type to use for Dates and Times!
#Exact parse by format to DateTime object
$dt = [DateTime]::ParseExact($string, 'yyyy:MM:dd hh:mm:ss', [System.Globalization.CultureInfo]::InvariantCulture)
#Convert DateTime to String
$result = $dt.ToString('yyyy\/MM\/dd hh:mm:ss')
.Net's String.Split has optional parameter count that means split no more than into # pieces. You can use it:
# Variant1
$result = [string]::Join('/',$string.Split(':', 3))
# Variant2
$result = $string.Split(':', 3) -join '/'
String.Replace() does not support regex patterns, nor does it accept a maximum count.
Use the -replace regex operator instead:
$string = '2020:10:07 08:45:49'
$string -replace '(?<=^[^:]*):(.*?):','/$1/'
This will replace only the first and second occurrence of : with /
Specifically for date/time representations, you may want to parse it as such, at which point you can easily re-format it:
$string = '2020:10:07 08:45:49'
$datetime = [datetime]::ParseExact($string, "yyyy:MM:dd HH:mm:ss", $null)
# Now we can create a new string with the desired format
Get-Date $datetime -Format 'yyyy/MM/dd HH:mm:ss'
# This might be easier than figuring out regex patterns
'{0:dd/MMM/yyyy-HH.mm.ss}' -f $datetime

Using powershell to manipulate URL header with real live system data

I am trying to use powershell to manipulate a url value for a command program that is accessing a web Url.
Basically the case is like this
run in Powershell:
Program Argument https://www.example.com/dash/926846/l.php?link=bTP77O5LyLorxCtjnkdE0g&sectime=1598048132
The Sectime is in Unix time format. What i am trying to do is :
use the powershell command (Get-Date -Date ((Get-Date).DateTime) -UFormat %s) to generate the system time in real time,
Append the result to the end of the Url as a value for sectime.
I tried to concatnate the arguments using call operator :
Arg1=program
Arg2=parameter
Arg3=Url
& $Arg1 Arg2 $Arg3
now the issue is i can do
this is the issue. & $Arg1 Arg2 $Arg3 and that works , but i can not modify the URL to take the real time command (Get- Date -Date ((Get-Date).DateTime) -UFormat %s)
if i split the URL arg into two i cant not concatnate them like this
"https://www.example.com/dash/926846/l.php?link=bTP77O5LyLorxCtjnkdE0g&sectime=(Get-Date -Date ((Get-Date).DateTime) -UFormat %s)."
Since it is a string and an command
An idea how to do this?
$uriTemplate = 'https://www.example.com/dash/{0}/l.php?link={1}&sectime={2}'
$id = '926846'
$link = 'bTP77O5LyLorxCtjnkdE0g'
$timeunixseconds = [System.DateTimeOffset]::UtcNow.ToUnixTimeSeconds().ToString()
$uriSting = [String]::Format($uriTemplate, # Template with placeholders {0}, {1}, {2}...
$id, # first argument goes {0}
$link, # second goes {1}
$timeunixseconds ) # third goes {2}, etc etc
$isUriOk = [System.Uri]::IsWellFormedUriString($uriSting, [System.UriKind]::Absolute)
DateTimeOffset class starting with some .net version (4.5th .net, 5th powershell, AFAIR) has To(From)UnixTimeSeconds and To(From)UnixTimeMilliseconds methods.
DateTime (and Get-Date, which returns DateTime) does not have such methods! Use DateTimeOffset.
And for your original case:
Inside double-quoted strings, variables (even simple, in my opinion) should be added in $() brackets:
"Hello, $($env:USERNAME), it's $(Get-Date -Format 'D') today!"
# Hello, User1, it's Aug 22 2020 today!
Single variables can be added without $() syntax, but I'd recommed add $() always.
Inside single-quoted strings, $() or $var does not work:
'Hello, $($env:USERNAME), it is $(Get-Date -Format "D") today!'
# Hello, $($env:USERNAME), it is $(Get-Date -Format "D") today!

Culture based formatting of time variable

In this example it seems to me that the first two outputs should match, giving me formatting based on my defined culture. The last should be different because French formatting is different. Instead, the last two are the same, and are both getting some kind of default formatting. So, how do I do Culture based formatting when the time is a variable rather than formatting directly with Get-Date? It seems like it should be the same, but it's not.
get-date -format ((Get-Culture).DateTimeFormat.FullDateTimePattern)
$time = Get-Date
$pattern = 'FullDateTimePattern'
$formattedTime = $time -f (Get-Culture).DateTimeFormat.$pattern
Write-Host "$formattedTime"
$culture = New-Object system.globalization.cultureinfo('fr-FR')
$formattedTime = $time -f ($culture).DateTimeFormat.$pattern
Write-Host "$formattedTime"
The output I get is
July 9, 2019 11:22:01 AM
07/09/2019 11:22:01
07/09/2019 11:22:01
What I want to get is
July 9, 2019 11:26:46 AM
July 9, 2019 11:26:46 AM
Tuesday 9 July 2019 11:26:46
EDIT: So, based on I.T Delinquent's response, I tried this
$pattern = 'longDateTimePattern'
$date = Get-Date
$format = (Get-Culture).DateTimeFormat.$pattern
$string = ($date).ToString($format)
Write-Host $string
$culture = New-Object system.globalization.cultureinfo('de-DE')
$format = $culture.DateTimeFormat.$pattern
$string = ($date).ToString($format)
Write-Host $string
And it gave me identical results. Because it's not 'longDateTimePattern', its 'longDatePattern'. Given that the pattern could become a user supplied string, I better validate them.
Your attempt at using the -f operator is flawed (see bottom section).
To get the desired output, use the [datetime] type's appropriate .ToString() overload:
$time.ToString($culture.DateTimeFormat.$pattern, $culture)
Passing $culture as the 2nd argument ensures that the formatting is applied in the context of that culture.
If your intent is truly to use a format from another culture and apply it in the context of the current culture, simply omit the 2nd argument (as an alternative to the Get-Date -Format approach in your question):
$time.ToString($culture.DateTimeFormat.$pattern)
If there's no need to involve a different culture, the task becomes much simpler, by way of the standard date-time format strings, where single-character strings such as "D" refer to standard formats, such as LongDatePattern:
$time.ToString("D")
You can also pass these strings to Get-Date -Format
Get-Date -Format D
As for what you tried:
In order for the -f operator to work correctly, your LHS must be a string template with placeholders ({0} for the first one, {1} for the second, ...), to be replaced with the RHS operands.
Using a simple example:
Format the RHS, an [int], as a number with 2 decimal places.
PS> '{0:N2}' -f 1
1.00
Therefore, $time -f (Get-Culture).DateTimeFormat.$pattern doesn't perform (explicit) formatting at all, because the LHS - $time - contains no placeholders.
That is, the RHS is ignored, and the LHS is returned as a string: It is effectively the same as calling $time.ToString() in the context of the invariant culture (because the result of applying the -f operator is always a string and PowerShell uses the invariant culture in many string-related contexts).
While you can incorporate a specific date-time format string into a template-string placeholder - by following the placeholder index with : and a format string, as shown above ({0:N2}) - you cannot also provide a culture context for it.
You'd have to (temporarily) switch to the desired culture first:
# Save the currently effective culture and switch to the French culture
$prev = [cultureinfo]::CurrentCulture
[cultureinfo]::CurrentCulture = 'fr-FR'
# Format with the desired format string.
"{0:$($culture.DateTimeFormat.$pattern)}" -f $time
[cultureinfo]::CurrentCulture = $prev
I think this has something to do with how the Get-Date is passed using the variable, it seems to lose the format capability. In fact, if you try using Write-Host ($date -Format $format) gives an error:
Unexpected token '$format' in expression or statement
Here are my setup variables:
$pattern = 'FullDateTimePattern'
$format = (Get-Culture).DateTimeFormat.$pattern
$date = Get-Date
As stated above, using Write-Host ($date -f $format) and incorrectly outputs 07/09/2019 12:24:38. However, using any of the below options does work and correctly outputs 09 July 2019 12:24:38:
Write-Host (Get-Date -Format $format)
Write-Host (Get-Date).ToString($format)
Write-Host ($date).ToString($format)
Hope this helps :)

PowerShell - formatting date to yyMMdd format

I run a PowerShell script that passes a parameter, such as "20160428".
I need to format this into yyMMdd (i.e., getting "160428" as the result). I could just strip out the "20", but I would like to get this right. For such I did so many attempts, such as:
#$COBDATE= '{0:yyMMdd}' -f $COBDATE
#$COBDATE = ([datetime]::ParseExact($COBDATE, "yyMMdd", [System.Globalization.CultureInfo]::InvariantCulture )).DayOfWeek
And the last one:
$COBDATE = ("{0:yyMMdd}" -f [datetime]::parse($COBDATE))
The below works, but once I replace "Get-Date" by my date "20160428" it just prints out the yyMMdd string.
$b = (Get-Date).AddDays(-1).ToString("yyMMdd")
So if I try this:
$input = "20160428"
$format = "yyMMdd"
$input_toDate_up = [DateTime]::ParseExact($input, $format, $null).ToString($format)
$input_toDate_up
It just says that the string is not a valid Date Time, which seems to be the root cause.
How can I fix this?
$Input = "20160428"
Get-Date -Year $Input.Substring(0,4) -Month $Input.Substring(4,2) -Day $Input.Substring(6,2) -Format "yyMMdd"
I think for one $input is a reserved variable so you shouldn't use it as nothing will really work in there as you expect. See here about_Automatic_Variables
I have used this drawn out substring process before with varied abstract date formats.
$dateinput = "20160428"
$dateformat = "yyMMdd"
Get-Date($dateinput.Substring(4,2) + "/" + $dateinput.Substring(2,2) + "/" + $dateinput.substring(0,4)) -Format $dateformat
I'm sure there is a shorter regex method, but that is not under my hat yet.