Copying a File from Within a Remote Powershell Session

Recently I needed a way to copy a certificate file from within a PowerShell session to another Windows machine without opening a nested PowerShell session.

Here’s my setup:

  • A Windows 10 laptop, from which I’m remoting
  • NC1, a Server 2016 virtual machine I’m remoted into. It’s a member of a domain.
  • HYPERV1, the Server 2016 machine I want to copy a certificate file to. It’s not a member of a domain.

I execute all of the following commands on NC1, the VM I’m remoted into.

Here’s the first thing I tried. The HYPERV1 machine is not a member of a domain, so the following doesn’t work:
$ Copy-Item .\nccert.cer \\hyperv1\c$
Access is denied
+ CategoryInfo          : NotSpecified: (:) [Copy-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.CopyItemCommand

What about specifying the -Credential parameter? That doesn’t work either.
$ Copy-Item .\nccert.cer \\hyperv1\c$ -Credential hyperv1\administrator
The FileSystem provider supports credentials only on the New-PSDrive cmdlet. Perform the operation again without specifying credentials.
+ CategoryInfo          : NotImplemented: (:) [], PSNotSupportedException
+ FullyQualifiedErrorId : NotSupported

And that error pretty much tells me what I need to do: use the New-PSDrive cmdlet!
$ New-PSDrive -Name H -PSProvider FileSystem -root \\hyperv1\c$ -Credential hyperv1\administrator
$ Copy-Item .\nccert.cer h:\
$ Remove-PSDrive -Name H

Building Windows Server with Puppet and Chocolatey

Forget using scripts and group policies to configure a new Windows Server machine. Using Chocolatey and Puppet, you can do it faster & easier than ever (and it’s more fun too). This is especially true if you’re using a Server Core installation and don’t have a GUI to help you along. Oh, and if you don’t know Puppet, you really should watch my course Puppet Fundamentals for System Administrators on Pluralsight 🙂

Assign IP address using PowerShell:

$ New-NetIPAddress –InterfaceAlias "Ethernet" –IPAddress "192.168.51.29" –PrefixLength 24 -DefaultGateway 192.168.51.8

$ Set-DnsClientServerAddress -InterfaceAlias “Ethernet” -ServerAddresses 192.168.50.20, 192.168.50.21

Install Chocolatey:

$ set-executionpolicy unrestricted
$ iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))

Restart PowerShell

Install VMware tools

$ choco install vmware-tools

The server will automatically restart.

Rename server

$ rename-computer -newname newservername

Reboot

restart-computer

Join to domain
add-computer -domain benpiper.com

Reboot again
restart-computer

Install Puppet
choco install puppet

Configure Puppet
Configure c:\programdata\puppetlabs\puppet\etc\puppet.conf

Generate puppet certificate
puppet_interactive

Sign puppet certificate on puppet master
puppet cert sign newservername

Apply appropriate profiles to server. Remember to restart the Puppet master if you change your Hiera configuration.

Run Puppet agent
puppet_interactive

Verify
puppet resource dism
puppet resource package

Forcing Apps to Run in 32-bit mode in 64-bit Windows

Have you ever had an application that seemed to initially run fine under Windows x64, only to have it crash or complain when performing a certain function inside the app? I have noticed this in a couple of applications that hook into Crystal Reports to display reports inside the app. If you’ve run into this problem, take heart because the fix is really simple.

But first, it’s helpful to understand what happens when you run an application under 64-bit Windows. Some applications and libraries (DLLs) are compiled in such a way that they can run either as native 64-bit or 32-bit mode. Other applications and DLLs, however, can only run as 32-bit.

Let’s say you have an application that easily runs as a 64-bit app under Windows 2008 R2 (which is a 64-bit OS). No problem, right? But what if that app makes a call to a Crystal Reports DLL that is compiled only as a 32-bit DLL? Trouble! That’s what happens! The application will not be able to find the DLL. As far as the app is concerned, the DLL doesn’t exist.

To understand why, we must understand how Windows separates 32 and 64-bit components. Windows x64 stores 32-bit DLLs in the Windows\SysWoW64 folder, while 64-bit DLLs go in the Windows\System32 folder. That seems backwards, doesn’t it? But it gets even more counter-intuitive. When a 32-bit mode application runs under Windows x64 and wants a DLL from “c:\windows\system32”, Windows will “lie” to the app and give it the DLL from C:\windows\syswow64!

The flipside of this redirection scheme is that 64-bit apps are affected as well. 64-bit applications cannot see or access the Windows\SysWoW64 folder. They can only see Windows\System32. If an application installer places a 32-bit DLL in Windows\SysWoW64, then later a 64-bit application tries to call that DLL, it will simply fail because, to the application, that DLL doesn’t exist.

But what if we get sneaky and copy that 32-bit DLL to the System32 folder? Our 64-bit app will find the DLL, but it will not be able to load it into its memory space (For a technical explanation why, see Why can’t you thunk between 32-bit and 64-bit Windows?). Once again, the app will crash or yield an error.

So what is the solution? We just have to get the 64-bit app to run as a 32-bit application. This will allow the app to see the 32-bit DLLs in the Windows\SysWoW64 folder and load them into its memory space. We will lose some of the benefits of 64-bit execution, but at least the app will work properly. And fortunately, we don’t have to get the vendor to send us a recompiled executable. We can force the app to run as a 32-bit app by changing the execution headers using the Microsoft CorFlags utility. All you have to do is install the Microsoft Windows SDK and grab CorFlags.exe from the Bin folder of the SDK program files directory.

Then all you have to do is run:

CorFlags /32BIT+ application.exe

where application.exe is the application you want to force to run as 32-bit. The next time you execute the application, Windows will see the new header and will execute it as a 32-bit application.