El TecnoBaúl de Kiquenet

Kiquenet boring stories

Archive for the ‘PowerShell’ Category

Modify machine.config (config files) using Powershell

Posted by kiquenet en 22 enero 2015

ConfigurationManager

$config = [System.Configuration.ConfigurationManager]::OpenMachineConfiguration() 

"{0,-25}     {1,25}"  -f "   Name", "   Allow Definition"
"{0,-25}     {1,25}"  -f "   —-", "   —————-"
$i = 0 

foreach ($section in $config.Sections) 

     "{0,-25}     {1,25}" -f $section.SectionInformation.Name,$section.SectionInformation.AllowExeDefinition 
     $i++ 

"Total number of sections: {0}" -f $i

get-content and DocumentElement

$xml = [xml](get-content $machineConfig)
$xml.Save($machineConfig + "_$currentDate")
$root = $xml.get_DocumentElement()
$system_web = $root."system.web"
if ($system_web.machineKey -eq $nul) {
$machineKey = $xml.CreateElement("machineKey")
$a = $system_web.AppendChild($machineKey)
}
$system_web.SelectSingleNode("machineKey").SetAttribute("validationKey","$validationKey")
$system_web.SelectSingleNode("machineKey").SetAttribute("decryptionKey","$decryptionKey")
$system_web.SelectSingleNode("machineKey").SetAttribute("validation","$validation")
$a = $xml.Save($machineConfig)

XmlDocument

if (!$origXml.configuration.’system.serviceModel’.bindings)
{
    $tempXmlDoc = new-object System.Xml.XmlDocument
    $tempXmlDoc.LoadXml($newXml)
    $newNode = $origXml.ImportNode($tempXmlDoc.DocumentElement, $true)
    $origXml.configuration.’system.serviceModel’.AppendChild($newNode)
}

Sources:
http://sunauskas.com/blog/edit-config-file-with-powershell/
http://geekswithblogs.net/nharrison/archive/2011/05/25/updating-the-machine.config–with-powershell.aspx

http://pshscripts.blogspot.com.es/2009/02/get-machineconfig.html
http://jeffgraves.me/2012/06/05/read-write-net-machine-key-with-powershell/
http://stackoverflow.com/questions/10342657/how-can-i-add-a-section-to-a-web-config-using-powershell

Posted in PowerShell, Scripts | Etiquetado: , , | Leave a Comment »

Installing PowerShell Active Directory Module for Windows 8.1

Posted by kiquenet en 21 enero 2015

STEP 1.) Download and install Remote Server Administration Tools (RSAT) for Windows 8.1
http://www.microsoft.com/en-us/download/details.aspx?id=39296

STEP 2.) For x64, install Windows8.1-KB2693643-x64.msu

STEP 3.) Active Feature

Select AD DS and AD LDS Tools and then select Active Directory Module for Windows PowerShell.

To turn off specific tools

  1. On the desktop, hover in the upper right corner of the screen, and then click Settings.
  2. On the Desktop menu, click Control Panel.
  3. Click Programs, and then in Programs and Features, click Turn Windows features on or off.
  4. In the Windows Features dialog box, expand Remote Server Administration Tools, and then expand either Role Administration Tools or Feature Administration Tools.
  5. Clear the check boxes for any tools that you want to turn off. Click OK, and then close Control Panel.

STEP 4.)
Open a PowerShell prompt and type PS C:\> Get-Module –ListAvailable.

STEP 5.)

To ensure the Active Directory Module is present, using PowerShell type PS C:> Import-Module ActiveDirectory.

NOTE: You will need to do this for every PowerShell session.

If you wish to have the Active Directory Module automatically loaded any time you run PowerShell, prepare a shortcut with the following content: %windir%\system32\WindowsPowerShell\v1.0\powershell.exe -noexit -command import-module ActiveDirectory

STEP 6.)

PS C:> Get-ADGroupMember "MY CUSTOM GROUP IN AD" | select name

Appenders:

Installation and Uninstallation of MSU in silent mode
http://msiworld.blogspot.com.es/2012/04/silent-install-and-uninstall-of-msu.html

