Wednesday, January 6, 2016

Modifying SCSM Management Pack to add Categories

Hello everyone!

There was some unfolding developments on my last post regarding the SCSM categories. The SCSM Admistrator asked me that he had received a request that required him to add about 50+ different categories through several parent categories, but that the way to add them through SCSM was extremely inefficient and was hoping that I could write a script or program to make it more streamlined.

I spoke with the Administrator and asked him to first tell me how it would be done manually, without the SCSM GUI, and found that it is all modified through the XML Management Pack. I first looked around for someone who maybe already created something for it, and I did found tools that allowed you to create MP through an Excel sheet, like this, but if you wanted to modify the existing MP I couldn't find anything.

I decided I'll have to create something. I originally planned to create him a desktop application with C#; however, my free trial for Visual Studio ran out, which I knew it was coming but I didn't want to request a license from the company because I have a feeling it would get denied. Anyways, so instead I decided to go with PowerShell.

I had been avoiding working with XML for a while, so it was a good opportunity to finally sit down and try to learn the ways. I got quite a big of help from the scripting guy, but mostly it was trial and error. In the end I was able to create 3 functions:

I created 3 cmdlets that will allow us to get quick information on the support group/category (list information, and treeview) and be able to add one or multiple lists in an instance.

Requirements:
Exported Management Pack containing the lists.
Name of the list that you wish to get information on/add more lists to.

The first cmdlet is 'Get-SCSMListItem' this cmdlet will provide you with information about list, you'll need to know the name of it, or GUID, and will provide the following output:


Notice that if you use the name parameter you can get multiple results, so you must know which one you need to use in order to accurately assess which one should be the parent when you are creating new lists. 

The second cmdlet is 'Get-SCSMListChildItems' this cmdlet will print out a 'structure' of the lists, depending on which parent you give it, please see below for an example that will further explain this:


Also notice the same parameter here, which i did, it will print out the structure for both lists. Making it simple to see which one is the one you wish to work with, and they'll print out in the same order, so once you know which one you need to work with you can use the necessary IDs. 

The last cmdlet is Add-SCSMListItems this cmdlet supports the following parameters:
  • -Lists: This parameter will contain the name of the lists that you want to add. This parameter will accept array. For example:
    • Single List:  -List ‘My New Category’
    • Multiple Lists: -List ‘My New Category1’,’My New Category2’
  • -ParentName: This parameter will be the name of the Parent where you wish to add your lists. Keep in mind that This cmdlet will not support multiple results for the ‘Name’ parameter, if multiple lists contain the same name, as shown in the past for ‘Group IT’, the command will fail. 
  • -ParentID: This parameter will be the ID of the Parent where you wish to add the lists. This parameter cannot be used with the ParentName parameter.
  • -ManagementPackXML: This parameter requires that you provide the exact path of the Management Pack XML file you exported from SCSM.
  • -ExportLocation: This is the file path where the modified XML file will be exported. If this is left blank the export will overwrite the imported Management Pack XML. If the export path provided does not exist the command will fail and no changes will be saved. 
There is no console output for this command.

Here is the command will do:
For each given list, it will create a new DisplayString item in the Management Pack, worth noting that this is hard coded to add it to the ENU LanguagePack; however, it can be easily modified to accept a parameter for the language pack as well, see the XML code examples below:

<DisplayString ElementID="$newGUID">
       <Name>$providedName</Name>
</DisplayString>

<EnumerationValue ID="$newGUID" Accessibility="Public" Parent="$providedParent" Ordinal="$ordinal" />

I'd also like to point out that as long as you know the parent you can use a CSV file to quickly create multiple lists. 

First you’ll need to create a CSV file that will look like the one below:

Parent
ListName
ParentGUID
Cat1_UnderRootParent
ParentGUID
Cat2_UnderRootParent
ParentGUID
Cat3_UnderRootParent
ParentGUID2
Cat1_UnderDifferentParent
ParentGUID2
Cat2_UnderDifferentParent
ParentGUID3
Cat1_SCSMParent
ParentGUID3
Cat2_SCSMParent

