PowerShellGet Install and Import Module

on Friday, July 25, 2014

WMF v5.0 Preview’s PowerShellGet module is pretty nice, but it is lacking some functionality. Today I went through and added two new features: Install-Module also Imports module and NuGet.exe is now located with the module.

Install-Module Also Imports the Module

… even when it doesn’t install the module, it still imports the module. This allows for all Import-Module statements to be replaced with Install-Module statements.

PSGet had this feature, and that made it just a little more user friendly. But, I also think I understand why Microsoft didn’t implement this feature. It seems to complicate the lifecycle of when to Update the modules. How do you answer these questions:

  • If the current version on the gallery is newer than the installed version, should the installed version be updated?
  • If Install-Module replaces the usage of Import-Module how does the management of which versions are on which servers play out? Does it break Server Management consistency?

I choose to ignore those concerns, and I’ll circle back to them at a later date. For now, it can replace the Import-Module statement.

NuGet.exe is now located with the Module

There were actually 3 updates with this one:

  • NuGet.exe is no longer downloaded to %UserAppData%\Local\Microsoft\Windows\PowerShell\PowerShellGet\NuGet.exe. It’s now downloaded to %ProgramFiles%\WindowsPowerShell\Modules\PowerShellGet. The same location as the rest of the module.
  • A default NuGet.config is installed to the same location if it doesn’t exist.
  • The prompt which asks if you want to download NuGet.exe has been removed.

If NuGet.exe is downloaded into a user specific folder, then it has to download it for every user which runs Install-Module. Since PowerShell scripts can be run by both privileged users and by service accounts on a server, this made for multiple copies.

And, a default NuGet.config file lowers the cost on new users to find the config file and update it.

 

Since I’m starting to work on these enhancements, I’ll try to keep this community feed updated with stable builds on a weekly basis. (It doesn’t have the latest at the time of this posting, my apologizes.)

Custom IIS log files with PowerShell

on Friday, June 27, 2014

Depending on your infrastructure you may have a need to place IIS logs onto a separate disk. A disk which can fill up without taking down the server. The easiest solution to this is to set the Default Site Settings with log file locations other than the C: drive. But, then you still run into the problem of each log file being written under a folder with a name like W3SVC12.

The name W3SVC12 corresponds with the website which has SiteID 12. Unfortunately, you can only find out that information if you have access to IIS manager. And, most developers don’t have access to IIS manager on the production servers. So, it would be nice to give the log files a location with a more friendly name.

I’m sure there’s an appcmd which can setup both IIS log files and Failed Request Tracing log files for an individual website. But, in this post, I’ll show the few commands needed to setup those locations by directly editing the applicationHost.config file.

When an individual website is setup with custom IIS log file and Failed Request Tracing log file locations, the applicationHost.config file will look like this:

<site name="unittest.dev.yoursite.com" id="15" serverAutoStart="true">
<application path="/">
  <virtualDirectory path="/" physicalPath="D:\AllContent\Websites\unittest.dev.yoursite.com\" />
 </application>
 <application path="/normal/childapp">
  <virtualDirectory path="/" />
 </application>
 <bindings>
  <binding protocol="http" bindingInformation="*:80:" />
 </bindings>
 <traceFailedRequestsLogging enabled="false" directory="D:\AllContent\logs\unittest.dev.yoursite.com\FailedReqLogFiles" />
 <logFile directory="D:\AllContent\logs\unittest.dev.yoursite.com\LogFiles" />
</site>

The two commands below create and remove those xml elements. The script will also use the name of the website when creating the log file location path.

<#
.SYNOPSIS
 Adds a specialized log folder and FRT folder. See ConvertTo-WebUriPaths to create a $UriPaths Hashtable.

.EXAMPLE
 New-WebAppLogFile -UriPaths $paths

