How to run all the unit test in a solution directory using Powershell Script.
I tried with the below command
$tool = '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\MSTest.exe"'
$x = ""; dir D:\DropBuildOutput\*.Tests.dll -Recurse | foreach { $x += "/testcontainer:""$_"" " }; iex "$tool $x"
But its failing with error below.How can i run all the tests and generate results?
iex : At line:1 char:79
+ ... (x86)\Microsoft Visual Studio 14.0\Common7\IDE\MSTest.exe" /testcont ...
+ ~
You must provide a value expression following the '/' operator.
At line:1 char:79
+ ... STest.exe" /testcontainer:"D:\DropBuildOutput\_PublishedWebsites\SCJ. ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token
'testcontainer:"D:\DropBuildOutput\_PublishedWebsites\aaa.aaa.aaa.aaa\bin\xxx.aaa.aaa.Tests.dll"' in
expression or statement.
At line:2 char:100
+ ... -Recurse | foreach { $x += "/testcontainer:""$_"" " }; iex "$tool $x"
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException
+ FullyQualifiedErrorId : ExpectedValueExpression,Microsoft.PowerShell.Commands.InvokeExpressionCommand
Use the call operator & instead of Invoke-Expression:
& $Tool $x
Related
How do I pipe the objects of a CSV file into the DeviceName parameter of Get-CMUserDeviceAffinity?
I have a list of computers. I'd like to generate a list of the primary users for each of the computers in this list. I'm using powershell and the SCCM module and so far I've tried a one-liner as well as something more wordy to no avail.
One-Liner fail:
Import-CSV C:\temp\computerlist.csv | Get-CMUserDeviceAffinity -DeviceName $($_.Name)
Script fail:
$Computers = C:\computers.CSV
ForEach ($Computer in $Computers) {
Get-CMUserDeviceAffinity -DeviceName $_.Name
Results of both fails:
Cannot validate argument on parameter 'DeviceName'. The argument is null or empty. Provide
an argument that is not null or empty, and then try the command again.
At line:1 char:77
+ ... p\computerlist.csv | Get-CMUserDeviceAffinity -DeviceName $($_.Name)
+ ~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-CMUserDeviceAffinity], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ConfigurationManagement.Cmdlets.Collections.C
ommands.GetUserDeviceAffinityCommand
You are using the automatic pipeline varaible $_ whereas you don't have a pipeline object in your foreach loop. Just use $Computer instead:
$Computers = C:\computers.CSV
ForEach ($Computer in $Computers) {
Get-CMUserDeviceAffinity -DeviceName $Computer.Name
}
Assuming your csv is like this
You can try to use below PowerShell script:
$Computers = Import-Csv C:\computerlist.CSV
ForEach ($Computer in $Computers) {
$Name = (Get-CMUserDeviceAffinity -DeviceName $Computer.Name).uniqueusername
write-host "$($computer.name) ------> $($Name) "
}
The Output:
I have written a log tailer with Powershell, the tailer loads in an xml file which contains configuration information regarding when to report on a word match in the log tail (basically if certain patterns occur X amount of times in the tail).
At the moment the tailer is not returning matches for many of the lines that contain matches.
For example we are retrieving a log file with many INFO lines, if I check for the word INFO nothing is detected, however if I look for the work shutdown it returns matches (the line with shutdown also contains INFO on the line).
The really strange thing is that using the same log file and same Powershell script seems to produce perfectly accurate results on my own machine but behaves strangely on the server.
I suspect that this might be an issue with the version of Powershell that is running on the server, so I was hoping someone here might know of issues that can come up with different versions. I have also noticed that when I print out the number of matches, if nothing is found the output is blank, perhaps this should be 0 and is causing some weird issue to trigger?
function Main()
{
#### GLOBAL SETTINGS
$DebugPreference = "Continue"
$serverName = $env:COMPUTERNAME
$scriptPath = Split-Path $script:MyInvocation.MyCommand.Path
$logConfigPath = "$scriptPath/config.xml"
#### VARIABLES RELATING TO THE LOG FILE
#contains the log path and log file mask
$logPaths = #()
$logFileMasks = #()
# the total number of lines grabbed from the end of the log file for evaluation
$numLinesToTail = 1000
# key value pair for the strings to match and the max count of matches before they are considered an issue
$keywords = #()
$maxCounts = #()
#### VARIABLES RELATING TO THE EMAIL SETTINGS
$smtpServer = "mail server"
$emailSubject = "$serverName log report"
$toEmailAddress = "email accounts"
$fromEmailAddress = ""
# any initial content you want in the email body should go here (e.g. the name of the server that this is on)
$htmlBodyContent = "<p><h3>SERVER $serverName : </h3></p><p>Items that appear in red have exceeded their match threshold and should be investigated.<br/>Tail Lines: $numLinesToTail</p>"
#### FUNCTION CALLS
LoadLogTailerConfig $logConfigPath ([ref]$logPaths) ([ref]$logFileMasks) ([ref]$keywords) ([ref]$maxCounts)
for ($i = 0; $i -lt $logPaths.Count; $i++)
{
$tail = GetLogTail $numLinesToTail $logPaths[$i] $logFileMasks[$i]
$tailIssueTable = CheckForKeywords $tail $keywords[$i] $maxCounts[$i]
if ($tailIssueTable -ne "")
{
$htmlBodyContent += "<br/>Logs scanned: " + (GetLatestLogFileFullName $logPaths[$i] $logFileMasks[$i]) + "<br/><br/>" + $tailIssueTable
SendIssueEmail $smtpServer $emailSubject $toEmailAddress $ccEmailAddress $fromEmailAddress $htmlBodyContent
}
}
}
# Loads in configuration data for the utility to use
function LoadLogTailerConfig($logConfigPath, [ref]$logPaths, [ref]$logFileMasks, [ref]$keywords, [ref]$maxCounts)
{
Write-Debug "Loading config file data from $logConfigPath"
[xml]$configData = Get-Content $logConfigPath
foreach ($log in $configData.Logs.Log) {
$logPaths.Value += $log.FilePath
$logFileMasks.Value += $log.FileMask
$kwp = #()
$kwc = #()
foreach ($keywordSet in $log.Keywords.Keyword)
{
$kwp += $keywordSet.Pattern
$kwc += $keywordSet.MaxMatches
}
$keywords.Value += #(,$kwp)
$maxCounts.Value += #(,$kwc)
}
}
# Gets a string containing the last X lines of the most recent log file
function GetLogTail($numLinesToTail, $logPath, $logFileMask)
{
$logFile = GetLatestLogFileFullName $logPath $logFileMask #Get-ChildItem $logPath -Filter $logFileMask | sort LastWriteTime | select -Last 1
Write-Debug "Getting $numLinesToTail line tail of $logFile"
$tail = Get-Content "$logFile" | select -Last $numLinesToTail
return $tail
}
function GetLatestLogFileFullName($logPath, $logFileMask)
{
$logFile = Get-ChildItem $logPath -Filter $logFileMask | sort LastWriteTime | select -Last 1
return "$logPath$logFile"
}
# Returns body text for email containing details on keywords in the log file and their frequency
function CheckForKeywords($tail, $keywords, $maxCounts)
{
$issuesFound = 0
$htmlBodyContent += "<table><tr><th style=""text-align : left;"">Keyword</th><th>Max Count Value</th><th>Count Total<th></tr>"
for ($i = 0; $i -lt $keywords.Count; $i++)
{
$keywordCount = ($tail | Select-String $keywords[$i] -AllMatches).Matches.Count
Write-Debug (("Match count for {0} : {1}" -f $keywords[$i], $keywordCount))
if ($keywordCount -gt $maxCounts[$i])
{
# style red if the count threshold has been exceeded
$htmlBodyContent += "<tr style=""color : red;""><td>" + $keywords[$i] + "</td><td>" + $maxCounts[$i] + "</td><td>" + $keywordCount + "</td></tr>"
$issuesFound = 1
}
else
{
# style green if the count threshold has not been exceeded
$htmlBodyContent += "<tr style=""color : green;""><td>" + $keywords[$i] + "</td><td>" + $maxCounts[$i] + "</td><td>" + $keywordCount + "</td></tr>"
}
}
$htmlBodyContent += "</table>"
if ($issuesFound -eq 1)
{
return $htmlBodyContent
}
return ""
}
# Sends out an email to the specified email address
function SendIssueEmail($smtpServer, $subject, $toAddress, $ccAddress, $fromAddress, $bodyContent)
{
Write-Debug "Sending email with subject: $subject, To: $toAddress, via SMTP ($smtpServer)"
Send-MailMessage -SmtpServer $smtpServer -Subject $subject -To $toAddress -From $fromAddress -BodyAsHtml $bodyContent
}
cls
Main
And a XML config example:
<Logs>
<Log>
<FilePath>C:/Some/Path</FilePath>
<FileMask>log.*</FileMask>
<Keywords>
<Keyword>
<Pattern>NullReferenceException</Pattern>
<MaxMatches>10</MaxMatches>
</Keyword>
<Keyword>
<Pattern>Exception</Pattern>
<MaxMatches>10</MaxMatches>
</Keyword>
</Keywords>
</Log>
<Log>
<FilePath>C:/Some/Path</FilePath>
<FileMask>test.*</FileMask>
<Keywords>
<Keyword>
<Pattern>NullReferenceException</Pattern>
<MaxMatches>100</MaxMatches>
</Keyword>
</Keywords>
</Log>
</Logs>
EDIT : The server that is having the issues is running Powershell V 1.0, however the test servers are also running the same version perfectly fine...
Your function GetLatestLogFileFullName is one problem. It can and will generate invalid paths.
function GetLatestLogFileFullName($logPath, $logFileMask)
{
$logFile = Get-ChildItem $logPath -Filter $logFileMask | sort LastWriteTime | select -Last 1
return "$logPath$logFile"
}
Use this instead:
return $logfile.FullName
And you should also check for cases where there is no valid log file:
if ($logfile) {
return $logfile.FullName
} else {
return $null
}
The second problem will be your Select-String usage.
$keywordCount = ($tail | Select-String $keywords[$i] -AllMatches).Matches.Count
In PowerShell v1 Select-String does not have -AllMatches parameter.
PS> Get-Help Select-String
NAME
Select-String
SYNOPSIS
Identifies patterns in strings.
SYNTAX
Select-String [-pattern] <string[]> -inputObject <psobject>[-include <string[]>] [-exclude <string[]>] [-simpleMatch] [-caseSensitive] [-quiet] [-list] [<CommonParameters>]
Select-String [-pattern] <string[]> [-path] <string[]> [-include<string[]>] [-exclude <string[]>] [-simpleMatch] [-caseSensitive] [-quiet] [-list] [<CommonParameters>]
Check the PowerShell versions on your servers using the $PSVersionTable variable. Do not rely on the version displayed in the title bar!
If the variable does not exist you have Version 1.
## Declaire Variables
## File Path Variables
$savePath = $env:TEMP
$sourceFileAccellerator = "C:\ALL_SALES_WITH_uuid_07-09-2014.txt" ##Path to Source File goes here
$sourceFileLineBreaks = $($savePath + "NifaLeadsListCategoriesWLineBreaks.txt")
$categoryOutput = $($savePath + "CategoryParsedforPowerShell.txt")
$categoryOutputXtraSlash = $($savePath + "CategoriesXtraSlash.txt")
$categoryOutputNoNull = $($savePath + "CategoriesNoNULL.txt")
$searchedFile = $($savePath + $exactSearchTerm + "Temp.txt")
$uuidOutput = $($savePath + $exactSearchTerm + "uuid.SQL")
$uuidColumnSQL = $($savePath + $exactSearchTerm + "Table.sql")
## .sql file creation strings
$sqlUpdate = $("UPDATE ADC.dbo.Contacts SET [" + $exactSearchTerm + "] = 1 WHERE NifaID = '")
$columnAddLine1 = "ALTER TABLE ADC.dbo.Contacts"
$columnAdd = $("ADD [" + $exactSearchTerm + "] nvarchar(10)")
## Regex Variables
$uuidRegEx = '[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}'
$categoryRegEX = '(?<=\\)[^\\\r\n]*\\[^\\\r\n]*$'
## Get the original text file and add line breaks to the categories and output to a new file.
Get-Content $sourceFileAccellerator |% {$_-replace "`t","`n"} > $sourceFileLineBreaks
## Look for Categories and pars the last 2 categories
select-string -Path $sourceFileLineBreaks -Pattern $categoryRegEX -AllMatches | % { $_.Matches } | % { $_.Value } > $categoryOutput
## Cleanup the Categories for input into the ForEach loop.
$job1 = Start-Job { Get-Content $categoryOutput |% {$_-replace "\\\\", "\\\\\\\\"} > $categoryOutputXtraSlash }
Wait-Job $job1
Receive-Job $job1
$job2 = Start-Job { Get-Content $categoryOutputXtraSlash |% {$_-replace '/(?:(?:\r\n|\r|\n)\s*){2}/s', "\n\n"} > $categoryOutputNoNull }
Wait-Job $job2
Receive-Job $job2
## Import the SQL Cmdlets
Import-Module SQLPS
## Load the searchFile and run the script on each column
$SearchFile = New-Object System.IO.StreamReader -Arg $categoryOutputNoNull
while ($line = $file.ReadLine()) {
Select-String -Path $sourceFile -Pattern $line > $searchedFile
Select-String -Path $searchedFile -Pattern $uuidRegEx -AllMatches | % { $_.Matches } | % { $sqlUpdate + $_.Value + "';"} > $uuidOutput
## Create the sql script to add a column
Add-Content -Path $uuidColumnSQL -Value $($columnAddLine1 + " " + $columnAdd)
## Run the SQL scripts
Invoke-Sqlcmd -InputFile $uuidColumnSQL -OutputSqlErrors $true -ServerInstance DUMPSTER\DB_DEFAULT -QueryTimeout 0
Invoke-Sqlcmd -InputFile $uuidOutput -OutputSqlErrors $true -ServerInstance DUMPSTER\DB_DEFAULT -QueryTimeout 0
## Remove Temporary files
Remove-Item $searchedFile
Remove-Item $uuidOutput
Remove-Item $uuidColumnSQL
}
$file.close()
Remove-Item $categoryOutput
Remove-Item $sourceFileLineBreaks
Remove-Item $categoryOutputXtraSlash
I'm working on the above script that parses out data from a tab delimited .txt file and and have tested every component of the script and have had success, but when they're combined into a while loop, Powershell is throwing the errors below:
Output:
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
6 Job6 BackgroundJob Completed True localhost Get-Content $category...
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentCommand
+ PSComputerName : localhost
8 Job8 BackgroundJob Completed True localhost Get-Content $category...
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentCommand
+ PSComputerName : localhost
You cannot call a method on a null-valued expression.
At C:\CategoryParseAndSQLUpdate.ps1:53 char:8
+ while ($line = $file.ReadLine()) {
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\CategoryParseAndSQLUpdate.ps1:66 char:1
+ $file.close()
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
When you use jobs (e.g. with Start-Job cmdlet) you have to look carefully at the scope of variable(s). Depending on the version: you can either:
access variable from parent scope with $using:VariableName (v. 3+)
use ArgumentList parameter from Start-Job and param() block inside script block
EDIT
Just noticed: I can't see where you define $file - looks like it's missing?
any idea why the following isnt working?
.................................................................................................................................................................................................................................................................................
$files = #'
name 14122012 text.doc
things 08092003.docx
hi v03.03 text 05062007 file.txt
hello world 31052006.ppt
names v04 12122012.xml
sdsf 29082013 dsf.php
'# -split '\n'
foreach ($File in $files) {
$file -match '(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(19|20)[0-9]{2}' | Out-Null
$File -replace "$(($matches).values)" , "$(get-date "$(($matches).Values)" -Format yyyyddMM)"
}
powershell output error is, for some reason its trying to add "20 12 14" to the string for conversion :S
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "20 12 14 14122012" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:13 char:9
+ get-date <<<< "$(($matches).Values)" -Format yyyyddMM
+ CategoryInfo : InvalidArgument: (:) [Get-Date], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand
and
$files = #'
11.12.2012
11.12.12
15 12 2013
5 06 2013
'# -split '\n'
foreach ($File in $files) {
$file -match '\d{2}\.\d{2}\.\d{2,4}' | Out-Null
$file -match '(0[1-9]|[12]\d|3[01])\s\d{2}\s\d{2,4}'| Out-Null
$File -replace "$(($matches).values)" , "$(get-date "$(($matches).Values)" -Format yyyyMMdd)"
}
15 12 2013
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "15 15 12 2013" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:13 char:9
+ get-date <<<< "$(($matches).Values)" -Format yyyyMMdd
+ CategoryInfo : InvalidArgument: (:) [Get-Date], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand
5 06 2013
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "15 15 12 2013" to type "System.DateTime". Error: "String was not recognized as a valid DateTime."
At line:13 char:9
+ get-date <<<< "$(($matches).Values)" -Format yyyyMMdd
+ CategoryInfo : InvalidArgument: (:) [Get-Date], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand
It's doing what it's supposed to do. $matches is a hash table of the the base capture (0) and each capture group:
$text = 'name 14122012 text.doc'
$regex = $file -match '(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(19|20)[0-9]{2}' | Out-Null
$matches
Name Value
---- -----
3 2013
2 08
1 29
0 29082013
When you ouput the collection of values as a string, it's going to space separate them:
"$(($matches).values)"
2013 08 29 29082013
That's the normal behaviour for any collection that's converted to a string. You can change the separator character from the default space by changing the Output Field Separator ($OFS)
$OFS = ';'
"$(($matches).values)"
2013;08;29;29082013
That being said, you really don't need to jump through the datetime conversion hoops. You have all the data you need already:
$files = #'
name 14122012 text.doc
things 08092003.docx
hi v03.03 text 05062007 file.txt
hello world 31052006.ppt
names v04 12122012.xml
sdsf 29082013 dsf.php
'# -split '\n'
foreach ($File in $files) {
$file -match '(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])((?:19|20)[0-9]{2})' | Out-Null
$File -replace "$($matches[0])" , ($matches[3,2,1] -join '')
}
name 20121214 text.doc
things 20030908.docx
hi v03.03 text 20070605 file.txt
hello world 20060531.ppt
names v04 20121212.xml
sdsf 20130829 dsf.php
It just took a minor re-factoring of the regex to capture all of the year digits, then arrange the captures in the right order and join them together.
Your first problem is that you weren't capturing the entire year (only the first 2 digits), so you need to move the group capture bracket:
$file -match '(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(19|20[0-9]{2})'
Also, $matches returns an array that contains the entire matched string in the first element, followed by an element for each captured group.
For example:
"name 14122012 text.doc" -match '(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])(19|20[0-9]{2})'
$matches
Name Value
---- -----
3 2012
2 12
1 14
0 14122012
So you have to recombine the string in a format the get-date will like. In my locale, it would look like this:
$matches[2,1,3] -join " "
12 14 2012
If your locale needs the day of month first, then:
$matches[1..3] -join " "
14 12 2012
which then gives:
$File -replace "$($matches[0])" , "$(get-date $($matches[2,1,3] -join ' ') -Format yyyyddMM)"
for your second line.
I have the following powershell script running over a C# class in order to replace the constructor with an empty constructor. I am doing this over a number of files that were autogenerated.
$nl = [Environment]::NewLine
foreach($item in Get-ChildItem $path) {
if($item.extension -eq ".cs") {
$name = $item.name
$name = $name.replace('.cs', '')
$reg = '(public ' + $name + '\(.*?\})'
$constructorString = [regex]$reg
$emptyConstructor = 'public ' + $name + '()' + $nl + '{' + $nl + '}' + $nl
Get-Content $item.fullname -Raw | Where-Object { $_ -match $constructorString } | ForEach-Object { $_ -replace $constructorString, '$1'}
}
}
The classes have a form of
public Bar()
{
this.foo = new Foo();
}
This results in no matches, let me know if more information is required.
There is no need to convert the pattern to a regex. Try this:
$item | Get-Content -raw | Where {$_ -match "(?s)(public\s+${name}\s*\(.*?\})"} | ...
I believe the issue you are running into is that although you've read the C# file as a single string using the -Raw parameter, there are line breaks in the string that .* won't traverse unless you use singleline mode in the regex. That is what the (?s) does.
Also, if you are on PowerShell V3 you can use basename instead of replace e.g.:
$name = $item.basename
BTW have you looked at Roslyn as an alternative to the regex search/replace approach? Roslyn will build an AST for you for each source file. With that you could easily find default constructors and replace it with an empty constructor.