Merge pull request #761 from PowerShell/andschwa/cli

Switch dotnet publish for dotnet build (and more)
This commit is contained in:
Andy Schwartzmeyer 2016-04-04 15:33:23 -04:00
commit b7a7d8f048
107 changed files with 17331 additions and 372 deletions

11
.gitmodules vendored
View file

@ -1,6 +1,3 @@
[submodule "src/libpsl-native"]
path = src/libpsl-native
url = https://github.com/PowerShell/psl-native.git
[submodule "src/omi"]
path = src/omi
url = https://github.com/Microsoft/omi.git
@ -11,8 +8,12 @@
[submodule "src/windows-build"]
path = src/windows-build
url = https://github.com/PowerShell/psl-windows-build.git
[submodule "src/Microsoft.PowerShell.Linux.Host/Modules/Pester"]
path = src/Microsoft.PowerShell.Linux.Host/Modules/Pester
[submodule "src/Modules/Pester"]
path = src/Modules/Pester
url = https://github.com/PowerShell/psl-pester.git
branch = develop
ignore = dirty
[submodule "src/libpsl-native/test/googletest"]
path = src/libpsl-native/test/googletest
url = https://github.com/google/googletest.git
ignore = dirty

View file

@ -1,25 +1,16 @@
language: cpp
sudo: required
dist: trusty
cache:
apt: true
directories:
- $HOME/.nuget
git:
submodules: false
before_install:
- git config --global url.git@github.com:.insteadOf https://github.com/
- git submodule update --init --recursive -- src/libpsl-native src/windows-build src/Microsoft.PowerShell.Linux.Host/Modules/Pester
- sudo sh -c 'echo "deb [arch=amd64] http://apt-mo.trafficmanager.net/repos/dotnet/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
- sudo apt-key adv --keyserver apt-mo.trafficmanager.net --recv-keys 417A0893
- sudo apt-get -qq update
- sudo apt-get install -y dotnet=1.0.0.001675-1
- git submodule update --init -- src/windows-build src/Modules/Pester src/libpsl-native/test/googletest
- ./bootstrap.sh
- ./download.sh
- sudo dpkg -i powershell.deb
- sudo dpkg -i ./powershell.deb
script:
- powershell -c "Import-Module ./PowerShellGitHubDev.psm1; Start-PSBuild"
- ./pester.sh
- ./xunit.sh
- powershell -c "Import-Module ./PowerShellGitHubDev.psm1; Start-PSBuild; Start-PSxUnit; Start-PSPester"
notifications:
slack:
secure: sKYd4n61+ZFzGZuWGUl8V1kN0NM16wRVOFVlNhlFCwnkrEsKROb++EvXf5uwnKuzxkhEjvPWO+UFgeshQDoR93y4s5YLfhC5JupK4nUzjPzWs208KTrh8u/x9MY8X6Ojxi85EEAiku5GzMoMlkucSStZUYwbIfnelzqdw8uoRwmm2MW4XCPwsuEuDUVghyiva0Mdx1G6MopCrK8T96WywJXT3chhfZQgVt+sQCBt9g+2kjDaObKrzG0P07IVK43ZpDgnu6AoxlyBzIx9mJH2Oa/tki3/kTO72Wcp3ps3qvmiStADamzVKR9p1VlWCLWAd6VOehxuByCGEyujpzk135Wud2DZYO+8LD6inZVhFe3Wt5pCU9BDXZppiATfMCqgXEH7nK54pEn79yHcjthRJ2+Z9ot7As2fu3RSBmTAi8nRP0fxRyX/jctR3S6P0qt0y1ynx9nzBfhmhPQW0PMVazWS/nruQIvK/3iiYXjZxM5bBwIvabmwV00EYeTdbL6ufXWNgQcG1ZWkDsi2I3vst/ytUbHwaFYg83bXWpxg9DCzJeWLVUvE5/3NfBxRAuCTot/fgTEA9IYScvrlL7Q/bT0cOt0vEM98MPf1UO+WP85uxhsRgHtwDEo+jMaL6ZFkPhlV6mmmED4NdY2//a571cLNXdnuMAze5O3TWGBG53g=

View file