#>
Function New-WebAppLogFile {
Param (
 [Parameter(Mandatory = $true)]
 [Hashtable]$UriPaths,
 [string]$PhysicalPath = "",
 [string]$ServerName = $env:COMPUTERNAME
)
Process {
 # if the web application can't be found, then skip
 $configPath = Get-WebConfigPath $ServerName;
 $appHost = [System.Xml.XmlDocument](Read-WebConfig -ConfigPath $configPath);
 $sites = $appHost.configuration.'system.applicationHost'.sites;
 $site = [System.Xml.XmlElement]($sites.site |? { $_.name -eq $UriPaths.SiteName });
 if($site -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) couldn't be found. The log and FRT paths will be skipped.";
  return;
 }

 # get the physical path
 $rootLogsPath = $PhysicalPath;
 if($rootLogsPath -eq "") {
  $rootLogsPath = Join-Path $global:WebAdministrationUcsb.DefaultLogPath $UriPaths.SiteName;
 }
 $frtPath = Join-Path $rootLogsPath "FailedReqLogFiles";
 $logPath = Join-Path $rootLogsPath "LogFiles";

 # add the FRT location
 $frt = [System.Xml.XmlElement]($appHost.CreateElement("traceFailedRequestsLogging"));
 $frt.SetAttribute("enabled", "false");
 $frt.SetAttribute("directory", $frtPath);
 $frt = $site.AppendChild($frt);
 
 Write-Warning "IIS $ServerName - Adding custom FRT path for $($UriPaths.SiteName) to $frtPath.";
 Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
 Write-Host "IIS $ServerName - Added custom FRT path for $($UriPaths.SiteName) to $frtPath.";

 # add the log location
 $log = [System.Xml.XmlElement]($appHost.CreateElement("logFile"));
 $log.SetAttribute("directory", $logPath);
 $log = $site.AppendChild($log);
 
 Write-Warning "IIS $ServerName - Adding custom log file path for $($UriPaths.SiteName) to $logPath.";
 Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
 Write-Host "IIS $ServerName - Added custom log file path for $($UriPaths.SiteName) to $logPath.";
}
}


<#
.SYNOPSIS
 Remove a specialized log folder and FRT folder. See ConvertTo-WebUriPaths to create a $UriPaths Hashtable.

.EXAMPLE
 Remove-WebAppLogFile -UriPaths $paths
#>
Function Remove-WebAppLogFile {
Param (
 [Parameter(Mandatory = $true)]
 [Hashtable]$UriPaths,
 [string]$ServerName = $env:COMPUTERNAME
)
Process {
 # if the web application can't be found, then skip
 $configPath = Get-WebConfigPath $ServerName;
 $appHost = Read-WebConfig -ConfigPath $configPath;
 $sites = $appHost.configuration.'system.applicationHost'.sites;
 $site = $sites.site |? { $_.name -eq $UriPaths.SiteName };
 if($site -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) couldn't be found. The log and FRT path removal will be skipped.";
  return;
 }

 # remove the FRT location
 $frt = $site.traceFailedRequestsLogging
 if($frt -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) doesn't have a custom FRT path. Skipping its removal.";
 } else {
  $frt = $site.RemoveChild($frt)

  Write-Warning "IIS $ServerName - Removing custom FRT path from $($UriPaths.SiteName).";
  Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
  Write-Host "IIS $ServerName - Removed custom FRT path from $($UriPaths.SiteName).";
 }

 # remove the log location
 $log = $site.logFile
 if($log -eq $null) {
  Write-Warning "IIS $ServerName - Web site $($UriPaths.SiteName) doesn't have a custom log file path. Skipping its removal.";
 } else {
  $log = $site.RemoveChild($log)

  Write-Warning "IIS $ServerName - Removing custom log file path from $($UriPaths.SiteName).";
  Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
  Write-Host "IIS $ServerName - Removed custom log file path from $($UriPaths.SiteName).";
 }
}
}

These commands rely on the Read-WebConfig and Save-WebConfig from an earlier post.

Enable an Application Server on all Web Farms

on Friday, June 20, 2014

Last time, I looked at Enabling/Disabling an Application Server within a single Web Farm. I’ll try to continue on that same thread and update the script to Enable or Disable an Application Server on all Web Farms on a Proxy Server.

The core of the work is done by searching for all web farms which use the server, Get-WebFarmsByAppServer. After that, it’s just a matter of calling a mass update function, Set-WebFarmsAppServerEnabled.

<#
.SYNOPSIS
 Retrieves a list of all Web Farms which contain the given list of App Servers on the given Proxy Server.

 This is used to retrieve the list of Web Farms which will need to up updated in order to remove a single
 server from all Web Farms at once.

 The resulting list will be of type [System.Collections.Generic.List[PSObject]]. The 
 inner PSObject's will have these properties:

 WebFarmName The name of the web farm which has the given App Server in its list
 AppServerName The search will look for both shorthand names (App1) and FQDN's (App1.your.domain.here), this
   will have the value which was matched
 Enabled  Is the server currently enabled.

