Adding ConfigFileReader back into the plugin and fixing it to more efficiently parse the configuration file.
This commit is contained in:
parent
d7618d731d
commit
4e7f582d43
@ -99,12 +99,11 @@ function Start-PSBuild {
|
||||
Use-MSBuild
|
||||
|
||||
#mc.exe is Message Compiler for native resources
|
||||
<# This currently doesn't work reliably and clean systems. Removing for now since mc.exe is not being used yet.
|
||||
# This currently doesn't work reliably and clean systems. Removing for now since mc.exe is not being used yet.
|
||||
$mcexe = Get-ChildItem "${env:ProgramFiles(x86)}\Microsoft SDKs\Windows\" -Recurse -Filter 'mc.exe' | ? {$_.FullName -match 'x64'} | select -First 1 | % {$_.FullName}
|
||||
if (-not $mcexe) {
|
||||
throw 'mc.exe not found. Install Microsoft Windows SDK.'
|
||||
}
|
||||
#>
|
||||
|
||||
$vcVarsPath = (Get-Item(Join-Path -Path "$env:VS140COMNTOOLS" -ChildPath '../../vc')).FullName
|
||||
if ((Test-Path -Path $vcVarsPath\vcvarsall.bat) -eq $false)
|
||||
@ -223,7 +222,6 @@ function Start-PSBuild {
|
||||
try {
|
||||
Push-Location "$PSScriptRoot\src\powershell-native"
|
||||
|
||||
<#
|
||||
# Compile native resources
|
||||
@("nativemsh/pwrshplugin") | % {
|
||||
$nativeResourcesFolder = $_
|
||||
@ -231,7 +229,6 @@ function Start-PSBuild {
|
||||
& $mcexe -o -d -c -U $_.FullName -h $nativeResourcesFolder -r $nativeResourcesFolder
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
# Disabling until I figure out if it is necessary
|
||||
# $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt"
|
||||
|
@ -4,7 +4,9 @@
|
||||
#
|
||||
add_library(pwrshcommon
|
||||
pwrshcommon.cpp
|
||||
WinSystemCallFacade.cpp)
|
||||
WinSystemCallFacade.cpp
|
||||
ConfigFileReader.cpp
|
||||
)
|
||||
|
||||
target_include_directories(pwrshcommon PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace NativeMsh
|
||||
//
|
||||
// The following methods are direct thin wrappers for the host calls.
|
||||
//
|
||||
virtual HMODULE SetupWrapper(LPCSTR coreClrPathPtr) = 0;
|
||||
virtual unsigned int SetupWrapper(LPCSTR coreClrPathPtr) = 0;
|
||||
|
||||
virtual int InitializeClr(
|
||||
const char* exePath,
|
||||
@ -123,15 +123,13 @@ namespace NativeMsh
|
||||
{
|
||||
return (NULL != coreClrHandle);
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: This shouldn't return HMODULE because that breaks encapsulation. I need a better way to
|
||||
// have the caller extract the value. Either Pass as a reference or provide an accessor.
|
||||
//
|
||||
|
||||
//
|
||||
// Attempts to load CoreCLR.dll from the specified directory.
|
||||
// On success pins the dll, sets coreCLRDirectoryPath and returns the HMODULE.
|
||||
// On failure returns NULL.
|
||||
virtual HMODULE SetupWrapper(LPCSTR coreClrPathPtr)
|
||||
//
|
||||
virtual unsigned int SetupWrapper(LPCSTR coreClrPathPtr)
|
||||
{
|
||||
std::string coreClrPath(coreClrPathPtr);
|
||||
coreClrPath += coreClrDllName;
|
||||
@ -139,13 +137,13 @@ namespace NativeMsh
|
||||
HMODULE result = LoadLibraryExA(coreClrPath.c_str(), NULL, 0);
|
||||
if (!result)
|
||||
{
|
||||
return NULL;
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
|
||||
// Pin the module - CoreCLR.dll does not support being unloaded.
|
||||
if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_PIN, coreClrPath.c_str(), &pinnedModuleHandle))
|
||||
{
|
||||
return NULL;
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
|
||||
initPtr = (coreclr_initialize_ptr)GetProcAddress(result, "coreclr_initialize");
|
||||
@ -156,12 +154,12 @@ namespace NativeMsh
|
||||
NULL == shutdownPtr ||
|
||||
NULL == createDelegatePtr)
|
||||
{
|
||||
return NULL;
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
|
||||
// Initialization succeeded. Save the handle and return success;
|
||||
coreClrHandle = result;
|
||||
return result;
|
||||
return EXIT_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
virtual unsigned int CleanUpHostWrapper()
|
||||
@ -246,6 +244,7 @@ namespace NativeMsh
|
||||
private:
|
||||
// The path to this module
|
||||
char m_hostPath[MAX_PATH];
|
||||
wchar_t m_hostPathW[MAX_PATH];
|
||||
|
||||
// The path to the directory containing this module
|
||||
char m_hostDirectoryPath[MAX_PATH];
|
||||
@ -253,11 +252,56 @@ namespace NativeMsh
|
||||
|
||||
// The name of this module, without the path
|
||||
std::string m_hostBinaryName;
|
||||
std::wstring m_hostBinaryNameW;
|
||||
|
||||
// The path to the directory that CoreCLR is in
|
||||
char m_coreCLRDirectoryPath[MAX_PATH];
|
||||
wchar_t m_coreCLRDirectoryPathW[MAX_PATH];
|
||||
|
||||
void convertAnsiToWide(char* ansiArray, wchar_t* wideArray)
|
||||
{
|
||||
// Generate the wide version of the string and save its value;
|
||||
//
|
||||
// This is a two call function. The first call is to get the necessary length.
|
||||
// The second call is to perform the actual operation.
|
||||
int length = ::MultiByteToWideChar(CP_UTF8, 0, ansiArray, -1, NULL, 0);
|
||||
if (0 < length)
|
||||
{
|
||||
LPWSTR result = new wchar_t[length];
|
||||
if (NULL != result)
|
||||
{
|
||||
length = ::MultiByteToWideChar(CP_UTF8, 0, ansiArray, -1, result, length);
|
||||
if (0 < length)
|
||||
{
|
||||
wcscpy_s(wideArray, MAX_PATH, result);
|
||||
}
|
||||
delete[] result; // Free the allocated string to avoid a memory leak
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void convertWideToAnsi(wchar_t* wideArray, char* ansiArray)
|
||||
{
|
||||
// Generate the ansi version of the string and save its value;
|
||||
//
|
||||
// This is a two call function. The first call is to get the necessary length.
|
||||
// The second call is to perform the actual operation.
|
||||
int length = ::WideCharToMultiByte(CP_ACP, 0, wideArray, -1, NULL, 0, NULL, NULL);
|
||||
if (0 < length)
|
||||
{
|
||||
LPSTR result = new char[length];
|
||||
if (NULL != result)
|
||||
{
|
||||
length = ::WideCharToMultiByte(CP_ACP, 0, wideArray, -1, result, length, NULL, NULL);
|
||||
if (0 < length)
|
||||
{
|
||||
strcpy_s(ansiArray, MAX_PATH, result);
|
||||
}
|
||||
delete[] result; // Free the allocated string to avoid a memory leak
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
HostEnvironment()
|
||||
@ -275,6 +319,17 @@ namespace NativeMsh
|
||||
if (hostPath)
|
||||
{
|
||||
::ExpandEnvironmentStringsA(hostPath, m_hostPath, MAX_PATH);
|
||||
|
||||
convertAnsiToWide(m_hostPath, m_hostPathW);
|
||||
}
|
||||
}
|
||||
void SetHostPathW(PCWSTR hostPath)
|
||||
{
|
||||
if (hostPath)
|
||||
{
|
||||
::ExpandEnvironmentStringsW(hostPath, m_hostPathW, MAX_PATH);
|
||||
|
||||
convertWideToAnsi(m_hostPathW, m_hostPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,6 +339,11 @@ namespace NativeMsh
|
||||
return m_hostPath;
|
||||
}
|
||||
|
||||
PCWSTR GetHostPathW()
|
||||
{
|
||||
return m_hostPathW;
|
||||
}
|
||||
|
||||
// Safely copies in a host binary name
|
||||
void SetHostBinaryName(PCSTR hostBinaryName)
|
||||
{
|
||||
@ -293,12 +353,25 @@ namespace NativeMsh
|
||||
}
|
||||
}
|
||||
|
||||
void SetHostBinaryNameW(PCWSTR hostBinaryName)
|
||||
{
|
||||
if (hostBinaryName)
|
||||
{
|
||||
m_hostBinaryNameW = std::wstring(hostBinaryName);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the name of the host module
|
||||
PCSTR GetHostBinaryName()
|
||||
{
|
||||
return m_hostBinaryName.c_str();
|
||||
}
|
||||
|
||||
PCWSTR GetHostBinaryNameW()
|
||||
{
|
||||
return m_hostBinaryNameW.c_str();
|
||||
}
|
||||
|
||||
// Safely copies in a host directory path
|
||||
void SetHostDirectoryPath(PCSTR hostDirPath)
|
||||
{
|
||||
@ -306,24 +379,17 @@ namespace NativeMsh
|
||||
{
|
||||
::ExpandEnvironmentStringsA(hostDirPath, m_hostDirectoryPath, MAX_PATH);
|
||||
|
||||
// Generate the wide version of the string and save its value;
|
||||
//
|
||||
// This is a two call function. The first call is to get the necessary length.
|
||||
// The second call is to perform the actual operation.
|
||||
int length = MultiByteToWideChar(CP_UTF8, 0, m_hostDirectoryPath, -1, NULL, 0);
|
||||
if (0 < length)
|
||||
{
|
||||
LPWSTR result = new wchar_t[length];
|
||||
if (NULL != result)
|
||||
{
|
||||
length = ::MultiByteToWideChar(CP_UTF8, 0, m_hostDirectoryPath, -1, result, length);
|
||||
if (0 < length)
|
||||
{
|
||||
wcscpy_s(m_hostDirectoryPathW, MAX_PATH, result);
|
||||
}
|
||||
delete[] result; // Free the allocated string to avoid a memory leak
|
||||
}
|
||||
}
|
||||
convertAnsiToWide(m_hostDirectoryPath, m_hostDirectoryPathW);
|
||||
}
|
||||
}
|
||||
|
||||
void SetHostDirectoryPathW(PCWSTR hostDirPath)
|
||||
{
|
||||
if (hostDirPath)
|
||||
{
|
||||
::ExpandEnvironmentStringsW(hostDirPath, m_hostDirectoryPathW, MAX_PATH);
|
||||
|
||||
convertWideToAnsi(m_hostDirectoryPathW, m_hostDirectoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,24 +412,17 @@ namespace NativeMsh
|
||||
{
|
||||
::ExpandEnvironmentStringsA(hostClrPath, m_coreCLRDirectoryPath, MAX_PATH);
|
||||
|
||||
// Generate the wide version of the string and save its value;
|
||||
//
|
||||
// This is a two call function. The first call is to get the necessary length.
|
||||
// The second call is to perform the actual operation.
|
||||
int length = MultiByteToWideChar(CP_UTF8, 0, m_coreCLRDirectoryPath, -1, NULL, 0);
|
||||
if (0 < length)
|
||||
{
|
||||
LPWSTR result = new wchar_t[length];
|
||||
if (NULL != result)
|
||||
{
|
||||
length = ::MultiByteToWideChar(CP_UTF8, 0, m_coreCLRDirectoryPath, -1, result, length);
|
||||
if (0 < length)
|
||||
{
|
||||
wcscpy_s(m_coreCLRDirectoryPathW, MAX_PATH, result);
|
||||
}
|
||||
delete[] result; // Free the allocated string to avoid a memory leak
|
||||
}
|
||||
}
|
||||
convertAnsiToWide(m_coreCLRDirectoryPath, m_coreCLRDirectoryPathW);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCoreCLRDirectoryPathW(PCWSTR hostClrPath)
|
||||
{
|
||||
if (hostClrPath)
|
||||
{
|
||||
::ExpandEnvironmentStringsW(hostClrPath, m_coreCLRDirectoryPathW, MAX_PATH);
|
||||
|
||||
convertWideToAnsi(m_coreCLRDirectoryPathW, m_coreCLRDirectoryPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,5 +437,7 @@ namespace NativeMsh
|
||||
{
|
||||
return m_coreCLRDirectoryPathW;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
} // namespace NativeMsh
|
||||
|
131
src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp
Normal file
131
src/powershell-native/nativemsh/pwrshcommon/ConfigFileReader.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <windef.h>
|
||||
|
||||
#include "NativeMsh.h"
|
||||
#include "ConfigFileReader.h"
|
||||
|
||||
namespace NativeMsh
|
||||
{
|
||||
// The name of the PowerShell config file that identifies the PowerShell install location.
|
||||
// We use a config file to avoid writing to the registry during install
|
||||
// or hard coding paths into the binary.
|
||||
static PCWSTR powerShellConfigFileName = L"RemotePowerShellConfig.txt";
|
||||
|
||||
ConfigFileReader::ConfigFileReader()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int ConfigFileReader::Read(
|
||||
std::wstring pathToConfig)
|
||||
{
|
||||
std::wstring absolutePathToConfigFile(pathToConfig);
|
||||
absolutePathToConfigFile += powerShellConfigFileName;
|
||||
std::wfstream psConfigFile(absolutePathToConfigFile.c_str());
|
||||
|
||||
if (!psConfigFile.is_open())
|
||||
{
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
|
||||
std::wstring line;
|
||||
std::wstring psHomeDirTag(L"PSHOMEDIR=");
|
||||
std::wstring coreClrDirTag(L"CORECLRDIR=");
|
||||
while (std::getline(psConfigFile, line))
|
||||
{
|
||||
std::wstring::const_iterator iter = line.begin();
|
||||
|
||||
// Search for the first actionable character in the line to
|
||||
// limit the number of passes that are made iterating through the line.
|
||||
while(iter != line.end())
|
||||
{
|
||||
if (*iter == L'#')
|
||||
{
|
||||
// Stop parsing the line because the rest of it is a comment
|
||||
break;
|
||||
}
|
||||
else if (*iter == L'p' || *iter == L'P')
|
||||
{
|
||||
this->pathToPowerShellAssemblies = this->getValueFromLine(line, psHomeDirTag);
|
||||
if (this->pathToPowerShellAssemblies.size() > 0) // Found a match
|
||||
{
|
||||
std::wstring::const_iterator slashIter = this->pathToPowerShellAssemblies.end();
|
||||
slashIter--;
|
||||
if (*slashIter != L'\\')
|
||||
{
|
||||
// Guarantee that there is a '\' at the end of the path
|
||||
this->pathToPowerShellAssemblies.append(L"\\");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*iter == L'c' || *iter == L'C')
|
||||
{
|
||||
this->coreClrDirectory = this->getValueFromLine(line, coreClrDirTag);
|
||||
if (this->coreClrDirectory.size() > 0) // Found a match
|
||||
{
|
||||
std::wstring::const_iterator slashIter = this->coreClrDirectory.end();
|
||||
slashIter--;
|
||||
if (*slashIter != L'\\')
|
||||
{
|
||||
// Guarantee that there is a '\' at the end of the path
|
||||
this->coreClrDirectory.append(L"\\");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do nothing to ignore unmatched characters (whitespace, etc.)
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
if (0 == this->pathToPowerShellAssemblies.size() ||
|
||||
0 == this->coreClrDirectory.size())
|
||||
{
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EXIT_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// This trim function removes beginning and ending whitespace. It does not
|
||||
// remove internal whitespace because that is valid within paths.
|
||||
std::wstring ConfigFileReader::trim(
|
||||
const std::wstring& toTrim)
|
||||
{
|
||||
static PCWSTR WHITESPACE_CHARS = L" \n\r\t";
|
||||
std::wstring copyToTrim = toTrim;
|
||||
std::size_t first = copyToTrim.find_first_not_of(WHITESPACE_CHARS);
|
||||
|
||||
if (first == std::wstring::npos)
|
||||
{
|
||||
// No non-whitespace found
|
||||
return std::wstring(L"");
|
||||
}
|
||||
|
||||
// Result not checked for std::wstring::npos because it is guaranteed to have a value if the first pass succeeded.
|
||||
copyToTrim.erase(copyToTrim.find_last_not_of(WHITESPACE_CHARS)+1);
|
||||
|
||||
return copyToTrim.substr(first);
|
||||
}
|
||||
|
||||
// Parses the specified line for the given tag. Tags are assumed to include
|
||||
// the "=" separator character.
|
||||
std::wstring ConfigFileReader::getValueFromLine(
|
||||
const std::wstring& line, // Passed by value to preserve the original line.
|
||||
std::wstring& tagToFind)
|
||||
{
|
||||
std::wstring trimmedLine = this->trim(line);
|
||||
std::size_t index = trimmedLine.find(tagToFind);
|
||||
if (std::string::npos != index)
|
||||
{
|
||||
std::wstring value = trimmedLine.substr(index + tagToFind.size()); // Everything else after the tag
|
||||
return this->trim(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::wstring(L"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// Microsoft Windows NT
|
||||
// Copyright (C) Microsoft Corporation, 2014.
|
||||
//
|
||||
// Contents: A class that extracts the path to $PSHOME and the path to its
|
||||
// CoreCLR from a configuration file.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace NativeMsh
|
||||
{
|
||||
class ConfigFileReader
|
||||
{
|
||||
private:
|
||||
std::wstring pathToPowerShellAssemblies;
|
||||
std::wstring coreClrDirectory;
|
||||
|
||||
std::wstring trim(const std::wstring& toTrim);
|
||||
std::wstring getValueFromLine(const std::wstring& line, std::wstring& tagToFind);
|
||||
|
||||
public:
|
||||
ConfigFileReader();
|
||||
|
||||
// Initiates a Read operation of the specified configuration file.
|
||||
unsigned int Read(std::wstring pathToConfig);
|
||||
|
||||
// Information Getters
|
||||
std::wstring GetPathToPowerShell() { return pathToPowerShellAssemblies; }
|
||||
std::wstring GetPathToCoreClr() { return coreClrDirectory; }
|
||||
};
|
||||
} // namespace NativeMsh
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "NativeMshConstants.h"
|
||||
#include "ClrHostWrapper.h"
|
||||
#include "SystemCallFacade.h"
|
||||
#include "ConfigFileReader.h"
|
||||
#include "IPwrshCommonOutput.h"
|
||||
|
||||
#if !CORECLR
|
||||
@ -29,6 +30,7 @@ namespace NativeMsh
|
||||
{
|
||||
private:
|
||||
IPwrshCommonOutput* output;
|
||||
ConfigFileReader* reader;
|
||||
SystemCallFacade* sysCalls;
|
||||
|
||||
public:
|
||||
@ -41,6 +43,7 @@ namespace NativeMsh
|
||||
// allocate them with "new".
|
||||
PwrshCommon(
|
||||
IPwrshCommonOutput* outObj, // Enables clients to specify how error messages are displayed or suppressed
|
||||
ConfigFileReader* rdr, // Enables specification of how the config file is read.
|
||||
SystemCallFacade* systemCalls); // Wraps all calls to Windows APIs to allow for dependency injection via unit test
|
||||
|
||||
~PwrshCommon();
|
||||
|
@ -820,29 +820,40 @@ namespace NativeMsh
|
||||
// The name of the CoreCLR native runtime DLL.
|
||||
static PCSTR coreClrDll = "CoreCLR.dll";
|
||||
|
||||
// The location where CoreCLR is expected to be installed. If CoreCLR.dll isn't
|
||||
// The location where CoreCLR is expected to be installed for inbox PowerShell. If CoreCLR.dll isn't
|
||||
// found in the same directory as the host, it will be looked for here.
|
||||
static PCSTR coreCLRInstallDirectory = "%windir%\\system32\\DotNetCore\\v1.0\\";
|
||||
|
||||
// The location where CoreCLR PowerShell Ext binaries are expected to be installed.
|
||||
// The location where CoreCLR PowerShell Ext binaries are expected to be installed for inbox PowerShell.
|
||||
static PCSTR coreCLRPowerShellExtInstallDirectory = "%windir%\\system32\\CoreClrPowerShellExt\\v1.0\\";
|
||||
|
||||
// The default PowerShell install directory. This location may be overridden through a config file in %windir%\System32.
|
||||
// The default PowerShell install directory for inbox PowerShell.
|
||||
// This location may be overridden by placing a config file in the same directory as the PowerShell host.
|
||||
static PCSTR powerShellInstallPath = "%windir%\\System32\\WindowsPowerShell\\v1.0\\";
|
||||
|
||||
unsigned int PwrshCommon::IdentifyHostDirectory(
|
||||
HostEnvironment& hostEnvironment)
|
||||
{
|
||||
// Discover the path to the exe's module (powershell.exe or wsmprovhost.exe).
|
||||
// For remoting, this is expected to be %windir%\system32 since that is the location of wsmprovhost.exe.
|
||||
char hostPath[MAX_PATH];
|
||||
DWORD thisModuleLength = sysCalls->GetModuleFileNameA(sysCalls->GetModuleHandleA(NULL), hostPath, MAX_PATH);
|
||||
// Discover the path to the plugin or the executable (pwrshplugin.dll or powershell.exe).
|
||||
// For PowerShell Core, the plugin no longer resides in %windir%\\system32 (it is in a sub-directory).
|
||||
// If pwrshplugin.dll is not loaded, it means that this is running via powershell.exe.
|
||||
wchar_t hostPath[MAX_PATH];
|
||||
DWORD thisModuleLength;
|
||||
|
||||
if (0 == thisModuleLength)
|
||||
if (GetModuleHandleW(L"pwrshplugin.dll"))
|
||||
{
|
||||
thisModuleLength = GetModuleFileNameW(GetModuleHandleW(L"pwrshplugin.dll"), hostPath, MAX_PATH);
|
||||
}
|
||||
else
|
||||
{
|
||||
thisModuleLength = GetModuleFileNameW(GetModuleHandleW(NULL), hostPath, MAX_PATH);
|
||||
}
|
||||
if (0 == thisModuleLength) // Greater than zero means it is the length of the fully qualified path (without the NULL character)
|
||||
{
|
||||
// TODO: Use GetLastError() to find the specific error #
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
|
||||
// Search for the last backslash in the host path.
|
||||
int lastBackslashIndex;
|
||||
for (lastBackslashIndex = thisModuleLength - 1; lastBackslashIndex >= 0; lastBackslashIndex--)
|
||||
@ -854,14 +865,34 @@ namespace NativeMsh
|
||||
}
|
||||
|
||||
// The remaining part of the path after the last '\' is the binary name.
|
||||
hostEnvironment.SetHostBinaryName(hostPath + lastBackslashIndex + 1);
|
||||
hostEnvironment.SetHostBinaryNameW(hostPath + lastBackslashIndex + 1);
|
||||
|
||||
// Copy the directory path portion of the path
|
||||
hostPath[lastBackslashIndex + 1] = '\0';
|
||||
hostEnvironment.SetHostPath(hostPath);
|
||||
|
||||
hostEnvironment.SetHostDirectoryPath(powerShellInstallPath);
|
||||
hostEnvironment.SetHostPathW(hostPath);
|
||||
|
||||
// Read the config file to determine the appropriate host path and CoreCLR path to use.
|
||||
unsigned int result = reader->Read(hostPath);
|
||||
if (EXIT_CODE_SUCCESS == result)
|
||||
{
|
||||
// The config file was successfully parsed. Use those directories.
|
||||
hostEnvironment.SetHostDirectoryPathW(reader->GetPathToPowerShell().c_str());
|
||||
hostEnvironment.SetCoreCLRDirectoryPathW(reader->GetPathToCoreClr().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// There was an issue accessing or parsing the config file OR
|
||||
// we are working for the EXE.
|
||||
//
|
||||
// TODO: This should not be the fallback for inbox PowerShell.exe.
|
||||
// It should use coreCLRInstallDirectory and coreCLRPowerShellExtInstallDirectory.
|
||||
//
|
||||
// Use the directory detected via GetModuleFileName + GetModuleHandle
|
||||
hostEnvironment.SetHostDirectoryPathW(hostPath);
|
||||
// At the moment, CoreCLR is in the same directory as PowerShell Core.
|
||||
// This path must be modified if we decide to use a different directory.
|
||||
hostEnvironment.SetCoreCLRDirectoryPathW(hostPath);
|
||||
}
|
||||
return EXIT_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
@ -959,20 +990,26 @@ namespace NativeMsh
|
||||
//
|
||||
|
||||
PwrshCommon::PwrshCommon()
|
||||
: output(new PwrshCommonOutputDefault()), sysCalls(new WinSystemCallFacade())
|
||||
: output(new PwrshCommonOutputDefault()), reader(new ConfigFileReader()), sysCalls(new WinSystemCallFacade())
|
||||
{
|
||||
}
|
||||
|
||||
PwrshCommon::PwrshCommon(
|
||||
IPwrshCommonOutput* outObj,
|
||||
ConfigFileReader* rdr,
|
||||
SystemCallFacade* systemCalls)
|
||||
: output(outObj), sysCalls(systemCalls)
|
||||
: output(outObj), reader(rdr), sysCalls(systemCalls)
|
||||
{
|
||||
if (NULL == output)
|
||||
{
|
||||
output = new PwrshCommonOutputDefault();
|
||||
}
|
||||
|
||||
if (NULL == reader)
|
||||
{
|
||||
reader = new ConfigFileReader();
|
||||
}
|
||||
|
||||
if (NULL == sysCalls)
|
||||
{
|
||||
sysCalls = new WinSystemCallFacade();
|
||||
@ -987,6 +1024,12 @@ namespace NativeMsh
|
||||
output = NULL;
|
||||
}
|
||||
|
||||
if (reader)
|
||||
{
|
||||
delete reader;
|
||||
reader = NULL;
|
||||
}
|
||||
|
||||
if (sysCalls)
|
||||
{
|
||||
delete sysCalls;
|
||||
@ -1299,37 +1342,13 @@ namespace NativeMsh
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
// Try to load from the well-known location.
|
||||
char coreCLRInstallPath[MAX_PATH];
|
||||
exitCode = ::ExpandEnvironmentStringsA(coreCLRInstallDirectory, coreCLRInstallPath, MAX_PATH);
|
||||
if (0 == exitCode || _countof(coreCLRInstallPath) <= exitCode)
|
||||
exitCode = hostWrapper->SetupWrapper(hostEnvironment.GetCoreCLRDirectoryPath());
|
||||
if (EXIT_CODE_SUCCESS != exitCode)
|
||||
{
|
||||
this->output->DisplayMessage(false, g_STARTING_CLR_FAILED, GetLastError());
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
}
|
||||
|
||||
HMODULE coreClrModule = hostWrapper->SetupWrapper(coreCLRInstallPath);
|
||||
if (!coreClrModule)
|
||||
{
|
||||
this->output->DisplayMessage(false, g_STARTING_CLR_FAILED, GetLastError());
|
||||
return EXIT_CODE_INIT_FAILURE;
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
// Save the directory that CoreCLR was found in
|
||||
char coreCLRDirectoryPath[MAX_PATH];
|
||||
DWORD modulePathLength = sysCalls->GetModuleFileNameA(coreClrModule, coreCLRDirectoryPath, MAX_PATH);
|
||||
|
||||
// Search for the last backslash and terminate it there to keep just the directory path with trailing slash
|
||||
for (int lastBackslashIndex = modulePathLength - 1; lastBackslashIndex >= 0; lastBackslashIndex--)
|
||||
{
|
||||
if (coreCLRDirectoryPath[lastBackslashIndex] == L'\\')
|
||||
{
|
||||
coreCLRDirectoryPath[lastBackslashIndex + 1] = L'\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
hostEnvironment.SetCoreCLRDirectoryPath(coreCLRDirectoryPath);
|
||||
|
||||
const int nMaxProps = 8;
|
||||
LPCSTR props[nMaxProps];
|
||||
LPCSTR vals[nMaxProps];
|
||||
|
@ -34,7 +34,7 @@ else ()
|
||||
# CoreCLR libs
|
||||
${STATIC_MT_CRT_LIB}
|
||||
${STATIC_MT_VCRT_LIB}
|
||||
${STATIC_UCRT_LIB}
|
||||
# ${STATIC_UCRT_LIB}
|
||||
# ole32.lib
|
||||
# oleaut32.lib
|
||||
# uuid.lib
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "NativeMsh.h"
|
||||
#include "ClrHostWrapper.h"
|
||||
#include "OutputWriter.h"
|
||||
#include "ConfigFileReader.h"
|
||||
#include "WinSystemCallFacade.h"
|
||||
|
||||
namespace NativeMsh
|
||||
@ -35,7 +36,7 @@ namespace NativeMsh
|
||||
|
||||
// All these objects will be destroyed when commonFuncs goes out of scope.
|
||||
PwrshExeOutput* output = new PwrshExeOutput();
|
||||
PwrshCommon commonFuncs(output, new WinSystemCallFacade());
|
||||
PwrshCommon commonFuncs(output, new ConfigFileReader(), new WinSystemCallFacade());
|
||||
CoreClrHostingApiWrapper hostWrapper;
|
||||
|
||||
exitCode = commonFuncs.LaunchCoreCLR(&hostWrapper, hostEnvironment, "powershell");
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <msxml6.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include "OutputWriter.h"
|
||||
#include "ConfigFileReader.h"
|
||||
#include "WinSystemCallFacade.h"
|
||||
|
||||
// include the tlb for mscorlib for access to the default AppDomain through COM Interop
|
||||
@ -49,7 +50,7 @@ WCHAR g_IconApp[MAX_PATH+1];
|
||||
|
||||
// All these objects will be destroyed when pwrshCommon goes out of scope.
|
||||
PwrshExeOutput* pwrshExeOutput = new PwrshExeOutput();
|
||||
PwrshCommon pwrshCommon(pwrshExeOutput, new WinSystemCallFacade());
|
||||
PwrshCommon pwrshCommon(pwrshExeOutput, new ConfigFileReader(), new WinSystemCallFacade());
|
||||
|
||||
bool ConvertArgvToSafeArray(
|
||||
IN int argc,
|
||||
|
@ -5,7 +5,8 @@ add_library(pwrshplugin SHARED
|
||||
entrypoints.cpp
|
||||
pwrshclrhost.cpp
|
||||
pwrshpluginerrorcodes.mc
|
||||
pwrshpluginerrorcodes.rc
|
||||
#pwrshpluginerrorcodes.rc
|
||||
pwrshpluginResources.rc
|
||||
pwrshplugin.def
|
||||
)
|
||||
|
||||
@ -40,7 +41,7 @@ else ()
|
||||
# CoreCLR lib
|
||||
${STATIC_MT_CRT_LIB}
|
||||
${STATIC_MT_VCRT_LIB}
|
||||
${STATIC_UCRT_LIB}
|
||||
# ${STATIC_UCRT_LIB}
|
||||
legacy_stdio_definitions.lib # Resolves: LNK2019: unresolved external symbol _vsnwprintf
|
||||
)
|
||||
set(pwrshplugin_definitions ${common_pwrsh_definitions})
|
||||
|
@ -130,7 +130,7 @@ PowerShellCoreClrWorker::PowerShellCoreClrWorker(
|
||||
|
||||
if (NULL == commonLib)
|
||||
{
|
||||
commonLib = new PwrshCommon(new PwrshPluginOutputDefault(), new WinSystemCallFacade());
|
||||
commonLib = new PwrshCommon(new PwrshPluginOutputDefault(), new ConfigFileReader(), new WinSystemCallFacade());
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,7 +344,8 @@ unsigned int PowerShellClrManagedWorker::LoadWorkerCallbackPtrs(
|
||||
|
||||
// use CreateInstance because we use the assembly strong name (as opposed to CreateInstanceFrom)
|
||||
//
|
||||
// wszMgdPlugInFileName is %systemdir%\Windows\System32\WindowsPowerShell\v1.0\system.management.automation.dll.
|
||||
// wszMgdPlugInFileName is system.management.automation.dll within the powershell install path.
|
||||
// For inbox PowerShell, this is %systemdir%\Windows\System32\WindowsPowerShell\v1.0\system.management.automation.dll (Aka $PSHOME\system.management.automation.dll)
|
||||
_bstr_t bstrConsoleHostAssemblyName = _bstr_t(L"System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
|
||||
_bstr_t bstrUnmanagedMshEntryClass = _bstr_t(L"System.Management.Automation.Remoting.WSManPluginManagedEntryInstanceWrapper");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user