Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion build.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,24 @@ cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$
log " Copying $srcPath to $dstPath"
Copy-Item $srcPath $dstPath
}

#
# Build the ETW manifest resource-only binary
#
$location = "$PSScriptRoot\src\PowerShell.Core.Instrumentation"
Set-Location -Path $location

$command = @"
cmd.exe /C cd /d "$location" "&" "$($vcPath)\vcvarsall.bat" "$Arch" "&" cmake "$overrideFlags" -DBUILD_ONECORE=ON -DBUILD_TARGET_ARCH=$Arch -G "$cmakeGenerator" . "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$Configuration"
"@
log " Executing Build Command for PowerShell.Core.Instrumentation: $command"
Start-NativeExecution { Invoke-Expression -Command:$command }

# Copy the binary to the packaging directory
# NOTE: No PDB file; it's a resource-only DLL.
$srcPath = [IO.Path]::Combine($location, $Configuration, 'PowerShell.Core.Instrumentation.dll')
Copy-Item -Path $srcPath -Destination $dstPath

} finally {
Pop-Location
}
Expand Down Expand Up @@ -600,7 +618,7 @@ function New-PSOptions {
[string]$Output,

[switch]$SMAOnly,

[switch]$PSModuleRestore
)

Expand Down
75 changes: 75 additions & 0 deletions src/PowerShell.Core.Instrumentation/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
cmake_minimum_required(VERSION 3.5)
#
# Builds PowerShell.Core.Instrumentation.dll resource-only DLL containing ETW event resources
#

# The fully qualified path to the event manifest
SET(EVENTS_MANIFEST "${CMAKE_CURRENT_SOURCE_DIR}/PowerShell.Core.Instrumentation.man")

# User mode manifest resource-only dll
function(add_manifest_binary)

add_definitions(-D_DLL=1)
add_library(${ARGV})

# NOTE: EVENTS_MANIFEST must be the fully qualified path to the manifest
SET(MC_MANIFEST_FULLNAME ${EVENTS_MANIFEST})

# get the ETW manifest's filename without the directory or extension
get_filename_component(MC_MANIFEST_BASENAME ${EVENTS_MANIFEST} NAME_WE)

SET(MC_COMMAND "mc.exe")
SET(GeneratedManifestFiles)

# The target directory for generated managed files
SET (MC_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}")

# include the generated directory in the include path
include_directories("${MC_GENERATED_DIR}")

SET (MC_GENERATED_FILES
${MC_GENERATED_DIR}/${MC_MANIFEST_BASENAME}.rc
${MC_GENERATED_DIR}/${MC_MANIFEST_BASENAME}TEMP.BIN
${MC_GENERATED_DIR}/${MC_MANIFEST_BASENAME}_MSG00001.BIN
)

SET(MC_COMMAND "mc.exe -h ${MC_GENERATED_DIR} -r ${MC_GENERATED_DIR} ${MC_MANIFEST_FULLNAME}")

add_custom_command(
COMMENT "Generating native event manifest files for ${EVENTS_MANIFEST}"
OUTPUT ${MC_GENERATED_FILES}
DEPENDS ${MC_MANIFEST_FULLNAME}
COMMAND cmd.exe /c ${MC_COMMAND}
WORKING_DIRECTORY ${MC_GENERATED_DIR}
VERBATIM
)

list (APPEND GeneratedManifestFiles ${MC_GENERATED_DIR}/${MC_MANIFEST_BASENAME}.rc)

set_source_files_properties(${GeneratedManifestFiles} PROPERTIES GENERATED TRUE)
add_custom_target(GeneratedManifestFiles DEPENDS ${GeneratedManifestFiles})

# for a resource only dll, cmake can report an error
# if there is no linker language set.
# CMake Error: Error required internal CMake variable not set, cmake may be not be built correctly.
# Missing variable is: CMAKE_RC_CREATE_SHARED_LIBRARY
get_property(isSet TARGET ${ARGV0} PROPERTY LINKER_LANGUAGE SET)
if (NOT ${isSet})
set_target_properties(${ARGV0} PROPERTIES LINKER_LANGUAGE "CXX")
endif()

set_target_properties(${ARGV0} PROPERTIES LINK_FLAGS "/NODEFAULTLIB /NOENTRY")

if (BUILD_ONECORE)
set_target_properties(${ARGV0} PROPERTIES COMPILE_DEFINITIONS "CORECLR")
endif (BUILD_ONECORE)

# ensure the target is dependent on the generated files.
add_dependencies(${ARGV0} GeneratedManifestFiles)

endfunction()

file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/version.rc)