.PARAMETER ServerName
 The name of the proxy server to update. If this parameter is not supplied, the local computers config
 file will be updated.

.PARAMETER AppServerNames
 The name of the App Servers to search for.

.EXAMPLE
 Get-WebFarmsByAppServer -ServerName "Proxy1" -AppServerNames "App1"
#>
Function Get-WebFarmsByAppServer {
Param (
 [string] $ServerName = $env:COMPUTERNAME,
 [Parameter(Mandatory = $true)]
 [System.Array] $AppServerNames
)
 $configPath = Get-WebConfigPath $ServerName
 $appHost = [System.Xml.XmlDocument](Read-WebConfig -ConfigPath $configPath)

 $farms = $appHost.configuration.webFarms.webfarm;

 # if there are no web farms defined, write a warning and return an empty array
 if($farms -eq $null) {
  Write-Warning "IIS Proxy $ServerName - No web farms are currently defined."
  return @();
 }

 # determine search values, check if an fqdn might also be possible value to search on
 $searchValues = New-Object System.Collections.Generic.List[string]
 $AppServerNames |% { $searchValues.Add($_); }

 <# You could add a check for Fully Qualified Domain Names along with the supplied values
 $AppServerNames |% {
  $isFqdn = $_ -match "\.your\.domain\.here"
  if($isFqdn -eq $false) {
   $fqdn = $_ + ".your.domain.here"
   try {
    $result = [System.Net.Dns]::GetHostAddresses($fqdn);

    $searchValues.Add($fqdn);
   } catch {}
  }
 }
 #>

 # search for all occurrences in the web farm list
 $found = New-Object System.Collections.Generic.List[PSObject]
 for($i = 0; $i -lt $farms.Count; $i++) {
  $farm = $farms[$i];

  $servers = New-Object System.Collections.Generic.List[System.Xml.XmlElement]
  $serverlist = $farm.server;
  $serverlist |% { $servers.Add($_); }

  for($j = 0; $j -lt $servers.Count; $j++) {
   $server = $servers[$j];

   $searchValues |% {
    if($server.address.ToLower() -eq $_.ToLower()) {
     # http://stackoverflow.com/questions/59819/how-do-i-create-a-custom-type-in-powershell-for-my-scripts-to-use
     $m = new-object PSObject
     $m.PSObject.TypeNames.Insert(0,'WebAdministrationExt.WebFarmAppServerMatch')

     $m | add-member -type NoteProperty -Name WebFarmName -Value $farm.Name
     $m | add-member -type NoteProperty -Name AppServerName -Value $server.Address
     $m | add-member -type NoteProperty -Name Enabled -Value $server.Enabled
     
     $found.Add($m);
    }
   }
  }
 }

 # return the list
 return $found;
}


<#
.SYNOPSIS
 Set the given list of AppServers to be enabled/disabled in all Web Farms on the Proxy Server.

 TODO: This could probably be updated to handle pipeline input

.PARAMETER ServerName
 The name of the proxy server to update. If this parameter is not supplied, the local computers config
 file will be updated.

.PARAMETER AppServerNames
 The name of the App Servers to set to enabled/disabled.

.PARAMETER Enabled
 Set the server to enabled or disabled.

.EXAMPLE
 $updatedFarms = Set-WebFarmsAppServerEnabled -ServerName "Proxy1" -AppServerNames "App1" -Enabled $false
#>
Function Set-WebFarmsAppServerEnabled {
[CmdletBinding()]
Param (
 [string] $ServerName = $env:COMPUTERNAME,
 [Parameter(Mandatory = $true)]
 [System.Array] $AppServerNames,
 [Parameter(Mandatory = $true)]
 [bool] $Enabled
)

 $farms = Get-WebFarmsByAppServer -ServerName $ServerName -AppServerNames $AppServerNames

 # if no farms we're found, then skip this
 if($farms -eq $null) {
  Write-Warning "IIS Proxy $ServerName - No web farms we're found which use $AppServerNames. Skipping setting the App Servers to $Enabled."
  return;
 }

 # set the servers to the desired values
 for($i = 0; $i -lt $farms.Count; $i++) {
  $farm = $farms[$i];

  # NOTE: SkipLoadBalancingDelay is set to true because it incurs a 10 second delay for each update. That could
  # be a long time for large updates. The LoadBalancingDelay was introduced to handle web deployments, this
  # function is expected to be used with Windows Server updates (Windows Servers updates will have a delay built into them).
  Set-WebFarmServerEnabled -ServerName $ServerName `
   -WebFarmName $farm.WebFarmName -AppServerName $farm.AppServerName -Enabled $Enabled `
   -SkipLoadBalancingDelay $true
 }

 return $farms;
}