The first column will specify the parent that you wish to use, and the second the category that you wish to create. Once you have the CSV create you’ll use it in PowerShell like so:

$csv = Import-Csv C:\myCSVFile.csv

foreach($category in $csv)
{
    Add-SCSMListItems -Lists $category.ListName `
                      -ParentID $category.Parent `
                      -ManagementPackXML C:\ManagementPackPath.xml
                      -ExportLocation C:\ManagementPackPath_new.xml [see edit for details]

Once the changes are done then you can simply export the MP XML file back into SCSM and voila all done. 

Now for the source code:


function Get-SCSMListItem
{
    <#
      .SYNOPSIS
      This function will get information on an SCSM List Item.
      .DESCRIPTION
      This function will get information on the SCSM List Item specified. It will provide the Name, Parent, ID and Ordinance. 
      .EXAMPLE
      Get-SCSMList -Name "MyArea/CategoryName" -ManagementPackXML C:\MP_xmlFile.xml
      .EXAMPLE
      Get-SCSMList -ID "Enum.GUID" -ManagementPackXML C:\MP_xmlFile.xml
      .PARAMETER Name
      The name of the list you want to get information on
      .PARAMETER ID
      The ID of the list you want to get information on
      .PARAMETER ManagementPackXML
      The location where the XML File is saved
    #>
    [CmdletBinding()]
    Param
    (
        #Name
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What name of the list do you want to get?',
            ParameterSetName="Name")]
        [Alias('ListName')]
        [ValidateLength(3,250)]
        [string]$Name,
        #ID
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What ID of the list do you want to get?',
            ParameterSetName="ID")]
        [Alias('ElementID')]
        [ValidateLength(0,250)]
        [string]$ID,
        #ManagementPackXML
        [Parameter(Mandatory=$True,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='Where is the Management Pack XML Located?')]
        [Alias('XMLPath')]
        [ValidateLength(3,255)]
        [string]$ManagementPackXML
    )
    begin
    {        
    }
    process
    {
        Write-Verbose "Checking the XML file exists."
        Test-Path $ManagementPackXML -ErrorAction Stop | Out-Null
        Write-Verbose "File exists."

        Write-Verbose "Opening XML File with UTF8 encoding."
        [xml]$xml = Get-Content $ManagementPackXML -Encoding UTF8
        Write-Verbose "File opened successful."

        if($ID.Length -ne 0)
        {
            Write-Verbose "ID Provided. Attempting to find in the XMLElement DisplayStrings."
            $listResult = $xml.ManagementPack.LanguagePacks.LanguagePack | ? ID -eq "ENU" | %{$_.DisplayStrings.DisplayString} | ? ElementID -eq $ID
        }
        else
        {
            Write-Verbose "No ID Provided. Attempting to find name in the XMLElement DisplayStrings."
            $listResult = $xml.ManagementPack.LanguagePacks.LanguagePack | ? ID -eq "ENU" | %{$_.DisplayStrings.DisplayString} | ? Name -eq $name
        }
        
        if($listResult -ne $null)
        {
            foreach($list in $listResult)
            {
                Write-Verbose "The element has been found in the XML file. Gathering information."
                $ListInformationObject = New-Object psobject
                $ListInformationObject | Add-Member -MemberType NoteProperty -Name "ID" -Value $list.ElementID
                $ListInformationObject | Add-Member -MemberType NoteProperty -Name "Name" -Value $list.Name
                $ListInformationObject | Add-Member -MemberType NoteProperty -Name "Parent" -Value ($Xml.GetElementsByTagName("EnumerationValue") | ? ID -eq $list.ElementID).Parent
                $ListInformationObject | Add-Member -MemberType NoteProperty -Name "Ordinal" -Value ($Xml.GetElementsByTagName("EnumerationValue") | ? ID -eq $list.ElementID).Ordinal
                $ListInformationObject
            }
        }        
        else
        {
            Write-Error -Message "No lists were found by the name $Name" -Category InvalidArgument -RecommendedAction "Please ensure that the list exists in the XML File." `
                        -CategoryActivity "Get-SCSMListItem, Filter-XMLElement(DisplayString) by Name" `
                        -CategoryReason "The List Name provided was not found." `
        }
    }
    end
    {
        Remove-Variable -Name xml
    }
}

function Get-SCSMListChildItems
{
    <#
      .SYNOPSIS
      This function will get a view of the child items.
      .DESCRIPTION
      This function will get a view of the child lists. Output:
        :: ListName
        ::    SubListName_L1_1
        ::    SubListName_L1_2
        ::       SubListName_L2_1
        ::    SubListName_L1_3
      .EXAMPLE
      Get-SCSMListChildItems -Name "MyArea/CategoryName" -ManagementPackXML C:\MP_xmlFile.xml
      .EXAMPLE
      Get-SCSMListChildItems -ID "Enum.GUID" -ManagementPackXML C:\MP_xmlFile.xml
      .PARAMETER Name
      The name of the list you want to get information on
      .PARAMETER ID
      The ID of the list you want to get information on
      .PARAMETER ManagementPackXML
      The location where the XML File is saved
    #>
    [CmdletBinding()]
    Param
    (
        #ID
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What is the ID of the list you wish to get child items for?',
            ParameterSetName="ID")]
        [Alias('ElementID')]
        [ValidateLength(3,250)]
        [string]$ID,
        #Name
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What is the name of the list you wish to get child items for?',
            ParameterSetName="Name")]
        [Alias('ListName')]
        [ValidateLength(0,250)]
        [string]$Name,
        #ManagementPackXML
        [Parameter(Mandatory=$True,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='Where is the Management Pack XML Located?')]
        [Alias('XMLPath')]
        [ValidateLength(3,255)]
        [string]$ManagementPackXML
    )
    begin
    {
    }
    process
    {
        Write-Verbose "Checking the XML file exists."
        Test-Path $ManagementPackXML -ErrorAction Stop | Out-Null
        Write-Verbose "File exists."

        Write-Verbose "Opening XML File with UTF8 encoding."
        [xml]$xml = Get-Content $ManagementPackXML -Encoding UTF8
        Write-Verbose "File opened successful."

        if($ID.Length -eq 0)
        {
            Write-Verbose "If the ID is not provided, search by name to get the ID."
            $nameSearch = Get-SCSMListItem -Name $Name -ManagementPackXML $ManagementPackXML
        }

        function Get-ChildNodes($parentNode, $depth)
        {
            $depth++
            $childNodes = $listNodes | ? Parent -eq $parentNode.ID
            foreach($child in $childNodes)
            {
                "$("`t"*$depth) - $((Get-SCSMListItem -ID $child.ID -ManagementPackXML $ManagementPackXML).Name) - $((Get-SCSMListItem -ID $child.ID -ManagementPackXML $ManagementPackXML).Ordinal)"
                get-childNodes $child $depth
            }
    
        }

        foreach($result in $nameSearch)
        {
            Write-Verbose "Get all of the Elements from XMLElement EnumerationValue."
            $listNodes = $xml.GetElementsByTagName("EnumerationValue")
            foreach($node in $listNodes)
            {
                $depth = 0
                if($node.ID -eq $result.ID)
                {
                    Write-Verbose "If the Node.ID is equal to the provided (acquired) ID, then Print information and get child elements."
                    " - $((Get-SCSMListItem -ID $node.ID -ManagementPackXML $ManagementPackXML).Name) - $((Get-SCSMListItem -ID $node.ID -ManagementPackXML $ManagementPackXML).Ordinal)"
                    get-childNodes $node, $depth
                }
            }
        }
    }
    end
    {
        Remove-Variable -Name xml
    }
}

