mirror of
https://github.com/leechristensen/UnmanagedPowerShell
synced 2026-06-08 15:26:18 +00:00
Add project
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
// UnmanagedPowerShell.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#pragma region Includes and Imports
|
||||
#include <windows.h>
|
||||
#include <comdef.h>
|
||||
#include <mscoree.h>
|
||||
#include "PowerShellRunnerDll.h"
|
||||
|
||||
#include <metahost.h>
|
||||
#pragma comment(lib, "mscoree.lib")
|
||||
|
||||
// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
|
||||
#import "mscorlib.tlb" raw_interfaces_only \
|
||||
high_property_prefixes("_get","_put","_putref") \
|
||||
rename("ReportEvent", "InteropServices_ReportEvent")
|
||||
using namespace mscorlib;
|
||||
#pragma endregion
|
||||
|
||||
|
||||
|
||||
extern const unsigned int PowerShellRunner_dll_len;
|
||||
extern unsigned char PowerShellRunner_dll[];
|
||||
void InvokeMethod(_TypePtr spType, wchar_t* method, wchar_t* command);
|
||||
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
ICLRMetaHost *pMetaHost = NULL;
|
||||
ICLRRuntimeInfo *pRuntimeInfo = NULL;
|
||||
ICorRuntimeHost *pCorRuntimeHost = NULL;
|
||||
|
||||
IUnknownPtr spAppDomainThunk = NULL;
|
||||
_AppDomainPtr spDefaultAppDomain = NULL;
|
||||
|
||||
// The .NET assembly to load.
|
||||
bstr_t bstrAssemblyName("PowerShellRunner");
|
||||
_AssemblyPtr spAssembly = NULL;
|
||||
|
||||
// The .NET class to instantiate.
|
||||
bstr_t bstrClassName("PowerShellRunner.PowerShellRunner");
|
||||
_TypePtr spType = NULL;
|
||||
|
||||
|
||||
// Start the runtime
|
||||
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
hr = pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Check if the specified runtime can be loaded into the process.
|
||||
BOOL fLoadable;
|
||||
hr = pRuntimeInfo->IsLoadable(&fLoadable);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (!fLoadable)
|
||||
{
|
||||
wprintf(L".NET runtime v2.0.50727 cannot be loaded\n");
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Load the CLR into the current process and return a runtime interface
|
||||
hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost,
|
||||
IID_PPV_ARGS(&pCorRuntimeHost));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Start the CLR.
|
||||
hr = pCorRuntimeHost->Start();
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
|
||||
// Get a pointer to the default AppDomain in the CLR.
|
||||
hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"ICorRuntimeHost::GetDefaultDomain failed w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"Failed to get default AppDomain w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Load the .NET assembly.
|
||||
// (Option 1) Load it from disk - usefully when debugging the PowerShellRunner app (you'll have to copy the DLL into the same directory as the exe)
|
||||
//hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
|
||||
|
||||
// (Option 2) Load the assembly from memory
|
||||
SAFEARRAYBOUND bounds[1];
|
||||
bounds[0].cElements = PowerShellRunner_dll_len;
|
||||
bounds[0].lLbound = 0;
|
||||
|
||||
SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds);
|
||||
SafeArrayLock(arr);
|
||||
memcpy(arr->pvData, PowerShellRunner_dll, PowerShellRunner_dll_len);
|
||||
SafeArrayUnlock(arr);
|
||||
|
||||
hr = spDefaultAppDomain->Load_3(arr, &spAssembly);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Get the Type of PowerShellRunner.
|
||||
hr = spAssembly->GetType_2(bstrClassName, &spType);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"Failed to get the Type interface w/hr 0x%08lx\n", hr);
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
// Call the static method of the class
|
||||
wchar_t* argument = L"Get-Process\n\
|
||||
#This is a PowerShell Comment\n\
|
||||
Write-Host \"`n`n******* The next command is going to throw an exception. This is planned *********`n`n\"\n\
|
||||
Read-Host\n";
|
||||
|
||||
InvokeMethod(spType, L"InvokePS", argument);
|
||||
|
||||
Cleanup:
|
||||
|
||||
if (pMetaHost)
|
||||
{
|
||||
pMetaHost->Release();
|
||||
pMetaHost = NULL;
|
||||
}
|
||||
if (pRuntimeInfo)
|
||||
{
|
||||
pRuntimeInfo->Release();
|
||||
pRuntimeInfo = NULL;
|
||||
}
|
||||
if (pCorRuntimeHost)
|
||||
{
|
||||
pCorRuntimeHost->Release();
|
||||
pCorRuntimeHost = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InvokeMethod(_TypePtr spType, wchar_t* method, wchar_t* command)
|
||||
{
|
||||
HRESULT hr;
|
||||
bstr_t bstrStaticMethodName(method);
|
||||
SAFEARRAY *psaStaticMethodArgs = NULL;
|
||||
variant_t vtStringArg(command);
|
||||
variant_t vtPSInvokeReturnVal;
|
||||
variant_t vtEmpty;
|
||||
|
||||
|
||||
psaStaticMethodArgs = SafeArrayCreateVector(VT_VARIANT, 0, 1);
|
||||
LONG index = 0;
|
||||
hr = SafeArrayPutElement(psaStaticMethodArgs, &index, &vtStringArg);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"SafeArrayPutElement failed w/hr 0x%08lx\n", hr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invoke the method from the Type interface.
|
||||
hr = spType->InvokeMember_3(
|
||||
bstrStaticMethodName,
|
||||
static_cast<BindingFlags>(BindingFlags_InvokeMethod | BindingFlags_Static | BindingFlags_Public),
|
||||
NULL,
|
||||
vtEmpty,
|
||||
psaStaticMethodArgs,
|
||||
&vtPSInvokeReturnVal);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
wprintf(L"Failed to invoke InvokePS w/hr 0x%08lx\n", hr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print the output of the command
|
||||
wprintf(vtPSInvokeReturnVal.bstrVal);
|
||||
}
|
||||
|
||||
|
||||
SafeArrayDestroy(psaStaticMethodArgs);
|
||||
psaStaticMethodArgs = NULL;
|
||||
}
|
||||
Reference in New Issue
Block a user