Add / Remove Web Farm Server

on Friday, June 6, 2014

Here’s a couple of PowerShell functions to enable and disable a web farm server on IIS 7+. They work directly with the applicationHost.config file so they aren’t dependent on any particular version of IIS. This also means that they can be used to update remote IIS installations.

Sorry for the misleading title, but it’s better to enable/disable a web farm server rather than add/remove it. When you remove a server from a web farm any requests currently being processed by it will be lost. When disabling the server, the hanging requests will finish processing.

<#
.SYNOPSIS
Checks if an application server is listed in web farm. And, if it is, is it enabled.

Used to check if a server is 'enabled' on a web farm.
>
Function Test-WebFarmServerEnabled {
[CmdletBinding()]
Param(
[string]$ProxyServerName = $env:COMPUTERNAME,
[Parameter(Mandatory = $true)]
[string]$WebFarmName,
[Parameter(Mandatory = $true)]
[string]$AppServerName
)
$configPath = Get-WebConfigPath $ProxyServerName
$appHost = Read-WebConfig -ConfigPath $configPath

$webFarm = $appHost.configuration.webFarms.webFarm |? {$_.name -eq $WebFarmName}
$webFarmServer = $webFarm.server |? {$_.address -eq $AppServerName}

$enabled = [System.Convert]::ToBoolean($webFarmServer.enabled);
return $enabled;
}

<#
.SYNOPSIS
Sets an application server in a web farm to either enabled or disabled. By setting the -Enabled
parameter the server will be enabled. If the parameter is missing the server will
be disabled.

Use when enabling or disabling servers in a web farm. This doesn't actually add or
remove a server to a web farm.

.EXAMPLE
To enable, set the -Enabled parameter to $true

Set-WebFarmServerEnabled -ProxyServerName "WebProxy1" -WebFarmName "WebFarm-Dev" `
-AppServerName "WebApp1" -Enabled $true

.EXAMPLE
To disable set the -Enabled parameter to $false

Set-WebFarmServerEnabled -ProxyServerName "WebProxy1" -WebFarmName "WebFarm-Dev" `
-AppServerName "WebApp1" -Enabled $false
>
Function Set-WebFarmServerEnabled {
[CmdletBinding()]
Param(
[string] $ProxyServerName = $env:COMPUTERNAME,
[Parameter(Mandatory = $true)]
[string] $WebFarmName,
[Parameter(Mandatory = $true)]
[string] $AppServerName,
[Parameter(Mandatory = $true)]
[bool] $Enabled,
[bool] $SkipLoadBalancingDelay = $false
)
$configPath = Get-WebConfigPath $ProxyServerName
$appHost = Read-WebConfig -ConfigPath $configPath

$webFarm = $appHost.configuration.webFarms.webFarm |? {$_.name -eq $WebFarmName}
$webFarmServer = $webFarm.server |? {$_.address -eq $AppServerName}

if($Enabled) {
$value = "true";
} else {
$value = "false";
}
$webFarmServer.enabled = $value;

Write-Warning "Updating Proxy $ProxyServerName - Setting webfarm $WebFarmName's server $AppServerName to enabled='$value'"
Save-WebConfig -WebConfig $appHost -ConfigPath $configPath
Write-Host "Updated Proxy $ProxyServerName - Setting webfarm $WebFarmName's server $AppServerName to enabled='$value'"

if($SkipLoadBalancingDelay -eq $false) {
Write-Warning "Waiting 10 seconds to let the proxy server handle any hanging requests or start load balancing"
Start-Sleep 10;
}
}

Get-WebConfigPath, Read-WebConfig, and Save-WebConfig are described in this previous post.

Background

In IIS 7 there were Web Farm PowerShell Cmdlets. There was a separate package for them because in IIS 7 the Web Farm Framework (WFF) was a separate package.

In IIS 8, WFF became integrated into Application Request Routing, but the PowerShell Cmdlet’s didn’t get integrated into the WebAdministration module. Nor, was there a separate PowerShell module made for ARR.