add_manifest_binary(PowerShell.Core.Instrumentation SHARED ${SOURCES})

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<assemblyIdentity
buildType="$(build.buildType)"
language="neutral"
name="PowerShellCore-Instrumentation"
name="PowerShell.Core.Instrumentation"
processorArchitecture="msil"
publicKeyToken="$(build.WindowsPublicKeyToken)"
version="$(build.version)"
Expand All @@ -31,9 +31,9 @@
first uninstalled and then installed again (using wevtutil)-->
<provider
guid="{f90714a8-5509-434a-bf6d-b1624c8a19a2}"
messageFileName="System.Management.Automation.dll"
messageFileName="PowerShell.Core.Instrumentation.dll"
name="PowerShellCore"
resourceFileName="System.Management.Automation.dll"
resourceFileName="PowerShell.Core.Instrumentation.dll"
symbol="PS_PROVIDER"
>
<!--The following section defines the events which can be written
Expand Down
94 changes: 94 additions & 0 deletions src/PowerShell.Core.Instrumentation/RegisterManifest.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<#
.Synopsis
Registers or unregisters the PowerShell ETW manifest
.Parameter Path
The fully qualified path to the PowerShell.Core.Instrumentation.man manifest file.
The default value is the location of this script.

.Parameter Unregister
Specify to unregister the manifest.
.Notes
The PowerShell.Core.Instrumentation.man and PowerShell.Core.Instrumentation.dll files are
expected to be at the location specified by the Path parameter.
When registered, PowerShell.Core.Instrumentation.dll is locked to prevent deleting or changing.
To update the binary, first unregister the manifest using the -Unregister switch.
#>
[CmdletBinding()]
param
(
[ValidateNotNullOrEmpty()]
[string] $Path = $PSScriptRoot,

[switch] $Unregister
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function Start-NativeExecution([scriptblock]$sb, [switch]$IgnoreExitcode)
{
$backupEAP = $script:ErrorActionPreference
$script:ErrorActionPreference = "Continue"
try
{
& $sb
# note, if $sb doesn't have a native invocation, $LASTEXITCODE will
# point to the obsolete value
if ($LASTEXITCODE -ne 0 -and -not $IgnoreExitcode)
{
throw "Execution of {$sb} failed with exit code $LASTEXITCODE"
}
}
finally
{
$script:ErrorActionPreference = $backupEAP
}
}

function Test-Elevated
{
[CmdletBinding()]
[OutputType([bool])]
Param()

# if the current Powershell session was called with administrator privileges,
# the Administrator Group's well-known SID will show up in the Groups for the current identity.
# Note that the SID won't show up unless the process is elevated.
return (([Security.Principal.WindowsIdentity]::GetCurrent()).Groups -contains "S-1-5-32-544")
}
$IsWindowsOs = $PSHOME.EndsWith('\WindowsPowerShell\v1.0', [System.StringComparison]::OrdinalIgnoreCase) -or $IsWindows

if (-not $IsWindowsOs)
{
throw 'This script must be run on Windows.'
}

if (-not (Test-Elevated))
{
throw 'This script must be run from an elevated process.'
}

$manifest = Get-Item -Path (Join-Path -Path $Path -ChildPath 'PowerShell.Core.Instrumentation.man')
$binary = Get-Item -Path (Join-Path -Path $Path -ChildPath 'PowerShell.Core.Instrumentation.dll')

$files = @($manifest, $binary)
foreach ($file in $files)
{
if (-not (Test-Path -Path $file))
{
throw "Could not find $($file.Name) at $Path"
}
}

[string] $command = "wevtutil um {0}" -f $manifest.FullName

# Unregister if present. Avoids warnings when registering the manifest
# and it is already registered.
Write-Verbose "unregister the manifest, if present: $command"
Start-NativeExecution {Invoke-Expression $command} $true

if (-not $Unregister)
{
$command = "wevtutil.exe im {0} /rf:{1} /mf:{1}" -f $manifest.FullName, $binary.FullName
Write-Verbose -Message "Register the manifest: $command"
Start-NativeExecution { Invoke-Expression $command }
}
15 changes: 15 additions & 0 deletions src/PowerShell.Core.Instrumentation/version.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// Copyright (C) Microsoft. All rights reserved.
//
#include <windows.h>
#include <ntverp.h>

#define VER_FILETYPE VFT_DLL
#define VER_FILESUBTYPE VFT2_UNKNOWN
#define VER_FILEDESCRIPTION_STR "PowerShellCore"
#define VER_INTERNALNAME_STR "PowerShell.Core.Instrumentation.dll"
#define VER_ORIGINALFILENAME_STR "PowerShell.Core.Instrumentation.dll"

#include "common.ver"

#include "PowerShell.Core.Instrumentation.rc"
2 changes: 1 addition & 1 deletion src/powershell-win-core/powershell-win-core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="..\..\license_thirdparty_proprietary.txt;..\..\DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY;..\powershell-native\Install-PowerShellRemoting.ps1">
<Content Include="..\..\license_thirdparty_proprietary.txt;..\..\DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY;..\powershell-native\Install-PowerShellRemoting.ps1;..\PowerShell.Core.Instrumentation\PowerShell.Core.Instrumentation.man;..\PowerShell.Core.Instrumentation\RegisterManifest.ps1">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
Expand Down