Combination into a file done in powershell (String + Variable) - string

My question is related about how can I write a line that combines a string (that contains a $ symbol) and a variable into a single line that goes into text file.
I'm creating a ps1 from a function.
function pwd{
param(
[Parameter(ValueFromPipeline=$True,position=0,mandatory=$true)][String]$Temp,
[Parameter(ValueFromPipeline=$True,position=1,mandatory=$true)][String]$Path,
[Parameter(ValueFromPipeline=$True,position=2,mandatory=$true)][String]$SubscriptionName
)
$NewFilePath = "$Path\newfile.ps1"
New-Item -ItemType file $NewFilePath -Force
Add-Content $NewFilePath ' $TimeStart=Get-Date'
Add-Content $NewFilePath " $AccountName=""$($SubscriptionName)"" " #Here's my doubt
}
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
pwdtest -Temp "String" -Path $ScriptPath -SubscriptionName "mail#something.com"
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
pwdtest -Temp "String" -Path $ScriptPath -SubscriptionName "mail#something.com"
So calling the function pwd this way:
$ScriptPath = split-path -parent $MyInvocation.MyCommand.Definition
pwd -Temp "String" -Path $ScriptPath -SubscriptionName "mail#something.com"
How can I rewrite that line?
Add-Content $NewFilePath " $AccountName=""$($AutomationAccount)"" "
Because I need to write in the text file this:
$TimeStart=Get-Date
$AccountName = "mail#something.com"
And right now if I use that line I've got this in the text file:
$TimeStart=Get-Date
="mail#something.com"
How can I say PowerShell Add-Content not interpretate the $AccountName as a "NULL" value and I need to use it as a content string and not a variable.
I had this idea of combination:
Add-Content $NewFilePath ' $AccountName=' + " ""$($SubscriptionName)"" "
But It doesn't work.
Add-Content : A positional parameter cannot be found that accepts argument '+'.
At C:\Users\JoseGabriel\test.ps1:10 char:5
+ Add-Content $NewFilePath ' $AccountName=' + " ""$($SubscriptionName)"" "
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Add-Content], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.AddContentCommand