It also wasn’t possible to use the IIS 7 PowerShell Cmdlets on IIS 8 because they called a particular set of dlls that were installed by IIS 7’s Web Farm Framework. Those dlls were integrated into other packages and aren’t available on IIS 8.

applicationHost.Config Backups and Updates

on Friday, May 30, 2014

IIS’s applicationHost.config is almost never stored in version control. Yet, it’s often updated to add new sites, ARR rules, and special configurations. There are a variety of ways to update the config: IIS Manager, appcmd.exe, PowerShell/WebAdministration, and editing the file by hand.

In general editing the .config file is pretty safe, with a low risk of affecting functionality on one website when updating a different website. But, it’s always nice to

  • have a backup
  • have an audit trail of updates

This PowerShell function can make a quick backup of the applicationHost.config file, with information on who was running the backup, and when it was run.

$global:WebAdministrationExt = @{}

# Used by unit tests. We run the unit tests so often, the backups can really grow in size. Most
# unit tests should turn off the backups by default; but the unit tests which actually test the
# backup functions turn it back on.
$global:WebAdministrationExt.AlwaysBackupHostConfig = $true;

<#
.SYNOPSIS
Saves an backup of an xml config file. The purpose is to ensure a backup gets
made before each update to an applicationHost.config or web.config.

Used by the Save-WebConfig function to ensure a backup gets made.
#>
Function Backup-WebConfig {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$ConfigPath
)
Process {
if($global:WebAdministrationExt.AlwaysBackupHostConfig -eq $false) {
Write-Warning ("Global:WebAdministrationExt.AlwaysBackupHostConfig has been set to false. " +
"Skipping backup of $configPath");
return $null;
}

if([System.IO.File]::Exists($ConfigPath) -eq $false) {
throw "Backup-WebConfig: No file to read from, at path $ConfigPath, could be found."
}

$fileInfo = (Get-ChildItem $ConfigPath)[0];
$basePath = Split-Path $fileInfo.FullName;
$filename = $fileInfo.Name;
$timestamp = Get-TimeStamp;
$appendString = "." + $env:UserName + "." + $timestamp;

$i = 0;
$backupPath = Join-Path $basePath ($filename + $appendString + ".bak");
while(Test-Path $backupPath) {
$i++;
$backupPath = Join-Path $basePath ($filename + $appendString + "-" + $i + ".bak");
}

Write-Warning "Backing up $ConfigPath to $backupPath"
Copy-Item $ConfigPath $backupPath
Write-Host "Backed up $ConfigPath to $backupPath"

return $backupPath
}
}

As long as there is now a backup function in PowerShell, might as well round out the suite with a Read and Save function for applicationHost.config.

In the Read function I’ve chosen to not preserve whitespace. Initially I was preserving whitespace to ensure the file stayed 'readable'. But, once I started adding in new xml elements using PowerShell, those new elements were very unreadable and causing weird new line issues wherever they were added. PowerShell’s xml functionality will preserve comments, and if you set the XmlWriter’s IndentChars property to something better than 2 spaces (like a tab) then the applicatHost.config file will stay very readable while avoiding the new xml element problem.


<#
.SYNOPSIS
Saves an xml config file. The purpose is to keep the logic for setting
up formatting to be the same way all the time.

Used to store applicationHost.config file updates.
#>
Function Save-WebConfig {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[xml]$WebConfig,
[Parameter(Mandatory = $true)]
[string]$ConfigPath
)
Process {
# First backup the current config
Backup-WebConfig $ConfigPath

# Set up formatting
$xwSettings = New-Object System.Xml.XmlWriterSettings;
$xwSettings.Indent = $true;
$xwSettings.IndentChars = " "; # could use `t
$xwSettings.NewLineOnAttributes = $false;

# Create an XmlWriter and save the modified XML document
$xmlWriter = [Xml.XmlWriter]::Create($ConfigPath, $xwSettings);
$WebConfig.Save($xmlWriter);
$xmlWriter.Close();
}
}

<#
.SYNOPSIS
Load an xml config file. The purpose is to keep the logic for setting
up formatting to be the same way all the time.

Used to load applicationHost.config files.
#>
Function Read-WebConfig {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$ConfigPath
)
Process {
[xml]$appHost = New-Object xml
#$appHost.psbase.PreserveWhitespace = $true
$appHost.Load($ConfigPath)
return $appHost;
}
}