function Add-SCSMListItems
{
    <#
      .SYNOPSIS
      This function will add a new item to the XML Management Pack.
      .DESCRIPTION
      This function will add a new item to the XML Management Pack. This will include the EnumerationValue and the DisplayString. 
        XML Example:
            <EnumerationTypes ID="Enum.6a70247ad154475fb9138d6d2c52c8a3" Accessibility="Public" Parent="ServiceRequest!ServiceRequestAreaEnum.Directory" Ordinal="500" />

            <DisplayString ElementID="Enum.6a70247ad154475fb9138d6d2c52c8a3">
                <Name>Test</Name>
            </DisplayString>
      .EXAMPLE
      Add-SCSMListItems -Lists "LIST ITEM NAME" -ParentName "Group IT" -ManagementPackXMl C:\MP_XML.xml -ExportLocation C:\MP_XML_New.xml
      .EXAMPLE
      Add-SCSMListItems -Name "LIST ITEM NAME" -ParentID "Enum.GUID" -ManagementPackXMl C:\MP_XML.xml -ExportLocation C:\MP_XML_New.xml
      .PARAMETER ParentName
      The name of the Parent that will store the new list item
      .PARAMETER ParentID
      The ID of the Parent that will store the new list item
      .PARAMETER Lists
      The name of the new list items
      .PARAMETER ManagementPackXML
      The location where the Management Pack XML file is located
      .PARAMETER ExportLocation
      The location where the new XML file will be saved. It can be the same but it is not recommended to over write the file.
    #>
    [CmdletBinding()]
    Param
    (
        #Lists
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What is the name of the list you wish to get child items for?')]
        [Alias('ListName')]
        [ValidateLength(3,250)]
        [string[]]$Lists,
        #ParentName
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What is the name of the Parent where the Lists should be added?',
            ParameterSetName="ParentName")]
        [Alias('Parent')]
        [ValidateLength(3,250)]
        [string]$ParentName,
        #ParentID
        [Parameter(Mandatory=$true,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='What is the ID of the Parent where the Lists should be added?',
            ParameterSetName="ParentID")]
        [Alias('PID')]
        [ValidateLength(3,250)]
        [string]$ParentID,
        #ManagementPackXML
        [Parameter(Mandatory=$True,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='Where is the Management Pack XML Located?')]
        [Alias('XMLPath')]
        [ValidateLength(3,255)]
        [string]$ManagementPackXML,
        #ExportLocation
        [Parameter(Mandatory=$false,
            ValueFromPipeline=$True,
            ValueFromPipelineByPropertyName=$True,
            HelpMessage='Where is the Management Pack XML Located?')]
        [Alias('exportPath')]
        [ValidateLength(3,255)]
        [string]$ExportLocation
    )
    begin
    {
        if($ExportLocation -eq $null -or $ExportLocation.Length -eq 0)
        {
            $ExportLocation = $ManagementPackXML
        }
    }
    process
    {
        Test-Path $ManagementPackXML -ErrorAction Stop | Out-Null
        [xml]$xml = Get-Content $ManagementPackXML -Encoding UTF8
        
        if($ParentID.Length -eq 0)
        {
            $nameSearch = Get-SCSMListItem -Name $ParentName -ManagementPackXML $ManagementPackXML
            if($nameSearch.Count -eq 1)
            {
                $ParentID = $nameSearch.ID
            }
            else
            {
                Write-Error -Message "Unable to create the lists as multiple parents were found." -Category InvalidResult -RecommendedAction "Find the ID of the parent you wish to add the list and try again with the ID." -CategoryActivity "MultipleResultsError" -ErrorAction Stop
            }
            
        }

        function Get-NextOrdinal($parentID)
        {
            return ($xml.ManagementPack.TypeDefinitions.EntityTypes.EnumerationTypes.EnumerationValue | ? Parent -eq $parentID | Measure-Object -Property Ordinal -Maximum).Maximum + 1
        }

        foreach($list in $Lists)
        {
            $element_EnumartionTypes = $xml.CreateElement("EnumerationValue")
            $element_EnumartionTypes.SetAttribute('ID',"Enum.$(([GUID]::NewGuid().Guid).replace("-",''))")
            $element_EnumartionTypes.SetAttribute('Accessibility',"Public")
            $element_EnumartionTypes.SetAttribute('Parent',$ParentID)
            $element_EnumartionTypes.SetAttribute('Ordinal', $(Get-NextOrdinal -parentID $ParentID))
            $xml.ManagementPack.TypeDefinitions.EntityTypes.EnumerationTypes.AppendChild($element_EnumartionTypes) | Out-Null

            $Element_DisplayName = $xml.CreateElement("DisplayString")
            $Element_DisplayName.SetAttribute('ElementID',$element_EnumartionTypes.id)
            $Element_DisplayName_Name = $xml.CreateElement("Name")
            $Element_DisplayName_Name.InnerText = $list
            $Element_DisplayName.AppendChild($Element_DisplayName_Name) | Out-Null
            $xml.ManagementPack.LanguagePacks.LanguagePack | ? ID -eq "ENU" | %{$_.DisplayStrings.AppendChild($Element_DisplayName)} | Out-Null
        }
        
        if(Test-Path (Split-Path $ExportLocation))
        {
            $xml.Save($ExportLocation)
        }
        else
        {
            Write-Error -Message "The provided export file cannot be found." -RecommendedAction "Ensure that the file path exists and try again." -Category ResourceUnavailable -ErrorAction Stop
        }
        
    }
    end
    {
        Remove-Variable -Name element_EnumartionTypes
        Remove-Variable -Name Element_DisplayName_Name
        Remove-Variable -Name Element_DisplayName
    }
}

