{"id":14470,"date":"2018-11-15T16:22:17","date_gmt":"2018-11-15T23:22:17","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/powershell\/?p=14470"},"modified":"2019-02-18T12:37:42","modified_gmt":"2019-02-18T19:37:42","slug":"announcing-general-availability-of-the-windows-compatibility-module-1-0-0","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/","title":{"rendered":"Announcing General Availability of the Windows Compatibility Module 1.0.0"},"content":{"rendered":"<h2>Announcing General Availability of the Windows Compatibility Module 1.0.0<\/h2>\n<p>The Windows Compatibility module (<code>WindowsCompatibility<\/code>) is a PowerShell module that lets PowerShell Core 6 scripts access Windows PowerShell modules that are not yet natively available on PowerShell Core. (Note: the list of unavailable commands is\u00a0<a href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/09\/13\/announcing-powershell-core-6-1\/\" rel=\"nofollow\">getting smaller<\/a>\u00a0with each new release of PowerShell Core. This module is just for things aren\u2019t natively supported yet.)<\/p>\n<p>You can install the module from the\u00a0<a href=\"https:\/\/www.powershellgallery.com\/\" rel=\"nofollow\">PowerShell Gallery<\/a>\u00a0using the command<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre>Install-Module WindowsCompatibility<\/pre>\n<\/div>\n<p>and the source code is available on\u00a0<a href=\"https:\/\/github.com\/PowerShell\/WindowsCompatibility\">GitHub<\/a>. (This is where you should open issues or make suggestions.)<\/p>\n<p>Once you have\u00a0<code>WindowsCompatibility<\/code>\u00a0installed, you can start using it. The first thing you might want to run is\u00a0<code>Get-WinModule<\/code>\u00a0which will show you the list of available modules. From that list, choose a module, say\u00a0<code>PKI<\/code>\u00a0and and load it. To do this, run the following command:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre>Import-WinModule PKI<\/pre>\n<\/div>\n<p>and you\u2019ll have the commands exported by the\u00a0<code>PKI<\/code>\u00a0module in your local session. You can run them just like any other command. For example:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre>New-SelfSignedCertificate -DnsName localhost<\/pre>\n<\/div>\n<p>As always, you can see what a module exported by doing:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre>Get-Command -module PKI<\/pre>\n<\/div>\n<p>just like any other module.<\/p>\n<p>These are the most important commands but the\u00a0<code>WindowsCompatibility<\/code>\u00a0module provides some others:<\/p>\n<ul>\n<li><code>Invoke-WinCommand<\/code>\u00a0allows you to invokes a one-time command in the compatibility session.<\/li>\n<li><code>Add-WinFunction<\/code>\u00a0allows you to define new functions that operate implicitly in the compatibility session.<\/li>\n<li><code>Compare-WinModule<\/code>\u00a0lets you compare what you have against what\u2019s available.<\/li>\n<li><code>Copy-WinModule<\/code>\u00a0will let you copy Window PowerShell modules that are known to work in PowerShell 6 to the PowerShell 6 command path.<\/li>\n<li><code>Initialize-WinSession<\/code>\u00a0gives you more control on where and how the compatibility session is created. For example. it will allow you to place the compatibility session on another machine.<\/li>\n<\/ul>\n<p>(See the module\u2019s command help for more details and examples on how to use the\u00a0<code>WindowsCompatibility<\/code>\u00a0functions.)<\/p>\n<h2><a id=\"user-content-how-it-works\" class=\"anchor\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/11\/15\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/#how-it-works\"><\/a>How It Works<\/h2>\n<p>The\u00a0<code>WindowsCompatibility<\/code>\u00a0module takes advantage of the \u2018<a href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2013\/09\/08\/remoting-the-implicit-way\/\" rel=\"nofollow\">Implicit Remoting<\/a>\u2018 feature that has been available in PowerShell since version 2. Implicit remoting works by retrieving command metadata from a remote session and synthesizing proxy functions in the local session. When you call one of these proxy function, it takes all of the parameters passed to it and forwards them to the real command in the \u201cremote\u201d session. Wait a minute you may be thinking \u2013 what does remoting have to do with the\u00a0<code>WindowsCompatibility<\/code>\u00a0module?\u00a0<code>WindowsCompatibility<\/code>\u00a0automatically creates and manages a \u2018local remote\u2019 session, called the \u2018compatibility session\u2019 that runs with Windows PowerShell on the local machine. It imports the specified module and then creates local proxy functions for all of commands defined in that module.<\/p>\n<p>OK \u2013 what about modules that exist in both Windows PowerShell and PowerShell core? Yes \u2013 you can import them. After all, there are still a fair number of base cmdlets that aren\u2019t available in PowerShell core yet.<\/p>\n<p>So how does this work?\u00a0<code>WindowsCompatibility<\/code>\u00a0is very careful to not overwrite native PowerShell core commands. It only imports the ones that are available with Windows PowerShell but not with PowerShell Core. For example, the following will import the PowerShell default management module<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre> Import-WinModule Microsoft.PowerShell.Management<\/pre>\n<\/div>\n<p>which contains, among others, the\u00a0<code>Get-EventLog<\/code>\u00a0cmdlet. None of the native PowerShell Core cmdlets get overwritten but now you have\u00a0<code>Get-EventLog<\/code>\u00a0available in your session.<\/p>\n<p>At this point, if you call\u00a0<code>Get-Module<\/code>, you will see something a bit strange:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre>Get-Module | ForEach-Object Name<\/pre>\n<\/div>\n<p>results in output that looks like:<\/p>\n<pre><code>Microsoft.PowerShell.Management\r\nMicrosoft.PowerShell.Management.WinModule\r\nMicrosoft.PowerShell.Utility\r\nNetTCPIP\r\n<\/code><\/pre>\n<p><code>Import-WinModule<\/code>\u00a0renames the compatibility module at load time to prevent collisions with identically named modules. This is so the module qualified commands will resolve against the current module. In fact, if you want to see what additional commands were imported, you can run:<\/p>\n<div class=\"highlight highlight-source-powershell\">\n<pre>Get-Command -Module  Microsoft.PowerShell.Management.WinModule<\/pre>\n<\/div>\n<h2><a id=\"user-content-limitations\" class=\"anchor\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/11\/15\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/#limitations\"><\/a>Limitations<\/h2>\n<p>Because\u00a0<code>WindowsCompatibility<\/code>\u00a0is based on implicit remoting, there are a number of significant limitations on the cmdlets imported by the module. First, because everything is done using the remoting protocol, the imported cmdlets will return deserialized objects that only contain properties. Much of the time, this won\u2019t matter because the parameter binder binds by property name rather than by object type. As long as the required properties are present on the object, it doesn\u2019t matter what type the object actually is. There are, however, cases where the cmdlet actually requires that the object be of a specific type or that it have methods.\u00a0<code>WindowsCompatibility<\/code>\u00a0won\u2019t work for these cmdlets.<\/p>\n<h3><a id=\"user-content-windows-forms-and-other-graphical-tools\" class=\"anchor\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/11\/15\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/#windows-forms-and-other-graphical-tools\"><\/a>Windows Forms and other graphical tools<\/h3>\n<p>The remoting session is considered non-interactive so graphical tools such as notepad or Winforms scripts will either fail, or worse hang.<\/p>\n<h3><a id=\"user-content-linux-and-mac-support\" class=\"anchor\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/11\/15\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/#linux-and-mac-support\"><\/a>Linux and Mac support<\/h3>\n<p>This module depends on WinRM and the client libraries on these platforms are known to be unstable and limited. So for this release, only PowerShell Core running on Windows is supported. (This may change in the future. But you\u2019ll still need a Windows machine with Windows PowerShell to host the compatibility session.)<\/p>\n<h3><a id=\"user-content-powershell-61-dependency\" class=\"anchor\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/11\/15\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/#powershell-61-dependency\"><\/a>PowerShell 6.1 Dependency<\/h3>\n<p><code>WindowsCompatibility<\/code>\u00a0depends on a feature introduced in PowerShell Core 6.1 for keeping the current working directory in both the local and compatibility sessions synchronized. Earlier versions of PowerShell will work with\u00a0<code>WindowsCompatibility<\/code>\u00a0but won\u2019t have this directory synchronization feature. So if you\u2019re running PowerShell Core 6.0, import a command that writes to files, do\u00a0<code>Set-Location<\/code>\u00a0to a new directory, then use that command to write to a file with an unqualified path; it will use the original path from when the module was imported rather than your sessions current working directory. On PowerShell Core 6.1, it will correctly use the current working directory.<\/p>\n<h2><a id=\"user-content-summary\" class=\"anchor\" href=\"https:\/\/blogs.msdn.microsoft.com\/powershell\/2018\/11\/15\/announcing-general-availability-of-the-windows-compatibility-module-1-0-0\/#summary\"><\/a>Summary<\/h2>\n<p>To sum it all up, the\u00a0<code>WindowsCompatibility<\/code>\u00a0module provides a set of commands that allow you to access Window PowerShell modules from PowerShell Core 6. There are however, some limitations that make it unsuitable for all scenarios. Over time, as more and more modules are ported to .NET Core\/PowerShell 6 natively there will be less need for this module.<\/p>\n<p>Cheers!\nBruce Payette,\nPowerShell Team.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Announcing General Availability of the Windows Compatibility Module 1.0.0 The Windows Compatibility module (WindowsCompatibility) is a PowerShell module that lets PowerShell Core 6 scripts access Windows PowerShell modules that are not yet natively available on PowerShell Core. (Note: the list of unavailable commands is\u00a0getting smaller\u00a0with each new release of PowerShell Core. This module is just [&hellip;]<\/p>\n","protected":false},"author":881,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-14470","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell"],"acf":[],"blog_post_summary":"<p>Announcing General Availability of the Windows Compatibility Module 1.0.0 The Windows Compatibility module (WindowsCompatibility) is a PowerShell module that lets PowerShell Core 6 scripts access Windows PowerShell modules that are not yet natively available on PowerShell Core. (Note: the list of unavailable commands is\u00a0getting smaller\u00a0with each new release of PowerShell Core. This module is just [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/14470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/881"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=14470"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/14470\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=14470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=14470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=14470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}