MSU are the Microsoft Update files.
You can easily install the MSU file silently without reboot with the following command line:
wusa.exe Windows6.1-KB123456-x86.msu /quiet /norestart
To Uninstall it Silently you need to follow this simple procedure:
1) Run this command:
expand c:\temp\Windows6.0-KB123456-x86.msu –F:Windows6.0-KB123456-x86.xml c:\temp
2) This will create an XML file in temp folder as per the name above.
Edit this xml in notepad.
3)Find the assemblyidentity tag. Then, note the values of the following attributes:

  • The name attribute
  • The publickeytoken attribute
  • The processArchitecture attribute
  • The version attribute

4) Use the below command to uninstall the MSU from your machine.
start /w pkgmgr /up:name~publickeytoken~processArchitecture~~version
Note: The variables above need to be replaced by the vaules you have copied in step 3.

Using powershell view http://powershell.org/wp/forums/topic/installing-msu-via-powershell-psexec/ and http://www.nigelboulton.co.uk/2011/01/installing-a-windows-hotfix-on-multiple-machines-using-a-powershell-script/#comment-23005 and http://randygray.com/powershell-install-multiple-windows-updates-msu/

Sources:

https://support.software.dell.com/es-es/appassure/kb/117489

Posted in PowerShell, Scripts | Etiquetado: , , , | Leave a Comment »

Arrays in Powershell

Posted by kiquenet en 9 enero 2015

Collections, Hashtables, Arrays, strings
https://www.simple-talk.com/sysadmin/powershell/powershell-one-liners–collections,-hashtables,-arrays-and-strings/

Define Array

$configs = @(

     "C:\tfs\Arquitectura\ConnectionStrings.config"; 
     "C:\tfs\VSIntegration\Test\App.config"; 
)

Foreach Array

for( $i = 0; $i -lt $configs.length; $i++) {
  $config = $configs[$i]
 
  Write-Host setting $config
 
}

Alternative

function ConvertTo-MyTypeOfItem
{
    PARAM (
        [ValidatePattern("([^_]+_){3}[^_]+")]
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$StringToParse
    )

    PROCESS {
        $custId, $invId, $prodId, [int]$value = $StringToParse -split "_"
        $myObject = New-Object PSObject -Property @{
            CustomerID = $custId;
            InvoiceID = $invId;
            ProductID = $prodId;
            Value = $value
        }
        Write-Output $myObject
    }
}

# In the test scenario I have replaced getting the list of files
# with an array of names. Just uncomment the first and second lines
# following this comment and remove the other $baseNames setter, to
# get the $baseNames from the file listing

#$files = Get-ChildItem test *.txt
#$baseNames = $files.BaseName
$baseNames = @(
    "cust1_inv1_prod1_1";
    "cust2_inv2_prod2_2";
    "cust3_inv3_prod3_3";
    "cust4_inv4_prod4_4";
)

$myObjectArray = $baseNames | ConvertTo-MyTypeOfItem

$myObjectArray

Sources:
http://stackoverflow.com/questions/21884828/powershell-array-to-store-strings
http://stackoverflow.com/questions/25191803/powershell-cli-foreach-loop-with-multiple-arrays
http://www.powershellpro.com/powershell-tutorial-introduction/variables-arrays-hashes/

Posted in PowerShell, Scripts | Etiquetado: , | Leave a Comment »

Members, Contributor, Groups, Identities in TFS

Posted by kiquenet en 5 enero 2015

Get members of TFS Group

private List<Identity> ListContributors()
{
    const string projectName = "<<TFS PROJECT NAME>>";
    const string groupName = "Contributors";
    const string projectUri = "<<TFS PROJECT COLLECTION OR URL TFS SERVER>>";

    TfsTeamProjectCollection projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(projectUri));
    ICommonStructureService css = (ICommonStructureService) projectCollection.GetService(typeof(ICommonStructureService));
    IGroupSecurityService gss = projectCollection.GetService<IGroupSecurityService>();

    // get the tfs project
    var projectList = css.ListAllProjects();
    var project = projectList.FirstOrDefault(o => o.Name.Contains(projectName));

    // project doesn’t exist
    if (project == null) return null;

    // get the tfs group
    var groupList = gss.ListApplicationGroups(project.Uri);
    var group = groupList.FirstOrDefault(o => o.DisplayName.Contains(groupName));  // you can also use DisplayName or AccountName. AccountName is empty for me.

    // group doesn’t exist
    if (group == null) return null;

    Identity sids = gss.ReadIdentity(SearchFactor.Sid, group.Sid, QueryMembership.Expanded);

    // there are no users
    if (sids.Members.Length == 0) return null;

    // convert to a list
    List<Identity> contributors = gss.ReadIdentities(SearchFactor.Sid, sids.Members, QueryMembership.Expanded).ToList();

    return contributors;
}