I hope that this may help someone out there. Do let me know if you have any questions, or issues, also if you find something else like it out there because I couldn't find that many people creating tools for SCSM. 

Kind regards,
Me.

Edit 1/14/2015: 

I found a bug when working with the batch addition of lists. The problem happens because for each loop the MP will overwrite the last change. 

In order to fix this you won't be able to use the 'Export-Path' parameter, and will have to overwrite the XML for every change. 

Sunday, December 20, 2015

Get-SCSMCategories

Hello everyone!

I have been doing quite a bit of DevOps work lately and I received a request the other day that might be worth sharing.

Our SCSM Administrator needed to get an export of our current categories, and he had found a script online to do so; however, it was only hard coded to go 3 levels deep and our categories would go much deeper than that. . He asked me if I could take a look into why this was happening, and it turned out that the way that the script works is that it was only hard coded to go 3 levels deep, so I wrote a function to recursively go through the main class, and its children and print out the categories regardless of the levels that you might have.

Import-Module SMLets

function get-childLists($listObjects)
{
    $count ++
    foreach($obj in $listObjects)
    {
        $id = $obj.id
        "$("`t"*$count) - $($obj.DisplayName)" | Out-File 'C:\FILE\PATH.txt' -Append
        $children = Get-SCSMEnumeration -ComputerName $scsm | ? Parent -match $id
        if($children -ne $null)
        {
            get-childLists $children, $listName
        }
    }

}

$scsm = 'YOURSCSMSERVER'
$areas = @("ActivityAreaEnum",
"IncidentClassificationEnum",
"ServiceRequestAreaEnum")

foreach($list in $areas)
{
    $count = -1
    $enumLists = Get-SCSMEnumeration -ComputerName $scsm | ? Name -eq $list
    get-childLists $enumLists
}

Let me know what you think, and if you all find this useful then I can probably make it into an actual advance function.

Kind regards,
Me

Friday, October 23, 2015

PowerShell 5.0

Hello everyone! 

I might be a little late with this but the other day I found out a nice little feature of the new PowerShell 5.0, and that is that not only does it come with nice color coding but it also supports Control+C, Control-X and Control-V ! A feature that was long overdue. 

Finding this new feature out made me realize that I haven't even looked into the new features, and so I did. Here are some of the features that I'm really excited about:


  1. Microsoft.PowerShell.Archive: Allows us to manage, extract and even create compressed files (zip files)
  2. PowerShell Gallery: A central repository for all PowerShell things. If it is deployed correctly and it actually is used by the community it will be a great resources, specially with the new 'PowerShellGet' Module that allows you to get stuff from the Gallery.
  3. The new -Depth parameter for the Get-ChildItems cmdlet sounds great, so far I had to use a function that I wrote to get this accomplished. It'll be nice to have it already built in.
  4. Transcript is now supported in the ISE and a new GPO can be enabled to setup global transcripts.
  5. Get-Clipboard and Set-Clipboard cmdlet sound like might come in handy too! They support images, audio files, file lists, and text.
Overall it seems that this new version has come with quite a few changes  very interesting changes. It's all very exciting. For more details be sure to visit the technet article.


Let me know what you guys think about version 5.0, and if you are exited about any particular feature, and why!

Kind regards,
Me.

Edit: It has been pointed out to me that it is not PowerShell that is now able to handle the copy, cut and paste features but the shell. Thanks to https://www.reddit.com/user/No1Asked4MyOpinion for pointing it out. 

Wednesday, August 12, 2015

Installing .NET Framework 3.5 offline

Hello everyone!

I just wanted to put this out there because I didn't think it was very clear. If you want to install Windows .NET Framwork 3.5 without access to the Internet you'll have to perform the installation from your disk:





















By selecting the 'Specify an alternaet source path' option. If you try to continue without doing this the installation will fail stating that it was not able to connect to the Windows Update service. If you try to download the installer from the website, filename "dotnetfx35", it will fail with the same error. ( I did read something about being able to perform an extraction on the dotnetfx35 file with a /x switch on installation but I wasn't able to get it working, if you know how this would be done drop me a line I'd love to find out)

The reason for this is that by default the installation will attempt to get the most recent updates for the installation.

Well I hope this might help someone out there.

Kind regards,
Me.

------------------------------

Oh yeah, you are also able to get this done by running the following command:

DISM /Image:C:\test\offline /Enable-Feature /FeatureName:NetFx3 /All /LimitAccess /Source:D:\sources\sxs

Where /Source: is the location in your DVD. 

Monday, May 18, 2015

The Case of the Mysterious Blank Desktop, part 2?

Hello everyone, 

I recently experienced an issues login into a Windows Server 2008 R2. Whenever I would log in, whether through RDP or VM Console, the only thing that would load was a blank desktop. No errors, no windows, no explorer. I wasn't able to use Remote Tools, but I was able to use PSRemote and from there was was able to pull the following log:

[HOSTNAME]: PS C:\Users\USERNAME\Documents> Get-EventLog -LogName Application | ?{$_.Source -eq 'Winlogon'} | ?{$_.EntryType -eq 'Warning'} | select -First 1 | fl * -Force


EventID            : 4006
MachineName        : HOSTNAME.DOMAIN.com
Data               : {5, 0, 0, 0}
Index              : 40795
Category           : (0)
CategoryNumber     : 0
EntryType          : Warning
Message            : The Windows logon process has failed to spawn a user application. Application name: . Command line
                      parameters: C:\Windows\system32\userinit.exe.
Source             : Winlogon
ReplacementStrings : {, C:\Windows\system32\userinit.exe}
InstanceId         : 2147487654
TimeGenerated      : 5/18/2015 8:47:26 PM
TimeWritten        : 5/18/2015 8:47:26 PM
UserName           :
Site               :
Container          :

I quickly pulled out Google and found the following article, but to my demise after checking the local group I found that the users were already added.

[HOSTNAME]: PS C:\Users\USERNAME\Documents> net localgroup users
Alias name     users
Comment        Users are prevented from making accidental or intentional system-wide changes and can run most applications

Members

-------------------------------------------------------------------------------
NT AUTHORITY\Authenticated Users
NT AUTHORITY\INTERACTIVE
DOMAIN\Domain Admins
DOMAIN\Domain Users
The command completed successfully.

Great so now what? I searched the internet trying to find someone who might have experienced a similar issue but i only found similar articles to the one linked above. I attempted to reboot, to remove the users Authenticated Users/Interactive off the group, reboot, add them again and reboot once again, but nothing.

I did have some idea of what might be causing the issue based on the article though, so I attempted moving the computer to a different OU that doesn't require UAC to be turned on. I updated the group policy and rebooted but still nothing. Frustrated I went to to Regedit and attempted to load the UAC settings to find out if it was turned on or off by using the following command that I got from this article.

[HOSTNAME]: PS C:\Users\USERNAME\Documents> (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).EnableLUA

To my surprise I got nothing. Null return value. I thought that was weird, so I confirmed on a different server with the same version to ensure that the command was correct, and it was returning a result of 0. So I re-added the setting using the following command, also found in the article. 

[HOSTNAME]: PS C:\Users\USERNAME\Documents> Set-ItemProperty -Path registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -Value 0

I rebooted and the server logged back in without any issues. I have no idea how this registry could have been deleted, or why it had this effect so if anyone has any more information please be sure to share.

I hope this might help someone out there. Do let me know if you have any questions, issues or comments. 

Kind regards, 
Me.

Thursday, May 14, 2015

Windows 10 Preview

Hello everyone, 

For the first time in my life I have a spare computer that I can use to test things on. So I signed up for Windows Insider and installed Windows 10 on my laptop which I have been using on the regular bases. I'm not much of a writer so I won't even attempt to do a full review on my experience, but I did want to comment on the quality of people that I have found on the Microsoft reviewing forums. 

The truth is that people are nasty. I went through quite a few posts and most of the posts was of people complaining and calling that Windows will be a failure. All because of the way that the UI looks. Instead of providing constructive criticism to help develop a better operating system we have people crying about the way that the task bar is, or the way the start menu looks, or the how the icons are flat! I mean come on people! We are all tech savvy here what does it matter what the system looks like as long as it works? 

Windows is quite frankly implementing some really good features not only on their desktop environment but on the server environment, and so what if it looks different? We shouldn't be using the system for how it looks but for what we can do with it. After all we can always hack our way to change the way things look. 

I do hope that people can change their outlook on how things are going with Windows 10. It will either be a success or a failure, and if its a failure its not like it was a few years back and we actually have options.

Kind regards, 
Me.

Get-DFSNFolderTarget

Hello! 

I been wondering how I can find out where a DFS target is through PowerShell for quite some time now, and perhaps I didn't look hard enough because today I found the cmdlet in the subject. 

Get-DfsnFolderTarget [-Path] <String> [[-TargetPath] <String> ] [-CimSession <CimSession[]> ] [-ThrottleLimit <Int32> ] [ <CommonParameters>]

It is a very handy command that will return the following output: 

PS Microsoft.PowerShell.Core\FileSystem::\\DFS\SHARE\PATH> Get-DfsnFolderTarget \\DFS\SHARE\PATH | fl *


Path                  : \\DFS\SHARE\PATH
State                 : Offline
ReferralPriorityClass : sitecost-normal
NamespacePath         : \\DFS\SHARE\PATH
ReferralPriorityRank  : 0
TargetPath            : \\targetServer\Share
PSComputerName        :
CimClass              : Root/Microsoft/Windows/dfsn:MSFT_DfsNamespaceFolderTarget
CimInstanceProperties : {NamespacePath, ReferralPriorityClass, ReferralPriorityRank, State...}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties

However, I have found it to be less than helpful if I don't know exactly 
where the DFS namespace ends and the targetPath begins, for example:

\\DFS\SHARE\PATH\Something\Folder 

If I try to find the root using this path I receive the following error:

Get-DfsnFolderTarget : Cannot get DFS folder properites on
"Microsoft.PowerShell.Core\FileSystem::\\DFS\SHARE\PATH\Something\Folder"
At line:1 char:1
+ Get-DfsnFolderTarget $((Get-Item .\).PSParentPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (MSFT_DfsNamespaceFolderTarget:ROOT\Microsoft\...aceFolderTarget) [Get-Dfs
   nFolderTarget], CimException
    + FullyQualifiedErrorId : Windows System Error 1722,Get-DfsnFolderTarget

Get-DfsnFolderTarget : A general error occurred that is not covered by a more specific error code.
At line:1 char:1
+ Get-DfsnFolderTarget $((Get-Item .\).PSParentPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (MSFT_DfsNamespaceFolderTarget:ROOT\Microsoft\...aceFolderTarget) [Get-Dfs
   nFolderTarget], CimException
    + FullyQualifiedErrorId : MI RESULT 1722,Get-DfsnFolderTarget

I am not sure why though. It is simple enough to get the information form the
GUI so perhaps is my inexperience or lack of knowledge, but why can't it be 
this easy on the cmd line as well?

I do hope that it is just my lack of knowledge and that maybe one of you
might show me the right way to get the DFSFolderTarget path. 

Kind regards, 
Me