There is almost always a reason to have PowerShell enter new xml elements into the applicationHost.config. Both IIS Manager and appcmd.exe have limitations that can only be overcome by hand editing the file or scripting the update in PowerShell (or .NET).

But when creating PowerShell functions to add new elements, it’s always nice to be able to unit test the code before using it on your servers. So, you can make a function which will get the location of an applicationHost.config file. That function can be overridden during a unit test to use a dummy file. This code snippet uses an example of how the unit tests could be used with the serviceAutoStartProviders.


# Used by unit tests. If a value is supplied here, then it will always be returned by Get-WebConfigPath
$global:WebAdministrationExt.ApplicationHostConfigPath = "";

<#
.SYNOPSIS
Contains the logic to get the path to an applicationHost.config file.

Used to allow for a config file path to be overloaded during unit tests.
#>
Function Get-WebConfigPath {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]$ServerName
)
Process {
if($global:WebAdministrationExt.ApplicationHostConfigPath -ne "") {
return $global:WebAdministrationExt.ApplicationHostConfigPath;
}

$configDir = "\\$ServerName\C$\Windows\System32\inetsrv\config"
$configPath = "$configDir\applicationHost.config"
return $configPath;
}
}

# Example usage
$global:WebAdministrationExt.ApplicationHostConfigPath = "C:\Modules\WebAdministrationExt\applicationHost.UnitTest.config";
$global:WebAdministrationExt.AlwaysBackupHostConfig = $false;

$providerName = Get-Random
Set-AutoStartProvider -SiteName "unittest.local.frabikam.com" -AutoStartProvider $providerName;
Get-AutoStartProvider -SiteName "unittest.local.frabikam.com" | Should Be $providerName;

$global:WebAdministrationExt.ApplicationHostConfigPath = "";
$global:WebAdministrationExt.AlwaysBackupHostConfig = $true;

PowerShellGet with Multiple Source Repositories

on Monday, May 26, 2014

The PowerShell Team added the PowerShellGet module in the May 2014 update to the v5.0 Preview. This created an official Microsoft repository for pulling in the latest modules. But, it also allowed for companies and teams to setup their own internal repositories. The PowerShell Team put together a post on how to setup a MyGet repository with just a few keystrokes.

The ability to have a private repository for your team is great. What would make it even better is if you could have multiple repositories that are all searched and used when Finding and Installing modules.

Internally, PowerShellGet uses NuGet to handle package management. Which is a wonderful thing. It’s a great product and has been used by other projects like MyGet and Chocolatey without any problems.

However, there was one little problem. The PowerShell Team didn’t want to have any conflicts with updates or end user configurations with their normal NuGet installations. Because of this, PowerShellGet downloads a separate installation of NuGet.exe and only allows for one repository to be used at a time. That repository is defined by the variable $PSGallerySourceUri. How could it be updated to work more like ‘normal’ NuGet and handle multiple repositories?

With a little bit of updating to the internal PSGallery.psm1 file, you can now get an updated version of PowerShellGet which can handle both a NuGet.Config file and multiple repositories defined within the $PSGallerySourceUri variable.

The module can be found with:

$PSGallerySourceUri = “https://www.myget.org/F/smaglio81-psmodule/api/v2

I think you should be cautious about using it as I set it up only to ask for the functionality to be added by the PowerShell Team. I don’t really have long term plans of maintaining it.

Source Code: https://github.com/smaglio81/powershellget

Two other things to look at with private repositories:

Using PowerShellGet on Win7

on Friday, May 23, 2014

The Windows Management Framework 5.0 Preview May 2014 contains a new module, PowerShellGet. The management framework has a requirement of at least Windows 8.1. But, the module itself only has PowerShell requirement of 3.0. So, it can run successfully on Windows 7.

If you have access to Windows Azure, then you have a quick and easy way to get the module without the problem of upgrading to Windows 8.1. Using Windows Azure, you can create a quick Windows 8.1 machine using the Visual Studio 2013 Update 2 image.

image

Once the machine is up and running, you can connect with Remote Desktop. After installing WMF 5.0, the virtual machine will have the module under C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PowerShellGet. Copy that folder down to your local Windows 7 installation and you should be ready to use it.

image

image


Creative Commons License
This site uses Alex Gorbatchev's SyntaxHighlighter, and hosted by herdingcode.com's Jon Galloway.