@ -17,19 +17,19 @@ try {
$IsWindows = $true
}
function Start-PSBuild
{
function Start-PSBuild {
[CmdletBinding(DefaultParameterSetName='CoreCLR')]
param(
[switch]$Restore,
[switch]$Clean,
[string]$Output,
# These runtimes must match those in project.json
# We do not use ValidateScript since we want tab completion
[ValidateSet("ubuntu.14.04-x64",
"centos.7.1-x64",
"win7-x64",
"win81-x64",
"win10-x64",
"osx.10.10-x64",
"osx.10.11-x64")]
@ -44,185 +44,213 @@ function Start-PSBuild
[Parameter(ParameterSetName='FullCLR')]
[ValidateSet("Debug",
"Release")]
[string]$msbuildConfiguration = "Release"
"Release")]
[string]$msbuildConfiguration = "Release"
)
function precheck([string]$command, [string]$missedMessage)
{
$c = Get-Command $command -ErrorAction SilentlyContinue
if (-not $c)
{
Write-Warning $missedMessage
return $false
}
else
{
return $true
}
}
function log([string]$message)
{
Write-Host -Foreground Green $message
}
# simplify ParameterSetNames, set output
if ($PSCmdlet.ParameterSetName -eq 'FullCLR')
{
# simplify ParameterSetNames
if ($PSCmdlet.ParameterSetName -eq 'FullCLR') {
$FullCLR = $true
}
if (-not $Output)
{
if ($FullCLR) { $Output = "$PSScriptRoot/binFull" } else { $Output = "$PSScriptRoot/bin" }
}
# verify we have all tools in place to do the build
$precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH! See: https://dotnet.github.io/getting-started/"
if ($FullCLR)
{
if ($FullCLR) {
# cmake is needed to build powershell.exe
$precheck = $precheck -and (precheck 'cmake' 'cmake not found. You can install it from https://chocolatey.org/packages/cmake.portable')
# msbuild is needed to build powershell.exe
# msbuild is part of .NET Framework, we can try to get it from well-known location.
if (-not (Get-Command -Name msbuild -ErrorAction Ignore))
{
if (-not (Get-Command -Name msbuild -ErrorAction Ignore)) {
$env:path += ";${env:SystemRoot}\Microsoft.Net\Framework\v4.0.30319"
}
$precheck = $precheck -and (precheck 'msbuild' 'msbuild not found. Install Visual Studio 2015.')
}
if (-not $precheck) { return }
} elseif ($IsLinux -Or $IsOSX) {
$InstallCommand = if ($IsLinux) {
'apt-get'
} elseif ($IsOSX) {
'brew'
}
# handle clean
if ($Clean) {
Remove-Item -Force -Recurse $Output -ErrorAction SilentlyContinue
foreach ($Dependency in 'cmake', 'make', 'g++') {
$precheck = $precheck -and (precheck $Dependency "Build dependency '$Dependency' not found. Run '$InstallCommand install $Dependency'")
}
}
New-Item -Force -Type Directory $Output | Out-Null
if (-Not $Runtime) {
$Runtime = dotnet --info | % {
if ($_ -match "RID") {
$_ -split "\s+" | Select-Object -Last 1
}
}
if (-Not $Runtime) {
Write-Warning "Could not determine Runtime Identifier, please update dotnet"
$precheck = $false
} else {
log "Runtime not specified, using $Runtime"
}
}
# Abort if any precheck failed
if (-not $precheck) {
return
}
# define key build variables
if ($FullCLR)
{
if ($FullCLR) {
$Top = "$PSScriptRoot\src\Microsoft.PowerShell.ConsoleHost"
$framework = 'net451'
$Framework = 'net451'
} else {
$Top = "$PSScriptRoot/src/Microsoft.PowerShell.Host"
$Framework = 'netstandardapp1.5'
}
else
{
$Top = "$PSScriptRoot/src/Microsoft.PowerShell.Linux.Host"
$framework = 'netstandardapp1.5'
if ($IsLinux -Or $IsOSX) {
$Configuration = "Linux"
$Executable = "powershell"
} else {
$Configuration = "Debug"
$Executable = "powershell.exe"
}
$Arguments = @()
$Arguments += "--framework", $Framework
$Arguments += "--configuration", $Configuration
$Arguments += "--runtime", $Runtime
# FullCLR only builds a library, so there is no runtime component
if ($FullCLR) {
$script:Output = [IO.Path]::Combine($Top, "bin", $Configuration, $Framework, $Executable)
} else {
$script:Output = [IO.Path]::Combine($Top, "bin", $Configuration, $Framework, $Runtime, $Executable)
}
Write-Verbose "script:Output is $script:Output"
# handle Restore
if ($Restore -Or -Not (Test-Path "$Top/project.lock.json")) {
log "Run dotnet restore"
$Arguments = @("--verbosity")
$RestoreArguments = @("--verbosity")
if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) {
$Arguments += "Info" } else { $Arguments += "Warning" }
$RestoreArguments += "Info"
} else {
$RestoreArguments += "Warning"
}
if ($Runtime) { $Arguments += "--runtime", $Runtime }
$RestoreArguments += "$PSScriptRoot"
$Arguments += "$PSScriptRoot"
dotnet restore $Arguments
dotnet restore $RestoreArguments
}
# Build native components
if (-not $FullCLR)
{
if ($IsLinux -Or $IsOSX) {
log "Start building native components"
$InstallCommand = if ($IsLinux) { "apt-get" } elseif ($IsOSX) { "brew" }
foreach ($Dependency in "cmake", "g++") {
if (-Not (Get-Command $Dependency -ErrorAction SilentlyContinue)) {
throw "Build dependency '$Dependency' not found in PATH! Run '$InstallCommand install $Dependency'"
}
}
$Ext = if ($IsLinux) { "so" } elseif ($IsOSX) { "dylib" }
$Native = "$PSScriptRoot/src/libpsl-native"
$Lib = "$Top/libpsl-native.$Ext"
Write-Verbose "Building $Lib"
try {
Push-Location $Native
cmake -DCMAKE_BUILD_TYPE=Debug .
make -j
make test
} finally {
Pop-Location
}
if (-Not (Test-Path $Lib)) { throw "Compilation of $Lib failed" }
if ($IsLinux -Or $IsOSX) {
$Ext = if ($IsLinux) {
"so"
} elseif ($IsOSX) {
"dylib"
}
}
else
{
$Native = "$PSScriptRoot/src/libpsl-native"
$Lib = "$Top/libpsl-native.$Ext"
log "Start building $Lib"
try {
Push-Location $Native
cmake -DCMAKE_BUILD_TYPE=Debug .
make -j
make test
} finally {
Pop-Location
}
if (-Not (Test-Path $Lib)) {
throw "Compilation of $Lib failed"
}
} elseif ($FullCLR) {
log "Start building native powershell.exe"
$build = "$PSScriptRoot/build"
if ($Clean) {
Remove-Item -Force -Recurse $build -ErrorAction SilentlyContinue
}
mkdir $build -ErrorAction SilentlyContinue
try
{
Push-Location $build
try {
Push-Location .\src\powershell-native
if ($cmakeGenerator)
{
cmake -G $cmakeGenerator ..\src\powershell-native
}
else
{
cmake ..\src\powershell-native
if ($cmakeGenerator) {
cmake -G $cmakeGenerator .
} else {
cmake .
}
msbuild powershell.vcxproj /p:Configuration=$msbuildConfiguration
cp -rec $msbuildConfiguration\* $Output
} finally {
Pop-Location
}
finally { Pop-Location }
}
log "Building PowerShell"
$Arguments = "--framework", $framework, "--output", $Output
if ($IsLinux -Or $IsOSX) { $Arguments += "--configuration", "Linux" }
if ($Runtime) { $Arguments += "--runtime", $Runtime }
if ($FullCLR)
{
# there is a problem with code signing:
# AssemblyKeyFileAttribute file path cannot be correctly located, if `dotnet publish $TOP` syntax is used
# we workaround it with calling `dotnet publish` from $TOP directory instead.
try {
# Relative paths do not work well if cwd is not changed to project
log "Run `dotnet build $Arguments` from $pwd"
Push-Location $Top
}
else
{
$Arguments += $Top
dotnet build $Arguments
log "PowerShell output: $script:Output"
} finally {
Pop-Location
}
Write-Verbose "Run dotnet publish $Arguments from $pwd"
}
# this try-finally is part of workaround about AssemblyKeyFileAttribute issue
try
{
dotnet publish $Arguments
function Get-PSOutput {
[CmdletBinding()]param()
if (-Not $Output) {
throw '$script:Output is not defined, run Start-PSBuild'
}
finally
{
if ($FullCLR) { Pop-Location }
$Output
}
function Start-PSPester {
[CmdletBinding()]param(
[string]$Flags = '-EnableExit -OutputFile pester-tests.xml -OutputFormat NUnitXml',
[string]$Tests = "*",
[ValidateScript({ Test-Path -PathType Container $_})]
[string]$Directory = "$PSScriptRoot/test/powershell"
)
& (Get-PSOutput) -c "Invoke-Pester $Flags $Directory/$Tests"
if ($LASTEXITCODE -ne 0) {
throw "$LASTEXITCODE Pester tests failed"
}
}
function Start-PSPackage
{
function Start-PSxUnit {
[CmdletBinding()]param()
if ($IsWindows) {
throw "xUnit tests are only currently supported on Linux / OS X"
}
$Content = Split-Path -Parent (Get-PSOutput)
$Arguments = "--configuration", "Linux"
try {
Push-Location $PSScriptRoot/test/csharp
dotnet build $Arguments
Copy-Item -ErrorAction SilentlyContinue -Recurse -Path $Content/* -Include Modules,libpsl-native* -Destination "./bin/Linux/netstandardapp1.5/ubuntu.14.04-x64"
dotnet test $Arguments
if ($LASTEXITCODE -ne 0) {
throw "$LASTEXITCODE xUnit tests failed"
}
} finally {
Pop-Location
}
}
function Start-PSPackage {
# PowerShell packages use Semantic Versioning http://semver.org/
#
# Ubuntu and OS X packages are supported.
param(
[CmdletBinding()]param(
[string]$Version,
[int]$Iteration = 1,
[ValidateSet("deb", "osxpkg", "rpm")]
@ -285,8 +313,8 @@ function Start-PSPackage
"$PSScriptRoot/package/powershell=/usr/local/bin"
}
function Start-DevPSGitHub
{
function Start-DevPSGitHub {
param(
[switch]$ZapDisable,
[string[]]$ArgumentList = '',
@ -295,27 +323,23 @@ function Start-DevPSGitHub
[switch]$NoNewWindow
)
try
{
if ($LoadProfile -eq $false)
{
try {
if ($LoadProfile -eq $false) {
$ArgumentList = @('-noprofile') + $ArgumentList
}
$env:DEVPATH = $binDir
if ($ZapDisable)
{
if ($ZapDisable) {
$env:COMPLUS_ZapDisable = 1
}
if (-Not (Test-Path $binDir\powershell.exe.config))
{
if (-Not (Test-Path $binDir\powershell.exe.config)) {
$configContents = @"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
<runtime>
<developmentMode developerInstallation="true"/>
</runtime>
</configuration>
"@
$configContents | Out-File -Encoding Ascii $binDir\powershell.exe.config
@ -333,71 +357,29 @@ function Start-DevPSGitHub
}
Start-Process @startProcessArgs
}
finally
{
} finally {
ri env:DEVPATH
if ($ZapDisable)
{
if ($ZapDisable) {
ri env:COMPLUS_ZapDisable
}
}
}
## this function is from Dave Wyatt's answer on
## http://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h
function Convert-PSObjectToHashtable
{
param (
[Parameter(ValueFromPipeline)]
$InputObject
)
process
{
if ($null -eq $InputObject) { return $null }
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string])
{
$collection = @(
foreach ($object in $InputObject) { Convert-PSObjectToHashtable $object }
)
Write-Output -NoEnumerate $collection
}
elseif ($InputObject -is [psobject])
{
$hash = @{}
foreach ($property in $InputObject.PSObject.Properties)
{
$hash[$property.Name] = Convert-PSObjectToHashtable $property.Value
}
$hash
}
else
{
$InputObject
}
}
}
<#
.EXAMPLE Copy-SubmoduleFiles # copy files FROM submodule TO src/<project> folders
.EXAMPLE Copy-SubmoduleFiles -ToSubmodule # copy files FROM src/<project> folders TO submodule
#>
function Copy-SubmoduleFiles {
[CmdletBinding()]
param(
[string]$mappingFilePath = "$PSScriptRoot/mapping.json",
[switch]$ToSubmodule
)
if (-not (Test-Path $mappingFilePath))
{
if (-not (Test-Path $mappingFilePath)) {
throw "Mapping file not found in $mappingFilePath"
}
@ -405,47 +387,38 @@ function Copy-SubmoduleFiles {
# mapping.json assumes the root folder
Push-Location $PSScriptRoot
try
{
try {
$m.GetEnumerator() | % {
if ($ToSubmodule)
{
if ($ToSubmodule) {
cp $_.Value $_.Key -Verbose:$Verbose
}
else
{
} else {
mkdir (Split-Path $_.Value) -ErrorAction SilentlyContinue > $null
cp $_.Key $_.Value -Verbose:$Verbose
cp $_.Key $_.Value -Verbose:$Verbose
}
}
}
finally
{
} finally {
Pop-Location
}
}
<#
.EXAMPLE Create-MappingFile # create mapping.json in the root folder from project.json files
.EXAMPLE Create-MappingFile # create mapping.json in the root folder from project.json files
#>
function New-MappingFile
{
function New-MappingFile {
param(
[string]$mappingFilePath = "$PSScriptRoot/mapping.json",
[switch]$IgnoreCompileFiles,
[switch]$Ignoreresource
)
function Get-MappingPath([string]$project, [string]$path)
{
if ($project -match 'TypeCatalogGen')
{
function Get-MappingPath([string]$project, [string]$path) {
if ($project -match 'TypeCatalogGen') {
return Split-Path $path -Leaf
}
if ($project -match 'Microsoft.Management.Infrastructure')
{
if ($project -match 'Microsoft.Management.Infrastructure') {
return Split-Path $path -Leaf
}
@ -456,8 +429,7 @@ function New-MappingFile
# assumes the root folder
Push-Location $PSScriptRoot
try
{
try {
$projects = ls .\src\ -Recurse -Depth 2 -Filter 'project.json'
$projects | % {
$project = Split-Path $_.FullName
@ -465,8 +437,7 @@ function New-MappingFile
if (-not $IgnoreCompileFiles) {
$json.compileFiles | % {
if ($_) {
if (-not $_.EndsWith('AssemblyInfo.cs'))
{
if (-not $_.EndsWith('AssemblyInfo.cs')) {
$fullPath = Join-Path $project (Get-MappingPath -project $project -path $_)
$mapping[$_.Replace('../', 'src/')] = ($fullPath.Replace("$($pwd.Path)\",'')).Replace('\', '/')
}
@ -485,38 +456,19 @@ function New-MappingFile
}
}
}
}
finally
{
} finally {
Pop-Location
}
Set-Content -Value ($mapping | ConvertTo-Json) -Path $mappingFilePath -Encoding Ascii
}
function Get-InvertedOrderedMap
{
param(
$h
)
$res = [ordered]@{}
foreach ($q in $h.GetEnumerator()) {
if ($res.Contains($q.Value))
{
throw "Cannot invert hashtable: duplicated key $($q.Value)"
}
$res[$q.Value] = $q.Key
}
return $res
}
<#
.EXAMPLE Send-GitDiffToSd -diffArg1 45555786714d656bd31cbce67dbccb89c433b9cb -diffArg2 45555786714d656bd31cbce67dbccb89c433b9cb~1 -pathToAdmin d:\e\ps_dev\admin
.EXAMPLE Send-GitDiffToSd -diffArg1 45555786714d656bd31cbce67dbccb89c433b9cb -diffArg2 45555786714d656bd31cbce67dbccb89c433b9cb~1 -pathToAdmin d:\e\ps_dev\admin
Apply a signle commit to admin folder
#>
function Send-GitDiffToSd
{
function Send-GitDiffToSd {
param(
[Parameter(Mandatory)]
[string]$diffArg1,
@ -533,32 +485,88 @@ function Send-GitDiffToSd
$affectedFiles = git diff --name-only $diffArg1 $diffArg2
$rev = Get-InvertedOrderedMap $m
foreach ($file in $affectedFiles) {
if ($rev.Contains)
{
if ($rev.Contains) {
$sdFilePath = Join-Path $pathToAdmin $rev[$file].Substring('src/monad/'.Length)
$diff = git diff $diffArg1 $diffArg2 -- $file
if ($diff)
{
if ($diff) {
Write-Host -Foreground Green "Apply patch to $sdFilePath"
Set-Content -Value $diff -Path $env:TEMP\diff -Encoding Ascii
if ($WhatIf)
{
if ($WhatIf) {
Write-Host -Foreground Green "Patch content"
cat $env:TEMP\diff
} else {
& $patchPath --binary -p1 $sdFilePath $env:TEMP\diff
}
else
{
& $patchPath --binary -p1 $sdFilePath $env:TEMP\diff
}
}
else
{
} else {
Write-Host -Foreground Green "No changes in $file"
}
}
else
{
} else {
Write-Host -Foreground Green "Ignore changes in $file, because there is no mapping for it"
}
}
}
}
function script:log([string]$message) {
Write-Host -Foreground Green $message
}
function script:precheck([string]$command, [string]$missedMessage) {
$c = Get-Command $command -ErrorAction SilentlyContinue
if (-not $c) {
Write-Warning $missedMessage
return $false
} else {
return $true
}
}
function script:Get-InvertedOrderedMap {
param(
$h
)
$res = [ordered]@{}
foreach ($q in $h.GetEnumerator()) {
if ($res.Contains($q.Value)) {
throw "Cannot invert hashtable: duplicated key $($q.Value)"
}
$res[$q.Value] = $q.Key
}
return $res
}
## this function is from Dave Wyatt's answer on
## http://stackoverflow.com/questions/22002748/hashtables-from-convertfrom-json-have-different-type-from-powershells-built-in-h
function script:Convert-PSObjectToHashtable {
param (
[Parameter(ValueFromPipeline)]
$InputObject
)
process {
if ($null -eq $InputObject) { return $null }
if ($InputObject -is [System.Collections.IEnumerable] -and $InputObject -isnot [string]) {
$collection = @(
foreach ($object in $InputObject) { Convert-PSObjectToHashtable $object }
)
Write-Output -NoEnumerate $collection
} elseif ($InputObject -is [psobject]) {
$hash = @{}
foreach ($property in $InputObject.PSObject.Properties)
{
$hash[$property.Name] = Convert-PSObjectToHashtable $property.Value
}
$hash
} else {
$InputObject
}
}
}

View file

@ -6,9 +6,6 @@ environment:
priv_key:
secure: <encryped-value>
cache:
- '%LocalAppData%\Microsoft\dotnet'
notifications:
- provider: Slack
incoming_webhook:
@ -20,9 +17,9 @@ install:
- ps: $fileContent += "`n-----END RSA PRIVATE KEY-----`n"
- ps: Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent
- git config --global url.git@github.com:.insteadOf https://github.com/
- git submodule update --init --recursive -- src/windows-build src/Microsoft.PowerShell.Linux.Host/Modules/Pester
- git submodule update --init -- src/windows-build src/Modules/Pester
- ps: Invoke-WebRequest -Uri https://raw.githubusercontent.com/dotnet/cli/rel/1.0.0/scripts/obtain/install.ps1 -OutFile install.ps1
- ps: ./install.ps1 -version 1.0.0.001888
- ps: ./install.ps1 -version 1.0.0-beta-002198
build_script:
- ps: |
@ -38,15 +35,17 @@ test_script:
$ErrorActionPreference = 'Stop'
#
# CoreCLR
$env:CoreOutput = "$pwd\src\Microsoft.PowerShell.Host\bin\Debug\netstandardapp1.5\win81-x64"
Write-Host -Foreground Green 'Run CoreCLR tests'
$testResultsFile = "$pwd\TestsResults.xml"
.\bin\powershell.exe --noprofile -c "Import-Module .\bin\Modules\Microsoft.PowerShell.Platform; Invoke-Pester test/powershell -OutputFormat NUnitXml -OutputFile $testResultsFile"
& ("$env:CoreOutput\powershell.exe") -c "Invoke-Pester test/powershell -OutputFormat NUnitXml -OutputFile $testResultsFile"
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile))
#
# FullCLR
$env:FullOutput = "$pwd\src\Microsoft.PowerShell.ConsoleHost\bin\Debug\net451"
Write-Host -Foreground Green 'Run FullCLR tests'
$testResultsFileFullCLR = "$pwd\TestsResults.FullCLR.xml"
Start-DevPSGitHub -binDir $pwd\binFull -NoNewWindow -ArgumentList '-command', "Import-Module .\src\Microsoft.PowerShell.Linux.Host\Modules\Pester; Import-Module .\bin\Modules\Microsoft.PowerShell.Platform; Invoke-Pester test/fullCLR -OutputFormat NUnitXml -OutputFile $testResultsFileFullCLR"
Start-DevPSGitHub -binDir $env:FullOutput -NoNewWindow -ArgumentList '-command', "Import-Module .\src\Modules\Pester; Import-Module .\bin\Modules\Microsoft.PowerShell.Platform; Invoke-Pester test/fullCLR -OutputFormat NUnitXml -OutputFile $testResultsFileFullCLR"
(New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFileFullCLR))
#
# Fail the build, if tests failed
@ -71,8 +70,8 @@ on_finish:
$zipFilePath = Join-Path $pwd "$name.zip"
$zipFileFullPath = Join-Path $pwd "$name.FullCLR.zip"
Add-Type -assemblyname System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory("$pwd\bin", $zipFilePath)
[System.IO.Compression.ZipFile]::CreateFromDirectory("$pwd\binFull", $zipFileFullPath)
[System.IO.Compression.ZipFile]::CreateFromDirectory($env:CoreOutput, $zipFilePath)
[System.IO.Compression.ZipFile]::CreateFromDirectory($env:FullOutput, $zipFileFullPath)
@(
# You can add other artifacts here

20
bootstrap.sh Executable file
View file

@ -0,0 +1,20 @@
#!/usr/bin/env bash
echo "Installing build dependencies"
curl http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -
echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.6 main" | sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt-get update -qq
sudo apt-get install -y wget make g++ cmake \
libc6 libgcc1 libstdc++6 \
libcurl3 libgssapi-krb5-2 libicu52 liblldb-3.6 liblttng-ust0 libssl1.0.0 libunwind8 libuuid1 zlib1g clang-3.5
wget -P /tmp https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-host-ubuntu-x64.latest.deb
sudo dpkg -i /tmp/dotnet-host-ubuntu-x64.latest.deb
wget -P /tmp https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-sharedframework-ubuntu-x64.latest.deb
sudo dpkg -i /tmp/dotnet-sharedframework-ubuntu-x64.latest.deb
wget -P /tmp https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-sdk-ubuntu-x64.latest.deb
sudo dpkg -i /tmp/dotnet-sdk-ubuntu-x64.latest.deb

View file

@ -5,7 +5,7 @@ hash cmake 2>/dev/null || { echo >&2 "No cmake, please run 'sudo apt-get install
hash g++ 2>/dev/null || { echo >&2 "No g++, please run 'sudo apt-get install g++'"; exit 1; }
hash dotnet 2>/dev/null || { echo >&2 "No dotnet, please visit https://dotnet.github.io/getting-started/"; exit 1; }
TOP="$(pwd)/src/Microsoft.PowerShell.Linux.Host"
TOP="$(pwd)/src/Microsoft.PowerShell.Host"
# Test for lock file
test -r "$TOP/project.lock.json" || { echo >&2 "Please run 'dotnet restore' to download .NET Core packages"; exit 2; }

View file

@ -42,3 +42,19 @@ provide a PID. (Please be careful not to commit such a change).
[vscode]: https://code.visualstudio.com/
[OmniSharp]: https://github.com/OmniSharp/omnisharp-vscode
[vscclrdebugger]: http://aka.ms/vscclrdebugger
corehost
--------
The native executable prouduced by .NET CLI will produce trace output
if launched with `COREHOST_TRACE=1 ./powershell`.
CoreCLR PAL
-----------
The native code in the CLR has debug channels to selectively output
information to the console. These are controlled by the
`PAL_DBG_CHANNELS`, e.g., `export PAL_DBG_CHANNELS="+all.all"`, as
detailed in the `dbgmsg.h` [header][].
[header]: https://github.com/dotnet/coreclr/blob/release/1.0.0-rc2/src/pal/src/include/pal/dbgmsg.h

View file

@ -1180,5 +1180,26 @@
"src/monad/monad/nttargets/assemblies/nativemsh/pwrshcommon/WinSystemCallFacade.h": "src/powershell-native/nativemsh/pwrshcommon/WinSystemCallFacade.h",
"src/monad/monad/nttargets/assemblies/nativemsh/pwrshexe/MainEntry.cpp": "src/powershell-native/nativemsh/pwrshexe/MainEntry.cpp",
"src/monad/monad/nttargets/assemblies/nativemsh/pwrshexe/OutputWriter.h": "src/powershell-native/nativemsh/pwrshexe/OutputWriter.h",
"src/monad/monad/src/graphicalhost/visualstudiopublic.snk": "src/signing/visualstudiopublic.snk"
"src/monad/monad/src/graphicalhost/visualstudiopublic.snk": "src/signing/visualstudiopublic.snk",
"src/monad/monad/miscfiles/modules/AppxProvider/AppxProvider.psd1": "src/Modules/AppxProvider/AppxProvider.psd1",
"src/monad/monad/miscfiles/modules/AppxProvider/AppxProvider.psm1": "src/Modules/AppxProvider/AppxProvider.psm1",
"src/monad/monad/miscfiles/modules/AppxProvider/AppxProvider.Resource.psd1": "src/Modules/AppxProvider/AppxProvider.Resource.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1": "src/Modules/Microsoft.PowerShell.Archive/ArchiveResources.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1": "src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1": "src/Modules/Microsoft.PowerShell.Archive/Microsoft.PowerShell.Archive.psm1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Diagnostics/CoreClr/Microsoft.PowerShell.Diagnostics.psd1": "src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1": "src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Diagnostics/Microsoft.PowerShell.Diagnostics.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1": "src/Modules/Microsoft.PowerShell.Host/Microsoft.PowerShell.Host.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1": "src/Modules/Microsoft.PowerShell.Management/Microsoft.PowerShell.Management.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1": "src/Modules/Microsoft.PowerShell.Security/Microsoft.PowerShell.Security.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/CoreClr/Microsoft.PowerShell.Utility.psd1": "src/Microsoft.PowerShell.Host/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1": "src/Microsoft.PowerShell.ConsoleHost/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psd1",
"src/monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1": "src/Modules/Microsoft.PowerShell.Utility/Microsoft.PowerShell.Utility.psm1",
"src/monad/monad/miscfiles/modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1": "src/Modules/Microsoft.WSMan.Management/Microsoft.WSMan.Management.psd1",
"src/monad/monad/miscfiles/modules/PSDiagnostics/PSDiagnostics.psd1": "src/Modules/PSDiagnostics/PSDiagnostics.psd1",
"src/monad/monad/miscfiles/modules/PSDiagnostics/PSDiagnostics.psm1": "src/Modules/PSDiagnostics/PSDiagnostics.psm1",
"src/monad/monad/miscfiles/modules/PSGet/PSGet.Format.ps1xml": "src/Modules/PSGet/PSGet.Format.ps1xml",
"src/monad/monad/miscfiles/modules/PSGet/PSGet.psd1": "src/Modules/PSGet/PSGet.psd1",
"src/monad/monad/miscfiles/modules/PSGet/PSGet.Resource.psd1": "src/Modules/PSGet/PSGet.Resource.psd1",
"src/monad/monad/miscfiles/modules/PSGet/PSModule.psm1": "src/Modules/PSGet/PSModule.psm1"
}

View file

@ -1,12 +0,0 @@
#!/usr/bin/env bash
test -x bin/powershell || { echo >&2 "No bin/powershell, please run './build.sh'"; exit 1; }
./bin/powershell --noprofile -c "Import-Module Microsoft.PowerShell.Platform; Invoke-Pester test/powershell/$1 -OutputFile pester-tests.xml -OutputFormat NUnitXml -EnableExit"
failed_tests=$?
# XML files are not executable
chmod -x pester-tests.xml
# Return number of failed tests as exit code (more than 0 will be an error)
exit $failed_tests

View file

@ -0,0 +1,16 @@
@{
GUID="CA046F10-CA64-4740-8FF9-2565DBA61A4F"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
CLRVersion="4.0"
AliasesToExport = @()
FunctionsToExport = @()
CmdletsToExport="Get-WinEvent", "Get-Counter", "Import-Counter", "Export-Counter", "New-WinEvent"
NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll"
TypesToProcess="GetEvent.types.ps1xml"
FormatsToProcess="Event.format.ps1xml","Diagnostics.format.ps1xml"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390783'
}

View file

@ -0,0 +1,33 @@
@{
GUID="1DA87E53-152B-403E-98DC-74D7B4D63D59"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.1.0.0"
PowerShellVersion="3.0"
CLRVersion="4.0"
CmdletsToExport= "Format-List", "Format-Custom", "Format-Table", "Format-Wide",
"Out-File", "Out-Printer", "Out-String",
"Out-GridView", "Get-FormatData", "Export-FormatData", "ConvertFrom-Json", "ConvertTo-Json",
"Invoke-RestMethod", "Invoke-WebRequest", "Register-ObjectEvent", "Register-EngineEvent",
"Wait-Event", "Get-Event", "Remove-Event", "Get-EventSubscriber", "Unregister-Event",
"New-Event", "Add-Member", "Add-Type", "Compare-Object", "ConvertTo-Html", "ConvertFrom-StringData",
"Export-Csv", "Import-Csv", "ConvertTo-Csv", "ConvertFrom-Csv", "Export-Alias", "Invoke-Expression",
"Get-Alias", "Get-Culture", "Get-Date", "Get-Host", "Get-Member", "Get-Random", "Get-UICulture",
"Get-Unique", "Export-PSSession", "Import-PSSession", "Import-Alias", "Import-LocalizedData",
"Select-String", "Measure-Object", "New-Alias", "New-TimeSpan", "Read-Host", "Set-Alias", "Set-Date",
"Start-Sleep", "Tee-Object", "Measure-Command", "Update-List", "Update-TypeData", "Update-FormatData",
"Remove-TypeData", "Get-TypeData", "Write-Host", "Write-Progress", "New-Object", "Select-Object",
"Group-Object", "Sort-Object", "Get-Variable", "New-Variable", "Set-Variable", "Remove-Variable",
"Clear-Variable", "Export-Clixml", "Import-Clixml", "ConvertTo-Xml", "Select-Xml", "Write-Debug",
"Write-Verbose", "Write-Warning", "Write-Error", "Write-Information", "Write-Output", "Set-PSBreakpoint", "Get-PSBreakpoint",
"Remove-PSBreakpoint", "Enable-PSBreakpoint", "Disable-PSBreakpoint", "Get-PSCallStack",
"Send-MailMessage", "Get-TraceSource", "Set-TraceSource", "Trace-Command", "Show-Command", "Unblock-File",
"Get-Runspace", "Debug-Runspace", "Enable-RunspaceDebug", "Disable-RunspaceDebug", "Get-RunspaceDebug", "Wait-Debugger",
"ConvertFrom-String", "Convert-String"
FunctionsToExport= "Get-FileHash", "New-TemporaryFile", "New-Guid", "Format-Hex", "Import-PowerShellDataFile",
"ConvertFrom-SddlString"
AliasesToExport= "CFS", "fhx"
NestedModules="Microsoft.PowerShell.Commands.Utility.dll","Microsoft.PowerShell.Utility.psm1"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390787'
}

View file

@ -14,6 +14,12 @@
"Microsoft.PowerShell.Commands.Utility": "1.0.0-*"
},
"content": [
"Modules",
"../Modules",
"powershell.exe"
],
"frameworks": {
"net451": {
}

View file

@ -0,0 +1,13 @@
@{
GUID="CA046F10-CA64-4740-8FF9-2565DBA61A4F"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
CmdletsToExport="Get-WinEvent", "New-WinEvent"
NestedModules="Microsoft.PowerShell.Commands.Diagnostics.dll"
TypesToProcess="..\..\GetEvent.types.ps1xml"
FormatsToProcess="..\..\Event.format.ps1xml"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390783'
}

View file

@ -1,4 +1,4 @@
namespace Microsoft.PowerShell.Linux.Host
namespace Microsoft.PowerShell.Host
{
using System;
using System.Globalization;

View file

@ -1,4 +1,4 @@
namespace Microsoft.PowerShell.Linux.Host
namespace Microsoft.PowerShell.Host
{
using System;
using System.Collections.Generic;

View file

@ -19,6 +19,7 @@
"content": [
"Modules",
"../Modules",
"*_profile.ps1",
"*.so",
"*.dylib"
@ -28,5 +29,15 @@
"netstandardapp1.5": {
"imports": [ "dnxcore50", "portable-net45+win8" ]
}
},
"runtimes": {
"ubuntu.14.04-x64": { },
"centos.7.1-x64": { },
"win7-x64": { },
"win81-x64": { },
"win10-x64": { },
"osx.10.10-x64": { },
"osx.10.11-x64": { }
}
}

View file

@ -10,7 +10,7 @@ using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Microsoft.PowerShell.Linux.Host
namespace Microsoft.PowerShell.Host
{
// this is all from https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspx

View file

@ -1,4 +1,4 @@
namespace Microsoft.PowerShell.Linux.Host
namespace Microsoft.PowerShell.Host
{
using System;
using System.Collections.ObjectModel;

View file

@ -1,4 +1,4 @@
namespace Microsoft.PowerShell.Linux.Host
namespace Microsoft.PowerShell.Host
{
using System;
using System.Collections.Generic;

View file

@ -1,26 +0,0 @@
#!/usr/bin/env bash
# Types files
cp ../monad/monad/miscfiles/types/CoreClr/types.ps1xml .
cp ../monad/monad/miscfiles/types/CoreClr/typesv3.ps1xml .
# Format files
cp ../monad/monad/miscfiles/display/Certificate.format.ps1xml .
cp ../monad/monad/miscfiles/display/Diagnostics.Format.ps1xml Diagnostics.format.ps1xml
cp ../monad/monad/miscfiles/display/DotNetTypes.format.ps1xml .
cp ../monad/monad/miscfiles/display/Event.format.ps1xml .
cp ../monad/monad/miscfiles/display/FileSystem.format.ps1xml .
cp ../monad/monad/miscfiles/display/Help.format.ps1xml .
cp ../monad/monad/miscfiles/display/HelpV3.format.ps1xml .
cp ../monad/monad/miscfiles/display/PowerShellCore.format.ps1xml .
cp ../monad/monad/miscfiles/display/PowerShellTrace.format.ps1xml .
cp ../monad/monad/miscfiles/display/Registry.format.ps1xml .
cp ../monad/monad/miscfiles/display/WSMan.format.ps1xml .
mkdir Modules
cp -r ../monad/monad/miscfiles/modules/Microsoft.PowerShell.Utility Modules
UTILSCLR=Modules/Microsoft.PowerShell.Utility/CoreClr
mv $UTILSCLR/* Modules/Microsoft.PowerShell.Utility && rmdir $UTILSCLR
cp -r ../monad/monad/miscfiles/modules/Microsoft.PowerShell.Security Modules
cp -r ../monad/monad/miscfiles/modules/Microsoft.PowerShell.Management Modules
cp -r ../monad/monad/miscfiles/modules/PSDiagnostics Modules

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,956 @@
#########################################################################################
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# Appx Provider Module
#
#########################################################################################
$script:ProviderName = "appx"
$script:AppxPackageExtension = ".appx"
$script:AppxManifestFile = "AppxManifest.xml"
$script:Architecture = "Architecture"
$script:ResourceId = "ResourceId"
$script:AppxPackageSources = $null
$script:AppxLocalPath="$env:LOCALAPPDATA\Microsoft\Windows\PowerShell\AppxProvider"
$script:AppxPackageSourcesFilePath = Microsoft.PowerShell.Management\Join-Path -Path $script:AppxLocalPath -ChildPath "AppxPackageSources.xml"
$Script:ResponseUri = "ResponseUri"
$Script:StatusCode = "StatusCode"
# Wildcard pattern matching configuration.
$script:wildcardOptions = [System.Management.Automation.WildcardOptions]::CultureInvariant -bor `
[System.Management.Automation.WildcardOptions]::IgnoreCase
#Localized Data
Microsoft.PowerShell.Utility\Import-LocalizedData LocalizedData -filename AppxProvider.Resource.psd1
#region Appx Provider APIs Implementation
function Get-PackageProviderName
{
return $script:ProviderName
}
function Initialize-Provider{
param(
)
}
function Get-DynamicOptions
{
param
(
[Microsoft.PackageManagement.MetaProvider.PowerShell.OptionCategory]
$category
)
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Get-DynamicOptions'))
switch($category)
{
Install {
Write-Output -InputObject (New-DynamicOption -Category $category -Name Architecture -ExpectedType String -IsRequired $false)
Write-Output -InputObject (New-DynamicOption -Category $category -Name ResourceId -ExpectedType String -IsRequired $false)
}
Package {
Write-Output -InputObject (New-DynamicOption -Category $category -Name Architecture -ExpectedType String -IsRequired $false)
Write-Output -InputObject (New-DynamicOption -Category $category -Name ResourceId -ExpectedType String -IsRequired $false)
}
}
}
function Find-Package
{
[CmdletBinding()]
param
(
[string[]]
$names,
[string]
$requiredVersion,
[string]
$minimumVersion,
[string]
$maximumVersion
)
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Find-Package'))
$ResourceId = $null
$Architecture = $null
$Sources = @()
$streamedResults = @()
$namesParameterEmpty = (-not $names) -or (($names.Count -eq 1) -and ($names[0] -eq ''))
Set-PackageSourcesVariable
if($RequiredVersion -and $MinimumVersion)
{
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $LocalizedData.VersionRangeAndRequiredVersionCannotBeSpecifiedTogether `
-ErrorId "VersionRangeAndRequiredVersionCannotBeSpecifiedTogether" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument
}
if($RequiredVersion -or $MinimumVersion)
{
if(-not $names -or $names.Count -ne 1 -or (Test-WildcardPattern -Name $names[0]))
{
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $LocalizedData.VersionParametersAreAllowedOnlyWithSinglePackage `
-ErrorId "VersionParametersAreAllowedOnlyWithSinglePackage" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument
}
}
$options = $request.Options
if($options)
{
foreach( $o in $options.Keys )
{
Write-Debug ( "OPTION: {0} => {1}" -f ($o, $options[$o]) )
}
if($options.ContainsKey('Source'))
{
$SourceNames = $($options['Source'])
Write-Verbose ($LocalizedData.SpecifiedSourceName -f ($SourceNames))
foreach($sourceName in $SourceNames)
{
if($script:AppxPackageSources.Contains($sourceName))
{
$Sources += $script:AppxPackageSources[$sourceName]
}
else
{
$sourceByLocation = Get-SourceName -Location $sourceName
if ($sourceByLocation -ne $null)
{
$Sources += $script:AppxPackageSources[$sourceByLocation]
}
else
{
$message = $LocalizedData.PackageSourceNotFound -f ($sourceName)
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $message `
-ErrorId "PackageSourceNotFound" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument `
-ExceptionObject $sourceName
}
}
}
}
else
{
Write-Verbose $LocalizedData.NoSourceNameIsSpecified
$script:AppxPackageSources.Values | Microsoft.PowerShell.Core\ForEach-Object { $Sources += $_ }
}
if($options.ContainsKey($script:Architecture))
{
$Architecture = $options[$script:Architecture]
}
if($options.ContainsKey($script:ResourceId))
{
$ResourceId = $options[$script:ResourceId]
}
}
foreach($source in $Sources)
{
$location = $source.SourceLocation
if($request.IsCanceled)
{
return
}
if(-not(Test-Path $location))
{
$message = $LocalizedData.PathNotFound -f ($Location)
Write-Verbose $message
continue
}
$packages = Get-AppxPackagesFromPath -path $location
foreach($pkg in $packages)
{
if($request.IsCanceled)
{
return
}
$pkgManifest = Get-PackageManfiestData -PackageFullPath $pkg.FullName
if(-not $pkgManifest)
{
continue
}
# $pkgManifest.Name has to match any of the supplied names, using PowerShell wildcards
if(-not($namesParameterEmpty))
{
if(-not(($names | Microsoft.PowerShell.Core\ForEach-Object { if ($pkgManifest.Name -like $_){return $true; break} } -End {return $false})))
{
continue
}
}
# Version
if($RequiredVersion)
{
if($RequiredVersion -ne $pkgManifest.Version)
{
continue
}
}
else
{
if(-not((-not $MinimumVersion -or ($MinimumVersion -le $pkgManifest.Version)) -and
(-not $MaximumVersion -or ($MaximumVersion -ge $pkgManifest.Version))))
{
continue
}
}
if($Architecture)
{
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Architecture, $script:wildcardOptions
if(-not($wildcardPattern.IsMatch($pkgManifest.Architecture)))
{
continue
}
}
if($ResourceId)
{
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $ResourceId, $script:wildcardOptions
if(-not($wildcardPattern.IsMatch($pkgManifest.ResourceId)))
{
continue
}
}
$sid = New-SoftwareIdentityFromPackage -Package $pkgManifest -Source $source.Name
$fastPackageReference = $sid.fastPackageReference
if($streamedResults -notcontains $fastPackageReference)
{
$streamedResults += $fastPackageReference
Write-Output -InputObject $sid
}
}
}
}
function Get-InstalledPackage
{
[CmdletBinding()]
param
(
[Parameter()]
[string]
$Name,
[Parameter()]
[string]
$RequiredVersion,
[Parameter()]
[string]
$MinimumVersion,
[Parameter()]
[string]
$MaximumVersion
)
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Get-InstalledPackage'))
$Architecture = $null
$ResourceId = $null
$options = $request.Options
if($options)
{
if($options.ContainsKey($script:Architecture))
{
$Architecture = $options[$script:Architecture]
}
if($options.ContainsKey($script:ResourceId))
{
$ResourceId = $options[$script:ResourceId]
}
}
$params = @{}
if($Name)
{
$params.Add("Name", $Name)
}
$packages = Appx\Get-AppxPackage @params
foreach($package in $packages)
{
if($RequiredVersion)
{
if($RequiredVersion -ne $package.Version)
{
continue
}
}
else
{
if(-not((-not $MinimumVersion -or ($MinimumVersion -le $package.Version)) -and
(-not $MaximumVersion -or ($MaximumVersion -ge $package.Version))))
{
continue
}
}
if($Architecture)
{
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $Architecture, $script:wildcardOptions
if(-not($wildcardPattern.IsMatch($package.Architecture)))
{
continue
}
}
if($ResourceId)
{
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $ResourceId,$script:wildcardOptions
if(-not($wildcardPattern.IsMatch($package.ResourceId)))
{
continue
}
}
$sid = New-SoftwareIdentityFromPackage -Package $package
write-Output $sid
}
}
function Install-Package
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$fastPackageReference
)
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Install-Package'))
Write-Debug -Message ($LocalizedData.FastPackageReference -f $fastPackageReference)
Appx\Add-AppxPackage -Path $fastPackageReference
}
function UnInstall-Package
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$fastPackageReference
)
Write-Debug -Message ($LocalizedData.ProviderApiDebugMessage -f ('Uninstall-Package'))
Write-Debug -Message ($LocalizedData.FastPackageReference -f $fastPackageReference)
Appx\Remove-AppxPackage -Package $fastPackageReference
}
function Add-PackageSource
{
[CmdletBinding()]
param
(
[string]
$Name,
[string]
$Location,
[bool]
$Trusted
)
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Add-PackageSource'))
Set-PackageSourcesVariable -Force
if(-not (Microsoft.PowerShell.Management\Test-Path $Location) -and
-not (Test-WebUri -uri $Location))
{
$LocationUri = [Uri]$Location
if($LocationUri.Scheme -eq 'file')
{
$message = $LocalizedData.PathNotFound -f ($Location)
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $message `
-ErrorId "PathNotFound" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument `
-ExceptionObject $Location
}
else
{
$message = $LocalizedData.InvalidWebUri -f ($Location, "Location")
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $message `
-ErrorId "InvalidWebUri" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument `
-ExceptionObject $Location
}
}
if(Test-WildcardPattern $Name)
{
$message = $LocalizedData.PackageSourceNameContainsWildCards -f ($Name)
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $message `
-ErrorId "PackageSourceNameContainsWildCards" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument `
-ExceptionObject $Name
}
$LocationString = Get-ValidPackageLocation -LocationString $Location -ParameterName "Location"
# Check if Location is already registered with another Name
$existingSourceName = Get-SourceName -Location $LocationString
if($existingSourceName -and
($Name -ne $existingSourceName))
{
$message = $LocalizedData.PackageSourceAlreadyRegistered -f ($existingSourceName, $Location, $Name)
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $message `
-ErrorId "PackageSourceAlreadyRegistered" `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument
}
# Check if Name is already registered
if($script:AppxPackageSources.Contains($Name))
{
$currentSourceObject = $script:AppxPackageSources[$Name]
$null = $script:AppxPackageSources.Remove($Name)
}
# Add new package source
$packageSource = Microsoft.PowerShell.Utility\New-Object PSCustomObject -Property ([ordered]@{
Name = $Name
SourceLocation = $LocationString
Trusted=$Trusted
Registered= $true
})
$script:AppxPackageSources.Add($Name, $packageSource)
$message = $LocalizedData.SourceRegistered -f ($Name, $LocationString)
Write-Verbose $message
# Persist the package sources
Save-PackageSources
# return the package source object.
Write-Output -InputObject (New-PackageSourceFromSource -Source $packageSource)
}
function Resolve-PackageSource
{
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Resolve-PackageSource'))
Set-PackageSourcesVariable
$SourceName = $request.PackageSources
if(-not $SourceName)
{
$SourceName = "*"
}
foreach($src in $SourceName)
{
if($request.IsCanceled)
{
return
}
$wildcardPattern = New-Object System.Management.Automation.WildcardPattern $src,$script:wildcardOptions
$sourceFound = $false
$script:AppxPackageSources.GetEnumerator() |
Microsoft.PowerShell.Core\Where-Object {$wildcardPattern.IsMatch($_.Key)} |
Microsoft.PowerShell.Core\ForEach-Object {
$source = $script:AppxPackageSources[$_.Key]
$packageSource = New-PackageSourceFromSource -Source $source
Write-Output -InputObject $packageSource
$sourceFound = $true
}
if(-not $sourceFound)
{
$sourceName = Get-SourceName -Location $src
if($sourceName)
{
$source = $script:AppxPackageSources[$sourceName]
$packageSource = New-PackageSourceFromSource -Source $source
Write-Output -InputObject $packageSource
}
elseif( -not (Test-WildcardPattern $src))
{
$message = $LocalizedData.PackageSourceNotFound -f ($src)
Write-Error -Message $message -ErrorId "PackageSourceNotFound" -Category InvalidOperation -TargetObject $src
}
}
}
}
function Remove-PackageSource
{
param
(
[string]
$Name
)
Write-Debug ($LocalizedData.ProviderApiDebugMessage -f ('Remove-PackageSource'))
Set-PackageSourcesVariable -Force
$SourcesToBeRemoved = @()
foreach ($sourceName in $Name)
{
if($request.IsCanceled)
{
return
}
# Check if $Name contains any wildcards
if(Test-WildcardPattern $sourceName)
{
$message = $LocalizedData.PackageSourceNameContainsWildCards -f ($sourceName)
Write-Error -Message $message -ErrorId "PackageSourceNameContainsWildCards" -Category InvalidOperation -TargetObject $sourceName
continue
}
# Check if the specified package source name is in the registered package sources
if(-not $script:AppxPackageSources.Contains($sourceName))
{
$message = $LocalizedData.PackageSourceNotFound -f ($sourceName)
Write-Error -Message $message -ErrorId "PackageSourceNotFound" -Category InvalidOperation -TargetObject $sourceName
continue
}
$SourcesToBeRemoved += $sourceName
$message = $LocalizedData.PackageSourceUnregistered -f ($sourceName)
Write-Verbose $message
}
# Remove the SourcesToBeRemoved
$SourcesToBeRemoved | Microsoft.PowerShell.Core\ForEach-Object { $null = $script:AppxPackageSources.Remove($_) }
# Persist the package sources
Save-PackageSources
}
#endregion
#region Common functions
function Get-AppxPackagesFromPath
{
param
(
[Parameter(Mandatory=$true)]
$Path
)
$filterAppxPackages = "*"+$script:AppxPackageExtension
$packages = Get-ChildItem -path $Path -filter $filterAppxPackages
return $packages
}
function Get-PackageManfiestData
{
param
(
[Parameter(Mandatory=$true)]
$PackageFullPath
)
$guid = [System.Guid]::NewGuid().toString()
try
{
[System.IO.Compression.ZipFile]::ExtractToDirectory($PackageFullPath, "$env:TEMP\$guid")
}
catch
{
Write-Verbose( $LocalizedData.MetaDataExtractionFailed -f ($PackageFullPath) )
return $null
}
[xml] $packageManifest = Get-Content "$env:TEMP\$guid\$script:AppxManifestFile" -ErrorAction SilentlyContinue
if($packageManifest)
{
$Identity = $packageManifest.Package.Identity
$manifestData = new-object psObject -Property @{Name=$Identity.Name; Architecture=$Identity.ProcessorArchitecture; Publisher=$Identity.Publisher; Version=$Identity.Version; ResourceId=$Identity.resourceId; PackageFullName=$PackageFullPath}
Remove-Item -Path "$env:TEMP\$guid" -Recurse -Force -ErrorAction SilentlyContinue
return $manifestData
}
else
{
Write-Verbose ($LocalizedData.MetaDataExtractionFailed -f ($PackageFullPath) )
}
return $null
}
function New-FastPackageReference
{
param
(
[Parameter(Mandatory=$true)]
[string]
$PackageFullName
)
return "$PackageFullName"
}
function New-SoftwareIdentityFromPackage
{
param
(
[Parameter(Mandatory=$true)]
$Package,
[string]
$Source
)
$fastPackageReference = New-FastPackageReference -PackageFullName $Package.PackageFullName
if(-not($Source))
{
$Source = $Package.Publisher
}
$details = @{
Publisher = $Package.Publisher
Architecture = $Package.Architecture
ResourceId = $Package.ResourceId
PackageFullName = $Package.PackageFullName
}
$params = @{
FastPackageReference = $fastPackageReference;
Name = $Package.Name;
Version = $Package.Version;
versionScheme = "MultiPartNumeric";
Source = $source;
Details = $details;
}
$sid = New-SoftwareIdentity @params
return $sid
}
function Test-WebUri
{
[CmdletBinding()]
[OutputType([bool])]
Param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[Uri]
$uri
)
return ($uri.AbsoluteURI -ne $null) -and ($uri.Scheme -match '[http|https]')
}
function Test-WildcardPattern
{
[CmdletBinding()]
[OutputType([bool])]
param(
[Parameter(Mandatory=$true)]
[ValidateNotNull()]
$Name
)
return [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Name)
}
function DeSerialize-PSObject
{
[CmdletBinding(PositionalBinding=$false)]
Param
(
[Parameter(Mandatory=$true)]
$Path
)
$filecontent = Microsoft.PowerShell.Management\Get-Content -Path $Path
[System.Management.Automation.PSSerializer]::Deserialize($filecontent)
}
function Get-SourceName
{
[CmdletBinding()]
[OutputType("string")]
Param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$Location
)
Set-PackageSourcesVariable
foreach($source in $script:AppxPackageSources.Values)
{
if($source.SourceLocation -eq $Location)
{
return $source.Name
}
}
}
function WebRequestApisAvailable
{
$webRequestApiAvailable = $false
try
{
[System.Net.WebRequest]
$webRequestApiAvailable = $true
}
catch
{
}
return $webRequestApiAvailable
}
function Ping-Endpoint
{
param
(
[Parameter()]
[ValidateNotNullOrEmpty()]
[string[]]
$Endpoint
)
$results = @{}
if(WebRequestApisAvailable)
{
$iss = [System.Management.Automation.Runspaces.InitialSessionState]::Create()
$iss.types.clear()
$iss.formats.clear()
$iss.LanguageMode = "FullLanguage"
$WebRequestcmd = @'
try
{{
$request = [System.Net.WebRequest]::Create("{0}")
$request.Method = 'GET'
$request.Timeout = 30000
$response = [System.Net.HttpWebResponse]$request.GetResponse()
$response
$response.Close()
}}
catch [System.Net.WebException]
{{
"Error:System.Net.WebException"
}}
'@ -f $EndPoint
$ps = [powershell]::Create($iss).AddScript($WebRequestcmd)
$response = $ps.Invoke()
$ps.dispose()
if ($response -ne "Error:System.Net.WebException")
{
$results.Add($Script:ResponseUri,$response.ResponseUri.ToString())
$results.Add($Script:StatusCode,$response.StatusCode.value__)
}
}
else
{
$response = $null
try
{
$httpClient = New-Object 'System.Net.Http.HttpClient'
$response = $httpclient.GetAsync($endpoint)
}
catch
{
}
if ($response -ne $null -and $response.result -ne $null)
{
$results.Add($Script:ResponseUri,$response.Result.RequestMessage.RequestUri.AbsoluteUri.ToString())
$results.Add($Script:StatusCode,$response.result.StatusCode.value__)
}
}
return $results
}
function Get-ValidPackageLocation
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$LocationString,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$ParameterName
)
# Get the actual Uri from the Location
if(-not (Microsoft.PowerShell.Management\Test-Path $LocationString))
{
$results = Ping-Endpoint -Endpoint $LocationString
if ($results.ContainsKey("Exception"))
{
$Exception = $results["Exception"]
if($Exception)
{
$message = $LocalizedData.InvalidWebUri -f ($LocationString, $ParameterName)
ThrowError -ExceptionName "System.ArgumentException" `
-ExceptionMessage $message `
-ErrorId "InvalidWebUri" `
-ExceptionObject $Exception `
-CallerPSCmdlet $PSCmdlet `
-ErrorCategory InvalidArgument
}
}
if ($results.ContainsKey("ResponseUri"))
{
$LocationString = $results["ResponseUri"]
}
}
return $LocationString
}
function Set-PackageSourcesVariable
{
param([switch]$Force)
if(-not $script:AppxPackageSources -or $Force)
{
if(Microsoft.PowerShell.Management\Test-Path $script:AppxPackageSourcesFilePath)
{
$script:AppxPackageSources = DeSerialize-PSObject -Path $script:AppxPackageSourcesFilePath
}
else
{
$script:AppxPackageSources = [ordered]@{}
}
}
}
function Save-PackageSources
{
if($script:AppxPackageSources)
{
if(-not (Microsoft.PowerShell.Management\Test-Path $script:AppxLocalPath))
{
$null = Microsoft.PowerShell.Management\New-Item -Path $script:AppxLocalPath `
-ItemType Directory -Force `
-ErrorAction SilentlyContinue `
-WarningAction SilentlyContinue `
-Confirm:$false -WhatIf:$false
}
Microsoft.PowerShell.Utility\Out-File -FilePath $script:AppxPackageSourcesFilePath -Force -InputObject ([System.Management.Automation.PSSerializer]::Serialize($script:AppxPackageSources))
}
}
function New-PackageSourceFromSource
{
param
(
[Parameter(Mandatory)]
$Source
)
# create a new package source
$src = New-PackageSource -Name $Source.Name `
-Location $Source.SourceLocation `
-Trusted $Source.Trusted `
-Registered $Source.Registered `
Write-Verbose ( $LocalizedData.PackageSourceDetails -f ($src.Name, $src.Location, $src.IsTrusted, $src.IsRegistered) )
# return the package source object.
Write-Output -InputObject $src
}
#endregion
# Utility to throw an errorrecord
function ThrowError
{
param
(
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCmdlet]
$CallerPSCmdlet,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ExceptionName,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ExceptionMessage,
[System.Object]
$ExceptionObject,
[parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ErrorId,
[parameter(Mandatory = $true)]
[ValidateNotNull()]
[System.Management.Automation.ErrorCategory]
$ErrorCategory
)
$exception = New-Object $ExceptionName $ExceptionMessage;
$errorRecord = New-Object System.Management.Automation.ErrorRecord $exception, $ErrorId, $ErrorCategory, $ExceptionObject
$CallerPSCmdlet.ThrowTerminatingError($errorRecord)
}
#endregion
Export-ModuleMember -Function Find-Package, `
Install-Package, `
Uninstall-Package, `
Get-InstalledPackage, `
Remove-PackageSource, `
Resolve-PackageSource, `
Add-PackageSource, `
Get-DynamicOptions, `
Initialize-Provider, `
Get-PackageProviderName

View file

@ -0,0 +1,12 @@
@{
GUID="eb74e8da-9ae2-482a-a648-e96550fb8733"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="1.0.0.0"
FunctionsToExport = @('Compress-Archive', 'Expand-Archive')
CmdletsToExport = @()
AliasesToExport = @()
NestedModules="Microsoft.PowerShell.Archive.psm1"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?LinkId=393254'
}

View file

@ -0,0 +1,14 @@
@{
GUID="56D66100-99A0-4FFC-A12D-EEE9A6718AEF"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
CLRVersion="4.0"
AliasesToExport = @()
FunctionsToExport = @()
CmdletsToExport="Start-Transcript", "Stop-Transcript"
NestedModules="Microsoft.PowerShell.ConsoleHost.dll"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390784'
}

View file

@ -0,0 +1,99 @@
@{
GUID="EEFCB906-B326-4E99-9F54-8B4BB6EF3C6D"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.1.0.0"
PowerShellVersion="3.0"
CLRVersion="4.0"
NestedModules="Microsoft.PowerShell.Commands.Management.dll"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390785'
AliasesToExport = @("gcb", "scb")
FunctionsToExport = @()
CmdletsToExport=@("Add-Content",
"Clear-Content",
"Clear-ItemProperty",
"Join-Path",
"Convert-Path",
"Copy-ItemProperty",
"Get-EventLog",
"Clear-EventLog",
"Write-EventLog",
"Limit-EventLog",
"Show-EventLog",
"New-EventLog",
"Remove-EventLog",
"Get-ChildItem",
"Get-Content",
"Get-ItemProperty",
"Get-ItemPropertyValue",
"Get-WmiObject",
"Invoke-WmiMethod",
"Move-ItemProperty",
"Get-Location",
"Set-Location",
"Push-Location",
"Pop-Location",
"New-PSDrive",
"Remove-PSDrive",
"Get-PSDrive",
"Get-Item",
"New-Item",
"Set-Item",
"Remove-Item",
"Move-Item",
"Rename-Item",
"Copy-Item",
"Clear-Item",
"Invoke-Item",
"Get-PSProvider",
"New-ItemProperty",
"Split-Path",
"Test-Path",
"Get-Process",
"Stop-Process",
"Wait-Process",
"Debug-Process",
"Start-Process",
"Remove-ItemProperty",
"Remove-WmiObject",
"Rename-ItemProperty",
"Register-WmiEvent",
"Resolve-Path",
"Get-Service",
"Stop-Service",
"Start-Service",
"Suspend-Service",
"Resume-Service",
"Restart-Service",
"Set-Service",
"New-Service",
"Set-Content",
"Set-ItemProperty",
"Set-WmiInstance",
"Get-Transaction",
"Start-Transaction",
"Complete-Transaction",
"Undo-Transaction",
"Use-Transaction",
"New-WebServiceProxy",
"Get-HotFix",
"Test-Connection",
"Enable-ComputerRestore",
"Disable-ComputerRestore",
"Checkpoint-Computer",
"Get-ComputerRestorePoint",
"Restart-Computer",
"Stop-Computer",
"Restore-Computer",
"Add-Computer",
"Remove-Computer",
"Test-ComputerSecureChannel",
"Reset-ComputerMachinePassword",
"Rename-Computer",
"Get-ControlPanelItem",
"Show-ControlPanelItem",
"Clear-Recyclebin",
"Get-Clipboard",
"Set-Clipboard")
}

View file

@ -0,0 +1,14 @@
@{
GUID="A94C8C7E-9810-47C0-B8AF-65089C13A35A"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
CLRVersion="4.0"
AliasesToExport = @()
FunctionsToExport = @()
CmdletsToExport="Get-Acl", "Set-Acl", "Get-PfxCertificate", "Get-Credential", "Get-ExecutionPolicy", "Set-ExecutionPolicy", "Get-AuthenticodeSignature", "Set-AuthenticodeSignature", "ConvertFrom-SecureString", "ConvertTo-SecureString", "Get-CmsMessage", "Unprotect-CmsMessage", "Protect-CmsMessage" , "New-FileCatalog" , "Test-FileCatalog"
NestedModules="Microsoft.PowerShell.Security.dll"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390786'
}

View file

@ -0,0 +1,709 @@
function Get-FileHash
{
[CmdletBinding(DefaultParameterSetName = "Path", HelpURI = "http://go.microsoft.com/fwlink/?LinkId=517145")]
param(
[Parameter(Mandatory, ParameterSetName="Path", Position = 0)]
[System.String[]]
$Path,
[Parameter(Mandatory, ParameterSetName="LiteralPath", ValueFromPipelineByPropertyName = $true)]
[Alias("PSPath")]
[System.String[]]
$LiteralPath,
[Parameter(Mandatory, ParameterSetName="Stream")]
[System.IO.Stream]
$InputStream,
[ValidateSet("SHA1", "SHA256", "SHA384", "SHA512", "MACTripleDES", "MD5", "RIPEMD160")]
[System.String]
$Algorithm="SHA256"
)
begin
{
# Construct the strongly-typed crypto object
# First see if it has a FIPS algorithm
$hasherType = "System.Security.Cryptography.${Algorithm}CryptoServiceProvider" -as [Type]
if ($hasherType)
{
$hasher = $hasherType::New()
}
else
{
# Check if the type is supported in the current system
$algorithmType = "System.Security.Cryptography.${Algorithm}" -as [Type]
if ($algorithmType)
{
if ($Algorithm -eq "MACTripleDES")
{
$hasher = $algorithmType::New()
}
else
{
$hasher = $algorithmType::Create()
}
}
else
{
$errorId = "AlgorithmTypeNotSupported"
$errorCategory = [System.Management.Automation.ErrorCategory]::InvalidArgument
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::AlgorithmTypeNotSupported -f $Algorithm
$exception = [System.InvalidOperationException]::New($errorMessage)
$errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null)
$PSCmdlet.ThrowTerminatingError($errorRecord)
}
}
function GetStreamHash
{
param(
[System.IO.Stream]
$InputStream,
[System.String]
$RelatedPath,
[System.Security.Cryptography.HashAlgorithm]
$Hasher)
# Compute file-hash using the crypto object
[Byte[]] $computedHash = $Hasher.ComputeHash($InputStream)
[string] $hash = [BitConverter]::ToString($computedHash) -replace '-',''
if ($RelatedPath -eq $null)
{
$retVal = [PSCustomObject] @{
Algorithm = $Algorithm.ToUpperInvariant()
Hash = $hash
}
}
else
{
$retVal = [PSCustomObject] @{
Algorithm = $Algorithm.ToUpperInvariant()
Hash = $hash
Path = $RelatedPath
}
}
$retVal.psobject.TypeNames.Insert(0, "Microsoft.Powershell.Utility.FileHash")
$retVal
}
}
process
{
if($PSCmdlet.ParameterSetName -eq "Stream")
{
GetStreamHash -InputStream $InputStream -RelatedPath $null -Hasher $hasher
}
else
{
$pathsToProcess = @()
if($PSCmdlet.ParameterSetName -eq "LiteralPath")
{
$pathsToProcess += Resolve-Path -LiteralPath $LiteralPath | Foreach-Object ProviderPath
}
if($PSCmdlet.ParameterSetName -eq "Path")
{
$pathsToProcess += Resolve-Path $Path | Foreach-Object ProviderPath
}
foreach($filePath in $pathsToProcess)
{
if(Test-Path -LiteralPath $filePath -PathType Container)
{
continue
}
try
{
# Read the file specified in $FilePath as a Byte array
[system.io.stream]$stream = [system.io.file]::OpenRead($filePath)
GetStreamHash -InputStream $stream -RelatedPath $filePath -Hasher $hasher
}
catch [Exception]
{
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FileReadError -f $FilePath, $_
Write-Error -Message $errorMessage -Category ReadError -ErrorId "FileReadError" -TargetObject $FilePath
return
}
finally
{
if($stream)
{
$stream.Dispose()
}
}
}
}
}
}
<# This cmdlet is used to create a new temporary file in $env:temp #>
function New-TemporaryFile
{
[CmdletBinding(
HelpURI='http://go.microsoft.com/fwlink/?LinkId=526726',
SupportsShouldProcess=$true)]
[OutputType([System.IO.FileInfo])]
Param()
Begin
{
try
{
if($PSCmdlet.ShouldProcess($env:TEMP))
{
$tempFilePath = [System.IO.Path]::GetTempFileName()
}
}
catch
{
$errorRecord = [System.Management.Automation.ErrorRecord]::new($_.Exception,"NewTemporaryFileWriteError", "WriteError", $env:TEMP)
Write-Error -ErrorRecord $errorRecord
return
}
if($tempFilePath)
{
Get-Item $tempFilePath
}
}
}
<# This cmdlet is used to generate a new guid #>
function New-Guid
{
[CmdletBinding(HelpURI='http://go.microsoft.com/fwlink/?LinkId=526920')]
[OutputType([System.Guid])]
Param()
Begin
{
[Guid]::NewGuid()
}
}
<############################################################################################
# Format-Hex cmdlet helps in displaying the Hexadecimal equivalent of the input data.
############################################################################################>
function Format-Hex
{
[CmdletBinding(
DefaultParameterSetName="Path",
HelpUri="http://go.microsoft.com/fwlink/?LinkId=526919")]
[Alias("fhx")]
[OutputType("Microsoft.PowerShell.Commands.ByteCollection")]
param
(
[Parameter (Mandatory=$true, Position=0, ParameterSetName="Path")]
[ValidateNotNullOrEmpty()]
[string[]] $Path,
[Parameter (Mandatory=$true, ParameterSetName="LiteralPath")]
[ValidateNotNullOrEmpty()]
[Alias("PSPath")]
[string[]] $LiteralPath,
[Parameter(Mandatory=$true, ParameterSetName="ByInputObject", ValueFromPipeline=$true)]
[Object] $InputObject,
[Parameter (ParameterSetName="ByInputObject")]
[ValidateSet("Ascii", "UTF32", "UTF7", "UTF8", "BigEndianUnicode", "Unicode")]
[string] $Encoding = "Ascii",
[Parameter(ParameterSetName="ByInputObject")]
[switch]$Raw
)
begin
{
$bufferSize = 16
$inputStreamArray = [System.Collections.ArrayList]::New()
<############################################################################################
# The ConvertToHexadecimalHelper is a helper method used to fetch unicode bytes from the
# input data and display the hexadecimial representaion of the of the input data in bytes.
############################################################################################>
function ConvertToHexadecimalHelper
{
param
(
[Byte[]] $inputBytes,
[string] $path,
[Uint32] $offset
)
# This section is used to display the hexadecimal
# representaion of the of the input data in bytes.
if($inputBytes -ne $null)
{
$byteCollectionObject = [Microsoft.PowerShell.Commands.ByteCollection]::new($offset, $inputBytes, $path)
Write-Output -InputObject $byteCollectionObject
}
}
<############################################################################################
# The ProcessFileContent is a helper method used to fetch file contents in blocks and
# process it to support displaying hexadecimal formating of the fetched content.
############################################################################################>
function ProcessFileContent
{
param
(
[string] $filePath,
[boolean] $isLiteralPath
)
if($isLiteralPath)
{
$resolvedPaths = Resolve-Path -LiteralPath $filePath
}
else
{
$resolvedPaths = Resolve-Path -Path $filePath
}
# If Path resolution has failed then a corresponding non-terminating error is
# written to the pipeline. We continue processing any remaining files.
if($resolvedPaths -eq $null)
{
return
}
if($resolvedPaths.Count -gt 1)
{
# write a non-terminating error message indicating that path specified is resolving to multiple file system paths.
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexResolvePathError -f $filePath
Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::InvalidData) -ErrorId "FormatHexResolvePathError"
}
$targetFilePath = $resolvedPaths.ProviderPath
if($targetFilePath -ne $null)
{
$buffer = [byte[]]::new($bufferSize)
try
{
try
{
$currentFileStream = [System.IO.File]::Open($targetFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
}
catch
{
# Failed to access the file. Write a non terminating error to the pipeline
# and move on with the remaining files.
$exception = $_.Exception
if($null -ne $_.Exception -and
$null -ne $_.Exception.InnerException)
{
$exception = $_.Exception.InnerException
}
$errorRecord = [System.Management.Automation.ErrorRecord]::new($exception,"FormatHexFileAccessError", ([System.Management.Automation.ErrorCategory]::ReadError), $targetFilePath)
$PSCmdlet.WriteError($errorRecord)
}
if($null -ne $currentFileStream)
{
$srcStream = [System.IO.BinaryReader]::new($currentFileStream)
$displayHeader = $true
$offset = 0
$blockCounter = 0
while($numberOfBytesRead = $srcStream.Read($buffer, 0, $bufferSize))
{
# send only the bytes that have been read
# if we send the whole buffer, we'll have extraneous bytes
# at the end of an incomplete group of 16 bytes
if ( $numberOfBytesRead -eq $bufferSize )
{
# under some circumstances if we don't copy the buffer
# and the results are stored to a variable, the results are not
# correct and one object replicated in all the output objects
ConvertToHexadecimalHelper ($buffer.Clone()) $targetFilePath $offset
}
else
{
# handle the case of the partial (and probably last) buffer
$bytesReadBuffer = [byte[]]::New($numberOfBytesRead)
[Array]::Copy($buffer,0, $bytesReadBuffer,0,$numberOfBytesRead)
ConvertToHexadecimalHelper $bytesReadBuffer $targetFilePath $offset
}
$displayHeader = $false
$blockCounter++;
# Updating the offset value.
$offset = $blockCounter*0x10
}
}
}
finally
{
If($null -ne $currentFileStream)
{
$currentFileStream.Dispose()
}
If($null -ne $srcStream)
{
$srcStream.Dispose()
}
}
}
}
}
process
{
switch($PSCmdlet.ParameterSetName)
{
"Path"
{
ProcessFileContent $Path $false
}
"LiteralPath"
{
ProcessFileContent $LiteralPath $true
}
"ByInputObject"
{
# If it's an actual byte array, then we directly use it for hexadecimal formatting.
if($InputObject -is [Byte[]])
{
ConvertToHexadecimalHelper $InputObject $null
return
}
# if it's a single byte, we'll assume streaming
elseif($InputObject -is [byte])
{
$null = $inputStreamArray.Add($InputObject)
}
# If the input data is of string type then directly get bytes out of it.
elseif($InputObject -is [string])
{
# The ValidateSet arribute on the Encoding paramter makes sure that only
# valid values (supported on all paltforms where Format-Hex is avaliable)
# are allowed through user input.
$inputBytes = [Text.Encoding]::$Encoding.GetBytes($InputObject)
ConvertToHexadecimalHelper $inputBytes $null
return
}
elseif($InputObject -is [System.IO.FileSystemInfo])
{
# If file path is provided as an input, use the file contents to show the hexadecimal format.
$filePath = ([System.IO.FileSystemInfo]$InputObject).FullName
ProcessFileContent $filePath $false
return
}
elseif($InputObject -is [int64])
{
$inputBytes = [BitConverter]::GetBytes($InputObject)
$null = $inputStreamArray.AddRange($inputBytes)
}
elseif($InputObject -is [int64[]])
{
foreach($i64 in $InputObject)
{
$inputBytes = [BitConverter]::GetBytes($i64)
$null = $inputStreamArray.AddRange($inputBytes)
}
}
elseif($InputObject -is [int])
{
# If we get what appears as ints, it may not be what the user really wants.
# for example, if the user types a small set of numbers just to get their
# character representations, as follows:
#
# 170..180 | format-hex
# Path:
# 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
#00000000 AA AB AC AD AE AF B0 B1 B2 B3 B4 ª«¬­®¯°±²³´
#
# any integer padding is likely to be more confusing than this
# fairly compact representation.
#
# However, some might like to see the results with the raw data,
# -Raw exists to provide that behavior:
# PS# 170..180 | format-hex -Raw
#
# Path:
#
# 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
#
# 00000000 AA 00 00 00 AB 00 00 00 AC 00 00 00 AD 00 00 00 ª...«...¬...­...
# 00000010 AE 00 00 00 AF 00 00 00 B0 00 00 00 B1 00 00 00 ®...¯...°...±...
# 00000020 B2 00 00 00 B3 00 00 00 B4 00 00 00 ²...³...´...
#
# this provides a representation of the piped numbers which includes all
# of the bytes which are in an int32
if ( $Raw )
{
$inputBytes = [BitConverter]::GetBytes($InputObject)
$null = $inputStreamArray.AddRange($inputBytes)
}
else
{
# first determine whether we can represent this as a byte
$possibleByte = $InputObject -as [byte]
# first determine whether we can represent this as a int16
$possibleInt16 = $InputObject -as [int16]
if ( $possibleByte -ne $null )
{
$null = $inputStreamArray.Add($possibleByte)
}
elseif ( $possibleint16 -ne $null )
{
$inputBytes = [BitConverter]::GetBytes($possibleInt16)
$null = $inputStreamArray.AddRange($inputBytes)
}
else
{
# now int
$inputBytes = [BitConverter]::GetBytes($InputObject)
$null = $inputStreamArray.AddRange($inputBytes)
}
}
}
else
{
# Otherwise, write a non-terminating error message indicating that input object type is not supported.
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::FormatHexTypeNotSupported -f $InputObject.GetType()
Write-Error -Message $errorMessage -Category ([System.Management.Automation.ErrorCategory]::ParserError) -ErrorId "FormatHexFailureTypeNotSupported"
}
# Handle streaming case here
# during this process we may not have enough characters to create a ByteCollection
# if we do, create as many ByteCollections as necessary, each being 16 bytes in length
if ( $inputStreamArray.Count -ge $bufferSize )
{
$rowCount = [math]::Floor($inputStreamArray.Count/$bufferSize)
$arrayLength = $bufferSize * $rowCount
for($i = 0; $i -lt $rowCount; $i++)
{
$rowOffset = $i * $bufferSize
ConvertToHexadecimalHelper -inputBytes $inputStreamArray.GetRange($rowOffset, $bufferSize) -path ' ' -offset $offset
$offset += $bufferSize
}
# We use RemoveRange because of the pathological case of having
# streamed combination of bytes, int16, int32, int64 which are greater
# than 16 bytes. Consider the case:
# $i = [int16]::MaxValue + 3
# $i64=[int64]::MaxValue -5
# .{ $i;$i;$i;$i64 } | format-hex
# which create an arraylist 20 bytes
# we need to remove only the bytes from the array which we emitted
$inputStreamArray.RemoveRange(0,$arrayLength)
}
}
}
}
end
{
# now manage any left over bytes in the $inputStreamArray
if ( $PSCmdlet.ParameterSetName -eq "ByInputObject" )
{
ConvertToHexadecimalHelper $inputStreamArray $null -path ' ' -offset $offset
}
}
}
## Imports a PowerShell Data File - a PowerShell hashtable defined in
## a file (such as a Module manifest, session configuration file)
function Import-PowerShellDataFile
{
[CmdletBinding(DefaultParameterSetName = "ByPath", HelpUri = "http://go.microsoft.com/fwlink/?LinkID=623621")]
[OutputType("System.Collections.Hashtable")]
param(
[Parameter(ParameterSetName = "ByPath", Position = 0)]
[String[]] $Path,
[Parameter(ParameterSetName = "ByLiteralPath", ValueFromPipelineByPropertyName = $true)]
[Alias("PSPath")]
[String[]] $LiteralPath
)
begin
{
function ThrowInvalidDataFile
{
param($resolvedPath, $extraError)
$errorId = "CouldNotParseAsPowerShellDataFile$extraError"
$errorCategory = [System.Management.Automation.ErrorCategory]::InvalidData
$errorMessage = [Microsoft.PowerShell.Commands.UtilityResources]::CouldNotParseAsPowerShellDataFile -f $resolvedPath
$exception = [System.InvalidOperationException]::New($errorMessage)
$errorRecord = [System.Management.Automation.ErrorRecord]::New($exception, $errorId, $errorCategory, $null)
$PSCmdlet.WriteError($errorRecord)
}
}
process
{
foreach($resolvedPath in (Resolve-Path @PSBoundParameters))
{
$parseErrors = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile(($resolvedPath.ProviderPath), [ref] $null, [ref] $parseErrors)
if ($parseErrors.Length -gt 0)
{
ThrowInvalidDataFile $resolvedPath
}
else
{
$data = $ast.Find( { $args[0] -is [System.Management.Automation.Language.HashtableAst] }, $false )
if($data)
{
$data.SafeGetValue()
}
else
{
ThrowInvalidDataFile $resolvedPath "NoHashtableRoot"
}
}
}
}
}
## Converts a SDDL string into an object-based representation of a security
## descriptor
function ConvertFrom-SddlString
{
[CmdletBinding(HelpUri = "http://go.microsoft.com/fwlink/?LinkId=623636")]
param(
## The string representing the security descriptor in SDDL syntax
[Parameter(Mandatory, Position = 0)]
[String] $Sddl,
## The type of rights that this SDDL string represents, if any.
[Parameter()]
[ValidateSet(
"FileSystemRights", "RegistryRights", "ActiveDirectoryRights",
"MutexRights", "SemaphoreRights", "CryptoKeyRights",
"EventWaitHandleRights")]
$Type
)
## Translates a SID into a NT Account
function ConvertTo-NtAccount
{
param($Sid)
if($Sid)
{
$securityIdentifier = [System.Security.Principal.SecurityIdentifier] $Sid
try
{
$ntAccount = $securityIdentifier.Translate([System.Security.Principal.NTAccount]).ToString()
}
catch{}
$ntAccount
}
}
## Gets the access rights that apply to an access mask, preferring right types
## of 'Type' if specified.
function Get-AccessRights
{
param($AccessMask, $Type)
## All the types of access rights understood by .NET
$rightTypes = [Ordered] @{
"FileSystemRights" = [System.Security.AccessControl.FileSystemRights]
"RegistryRights" = [System.Security.AccessControl.RegistryRights]
"ActiveDirectoryRights" = [System.DirectoryServices.ActiveDirectoryRights]
"MutexRights" = [System.Security.AccessControl.MutexRights]
"SemaphoreRights" = [System.Security.AccessControl.SemaphoreRights]
"CryptoKeyRights" = [System.Security.AccessControl.CryptoKeyRights]
"EventWaitHandleRights" = [System.Security.AccessControl.EventWaitHandleRights]
}
$typesToExamine = $rightTypes.Values
## If they know the access mask represents a certain type, prefer its names
## (i.e.: CreateLink for the registry over CreateDirectories for the filesystem)
if($Type)
{
$typesToExamine = @($rightTypes[$Type]) + $typesToExamine
}
## Stores the access types we've found that apply
$foundAccess = @()
## Store the access types we've already seen, so that we don't report access
## flags that are essentially duplicate. Many of the access values in the different
## enumerations have the same value but with different names.
$foundValues = @{}
## Go through the entries in the different right types, and see if they apply to the
## provided access mask. If they do, then add that to the result.
foreach($rightType in $typesToExamine)
{
foreach($accessFlag in [Enum]::GetNames($rightType))
{
$longKeyValue = [long] $rightType::$accessFlag
if(-not $foundValues.ContainsKey($longKeyValue))
{
$foundValues[$longKeyValue] = $true
if(($AccessMask -band $longKeyValue) -eq ($longKeyValue))
{
$foundAccess += $accessFlag
}
}
}
}
$foundAccess | Sort-Object
}
## Converts an ACE into a string representation
function ConvertTo-AceString
{
param(
[Parameter(ValueFromPipeline)]
$Ace,
$Type
)
process
{
foreach($aceEntry in $Ace)
{
$AceString = (ConvertTo-NtAccount $aceEntry.SecurityIdentifier) + ": " + $aceEntry.AceQualifier
if($aceEntry.AceFlags -ne "None")
{
$AceString += " " + $aceEntry.AceFlags
}
if($aceEntry.AccessMask)
{
$foundAccess = Get-AccessRights $aceEntry.AccessMask $Type
if($foundAccess)
{
$AceString += " ({0})" -f ($foundAccess -join ", ")
}
}
$AceString
}
}
}
$rawSecurityDescriptor = [Security.AccessControl.CommonSecurityDescriptor]::new($false,$false,$Sddl)
$owner = ConvertTo-NtAccount $rawSecurityDescriptor.Owner
$group = ConvertTo-NtAccount $rawSecurityDescriptor.Group
$discretionaryAcl = ConvertTo-AceString $rawSecurityDescriptor.DiscretionaryAcl $Type
$systemAcl = ConvertTo-AceString $rawSecurityDescriptor.SystemAcl $Type
[PSCustomObject] @{
Owner = $owner
Group = $group
DiscretionaryAcl = @($discretionaryAcl)
SystemAcl = @($systemAcl)
RawDescriptor = $rawSecurityDescriptor
}
}

View file

@ -0,0 +1,15 @@
@{
GUID="766204A6-330E-4263-A7AB-46C87AFC366C"
Author="Microsoft Corporation"
CompanyName="Microsoft Corporation"
Copyright="© Microsoft Corporation. All rights reserved."
ModuleVersion="3.0.0.0"
PowerShellVersion="3.0"
CLRVersion="4.0"
AliasesToExport = @()
FunctionsToExport = @()
CmdletsToExport="Disable-WSManCredSSP", "Enable-WSManCredSSP", "Get-WSManCredSSP", "Set-WSManQuickConfig", "Test-WSMan", "Invoke-WSManAction", "Connect-WSMan", "Disconnect-WSMan", "Get-WSManInstance", "Set-WSManInstance", "Remove-WSManInstance", "New-WSManInstance", "New-WSManSessionOption"
NestedModules="Microsoft.WSMan.Management.dll"
FormatsToProcess="WSMan.format.ps1xml"
HelpInfoURI = 'http://go.microsoft.com/fwlink/?linkid=390788'
}

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,202 @@
<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
<ViewDefinitions>
<View>
<Name>PSRepositoryItemInfo</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.PSRepositoryItemInfo</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>10</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>35</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>10</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>20</Width>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Version</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Type</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Repository</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Description</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>PSRepository</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.PSRepository</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>25</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>25</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>20</Width>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>PackageManagementProvider</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>InstallationPolicy</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>SourceLocation</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>PSScriptInfo</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.PSScriptInfo</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>10</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>25</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>20</Width>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Version</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Author</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Description</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>PSGetDscResourceInfo</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.PSGetCommandInfo</TypeName>
<TypeName>Microsoft.PowerShell.Commands.PSGetDscResourceInfo</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>35</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>10</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>35</Width>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Version</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>ModuleName</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Repository</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>PSGetRoleCapabilityInfo</Name>
<ViewSelectedBy>
<TypeName>Microsoft.PowerShell.Commands.PSGetRoleCapabilityInfo</TypeName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Width>35</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>10</Width>
</TableColumnHeader>
<TableColumnHeader>
<Width>35</Width>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Version</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>ModuleName</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Repository</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -3,8 +3,6 @@
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
#if CORECLR
using System.Globalization;
using System.Linq;
using System.Reflection;
@ -1679,5 +1677,3 @@ namespace Microsoft.PowerShell.CoreCLR
}
#endif
#endif

View file

@ -12,8 +12,6 @@ using System.Diagnostics.CodeAnalysis;
using Microsoft.Win32;
using System.Management.Automation.Remoting;
#if CORECLR
#pragma warning disable 1591, 1572, 1571, 1573, 1587, 1570, 0067
#region CLR_STUBS
@ -1874,5 +1872,3 @@ namespace System
#pragma warning restore 1591, 1572, 1571, 1573, 1587, 1570, 0067
#endif
#endif

View file

@ -17,7 +17,7 @@ namespace ConsoleApplication
var outputPath = "../TypeCatalogGen/powershell.inc";
// Get a context for our top level project
var context = ProjectContext.Create("../Microsoft.PowerShell.Linux.Host", NuGetFramework.Parse("netstandardapp1.5"));
var context = ProjectContext.Create("../Microsoft.PowerShell.Host", NuGetFramework.Parse("netstandardapp1.5"));
System.IO.File.WriteAllLines(outputPath,
// Get the target for the current runtime

View file

@ -13,5 +13,14 @@
"netstandardapp1.5": {
"imports": [ "dnxcore50", "portable-net45+win8" ]
}
},
"runtimes": {
"ubuntu.14.04-x64": { },
"centos.7.1-x64": { },
"win7-x64": { },
"win10-x64": { },
"osx.10.10-x64": { },
"osx.10.11-x64": { }
}
}

@ -1 +0,0 @@
Subproject commit 4bb241ad11c54985617343fbeb8700cfdcdf7ae0

12
src/libpsl-native/.gitignore vendored Normal file
View file

@ -0,0 +1,12 @@
CMakeCache.txt
CMakeFiles
CMakeScripts
Makefile
cmake_install.cmake
install_manifest.txt
CTestTestfile.cmake
Testing/
test/psl-native-test
src/libpsl-native.so
src/libpsl-native.dylib
test/native-tests.xml

View file

@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 2.8.4)
project(PSL-NATIVE)
add_compile_options(-std=c++11 -Wall -Werror)
set(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/../Microsoft.PowerShell.Host")
# test in BUILD_DIR
enable_testing()
add_subdirectory(src)
add_subdirectory(test)

View file

@ -0,0 +1,56 @@
# libpsl-native
This library provides functionality missing from .NET Core via system calls,
that are called from from the `CorePsPlatform.cs` file of PowerShell. The
method to do this is a Platform Invoke, which is C#'s Foreign Function
Interface to C code (and C++ by way of `extern C`).
## Build
[CMake][] is used to build the project, which results in a `libpsl-native.so`
library on Linux, and `libpsl-native.dylib` on OS X.
```sh
cmake -DCMAKE_BUILD_TYPE=Debug .
make -j
```
[CMake]: https://cmake.org/cmake/help/v2.8.12/cmake.html
## Test
The [Google Test][] framework is used for unit tests.
Use either `make test` or `ctest --verbose` for more output.
[Google Test]: https://github.com/google/googletest/tree/release-1.7.0
## Notes
Marshalling data from native to managed code is much easier on Linux than it is
on Windows. For instance, to return a string, you simply return a copy of it on
the heap. Since only one memory allocator is used on Linux, the .NET runtime
has no problem later freeing the buffer. Additionally, .NET presumes that the
codepage "Ansi" on Linux is always UTF-8. So just marshal the string as
`UnmanagedType.LPStr`.
### C# (Managed)
```c#
[DllImport("libpsl-native", CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string GetSomeString();
```
### C (Native)
```c
char *GetSomeString()
{
return strdup("some string");
}
```
The CoreFX team has an excellent guide for [UNIX Interop][].
[UNIX Interop]: https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/interop-guidelines.md#unix-shims

View file

@ -0,0 +1,14 @@
add_library(psl-native SHARED
getcurrentprocessorid.cpp
getusername.cpp
getcomputername.cpp
getlinkcount.cpp
getfullyqualifiedname.cpp
issymlink.cpp
isexecutable.cpp
setdate.cpp
createhardlink.cpp
createsymlink.cpp
followsymlink.cpp)
target_include_directories(psl-native PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View file

@ -0,0 +1,115 @@
//! @file createsymlink.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief create new hard link
#include <errno.h>
#include <unistd.h>
#include <string>
#include "createhardlink.h"
//! @brief Createhardlink create new symbolic link
//!
//! Createhardlink
//!
//! @param[in] link
//! @parblock
//! A pointer to the buffer that contains the symbolic link to create
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @param[in] target
//! @parblock
//! A pointer to the buffer that contains the existing file
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_FILE_NOT_FOUND: file does not exist
//! - ERROR_ACCESS_DENIED: access is denied
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_TOO_MANY_LINK: max number of hard links has been exceeded
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
//! - ERROR_BUFFER_OVERFLOW: file name is too long
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
//!
//! @retval 1 if creation is successful
//! @retval 0 if createion failed
//!
int32_t CreateHardLink(const char *newlink, const char *target)
{
errno = 0;
// Check parameters
if (!newlink || !target)
{
errno = ERROR_INVALID_PARAMETER;
return 0;
}
int returnCode = link(target, newlink);
if (returnCode == 0)
{
return 1;
}
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EDQUOT:
errno = ERROR_DISK_FULL;
break;
case EEXIST:
errno = ERROR_FILE_EXISTS;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case EIO:
errno = ERROR_GEN_FAILURE;
break;
case ELOOP:
errno = ERROR_TOO_MANY_LINKS;
break;
case EMLINK:
errno = ERROR_TOO_MANY_LINKS;
break;
case ENAMETOOLONG:
errno = ERROR_BAD_PATH_NAME;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
case ENOTDIR:
errno = ERROR_INVALID_NAME;
break;
case ENOSPC:
errno = ERROR_DISK_FULL;
break;
case EPERM:
errno = ERROR_ACCESS_DENIED;
break;
case EROFS:
errno = ERROR_ACCESS_DENIED;
break;
case EXDEV:
errno = ERROR_GEN_FAILURE;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return 0;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t CreateHardLink(const char *link, const char *target);
PAL_END_EXTERNC

View file

@ -0,0 +1,106 @@
//! @file createsymlink.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief create new symbolic link
#include <errno.h>
#include <unistd.h>
#include <string>
#include "createsymlink.h"
//! @brief Createsymlink create new symbolic link
//!
//! Createsymlink
//!
//! @param[in] link
//! @parblock
//! A pointer to the buffer that contains the symbolic link to create
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @param[in] target
//! @parblock
//! A pointer to the buffer that contains the existing file
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_FILE_NOT_FOUND: file does not exist
//! - ERROR_ACCESS_DENIED: access is denied
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
//! - ERROR_BUFFER_OVERFLOW: file name is too long
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
//!
//! @retval 1 if creation is successful
//! @retval 0 if createion failed
//!
int32_t CreateSymLink(const char *link, const char *target)
{
errno = 0;
// Check parameters
if (!link || !target)
{
errno = ERROR_INVALID_PARAMETER;
return 0;
}
int returnCode = symlink(target, link);
if (returnCode == 0)
{
return 1;
}
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EDQUOT:
errno = ERROR_DISK_FULL;
break;
case EEXIST:
errno = ERROR_FILE_EXISTS;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case EIO:
errno = ERROR_GEN_FAILURE;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_BAD_PATH_NAME;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
case ENOTDIR:
errno = ERROR_INVALID_NAME;
break;
case ENOSPC:
errno = ERROR_DISK_FULL;
break;
case EPERM:
errno = ERROR_GEN_FAILURE;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return 0;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t CreateSymLink(const char *link, const char *target);
PAL_END_EXTERNC

View file

@ -0,0 +1,90 @@
//! @file followSymLink.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief returns whether a path is a symbolic link
#include <errno.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include "followsymlink.h"
//! @brief Followsymlink determines target path of a sym link
//!
//! Followsymlink
//!
//! @param[in] fileName
//! @parblock
//! A pointer to the buffer that contains the file name
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_FILE_NOT_FOUND: file does not exist
//! - ERROR_ACCESS_DENIED: access is denied
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_STOPPED_ON_SYMLINK: too many symbolic links
//! - ERROR_GEN_FAILURE: I/O error occurred
//! - ERROR_INVALID_NAME: file provided is not a symbolic link
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_BAD_PATH_NAME: pathname is too long
//! - ERROR_OUTOFMEMORY insufficient kernal memory
//!
//! @retval target path, or NULL if unsuccessful
//!
char* FollowSymLink(const char* fileName)
{
errno = 0;
// Check parameters
if (!fileName)
{
errno = ERROR_INVALID_PARAMETER;
return NULL;
}
char buffer[PATH_MAX];
ssize_t sz = readlink(fileName, buffer, PATH_MAX);
if (sz == -1)
{
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case EINVAL:
errno = ERROR_INVALID_NAME;
break;
case EIO:
errno = ERROR_GEN_FAILURE;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_BAD_PATH_NAME;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_OUTOFMEMORY;
break;
case ENOTDIR:
errno = ERROR_BAD_PATH_NAME;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return NULL;
}
buffer[sz] = '\0';
return strndup(buffer, sz + 1);
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char* FollowSymLink(const char* fileName);
PAL_END_EXTERNC

View file

@ -0,0 +1,45 @@
//! @file getcomputername.cpp
//! @author George Fleming <v-geflem@microsoft>
//! @brief Implements GetComputerName Win32 API
#include <errno.h>
#include <unistd.h>
#include <string>
#include "getcomputername.h"
//! @brief GetComputerName retrieves the name of the host associated with
//! the current thread.
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code
//! - ERROR_INVALID_ADDRESS: buffer is an invalid address
//! - ERROR_GEN_FAILURE: buffer not large enough
//!
//! @retval username as UTF-8 string, or null if unsuccessful
char* GetComputerName()
{
errno = 0;
// Get computername from system, note that gethostname(2) gets the
// nodename from uname
std::string computername(_POSIX_HOST_NAME_MAX, 0);
int err = gethostname(&computername[0], computername.length());
// Map errno to Win32 Error Codes
if (err != 0)
{
switch (errno)
{
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case ENAMETOOLONG:
errno = ERROR_GEN_FAILURE;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return NULL;
}
return strdup(computername.c_str());
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char *GetComputerName();
PAL_END_EXTERNC

View file

@ -0,0 +1,9 @@
#include "getcurrentprocessorid.h"
#include <unistd.h>
int32_t GetCurrentProcessId()
{
pid_t pid = getpid();
return static_cast<int32_t>(pid);
}

View file

@ -0,0 +1,10 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t GetCurrentProcessId();
PAL_END_EXTERNC

View file

@ -0,0 +1,9 @@
#include "getcurrentthreadid.h"
#include <unistd.h>
#include <pthread.h>
HANDLE GetCurrentThreadId()
{
pid_t tid = pthread_self();
return reinterpret_cast<HANDLE>(tid);
}

View file

@ -0,0 +1,10 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
HANDLE GetCurrentThreadId();
PAL_END_EXTERNC

View file

@ -0,0 +1,64 @@
//! @file getfullyqualifiedname.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Implements GetFullyQualifiedName on Linux
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "getcomputername.h"
#include "getfullyqualifiedname.h"
//! @brief GetFullyQualifiedName retrieves the fully qualifed dns name of the host
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_FUNCTION: getlogin_r() returned an unrecognized error code (from GetComputerName)
//! - ERROR_INVALID_ADDRESS: buffer is an invalid address (from GetComputerName)
//! - ERROR_GEN_FAILURE: buffer not large enough (from GetComputerName)
//! - ERROR_BAD_NET_NAME: Cannot determine network short name
//!
//! @retval username as UTF-8 string, or null if unsuccessful
//!
char *GetFullyQualifiedName()
{
errno = 0;
char *computerName = GetComputerName();
if (computerName == NULL)
{
return NULL;
}
if (strchr(computerName, '.') != NULL)
{
return computerName;
}
struct addrinfo hints, *info;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; /*either IPV4 or IPV6*/
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
/* There are several ways to get the domain name:
* uname(2), gethostbyname(3), resolver(3), getdomainname(2),
* and getaddrinfo(3). Some of these are not portable, some aren't
* POSIX compliant, and some are being deprecated. getaddrinfo seems
* to be the best choice.
*/
if (getaddrinfo(computerName, "http", &hints, &info) != 0)
{
errno = ERROR_BAD_NET_NAME;
return NULL;
}
// info is actually a link-list. We'll just return the first full name
char *fullName = strndup(info->ai_canonname, strlen(info->ai_canonname));
freeaddrinfo(info);
free(computerName);
return fullName;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char *GetFullyQualifiedName();
PAL_END_EXTERNC

View file

@ -0,0 +1,104 @@
//! @file getlinkcount.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief Retrieve link count of a file
#include <errno.h>
#include <locale.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include "getlinkcount.h"
//! @brief GetLinkCount retrieves the file link count (number of hard links)
//! for the given file
//!
//! GetLinkCount
//!
//! @param[in] fileName
//! @parblock
//! A pointer to the buffer that contains the file name
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @param[out] count
//! @parblock
//! This function returns the number of hard links associated with this file
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_FILE_NOT_FOUND: file does not exist
//! - ERROR_ACCESS_DENIED: access is denied
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
//! - ERROR_BUFFER_OVERFLOW: file name is too long
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
//!
//! @retval 1 If the function succeeds, and the variable pointed to by buffer contains
//! infomation about the files
//! @retval 0 If the function fails, the return value is zero. To get
//! extended error information, call GetLastError.
//!
int32_t GetLinkCount(const char* fileName, int32_t *count)
{
errno = 0;
// Check parameters
if (!fileName)
{
errno = ERROR_INVALID_PARAMETER;
return 0;
}
struct stat statBuf;
int returnCode = lstat(fileName, &statBuf);
if (returnCode != 0)
{
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EBADF:
errno = ERROR_FILE_NOT_FOUND;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_GEN_FAILURE;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_NO_SUCH_USER;
break;
case ENOTDIR:
errno = ERROR_INVALID_NAME;
break;
case EOVERFLOW:
errno = ERROR_BUFFER_OVERFLOW;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return 0;
}
*count = statBuf.st_nlink;
return 1;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t GetLinkCount(const char* fileName, int32_t *count);
PAL_END_EXTERNC

View file

@ -0,0 +1,65 @@
//! @file getusername.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Implements GetUserName for Linux
#include <errno.h>
#include <locale.h>
#include <unistd.h>
#include <string>
#include <pwd.h>
#include "getusername.h"
//! @brief GetUserName retrieves the name of the user associated with
//! the current thread.
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_NO_SUCH_USER: there was no corresponding user
//! - ERROR_GEN_FAILURE: sysconf() or getpwuid() failed for unknown reasons
//!
//! @retval username as UTF-8 string, or null if unsuccessful
char* GetUserName()
{
errno = 0;
struct passwd pwd;
struct passwd* result;
// gets the initial suggested size for buf
int buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
if (buflen == -1)
{
errno = ERROR_GEN_FAILURE;
return NULL;
}
std::string buf(buflen, 0);
// geteuid() gets the effective user ID of the calling process, and is always successful
int ret = getpwuid_r(geteuid(), &pwd, &buf[0], buflen, &result);
// Map errno to Win32 Error Codes
if (ret)
{
switch (errno)
{
case ENOENT:
case ESRCH:
case EBADF:
case EPERM:
errno = ERROR_NO_SUCH_USER;
break;
default:
errno = ERROR_GEN_FAILURE;
}
return NULL;
}
// Check if no user matched
if (result == NULL)
{
errno = ERROR_NO_SUCH_USER;
return NULL;
}
// allocate copy on heap so CLR can free it
return strdup(result->pw_name);
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
char* GetUserName();
PAL_END_EXTERNC

View file

@ -0,0 +1,81 @@
//! @file isExecutable.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief returns whether a file is executable
#include <errno.h>
#include <unistd.h>
#include <string>
#include "isexecutable.h"
//! @brief IsExecutable determines if path is executable
//!
//! IsExecutable
//!
//! @param[in] fileName
//! @parblock
//! A pointer to the buffer that contains the file name
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_INVALID_PARAMETER: parameter to access(2) call is incorrect
//!
//! @retval 1 if path is an executable
//! @retval 0 if path is not a executable
//! @retval -1 If the function fails.. To get extended error information, call GetLastError.
//!
int32_t IsExecutable(const char* fileName)
{
errno = 0;
// Check parameters
if (!fileName)
{
errno = ERROR_INVALID_PARAMETER;
return -1;
}
int returnCode = access(fileName, X_OK);
if (returnCode == 0)
{
return 1;
}
switch(errno)
{
case EACCES:
return 0;
case EBADF:
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case EIO:
case ENOMEM:
errno = ERROR_GEN_FAILURE;
break;
case ENOTDIR:
case ENAMETOOLONG:
errno = ERROR_INVALID_NAME;
break;
case EINVAL:
errno = ERROR_INVALID_PARAMETER;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return -1;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t IsExecutable(const char* fileName);
PAL_END_EXTERNC

View file

@ -0,0 +1,96 @@
//! @file isSymLink.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief returns whether a path is a symbolic link
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include "issymlink.h"
//! @brief IsSymLink determines if path is a symbolic link
//!
//! IsSymLink
//!
//! @param[in] fileName
//! @parblock
//! A pointer to the buffer that contains the file name
//!
//! char* is marshaled as an LPStr, which on Linux is UTF-8.
//! @endparblock
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_INVALID_PARAMETER: parameter is not valid
//! - ERROR_FILE_NOT_FOUND: file does not exist
//! - ERROR_ACCESS_DENIED: access is denied
//! - ERROR_FILE_NOT_FOUND: the system cannot find the file specified
//! - ERROR_INVALID_ADDRESS: attempt to access invalid address
//! - ERROR_STOPPED_ON_SYMLINK: the operation stopped after reaching a symbolic link
//! - ERROR_GEN_FAILURE: device attached to the system is not functioning
//! - ERROR_NO_SUCH_USER: there was no corresponding entry in the utmp-file
//! - ERROR_INVALID_NAME: filename, directory name, or volume label syntax is incorrect
//! - ERROR_BUFFER_OVERFLOW: file name is too long
//! - ERROR_INVALID_FUNCTION: incorrect function
//! - ERROR_BAD_PATH_NAME: pathname is too long, or contains invalid characters
//!
//! @retval 1 if path is a symbolic link
//! @retval 0 if path is not a symbolic link
//! @retval -1 If the function fails.. To get extended error information, call GetLastError.
//!
int32_t IsSymLink(const char* fileName)
{
errno = 0;
// Check parameters
if (!fileName)
{
errno = ERROR_INVALID_PARAMETER;
return -1;
}
struct stat statBuf;
int returnCode = lstat(fileName, &statBuf);
if (returnCode != 0)
{
switch(errno)
{
case EACCES:
errno = ERROR_ACCESS_DENIED;
break;
case EBADF:
errno = ERROR_FILE_NOT_FOUND;
break;
case EFAULT:
errno = ERROR_INVALID_ADDRESS;
break;
case ELOOP:
errno = ERROR_STOPPED_ON_SYMLINK;
break;
case ENAMETOOLONG:
errno = ERROR_GEN_FAILURE;
break;
case ENOENT:
errno = ERROR_FILE_NOT_FOUND;
break;
case ENOMEM:
errno = ERROR_NO_SUCH_USER;
break;
case ENOTDIR:
errno = ERROR_INVALID_NAME;
break;
case EOVERFLOW:
errno = ERROR_BUFFER_OVERFLOW;
break;
default:
errno = ERROR_INVALID_FUNCTION;
}
return -1;
}
return S_ISLNK(statBuf.st_mode) ? 1 : 0;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
int32_t IsSymLink(const char* fileName);
PAL_END_EXTERNC

View file

@ -0,0 +1,45 @@
#pragma once
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <limits.h>
#define ERROR_INVALID_PARAMETER 87
#define ERROR_OUTOFMEMORY 14
#define ERROR_BAD_ENVIRONMENT 0x0000000A
#define ERROR_TOO_MANY_OPEN_FILES 0x00000004
#define ERROR_INSUFFICIENT_BUFFER 0x0000007A
#define ERROR_NO_ASSOCIATION 0x00000483
#define ERROR_NO_SUCH_USER 0x00000525
#define ERROR_INVALID_FUNCTION 0x00000001
#define ERROR_INVALID_ADDRESS 0x000001e7
#define ERROR_GEN_FAILURE 0x0000001F
#define ERROR_ACCESS_DENIED 0x00000005
#define ERROR_INVALID_NAME 0x0000007B
#define ERROR_STOPPED_ON_SYMLINK 0x000002A9
#define ERROR_BUFFER_OVERFLOW 0x0000006F
#define ERROR_FILE_NOT_FOUND 0x00000002
#define ERROR_BAD_PATH_NAME 0x000000A1
#define ERROR_BAD_NET_NAME 0x00000043
#define ERROR_DISK_FULL 0x00000070
#define ERROR_FILE_EXISTS 0x00000050
#define ERROR_TOO_MANY_LINKS 0x00000476
/*
**==============================================================================
**
** PAL_BEGIN_EXTERNC
** PAL_END_EXTERNC
**
**==============================================================================
*/
#if defined(__cplusplus)
# define PAL_BEGIN_EXTERNC extern "C" {
# define PAL_END_EXTERNC }
#else
# define PAL_BEGIN_EXTERNC
# define PAL_END_EXTERNC
#endif

View file

@ -0,0 +1,73 @@
//! @file setdate.cpp
//! @author George FLeming <v-geflem@microsoft.com>
//! @brief set local/system date and time
#include <errno.h>
#include <langinfo.h>
#include <locale.h>
#include <string>
#include <time.h>
#include <sys/time.h>
#include "setdate.h"
//! @brief SetDate sets the date and time on local computer. You must
//! be super-user to set the time.
//!
//! SetDate
//!
//! @param[in] info
//! @parblock
//! A struct that contains program to execute and its parameters
//!
//! @exception errno Passes these errors via errno to GetLastError:
//! - ERROR_BAD_ENVIRONMENT: locale is not UTF-8
//! - ERROR_INVALID_PARAMETER: time was not passed in correctly
//! - ERROR_ACCESS_DENIED: you must be super-user to set the date
//!
//! @retval 0 successfully set date
//! @retval -1 if failure occurred. To get extended error information, call GetLastError.
//!
int32_t SetDate(const SetDateInfo &info)
{
errno = 0;
// Select locale from environment
setlocale(LC_ALL, "");
// Check that locale is UTF-8
if (nl_langinfo(CODESET) != std::string("UTF-8"))
{
errno = ERROR_BAD_ENVIRONMENT;
return -1;
}
struct tm bdTime;
struct timeval tv;
bdTime.tm_year = info.Year - 1900;
bdTime.tm_mon = info.Month - 1; // This is zero-based
bdTime.tm_mday = info.Day;
bdTime.tm_hour = info.Hour;
bdTime.tm_min = info.Minute;
bdTime.tm_sec = info.Second;
bdTime.tm_isdst = info.DST;
time_t newTime = mktime(&bdTime);
if (newTime == -1)
{
errno = ERROR_INVALID_PARAMETER;
return -1;
}
tv.tv_sec = newTime;
tv.tv_usec = 0;
int result = settimeofday(&tv, NULL);
if (result == -1)
{
errno = ERROR_ACCESS_DENIED;
return -1;
}
return 0;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "pal.h"
PAL_BEGIN_EXTERNC
typedef struct setDateInfo
{
// the order of members does matter here
int32_t Year;
int32_t Month;
int32_t Day;
int32_t Hour;
int32_t Minute;
int32_t Second;
int32_t Millisecond;
int32_t DST;
} SetDateInfo;
int32_t SetDate(const SetDateInfo &info);
PAL_END_EXTERNC

View file

@ -0,0 +1,22 @@
add_subdirectory(googletest)
add_executable(psl-native-test
test-locale.cpp
test-getcurrentprocessid.cpp
test-getusername.cpp
test-getcomputername.cpp
test-getlinkcount.cpp
test-getfullyqualifiedname.cpp
test-issymlink.cpp
test-isexecutable.cpp
test-createsymlink.cpp
test-createhardlink.cpp
main.cpp)
# manually include gtest headers
target_include_directories(psl-native-test PRIVATE ${gtest_SOURCE_DIR}/include)
target_link_libraries(psl-native-test psl-native gtest)
add_test(NAME psl-native-test
COMMAND psl-native-test --gtest_output=xml:native-tests.xml)

@ -0,0 +1 @@
Subproject commit c99458533a9b4c743ed51537e25989ea55944908

View file

@ -0,0 +1,7 @@
#include <gtest/gtest.h>
int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View file

@ -0,0 +1,91 @@
//! @file test-createhardlink.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Implements test for CreateHardLink()
#include <gtest/gtest.h>
#include <errno.h>
#include <unistd.h>
#include "getlinkcount.h"
#include "createhardlink.h"
using namespace std;
class CreateHardLinkTest : public ::testing::Test
{
protected:
static const int bufSize = 64;
const string fileTemplate = "/tmp/symlinktest.fXXXXXX";
const string dirTemplate = "/tmp/symlinktest.dXXXXXX";
const string fileHardLink = "/tmp/symlinktest.flink";
const string dirHardLink = "/tmp/symlinktest.dlink";
char *file, *dir;
char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize];
CreateHardLinkTest()
{
// since mkstemp and mkdtemp modifies the template string, let's give them writable buffers
strcpy(fileTemplateBuf, fileTemplate.c_str());
strcpy(dirTemplateBuf, dirTemplate.c_str());
// First create a temp file
int fd = mkstemp(fileTemplateBuf);
EXPECT_TRUE(fd != -1);
file = fileTemplateBuf;
// Create a temp directory
dir = mkdtemp(dirTemplateBuf);
EXPECT_TRUE(dir != NULL);
// Create hard link to file
int ret1 = CreateHardLink(fileHardLink.c_str(), file);
EXPECT_EQ(ret1, 1);
// Create hard link to directory - should fail
int ret2 = CreateHardLink(dirHardLink.c_str(), dir);
EXPECT_EQ(ret2, 0);
}
~CreateHardLinkTest()
{
int ret;
ret = unlink(fileHardLink.c_str());
EXPECT_EQ(0, ret);
ret = unlink(file);
EXPECT_EQ(0, ret);
ret = rmdir(dir);
EXPECT_EQ(0, ret);
}
};
TEST_F(CreateHardLinkTest, FilePathNameIsNull)
{
int retVal = CreateHardLink(NULL, NULL);
EXPECT_EQ(retVal, 0);
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
}
TEST_F(CreateHardLinkTest, FilePathNameDoesNotExist)
{
std::string invalidFile = "/tmp/symlinktest_invalidFile";
std::string invalidLink = "/tmp/symlinktest_invalidLink";
// make sure neither exists
unlink(invalidFile.c_str());
unlink(invalidLink.c_str());
int retVal = CreateHardLink(invalidLink.c_str(), invalidFile.c_str());
EXPECT_EQ(retVal, 0);
}
TEST_F(CreateHardLinkTest, VerifyLinkCount)
{
int count = 0;
int retVal = GetLinkCount(fileHardLink.c_str(), &count);
EXPECT_EQ(1, retVal);
EXPECT_EQ(2, count);
}

View file

@ -0,0 +1,117 @@
//! @file test-createsymlink.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Implements test for CreateSymLink() and FollowSymLink()
#include <gtest/gtest.h>
#include <errno.h>
#include <unistd.h>
#include "issymlink.h"
#include "createsymlink.h"
#include "followsymlink.h"
using namespace std;
class CreateSymLinkTest : public ::testing::Test
{
protected:
static const int bufSize = 64;
const string fileTemplate = "/tmp/symlinktest.fXXXXXX";
const string dirTemplate = "/tmp/symlinktest.dXXXXXX";
const string fileSymLink = "/tmp/symlinktest.flink";
const string dirSymLink = "/tmp/symlinktest.dlink";
char *file, *dir;
char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize];
CreateSymLinkTest()
{
// since mkstemp and mkdtemp modifies the template string, let's give them writable buffers
strcpy(fileTemplateBuf, fileTemplate.c_str());
strcpy(dirTemplateBuf, dirTemplate.c_str());
// First create a temp file
int fd = mkstemp(fileTemplateBuf);
EXPECT_TRUE(fd != -1);
file = fileTemplateBuf;
// Create a temp directory
dir = mkdtemp(dirTemplateBuf);
EXPECT_TRUE(dir != NULL);
// Create symbolic link to file
int ret1 = CreateSymLink(fileSymLink.c_str(), file);
EXPECT_EQ(ret1, 1);
// Create symbolic link to directory
int ret2 = CreateSymLink(dirSymLink.c_str(), dir);
EXPECT_EQ(ret2, 1);
}
~CreateSymLinkTest()
{
int ret;
ret = unlink(fileSymLink.c_str());
EXPECT_EQ(0, ret);
ret = unlink(dirSymLink.c_str());
EXPECT_EQ(0, ret);
ret = unlink(file);
EXPECT_EQ(0, ret);
ret = rmdir(dir);
EXPECT_EQ(0, ret);
}
};
TEST_F(CreateSymLinkTest, FilePathNameIsNull)
{
int retVal = CreateSymLink(NULL, NULL);
EXPECT_EQ(retVal, 0);
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
}
TEST_F(CreateSymLinkTest, FilePathNameDoesNotExist)
{
std::string invalidFile = "/tmp/symlinktest_invalidFile";
std::string invalidLink = "/tmp/symlinktest_invalidLink";
// make sure neither exists
unlink(invalidFile.c_str());
unlink(invalidLink.c_str());
// Linux allows creation of symbolic link that points to an invalid file
int retVal = CreateSymLink(invalidLink.c_str(), invalidFile.c_str());
EXPECT_EQ(retVal, 1);
std::string target = FollowSymLink(invalidLink.c_str());
EXPECT_EQ(target, invalidFile);
unlink(invalidLink.c_str());
}
TEST_F(CreateSymLinkTest, SymLinkToFile)
{
int retVal = IsSymLink(fileSymLink.c_str());
EXPECT_EQ(1, retVal);
std::string target = FollowSymLink(fileSymLink.c_str());
EXPECT_EQ(target, file);
}
TEST_F(CreateSymLinkTest, SymLinkToDirectory)
{
int retVal = IsSymLink(dirSymLink.c_str());
EXPECT_EQ(1, retVal);
std::string target = FollowSymLink(dirSymLink.c_str());
EXPECT_EQ(target, dir);
}
TEST_F(CreateSymLinkTest, SymLinkAgain)
{
int retVal = CreateSymLink(fileSymLink.c_str(), file);
EXPECT_EQ(0, retVal);
EXPECT_EQ(ERROR_FILE_EXISTS, errno);
}

View file

@ -0,0 +1,33 @@
//! @file test-getcomputername.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Unit tests for GetComputerName
#include <gtest/gtest.h>
#include "getcomputername.h"
//! Test fixture for GetComputerNameTest
class GetComputerNameTest : public ::testing::Test
{
};
TEST_F(GetComputerNameTest, Success)
{
char expectedComputerName[_POSIX_HOST_NAME_MAX];
// the gethostname system call gets the nodename from uname
FILE *fPtr = popen("uname -n", "r");
ASSERT_TRUE(fPtr != NULL);
char *linePtr = fgets(expectedComputerName, sizeof(expectedComputerName), fPtr);
ASSERT_TRUE(linePtr != NULL);
// There's a tendency to have \n at end of fgets string, so remove it before compare
size_t sz = strlen(expectedComputerName);
if (sz > 0 && expectedComputerName[sz - 1] == '\n')
{
expectedComputerName[sz - 1] = '\0';
}
pclose(fPtr);
ASSERT_STREQ(GetComputerName(), expectedComputerName);
}

View file

@ -0,0 +1,16 @@
#include <gtest/gtest.h>
#include "getcurrentprocessorid.h"
// This is a very simple test case to show how tests can be written
TEST(GetCurrentProcessId,simple)
{
const int32_t currentProcessId = GetCurrentProcessId();
const pid_t pid = getpid();
// first make sure that on this platform those types are of the same size
ASSERT_TRUE(sizeof(int32_t) >= sizeof(pid_t));
// now compare the actual values
ASSERT_EQ(currentProcessId,static_cast<int32_t>(pid));
}

View file

@ -0,0 +1,16 @@
#include <gtest/gtest.h>
#include "getcurrentthreadid.h"
#include <pthread.h>
TEST(GetCurrentThreadId,simple)
{
const HANDLE currentThreadId = GetCurrentThreadId();
const pid_t tid = pthread_self();
// first make sure that on this platform those types are of the same size
ASSERT_TRUE(sizeof(HANDLE) >= sizeof(pid_t));
// now compare the actual values
ASSERT_EQ(currentThreadId,reinterpret_cast<HANDLE>(tid));
}

View file

@ -0,0 +1,40 @@
//! @file test-getfullyqualifiedname.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Unit tests for GetFullyQualifiedName
#include <gtest/gtest.h>
#include "getfullyqualifiedname.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string>
//! Test fixture for GetComputerNameTest
class GetFullyQualifiedNameTest : public ::testing::Test
{
};
TEST_F(GetFullyQualifiedNameTest, ValidateLinuxGetFullyQualifiedDomainName)
{
std::string actual(GetFullyQualifiedName());
std::string hostname(_POSIX_HOST_NAME_MAX, 0);
ASSERT_FALSE(gethostname(&hostname[0], hostname.length()));
// trim null characters from string
hostname = std::string(hostname.c_str());
struct addrinfo hints, *info;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
ASSERT_FALSE(getaddrinfo(hostname.c_str(), "http", &hints, &info));
// Compare hostname part of FQDN
ASSERT_EQ(hostname, actual.substr(0, hostname.length()));
// Compare canonical name to FQDN
ASSERT_EQ(info->ai_canonname, actual);
freeaddrinfo(info);
}

View file

@ -0,0 +1,95 @@
//! @file test-getlinkcount.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Implements test for getLinkCount()
#include <gtest/gtest.h>
#include <pwd.h>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include "getlinkcount.h"
class getLinkCountTest : public ::testing::Test
{
protected:
static const int bufSize = 64;
const std::string fileTemplate = "/tmp/createFile.XXXXXX";
char fileTemplateBuf[bufSize];
int32_t count;
char *file;
getLinkCountTest()
{
// since mkstemp modifies the template string, let's give it writable buffer
strcpy(fileTemplateBuf, fileTemplate.c_str());
int fd = mkstemp(fileTemplateBuf);
EXPECT_TRUE(fd != -1);
file = fileTemplateBuf;
}
void createFileForTesting(const std::string &theFile)
{
std::ofstream ofs;
ofs.open(theFile, std::ofstream::out);
ofs << "hi there, ms ostc!";
ofs.close();
}
std::string createHardLink(const std::string &origFile)
{
std::string newFile = origFile + "_link";
int ret = link(origFile.c_str(), newFile.c_str());
EXPECT_EQ(0, ret);
return newFile;
}
void removeFile(const std::string &fileName)
{
int ret = unlink(fileName.c_str());
EXPECT_EQ(0, ret);
}
};
TEST_F(getLinkCountTest, FilePathNameIsNull)
{
int32_t retVal = GetLinkCount(NULL, &count );
ASSERT_FALSE(retVal);
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
}
TEST_F(getLinkCountTest, FilePathNameDoesNotExist)
{
std::string invalidFile = "/tmp/createFile";
int32_t retVal = GetLinkCount(invalidFile.c_str(), &count);
ASSERT_FALSE(retVal);
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
}
TEST_F(getLinkCountTest, LinkCountOfSinglyLinkedFile)
{
createFileForTesting(file);
int32_t retVal = GetLinkCount(file, &count);
ASSERT_TRUE(retVal);
EXPECT_EQ(1, count);
removeFile(file);
}
TEST_F(getLinkCountTest, LinkCountOfMultipliLinkedFile)
{
createFileForTesting(file);
std::string newFile = createHardLink(file);
int32_t retVal = GetLinkCount(file, &count);
ASSERT_TRUE(retVal);
EXPECT_EQ(2, count);
removeFile(file);
removeFile(newFile);
}

View file

@ -0,0 +1,17 @@
//! @file test-getusername.cpp
//! @author Andrew Schwartzmeyer <andschwa@microsoft.com>
//! @brief Unit tests for GetUserName
#include <string>
#include <vector>
#include <unistd.h>
#include <gtest/gtest.h>
#include <pwd.h>
#include "getusername.h"
TEST(GetUserName, Success)
{
char* expected = getpwuid(geteuid())->pw_name;
ASSERT_TRUE(expected != NULL);
ASSERT_EQ(GetUserName(), std::string(expected));
}

View file

@ -0,0 +1,94 @@
//! @file test-isexecutable.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Implements test for isexecutable()
#include <gtest/gtest.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include "isexecutable.h"
using namespace std;
class IsExecutableTest : public ::testing::Test
{
protected:
static const int bufSize = 64;
const string fileTemplate = "/tmp/isexecutabletest.fXXXXXXX";
const mode_t mode_700 = S_IRUSR | S_IWUSR | S_IXUSR;
const mode_t mode_070 = S_IRGRP | S_IWGRP | S_IXGRP;
const mode_t mode_007 = S_IROTH | S_IWOTH | S_IXOTH;
const mode_t mode_777 = mode_700 | mode_070 | mode_007;
const mode_t mode_444 = S_IRUSR | S_IRGRP | S_IROTH;
char *file;
char fileTemplateBuf[bufSize];
IsExecutableTest()
{
// since mkstemp modifies the template string, let's give it writable buffers
strcpy(fileTemplateBuf, fileTemplate.c_str());
// First create a file
int fd = mkstemp(fileTemplateBuf);
EXPECT_TRUE(fd != -1);
file = fileTemplateBuf;
}
~IsExecutableTest()
{
int ret;
ret = unlink(file);
EXPECT_EQ(0, ret);
}
void ChangeFilePermission(const char* file, mode_t mode)
{
int ret = chmod(file, mode);
EXPECT_EQ(ret, 0);
}
};
TEST_F(IsExecutableTest, FilePathNameIsNull)
{
int32_t retVal = IsExecutable(NULL);
EXPECT_EQ(retVal, -1);
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
}
TEST_F(IsExecutableTest, FilePathNameDoesNotExist)
{
std::string invalidFile = "/tmp/isexecutabletest_invalidFile";
int32_t retVal = IsExecutable(invalidFile.c_str());
EXPECT_EQ(retVal, -1);
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
}
TEST_F(IsExecutableTest, NormalFileIsNotIsexecutable)
{
int32_t retVal = IsExecutable(file);
EXPECT_EQ(0, retVal);
ChangeFilePermission(file, mode_444);
retVal = IsExecutable(file);
EXPECT_EQ(0, retVal);
}
TEST_F(IsExecutableTest, FilePermission_700)
{
ChangeFilePermission(file, mode_700);
int32_t retVal = IsExecutable(file);
EXPECT_EQ(1, retVal);
}
TEST_F(IsExecutableTest, FilePermission_777)
{
ChangeFilePermission(file, mode_777);
int32_t retVal = IsExecutable(file);
EXPECT_EQ(1, retVal);
}

View file

@ -0,0 +1,104 @@
//! @file test-issymlink.cpp
//! @author George Fleming <v-geflem@microsoft.com>
//! @brief Implements test for isSymLink()
#include <gtest/gtest.h>
#include <errno.h>
#include <unistd.h>
#include "issymlink.h"
using namespace std;
class isSymLinkTest : public ::testing::Test
{
protected:
static const int bufSize = 64;
const string fileTemplate = "/tmp/symlinktest.fXXXXXX";
const string dirTemplate = "/tmp/symlinktest.dXXXXXX";
const string fileSymLink = "/tmp/symlinktest.flink";
const string dirSymLink = "/tmp/symlinktest.dlink";
char *file, *dir;
char fileTemplateBuf[bufSize], dirTemplateBuf[bufSize];
isSymLinkTest()
{
// since mkstemp and mkdtemp modifies the template string, let's give them writable buffers
strcpy(fileTemplateBuf, fileTemplate.c_str());
strcpy(dirTemplateBuf, dirTemplate.c_str());
// First create a file
int fd = mkstemp(fileTemplateBuf);
EXPECT_TRUE(fd != -1);
file = fileTemplateBuf;
// Create a temp directory
dir = mkdtemp(dirTemplateBuf);
EXPECT_TRUE(dir != NULL);
// Create symbolic link to file
int ret1 = symlink(file, fileSymLink.c_str());
EXPECT_EQ(ret1, 0);
// Create symbolic link to directory
int ret2 = symlink(dir, dirSymLink.c_str());
EXPECT_EQ(ret2, 0);
}
~isSymLinkTest()
{
int ret;
ret = unlink(fileSymLink.c_str());
EXPECT_EQ(0, ret);
ret = unlink(dirSymLink.c_str());
EXPECT_EQ(0, ret);
ret = unlink(file);
EXPECT_EQ(0, ret);
ret = rmdir(dir);
EXPECT_EQ(0, ret);
}
};
TEST_F(isSymLinkTest, FilePathNameIsNull)
{
int retVal = IsSymLink(NULL);
EXPECT_EQ(retVal, -1);
EXPECT_EQ(ERROR_INVALID_PARAMETER, errno);
}
TEST_F(isSymLinkTest, FilePathNameDoesNotExist)
{
std::string invalidFile = "/tmp/symlinktest_invalidFile";
int retVal = IsSymLink(invalidFile.c_str());
EXPECT_EQ(retVal, -1);
EXPECT_EQ(ERROR_FILE_NOT_FOUND, errno);
}
TEST_F(isSymLinkTest, NormalFileIsNotSymLink)
{
int retVal = IsSymLink(file);
EXPECT_EQ(0, retVal);
}
TEST_F(isSymLinkTest, SymLinkToFile)
{
int retVal = IsSymLink(fileSymLink.c_str());
EXPECT_EQ(1, retVal);
}
TEST_F(isSymLinkTest, NormalDirectoryIsNotSymbLink)
{
int retVal = IsSymLink(dir);
EXPECT_EQ(0, retVal);
}
TEST_F(isSymLinkTest, SymLinkToDirectory)
{
int retVal = IsSymLink(dirSymLink.c_str());
EXPECT_EQ(1, retVal);
}

View file

@ -0,0 +1,21 @@
//! @file test-locale.cpp
//! @author Alex Jordan <v-alexjo@microsoft.com>
//! @brief Unit tests for linux locale
#include <gtest/gtest.h>
#include <langinfo.h>
#include <locale.h>
#include <string>
#include <stdio.h>
//! Test fixture for LocaleTest
class LocaleTest : public ::testing::Test
{
};
TEST_F(LocaleTest, Success)
{
setlocale (LC_ALL, "");
ASSERT_FALSE (nl_langinfo(CODESET) == NULL);
ASSERT_TRUE(nl_langinfo(CODESET) == std::string("UTF-8"));
}

View file

@ -3,6 +3,13 @@ project(PowerShell)
add_compile_options()
# set the output path for `powershell.exe`
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../Microsoft.PowerShell.ConsoleHost")
foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES )
# set these flags, so build does static linking for msvcr120.dll
# otherwise this dll need to be present on the system
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")

View file

@ -1,7 +1,7 @@
using Xunit;
using System;
using System.Management.Automation;
using Microsoft.PowerShell.Linux.Host;
using Microsoft.PowerShell.Host;
// This collection fixture initializes Core PowerShell's AssemblyLoadContext once and only
// once. Attempting to initialize in a class level fixture will cause multiple

Some files were not shown because too many files have changed in this diff Show more