Asked  7 Months ago    Answers:  5   Viewed   27 times

I am updating a PowerShell script that manages some .NET assemblies. The script was written for assemblies built against .NET 2 (the same version of the framework that PowerShell runs with), but now needs to work with .NET 4 assemblies as well as .NET 2 assemblies.

Since .NET 4 supports running applications built against older versions of the framework, it seems like the simplest solution is to launch PowerShell with the .NET 4 runtime when I need to run it against .NET 4 assemblies.

How can I run PowerShell with the .NET 4 runtime?

 Answers

92

PowerShell (the engine) runs fine under .NET 4.0. PowerShell (the console host and the ISE) do not, simply because they were compiled against older versions of .NET. There's a registry setting that will change the .NET framework loaded systemwide, which will in turn allow PowerShell to use .NET 4.0 classes:

reg add hklmsoftwaremicrosoft.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1
reg add hklmsoftwarewow6432nodemicrosoft.netframework /v OnlyUseLatestCLR /t REG_DWORD /d 1

To update just the ISE to use .NET 4.0, you can change the configuration ($psHomepowershell_ise.exe.config) file to have a chunk like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup>
      <supportedRuntime version="v4.0.30319" />
    </startup>
</configuration>

You can build .NET 4.0 applications that call PowerShell using the PowerShell API (System.Management.Automation.PowerShell) just fine, but these steps will help get the in-the-box PowerShell hosts to work under .NET 4.0.


Remove the registry keys when you don't need them any more. These are machine-wide keys and forcibly migrate ALL applications to .NET 4.0, even applications using .net 2 and .net 3.5


Tuesday, June 1, 2021
 
Giovanni
answered 7 Months ago
93

Here is what you may want to do:

public async Task<PewPew> SomeMethod(Foo foo)
{
    // get the stuff on another thread 
    var cTask = Task.Run(() => GetAllTheCats(foo));
    var fTask = Task.Run(() => GetAllTheFood(foo));

    var cats = await cTask;
    var food = await fTask;

    return new PewPew
               {
                   Cats = cats,
                   Food = food
               };
}

public IList<Cat> GetAllTheCats(Foo foo)
{
    // Do stuff, like hit the Db, spin around, dance, jump, etc...
    // It all takes some time.
    return cats;
}

public IList<Food> GetAllTheFood(Foo foo)
{
    // Do more stuff, like hit the Db, nom nom noms...
    // It all takes some time.
    return food;
}

There are two things you need to understand here:

1) What is diff between this:

var cats = await cTask;
var food = await fTask;

And this:

Task.WaitAll(new [] {cTask, fTask});

Both will give you similar result in the sense let the 2 async tasks finish and then return new PewPew - however, difference is that Task.WaitAll() will block the current thread (if that is UI thread, then UI will freeze). instead, await will break down the SomeMethod say in a state machine, and return from the SomeMethod to its caller as it encounters await keyword. It will not block the thread. The Code below await will be scheduled to run when async task is over.

2) You could also do this:

var cats = await Task.Run(() => GetAllTheCats(foo));
var food = await Task.Run(() => GetAllTheFood(foo));

However, this will not start the async tasks simultaneously. Second task will start after the first is over. This is because how the await keyword works, hope that helps...

EDIT: How to use SomeMethod - somewhere at the start of the call tree, you have to use Wait() or Result property - OR - you have to await from async void. Generally, async void would be an event handler:

public async void OnSomeEvent(object sender, EventArgs ez) 
{ 
  Foo f = GetFoo();
  PewPew p = await SomeMethod(f);
}

If not then use Result property.

public Foo2 NonAsyncNonVoidMethod() 
{
   Foo f = GetFoo();
   PewPew p = SomeMethod(f).Result; //But be aware that Result will block thread

   return GetFoo2(p);
}
Monday, June 28, 2021
 
Corsair
answered 6 Months ago
100

As a more complete answer based on William Hampshire's one, Cuga's comment and my personal additions.


Short answer: using ChromeHeadless

You can just use Headless Chrome:

ng test --browsers ChromeHeadless

You need to have Chrome 59+.

But if you need PhantomJS (and/or chaning the default ng test behaviour with no arguments) read the following.


Longer answer: using PhantomJS

EDIT: Be aware that PhantomJS project has been archived, see this thread.

Setup

In order to be able to (optionally) run your tests without a browser, using PhantomJS, you should:

1) Install some dependencies:

npm install --save-dev karma-phantomjs-launcher
npm install --save intl

2) Add PhantomJS to the Karma's plugin list

Open karma.conf.js and add require('karma-phantomjs-launcher') to the plugins array, for example:

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-phantomjs-launcher'),
      // ...
    ],

3) Enable polyfills

Open your src/polyfills.ts file and uncomment the following lines:

BROWSER POLYFILLS

import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

APPLICATION IMPORTS

import 'intl';
import 'intl/locale-data/jsonp/en';

How to run the tests

Specifying the browsers when running the command

No you can either run the test using Chrome (the angular-cli default):

ng test --browsers Chrome

Or PhantomJS (headless):

ng test --browsers PhantomJS

Changing the default behaviour of just ng test

It is possible to change the default behaviour of ng test (so when no --browsers argument is provided) by changing the value of the browsers array in karma.conf.js.

It can now be set to just use Chrome (default angular-cli setup):

browsers: ['Chrome'],

or PhantomJS:

browsers: ['PhantomJS'],

or even both:

browsers: ['Chrome', 'PhantomJS'],

Monday, August 2, 2021
 
Marko Kevac
answered 4 Months ago
53

Try loading the configuration first and open your section on that:

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AssetsSection configSection = (AssetsSection)config.GetSection("test/assets");

I ran into the same issue with .NET 4 and this works for me.

Thursday, August 12, 2021
 
Kenny
answered 4 Months ago
33

You have two options given your setup.

  1. Use a third party library, something like the stuff available from SyncFusion
  2. Use the XML route, the initial setup isn't fun, but once you get it the process is easy.

A third, much more crude way would be to write an HTML file and save as .doc, but that is going to cause warnings on the user side with 2007 and later.

Thursday, August 26, 2021
 
Riyazul Aboobucker
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share