Add SID to a Readers group

# load the required dll
[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")

function get-tfs
{
    param(
    [string] $serverName = $(throw ‘serverName is required’)
    )

    $propertiesToAdd = (
        (‘VCS’, ‘Microsoft.TeamFoundation.VersionControl.Client’, ‘Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer’),
        (‘WIT’, ‘Microsoft.TeamFoundation.WorkItemTracking.Client’, ‘Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore’),
        (‘CSS’, ‘Microsoft.TeamFoundation’, ‘Microsoft.TeamFoundation.Server.ICommonStructureService’),
        (‘GSS’, ‘Microsoft.TeamFoundation’, ‘Microsoft.TeamFoundation.Server.IGroupSecurityService’)
    )

    [psobject] $tfs = [Microsoft.TeamFoundation.Client.TeamFoundationServerFactory]::GetServer($serverName)
    foreach ($entry in $propertiesToAdd) {
        $scriptBlock = ‘
            [System.Reflection.Assembly]::LoadWithPartialName("{0}") > $null
            $this.GetService([{1}])
        ‘ -f $entry[1],$entry[2]
        $tfs | add-member scriptproperty $entry[0] $ExecutionContext.InvokeCommand.NewScriptBlock($scriptBlock)
    }
    return $tfs
}
#set the TFS server url
[psobject] $tfs = get-tfs -serverName
http://YourTfsServer:8080/tfs/YourColleciton

$items = $tfs.vcs.GetAllTeamProjects( ‘True’ )
    $items | foreach-object -process {
    $proj = $_
    $readers = $tfs.GSS.ListApplicationGroups($proj.Name) | ?{$_.DisplayName -eq ‘Readers’ }

    $tfs.GSS.AddMemberToApplicationGroup($readers.Sid, ‘TheSidToTheGroupYouWantToAdd’)
}

var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://vsalm:8080/tfs/FabrikamFiberCollection"));

            var ims = tpc.GetService<IIdentityManagementService>();

            var tfsGroupIdentity = ims.ReadIdentity(IdentitySearchFactor.AccountName,
                                                    "[FabrikamFiber]\\Fabrikam Fiber Web Team",
                                                    MembershipQuery.None,
                                                    ReadIdentityOptions.IncludeReadFromSource);           

            var userIdentity = ims.ReadIdentity(IdentitySearchFactor.AccountName,
                                                    "VSALM\\Barry",
                                                    MembershipQuery.None,
                                                    ReadIdentityOptions.IncludeReadFromSource);

            ims.AddMemberToApplicationGroup(tfsGroupIdentity.Descriptor, userIdentity.Descriptor);

Sources:
http://stackoverflow.com/questions/16792995/get-members-of-tfs-group

http://stackoverflow.com/questions/7961727/how-to-grant-read-only-access-to-all-tfs-team-projects-to-a-group-of-users/7971731#7971731

http://blog.ronischuetz.com/2010/04/tfs-api-list-all-tfs-users.html

http://pauravlokesh.wordpress.com/2013/08/13/recursively-list-groups-users-tfsteamprojectcollection/

http://geekswithblogs.net/TarunArora/archive/2011/09/30/tfs-sdk-get-groups-users-permissions-using-tfs-api-with.aspx

Posted in .NET, PowerShell, Scripts, TFS | Etiquetado: , , | Leave a Comment »

Delete TestResults folder (Unit Testing Visual Studio)

Posted by kiquenet en 5 enero 2015

Cleaning up Visual Studio TestResults with PowerShell

If you write your unit tests using Visual Studio, then you know how quickly those pesky "TestResults" folders can eat up precious disk space over time.

Assuming all of your code is collocated in the same parent directory, replace "C:\TFS" with your parent directory.

(get-childitem C:\TFS\* -recurse) | where{$_.name -eq "TestResults"} |% {remove-item $_.fullname -recurse}

Improvements:

Error Handling when deleting folders and files.

Validating contents TestResults folder (subfolders In and Out, *.trx files, …)

$dir = "C:\TFS\"
(get-childitem $dir -recurse) | where { $_.name -eq "TestResults"} | foreach {

   $delete = $false;
   (get-childitem  $_.FullName -recurse) | where {$_.name -eq "Out"}  | foreach {
       
        $ParentS = ($_.Fullname).split("\")
        $Parent = $ParentS[@($ParentS.Length – 3)]
        if ($Parent -eq "TestResults") {$delete = $true;}

   }

   if ($delete)
   {
        Write-Host -ForegroundColor red ("Eliminando {0}" -f  $_.FullName )
        Remove-item $_.fullname -recurse
   }

}

Write-Host -ForegroundColor red ("Eliminado TestResults de {0}" -f  $dir )

Source:
http://captechconsulting.com/blog/mike-etheridge/cleaning-visual-studio-testresults-powershell

Posted in .NET, PowerShell, Productividad, Scripts, VisualStudio | Etiquetado: , , | Leave a Comment »

Troubleshooting: Sharepoint Deployments and Powershell

Posted by kiquenet en 13 agosto 2014

 

Account for Installations

http://sharepointlearningcurve.blogspot.com.es/2010/04/sharepoint-2010-installation-account.html

http://serverfault.com/questions/349300/permissions-error-setting-up-powershell-account-privileges-for-sharepoint-2010

http://sharepoint.stackexchange.com/questions/26831/permissions-error-setting-up-sharepoint-2010-powershell-account-privileges

Error This operation uses the SharePoint Administration service (spadminV4), which could not be contacted.  If the service is stopped or disabled, start it and try the operation again.

http://support.microsoft.com/kb/925727

http://sharepoint.stackexchange.com/questions/72106/remove-spwebapplication-not-working-if-spadminv4-service-is-run-by-local-system

http://sharepoint.stackexchange.com/questions/110928/spadminv4-which-could-not-be-contacted-in-deployment

Term Store in sharepoint 2013 using powershell

Error Current user has insufficient permissions to perform this operation

To resolve the issue:

•Go the Central Administration

•Go to : “Manage service applications” ( _admin/serviceapplications.aspx).

•Select “Managed Metadata Service” to get the Terms Store admin interface.

•In the section : “Term Store Administrators”. Add the user that you use to run sharepoint management shell

•Save the changes.

In SharePoint 2013 Enterprise, I followed the steps above, but it still didn’t work.

Following on from there, I went to the ‘Term Store Management Tool’ in Central Admin (/_layouts/15/termstoremanager.aspx) and added the user there too. This resolved the permissions issue for me.

Cmdlets Sharepoint and Powershell

http://blog.falchionconsulting.com/index.php/tag/cmdlets/page/2/

Read Logging Files Sharepoint

Reading the log file.

The simplest way is opening the log files from the 14$\logs in Notepad. This might be quickest way but not the most efficient in a live multiuser environment. I usually use this in a development environment in combination with a text editor that automatically reloads the file when it’s updated (Notepad++).

Using powershell with a correlation id

You can use powershell to quickly track down a correlation ID and dump the related log files into a file

1

get-splogevent -starttime (get-date).addminutes(-20) | where-object { $_.correlation -eq “b66db71a-3257-4470-adf9-5c01dc59ecb3″ } | fl message > c:\errors.txt

More info can be found here :
http://www.mysharepointadventures.com/2011/08/175/

Uls viewer

A Windows application for viewing the ULS logs more easily. Very handy when you are (trying to) reproduce a specific error and during debugging
I use it when I’m trying to track down a specific error and during debugging.

http://ulsviewer.codeplex.com/

image.png

Farm solution

Codeplex also has a nice solution which you can query the SharePoint logs with from within Central Administration.
The solution installs in your Central Administration. Very handy if you want a quick look in your logs files without having to connect over remote desktop to the actual server.
For detailed log digging this tool might not be sufficient.

http://sp2010getcorrelation.codeplex.com/

Visual Studio Integrated ULS Viewer
https://integrateduls.codeplex.com/Wikipage?ProjectName=integrateduls

tool.png

 

References:
http://sharepoint.stackexchange.com/questions/73022/cannot-create-a-group-in-term-store-using-powershell-current-user-has-insuffic
http://sharepoint.stackexchange.com/questions/7868/best-way-to-get-reference-to-local-sitecollection-term-store-group
http://blog.amtopm.be/2010/12/27/error-occurred-in-deployment-step-activate-features-the-current-user-has-insufficient-permissions-to-perform-this-operation/

http://blog.amtopm.be/2012/02/21/read-logging-files-in-sharepoint/

http://blog.falchionconsulting.com/index.php/tag/cmdlets/page/2/

http://sharepointlearningcurve.blogspot.com.es/2010/04/sharepoint-2010-installation-account.html

Posted in .NET, PowerShell, Scripts, Sharepoint | Etiquetado: , , , , | Leave a Comment »

Web Administration (IIS) , AppPools, WebSites using PowerShell

Posted by kiquenet en 6 agosto 2014

Trabajando con Powershell (Powershell Remoting) y AppPools – WebSites

Enter-PSSession –Computername SERVER-Credential SERVER\instalador

      (Nota:en este punto os pedirá la contraseña correspondiente al usuario)

Import-Module WebAdministration

Get-ChildItem IIS:\AppPools

Get-ChildItem IIS:\AppPools | ? {$_.state -eq "Started" -and $_.name –eq "myAppPool"}

Get-ChildItem -Path IIS:\Sites

Get-ChildItem -Path IIS:\Sites | ? {$_.state -eq "Started"}

Get-ChildItem -Path "IIS:\Sites\Default Web Site"

Get-ChildItem -Path "IIS:\Sites\Default Web Site" | ? {$_.name -eq "MyWebsite"}

Exit-PSSession

References:

http://technet.microsoft.com/es-es/library/ee909471(v=ws.10).aspx
http://www.iis.net/learn/manage/powershell/powershell-snap-in-creating-web-sites-web-applications-virtual-directories-and-application-pools
http://stackoverflow.com/questions/6616320/stop-default-web-site-by-powershell

Posted in PowerShell, Scripts | Etiquetado: , , | Leave a Comment »

Powershell Version–What Version is installed

Posted by kiquenet en 29 julio 2014

Use $PSVersionTable.PSVersion to determine the engine version. If the variable does not exist, it is safe to assume the engine is version 1.0.

Note that $Host.Version and (Get-Host).Version are not reliable – they reflect the version of the host only, not the engine. PowerGUI, PowerShellPLUS, etc. are all hosting applications, and they will set the host’s version to reflect their product version, which is entirely correct.

PS C:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

$PSVersionTable is more reliable and returns $PSVersion. You can also use $PSVersionTable.PSVersion. Even if you are connected remotely to the machine running different version (invoke-command -computername myRemotePC -Credential foo {$host}), it looks like $host will just show the lowest version they agreed upon for serializing. While $PSVersionTable will show the true version

About Host vs $PSVersionTable

Get-Host or $PSVersionTable. As Andy Schneider points out, $PSVersionTable doesn’t work in version 1; it was introduced in version 2.
$host.version is just plain wrong/unreliable. This gives you the version of the hosting executable (powershell.exe, powergui.exe, powershell_ise.exe, powershellplus.exe etc) and not the version of the engine itself.

The engine version is contained in $psversiontable.psversion. For PowerShell 1.0, this variable does not exist, so obviously if this variable is not available it is entirely safe to assume the engine is 1.0, obviously.

 

Microsoft recommends checking the registry to see which version, if any, is installed
https://blogs.msdn.com/b/powershell/archive/2009/06/25/detection-logic-poweshell-installation.aspx?Redirected=true

  • To check if any version of PowerShell is installed, check for the following value in the registry:

    • Key Location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1
    • Value Name: Install
    • Value Type: REG_DWORD
    • Value Data: 0x00000001 (1
  • To check whether version 1.0 or 2.0 of PowerShell is installed, check for the following value in the registry:
    • Key Location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine
    • Value Name: PowerShellVersion
    • Value Type: REG_SZ
    • Value Data: <1.0 | 2.0>

Remember: 

  • Depending on any other registry key(s), or version of PowerShell.exe or the location of PowerShell.exe is not guaranteed to work in the long term.

  • PowerShell 2.0 doesn’t support side by side installations with 1.0, but 2.0 is back-wards compatible with 1.0.

To determine if PowerShell is installed, you can check the registry for the existence of HKEY_LOCAL_MACHINE\Software\Microsoft\PowerShell\1\Install and, if it exists, whether the value is 1 (for installed), as detailed in the blog post Check if PowerShell installed and version.

To determine the version of PowerShell that is installed, you can check the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine\PowerShellVersion.

To determine the version of PowerShell that is installed from a .ps1 script, you can use the following one-liner, as detailed on PowerShell.com in Which PowerShell Version Am I Running.

For PowerScript 3.0 there seems to be a new entry,
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3 (in addition toHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1).


The proper place in this case for getting the version appears to be
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine\PowerShellV‌​ersion(sample value is "3.0").




$isV2 = test-path variable:\psversiontable

The same site also gives a function to return the version:

function Get-PSVersion {
    if (test-path variable:psversiontable) {$psversiontable.psversion} else {[version]"1.0.0.0"}
}

Test Powershell Version.cmd

@echo off
echo Checking powershell version...
del "%temp%\PSVers.txt" 2>nul
powershell -command "[string]$PSVersionTable.PSVersion.Major +'.'+ [string]$PSVersionTable.PSVersion.Minor | Out-File ([string](cat env:\temp) + '\PSVers.txt')" 2>nul
if errorlevel 1 (
 echo Powershell is not installed. Please install it from download.Microsoft.com; thanks.
) else (
 echo You have installed Powershell version:
 type "%temp%\PSVers.txt"
 del "%temp%\PSVers.txt" 2>nul
)
timeout 15

References:
http://stackoverflow.com/questions/1825585/how-to-determine-what-version-of-powershell-is-installed

Posted in PowerShell, Scripts | Etiquetado: , | Leave a Comment »

Using PowerShell to Manage Network Interfaces and Windows Services

Posted by kiquenet en 28 julio 2014

PowerShell is a new scripting language that allows you to interact with applications, services and objects as objects. It is a .NET application which shells commands out on your behalf. This is very powerful, because it allows you to leverage the strengths of an object oriented model within your scripting tasks with a very terse, yet simple scripting language. Because it is written in .NET, you can access .NET types, objects and WMI objects from a command prompt.

My current workstation runs Windows Server 2008 Standard Edition with Hyper-V. I use the host/parent partition as my office, and have a number of child partitions that are integrated into a Windows Server 2008 Domain. Needless to say, this configuration gives me everything I need to develop, test and integrate multiple Server OS’, platforms and technologies, and is my environment of choice for developing production code. It still amazes me how far we’ve come in such a short period of time. Not too long ago, I remember setting up similar lab environments at home running Windows NT 4 and Windows Server 2000 on dedicated physical machines.

Anyway, I have to say that I am absolutely delighted with my environment, but it took me some time and effort to learn how to tune Server 2008, and this is all well documented in previous posts. One of the the things that I do to keep performance high is that I only have the 3 services required for Hyper-V running when I need them. In other words, if I am only working with email and writing documents or design drawings, I don’t need to have the Hyper-V services running because they are resource intensive. In addition, I only want my loopback adapter (that provides me with a virtual LAN for all of the child partitions on my domain to communicate) enabled when I need it to be. One reason for this, is that if I leave my loopback on and reboot, boot times can take up to 10 minutes because the loopback is configured to use my domain controller as the primary DNS server, which is a VM. Because the DNS Server only runs when my Domain Controller VM  is up and running, the VM will only come up when I start it. As a result, Windows tries and tries to reach the DNS server for the Loopback adapter until it finally gives up (If anyone knows how to change this timeout, please shoot me a note or post a comment).

So, I only want Hyper-V services running when I need to work in my development environment, and I don’t want my loopback enabled unless it needs to be. For a while, I was managing this as follows…

First, I set the following services to "Manual", so that they do not start automatically:

  • vmms: Hyper-V Virtual Machine Management
  • vhdsvc: Hyper-V Image Management Service
  • nvspwmi: Hyper-V Networking Management Service

The service names are a bit obscure, but the "friendly" names are pretty self explanatory. When I need to start my development environment, I would go into Server Manager, and start each service one by one.

Next, I would enable my loopback adapter so that my child partitions can communicate with each other.

All together, this resulted in a number of clicks, which was somewhat mundane to do every time. Worse, once I enabled the loopback, I often would forget to disable it before shutting down (remember, servers running Hyper-V do not support hibernation). For a while, I thought about writing myself a sticky note and posting it to my forehead so that I would not forget to disable the loopback, and finally, I decided to create an easy button for starting and stopping my development environment.

This is where Powershell comes in.

Using PowerShell to Query and Manage Network Adapters

The first thing I did was figure out how to talk to my network adapters so that I could enable and disable my loopback as needed. It turns out that Microsoft provides a WMI object called Win32_NetworkAdapter. The object exposes a bunch of properties for working with an instance of a Win32_NetworkAdapter:

image

In addition, there are 4 public methods that are exposed, and well documented as shown below:

image

To enumerate all network adapters on my host/parent partition, I issued the following command:

   1: Get-wmiobject win32_NetworkAdapter | format-table 

PowerShell lists each adapter and certain properties in a tabular format because I added a pipe and format-table parameter:

image

To identify the instance that corresponds to my loopback, I simply need to find the "Internal VLAN" instance above, which has a DeviceID of 17:

image

Next, I want to retrieve an instance of the adapter with a DeviceId of 17, so I issue the following statement:

   1: Get-WmiObject win32_networkadapter | where {$_.DeviceId -eq 17}

The where keyword uses a bracketed expression to evaluate the condition. The "$" is a temporary variable, which is similar to the "this" keyword in C#, which provides context for the current instance. The "-eq" operator is the equality operator in PowerShell. So, we are querying all adapters for the adapter with a DeviceID equal to 17. The above command returns the following:

image

Notice that each property is an actual documented property of the WIN32_NetworkAdapter object. If we have access to properties, it would be helpful to determine if the adapter is enabled or disabled. To do this, I assign the adapter to a variable called $adapter as shown below, and then I get the value of the Availability property:

image

The value of the Availability property is 3. Referring to the WIN32_NetworkAdapter documentation, I can see that a status of 3 indicates that adapter is on, and running on full power.

image

Are you getting the hang of it yet? Hopefully, the interaction with PowerShell should feel object-oriented because it is! We are getting a reference to the WMI shell of the adapter and then using it’s get accessors to get the value of the public properties. So, if we can get a reference to the adapter, get properties, we should be able to call methods on it, right?

To disable the adapter, I simply call the Disable() method on my $adapter variable:

image

Now, to confirm that the adapter is disabled, you can look at Network Connections and you will see that the Status is in fact Disabled. To do this programmatically via PowerShell, you can use the ConfigManagerErrorCode property which is also documented. Get a new instance of the adapter, and call the ConfigManagerErrorCode property on it as shown below:

image

A return code of 22 can be matched to the table in the MSDN documentation:

image

Now, enable the adapter by calling the Enable() method:

image

A return code of 0 indicates that the adapter is enabled, and working properly:

image

As you can see, PowerShell is a very easy to use, yet powerful tool for managing system objects in an object-oriented manner. You don’t need to worry about writing VBScript or C# to accomplish simple administrative tasks such as enabling and disabling a network adapter. As you might imagine, the real power comes in being able to run a series of PowerShell commands in a batch, perhaps at the click of the button. This is exactly what I’ll cover next.

Using PowerShell to Query and Manage Windows Services

You’ll recall that I only want the 3 Hyper-V services to run when I need them, so what I want to do is create an "easy button" to toeggle my development environment on and off.

The "On" should:

  • Enable my Internal VLAN Adapter
  • Start the Hyper-V Virtual Machine Management
  • Start the Hyper-V Image Management Service
  • Start the Hyper-V Networking Management Service
  • Get me a cup of Starbucks coffee

The "Off" Button should:

  • Disable my Internal VLAN Adapter
  • Disable the Hyper-V Virtual Machine Management
  • Disable the Hyper-V Image Management Service
  • Disable the Hyper-V Networking Management Service


    I’ve already covered how to manage network adapters using PowerShell as a primer, so I’ll jump right into working with Windows Services. As with any program, sometimes it is helpful to group commands into a subroutine. In PowerShell, these functions are referred to as cmdlets (prounounced "commandlets"). You may not realize this, but you’ve already been working with cmdlets if you’ve tried the commands I covered above on your own machine. The get-wmiobject command is actually a cmdlet that provides a reference to the WMI object specified as the parameter. You could accomplish this without the cmdlet, but why would you want to?

  • Fortunately, a cmdlet is also available for working with Windows Services: get-service.

    To get information about a particular service, simply call get-service with the service name. The actual service name of the Hyper-V Virtual Machine Management service is "vmms", so issuing the get-service vmms command returns a few properties including the Name, DisplayName and Status of the service.

    image

    Starting and stopping the Hyper-V Virtual Machine Management service is as simple as calling the appropriate method: Stop() to stop the service and Start() to start it. While you could use a variable called $service to store the reference to the service object, an abbreviated way to accomplish this is shown below:

       1: (get-service vmms).Stop()

    Now, when you issue the get-service vmms command, you can see that the Status property is "Stopped":

    image

    Starting the service back up is as simple as calling Start() on the cmdlet expression:

    image

    Building the "Easy Buttons"

    There may very well be a more sophisticated way to do this, but I created two batch files, one called "Start.bat" and the other called "Stop.bat" and placed them in my documents folder. Each file contains the appropriate PowerShell syntax as shown below:

    image

    Note, to re-use variables across PowerShell sessions, you must first configure a PowerShell profile: http://msdn.microsoft.com/en-us/library/bb613488(VS.85).aspx

    Next I created two desktop shortcuts, appropriately named "Start" and "Stop" and set the target to each corresponding file.

    Now, I have two "Easy Buttons" for toggling my development environment on and off. While I can’t guarantee that I won’t forget to press the "off  button" before shutting down, it is a heck of a lot easier than going through the contortions manually.


  • References:

    http://rickgaribay.net/archive/2008/09/26/using-powershell-to-manage-network-interfaces-and-windows-services.aspx

    Posted in PowerShell, Scripts, Soporte | Etiquetado: , , | Leave a Comment »

    Powershell–Troubleshooting Group Policy – Privileges

    Posted by kiquenet en 28 julio 2014

    Useful when troubleshooting things like group policy, scripts or any other sources that may change privileges from what they should be. May generate a hash from this and automate a quick hash difference to monitor changes to privileges on systems.

    Command
    "secedit.exe", "/export /areas USER_RIGHTS /cfg $file"

    #Variables
    $computername= $env:COMPUTERNAME
    $tempdir = "c:\temp"
    $file = "$tempdir\privs.txt"
    [string] $readableNames
    $outHash = @{}

    ##### Generate report with just USER_RIGHTS ######
    $process = [diagnostics.process]::Start("secedit.exe", "/export /areas USER_RIGHTS /cfg $file")
    $process.WaitForExit()

    $in = get-content $file
    # start check of local userrights
    foreach ($line in $in) {
    if ($line.StartsWith("Se")) {
    $privilege = $line.substring(0,$line.IndexOf("=") – 1)
    $sids = $line.substring($line.IndexOf("=") + 1,$line.Length – ($line.IndexOf("=") + 1))
    $sids =  $sids.Trim() -split ","
    $readableNames = ""
    foreach ($str in $sids){
        Write-Host $str
        if ($str.StartsWith("*S-")) {
            $str = $str.substring(1) # For some reason, secedit appends a * to the SID like *S-1-5-32-544, this just strips the first character
            $sid = new-object System.Security.Principal.SecurityIdentifier($str)
            $readableName = $sid.Translate([System.Security.Principal.NTAccount])
            $readableNames = $readableNames + $readableName.Value + ","
        } else {
            $readableName = $str
            $readableNames = $readableNames + $readableName + ","
        }
      }
    $outHash.Add($privilege,$readableNames.substring(0,($readableNames.Length – 1))) #output edited version
    }
    }
    $outHash

    References:
    http://rcampi.blogspot.com.es/2011/08/powershell-ghetto-way-to-output.html

    Posted in PowerShell, Scripts | Etiquetado: , , | Leave a Comment »