Have you tried:
Add-Content $NewFilePath " `$TimeStart=Get-Date"
Add-Content $NewFilePath " `$AccountName=""$($SubscriptionName)"""
Escape characters, Delimiters and Quotes
The PowerShell escape character is the grave-accent(`).
The escape character can be used in three ways:
When used at the end of a line, it is a continuation character - so the command will continue on the next line.
To indicate that the next character following should be passed without substitution. For example $myVariable will normally be expanded to display the variables contents but `$myVariable will just be passed as $myVariable.
When used inside double quotation marks, the escape character indicates that the following character should be interpreted as a 'special' character.
Source: http://ss64.com/ps/syntax-esc.html

Related

Powershell excel to csv script works in ISE but not in powershell console

I have a short script that takes certain worksheets out of an excel file and saves them individually as a CSV file.
Function ExcelToCsv ($File) {
$myDir = Split-Path -Parent $($global:MyInvocation.MyCommand.Definition)
$path = "$myDir\csv_files"
If(!(test-path -PathType container $path))
{
Write-Host "Folder csv_files not found, creating..."
New-Item -ItemType Directory -Path $path
}
$excelFile = "$myDir\" + $File + ".xlsx"
$Excel = New-Object -ComObject Excel.Application
$wb = $Excel.Workbooks.Open($excelFile)
$excel.DisplayAlerts = $false;
foreach ($ws in $wb.Worksheets) {
if($ws.name -like '*sheet*') {
$ws.SaveAs("$myDir\csv_files\" + $ws.name + ".csv", 6, 0, 0, 0, 0, 0, 0, 0, $true)
Write-Host "Saved file: $myDir\csv_files\"$ws.name".csv"
} else {
Write-Host "Worksheet "$ws.name" not an correct sheet. Not saved"
}
}
$Excel.Quit()
}
$FileName = "myexcel"
ExcelToCsv -File $FileName
Write-Host "`nCSV files successfully created"
read-host "Press ENTER to exit...."
This is the entire code, not much to it and this is the correct output when run from ISE:
PS U:\excel_to_csv> U:\excel_to_csv\create_csv_files.ps1
Saved file: U:\excel_to_csv\csv_files\ 1sheet .csv
Saved file: U:\excel_to_csv\csv_files\ 2sheet .csv
Saved file: U:\excel_to_csv\csv_files\ 3sheet .csv
CSV files successfully created
Press ENTER to exit....:
But when I use a Powershell console:
Folder csv_files not found, creating...
New-Item : Cannot find drive. A drive with the name 'if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -
Scope Process Bypass }; & 'U' does not exist.
At U:\excel_to_csv\create_csv_files.ps1:7 char:9
+ New-Item -ItemType Directory -Path $path
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (if((Get-Executi... Bypass }; & 'U:String) [New-Item], DriveNotFoundExce
ption
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.NewItemCommand
Ľutujeme, if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'U:\excel_to_csv\
myexcel.xlsx sa nepodarilo nájsť. Je možné, že bol premiestnený, premenovaný alebo odstránený.
At U:\excel_to_csv\create_csv_files.ps1:11 char:5
+ $wb = $Excel.Workbooks.Open($excelFile)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
CSV files successfully created
Press ENTER to exit....:
Some of it is written in Slovakian, it roughly translates to:
Sorry, if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'U:\excel_to_csv\
myexcel.xlsx could not be found. It is possible it was moved, renamed or deleted.
I have tried searching for a solution but nothing worked yet.
I tried making a bash script like this:
powershell.exe -noexit -file U:\create_csv_files.ps1
But that didn't work, not sure if I screwed it up.
As I am on a company computer I am unable to use administrator privileges, but if you believe the lack of them is the problem, I might be able to do something about it.
Thank you for any and all help!
Replace
$myDir = Split-Path -Parent $($global:MyInvocation.MyCommand.Definition)
with
$myDir = $PSScriptRoot
The automatic $PSScriptRoot variable reliably reports the full path of the directory in which the currently executing script is located, irrespective of how the script was invoked. The related $PSCommandPath variable contains the script file's own full path.
Your symptom implies that you invoked your script from outside a PowerShell session, via powershell.exe -Command (with the -Command CLI parameter potentially being positionally implied), in which case $global:MyInvocation.MyCommand.Definition contains the entire command text passed to -Command.

How to find a word/phrase in a line using PowerShell?

I have been at this for days now but can't seem to figure it out.
I am trying to compare values(PartNumber) from the database to the first line of the text file. If the PartNumber exists(in the first line of the file) display a message "Part Number Matches" if it doesn't send an email.
The issue is that I get messages saying parts do not match when they are clearly the same.
All wrongly mismatched part numbers have a letter in the beginning for ex. D78948, C56234, etc. At first I thought maybe it is because the part number is alphanumeric. But then the parts that are correctly matched are also alphanumeric.
The PartNumber in the terminal is the one from the database.You can clearly see from the picture that the part number from the database and the one in the text file are exactly the same but the check still fails.
Instead of If (Get-Content -Path $fullPath -TotalCount 1 | Select-String -Pattern $partNo -AllMatches) I have tried
If($eiaContent -like "*$partno*") ,
If($eiaContent | Select-String -Pattern $partno)
But none of them seem to work.
Any help is appriciated!
Code:
$emailFrom = " CNC Data Discrepancy <DoNotReply#outlook.com>"
$emailTo = "ABC#nicholsonmfg.com"
$server = "Sidney.sidney.nii"
$database = "NML_Sidney"
#Query to get MAFN values in the last x hours(ET-Elapsed Time)
$MafnQueryEt = "SELECT [MAFN] As MAFNET FROM [NML_Sidney].[dbo].[MfgAidsDocLibraryTransactions]"
#Invoke Sql
$MafnSqlEt = Invoke-Sqlcmd -ServerInstance $server -Database $database -Query $MafnQueryEt
Write-Host $MafnSqlEt.MAFNET
$aidLibPathFolder = "C:\Users\Desktop\CNC_Transfer_Test_Folders\AidLib_Test"
$filterA = "MAZAK INTEGREX E-1550 WFO"
$filterB = "MILLING_MAZAK_INTEGREX_E1550"
#Filter child items to get the .EIA files
Get-ChildItem -Path $aidLibPathFolder -Include *.EIA -Recurse | ForEach-Object{
#Splitting the folder name because the first part of the name is the MAFN in the db(less the zeros). The second part after the dot(.) is the version number
$fullPath = $_.FullName
$baseName = $_.Name
$folderName = $_.Directory.Name
$splitFolderName = $folderName.Split('.')
$firstPart = $splitFolderName[0].TrimStart("0")
$version = "VER"+ " " + $splitFolderName[1]
$ver = $splitFolderName[1].TrimStart("0")
$versionNoZero = "VER"+ " " + $ver
#Filter the EIA files that have the specific line of text.
If(Get-Content -Path $fullPath | Select-String -Pattern $filterA,$filterB){
#Get first line of file.
$eiaContent= Get-Content -Path $fullPath -TotalCount 1
If($MafnSqlEt.MAFNET -eq $firstPart){
$partNoQuery = "SELECT [PartNo] FROM [NML_Sidney].[dbo].[vMADL_EngParts] Where MAFN=$firstPart"
$partNoSql = Invoke-Sqlcmd -ServerInstance $server -Database $database -Query $partNoQuery
$revQuery = "SELECT [MA_Rev] As Rev FROM [NML_Sidney].[dbo].[MADL_EngParts] Where MAFN=$firstPart"
$revSql = Invoke-Sqlcmd -ServerInstance $server -Database $database -Query $revQuery
[System.String]$partNo = $partNoSql.PartNo
$rev = "REV" + " "+ $revSql.Rev
$partNo.GetType()
}
If (Get-Content -Path $fullPath -TotalCount 1 | Select-String -Pattern $partNo -AllMatches){
Write-Host "PART matches" -BackgroundColor Green -ForegroundColor Black
Write-Host `PartNumberMatch` $partNo `Folder` $folderName `FileName` $baseName -BackgroundColor Green -ForegroundColor Black
}
Else{
Write-Host "PART does not match" -BackgroundColor Red -ForegroundColor Black
Send-MailMessage -From $emailFrom -To 'hargul.sidhu#nicholsonmfg.com' -Subject "ALERT! DATA DISCREPANCY - '$folderName'" -Body "Incorrect Part Number in '$baseName' Path -'$fullPath'. **DO NOT REPLY. THIS INBOX IS NOT MONITORED**" -SmtpServer 'XXXX
Write-Host `PartNumberMismatch` $partNo `Folder` $folderName `FileName` $baseName -BackgroundColor Red -ForegroundColor Black
}

Using select-string to output list from 1000+ files

I'm trying to get a specific string from a text file and output it and the filename to a separate txt file. I have tried the following but get an error message. I've looked for answers but haven't found any. Any help is appreciated.
I Should add that I'm fairly new to Powershell.
Select-String -Path C:\temp\test1.txt -Pattern 'batch3'|ForEach-Object {
#' File name - {0} {1}
..................... '# -f $_.Name, (Get-Content $_.FullName -Raw) }
| Out-File 'C:\temp\test_output.txt'
It works if I substitute Select-String for Get-Content. The problem then is that it takes the entire content of the file and that is not what I need.
error message:
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:6 char:29
+ '# -f $.Name, (Get-Content $.FullName -Raw)
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentCommand
Select-String does not output a property FullName. However, there is Path property. Try this:
(Get-Content $_.Path -Raw)
This will fix the error, but if you want to output just a line with the string you found, not the entire file contents, remove Get-Content and try this:
Select-String -Path C:\temp\test1.txt -Pattern 'batch3'|ForEach-Object {
#' File name - {0} {1}
..................... '# -f $_.Filename, $_.Line }
| Out-File 'C:\temp\test_output.txt'

Excel.Application: Microsoft Excel cannot access the file '[<filename>]' There are several possible reasons:

I have a PowerShell script that works, it helps me run multiple queries against multiple servers and save each output in different CSV and then merge them together into an Excel file.
$Servers = get-content -Path "Servers.txt"
$DatabaseName ="master"
#$credential = Get-Credential #Prompt for user credentials
$secpasswd = ConvertTo-SecureString "MyPassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ("sa", $secpasswd)
$QueriesFolder = "Queries\"
$ResultFolder = "Results\"
ForEach($Server in $Servers)
{
$DateTime = (Get-Date).tostring("yyyy-MM-dd")
ForEach ($filename in get-childitem -path $QueriesFolder -filter "*.sql" | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}} )
{
$oresults = invoke-sqlcmd -ServerInstance $Server -Database $DatabaseName -Credential $credential -InputFile $filename.fullname
write-host "Executing $filename on $Server"
$BaseNameOnly = Get-Item $filename.fullname | Select-Object -ExpandProperty BaseName
$oresults | export-csv $ResultFolder$BaseNameOnly.csv -NoTypeInformation -Force
}
$All_CSVs = get-childitem -path $ResultFolder -filter "*.csv" | sort-object {if (($i = $_.BaseName -as [int])) {$i} else {$_}}
$Count_CSVs = $All_CSVs.Count
Write-Host "Detected the following CSV files: ($Count_CSVs)"
Write-Host " "$All_CSVs.Name"`n"
$ExcelApp = New-Object -ComObject Excel.Application
$ExcelApp.SheetsInNewWorkbook = $All_CSVs.Count
$output = "C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
if (Test-Path $output)
{
Remove-Item $output
Write-Host Removing: $output because it exists already
}
$xlsx = $ExcelApp.Workbooks.Add()
for($i=1;$i -le $Count_CSVs;$i++)
{
$worksheet = $xlsx.Worksheets.Item($i)
$worksheet.Name = $All_CSVs[$i-1].Name
$file = (Import-Csv $All_CSVs[$i-1].FullName)
$file | ConvertTo-Csv -Delimiter "`t" -NoTypeInformation | Clip
$worksheet.Cells.Item(1).PasteSpecial()|out-null
}
$xlsx.SaveAs($output)
Write-Host Creating: $output
$ExcelApp.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xlsx) | Out-Null;
Write-Host "Closing all worksheet"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelApp) | Out-Null;
Write-Host "Closing Excel"
[System.GC]::Collect();
[System.GC]::WaitForPendingFinalizers()
Remove-Item "$ResultFolder\*" -Include *.csv
Write-Host "Cleaning all *.csv"
Start-Sleep -Seconds 3
}
In order to make this script more portable I want all the paths mentioned into it to be stored into a variable and then concatenated.
But as soon as I change:
$output = "C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
into:
$output = $ResultFolder + $Server + " $DateTime.xlsx"
things get nasty and I receive the error:
Microsoft Excel cannot access the file 'C:\Users\FrancescoM\Documents\Results\0DC80000'.
There are several possible reasons:
• The file name or path does not exist.
• The file is being used by another program.
• The workbook you are trying to save has the same name as a currently open workbook.
At C:\Users\FrancescoM\Desktop\CSV\QueryLauncher.ps1:50 char:2
+ $xlsx.SaveAs($output)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
I don't understand, I think I'm concatenating things right.
I also followed this StackOverflow post and restarted my computer after adding "C:\Windows\SysWOW64\config\systemprofile\desktop" but the problem isn't fixed.
How can a variable path mess things up with Excel?
Because you are not defining the full path in the $ResultFolder variable, it will be expanded using the current working directory.
Just look at the path you want it to be:
"C:\Users\FrancescoM\Desktop\CSV\Results\" + $Server + " $DateTime.xlsx"
and the resulting path using the partial $ResultFolder variable:
C:\Users\FrancescoM\Documents\Results\0DC80000
Since you want the output file in a folder on your desktop, set the $output to
$output = Join-Path $([Environment]::GetFolderPath("Desktop")) "CSV\Results\$Server $DateTime.xlsx"
EDIT
From your last comment I understand that you want the output to be in a subfolder called "Results" that resides inside the folder the script itself is in.
In that case do this:
# get the folder this script is running from
$ScriptFolder = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path $MyInvocation.MyCommand.Path }
# the following paths are relative to the path this script is in
$QueriesFolder = Join-Path -Path $ScriptFolder -ChildPath 'Queries'
$ResultFolder = Join-Path -Path $ScriptFolder -ChildPath 'Results'
# make sure the 'Results' folder exists; create if not
if (!(Test-Path -Path $ResultFolder -PathType Container)) {
New-Item -Path $ResultFolder -ItemType Directory | Out-Null
}
Then, when it becomes time to save the xlsx file, create the full path and filename using:
$output = Join-Path -Path $ResultFolder -ChildPath "$Server $DateTime.xlsx"
$xlsx.SaveAs($output)
P.S. I advice to use the Join-Path cmdlet to combine file paths or to make use of [System.IO.Path]::Combine() instead of joining paths together like you do with this line: $oresults | export-csv $ResultFolder$BaseNameOnly.csv. Using the latter can lead to unforeseen pathnames if ever you forget to postfix the first path part with a backslash.
P.S.2 Excel has its own default output path set in Tools->Options->General->Default File Location and has no idea of the relative path for the script. This is why you should save using a Full path and filename.

Variable concatenation in wrong order

I have the following:
function createFolder($folderName, $curPath)
{
$dest = $curPath + $folderName
write-host "Path is : " + $dest
# code to mess around with files etc
}
When I run this it gives me the following output:
Path is : + Test_Folder C:\Users\Me
Is there something I'm missing with the + operator, or a join/concat method that is meant for this kind of function? What is the correct way to create/concat/manipulate paths in PowerShell (I've just started using this to automate some cleanup tasks on my desktop).
EDIT: In case it makes a difference, this is what I see when I run the version command:
PS C:\Users\Me> version
BladeLogic Network Shell 8.2.01.273 (Release) [May 12 2012 21:56:02]
Copyright (C) 1996-2012 BladeLogic Inc.
Also, I'm on a work computer with no administrative privileges.
I tried:
$currentPath = "C:\Users\n0223270\Downloads"
$test = "test"
createFolder($test, $currentPath)
function createFolder($folderName, $curPath)
{
$dest = join-path -path $curPath -childpath $folderName
Write-Host $dest
}
This was the following error:
Join-Path : Cannot bind argument to parameter 'Path' because it is null.
At line:4 char:28
+ $dest = join-path -path <<<< $curPath -childpath $folderName
+ CategoryInfo : InvalidData: (:) [Join-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.JoinPathCommand
createFolder($test, $currentPath)
This isn't how you call a Powershell function. This is passing the first parameter as an array of two strings. The second parameter would be null because it's not specified and there's no default.
Try:
createFolder $test $currentPath

Resources