## Goal

I am trying to compare Dell driver packs that were extracted into a folder ( a very large list)
The goal is to filter by operating system, model, Dell CAB version (A01, A02, etc), and architecture.
I wrote a PowerShell script that will parse this folder structure (a small subset of the actual list):

\\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x64
\\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x86
\\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x64
\\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x86
\\share\drivers\E7470-win10-A05-6K6HR\E7470\win10\x64
\\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x64
\\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x86
\\share\drivers\M6700-win10-A02-T08R2\M6700\win10\x64
\\share\drivers\M6700-win10-A02-T08R2\M6700\win10\x86
\\share\drivers\E7470-win10-A09-PY2N2\E7470\win10\x64
\\share\drivers\E6500-win7-A05-JJ15G\E6500\win7\x64
\\share\drivers\E6500-win7-A05-JJ15G\E6500\win7\x86
\\share\drivers\E7470-win8.1-A01-DCD7V\E7470\win8.1\x64
\\share\drivers\9343-Win8.1-A04-HXWH4\9343\Win8.1\x64
\\share\drivers\E7470-win10-A07-WXGDV\E7470\win10\x64


## Script Breakdown

First grab all the folders and add it to a collection:
$scriptRoot = '\\share\drivers' #grab only root folders$RootDriverCabs = Get-ChildItem $AllDriversPath | ?{$_.PSIsContainer }

#create hashtable
$CabCollection = @() #loop through folder within root folder and break it apart into an hashtable ForEach ($Driver in $RootDriverCabs){ #$FullDir = $Driver.FullName$Model = ($Driver.Name -split '-')[0]$OS = ($Driver.Name -split '-')[1]$ver = ($Driver.Name -split '-')[2] #combine root driver path with model and OS sub-folders$FullPath = Join-Path -Path $Driver.FullName -ChildPath "$Model\$OS" #if the full path exists get architecture If (Test-Path$FullPath){
$arch = Get-ChildItem$FullPath | ForEach-Object {
$FullDir = "$FullPath\$($_.Name)"

#build object
$CabTable = New-Object -TypeName PSObject -Property ([ordered]@{ Model =$Model
OS       = $OS Ver =$ver
Arch     = $_.Name FullPath =$FullDir
})

$CabCollection +=$CabTable
}
}
Else{
Write-host "$FullPath is not found, drivers must have proper naming convention" -ForegroundColor White -BackgroundColor Red break } } Write-host "Collected$($CabCollection.Count) drivers packages"  the Cab Collection result is: Model : E6530 OS : win10 Ver : A01 Arch : x64 FullPath : \\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x64 Model : E6530 OS : win10 Ver : A01 Arch : x86 FullPath : \\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x86 Model : E7450 OS : win10 Ver : A04 Arch : x64 FullPath : \\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x64 Model : E7450 OS : win10 Ver : A04 Arch : x86 FullPath : \\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x86 Model : E7470 OS : win10 Ver : A05 Arch : x64 FullPath : \\share\drivers\E7470-win10-A05-6K6HR\E7470\win10\x64 Model : E6540 OS : win10 Ver : A03 Arch : x64 FullPath : \\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x64 Model : E6540 OS : win10 Ver : A03 Arch : x86 FullPath : \\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x86 Model : M6700 OS : win10 Ver : A02 Arch : x64 FullPath : \\share\drivers\M6700-win10-A02-T08R2\M6700\win10\x64 Model : M6700 OS : win10 Ver : A02 Arch : x86 FullPath : \\share\drivers\M6700-win10-A02-T08R2\M6700\win10\x86 Model : E7470 OS : win10 Ver : A09 Arch : x64 FullPath : \\share\drivers\E7470-win10-A09-PY2N2\E7470\win10\x64 Model : E6500 OS : win7 Ver : A05 Arch : x64 FullPath : \\share\drivers\E6500-win7-A05-JJ15G\E6500\win7\x64 Model : E6500 OS : win7 Ver : A05 Arch : x86 FullPath : \\share\drivers\E6500-win7-A05-JJ15G\E6500\win7\x86 Model : E7470 OS : win8.1 Ver : A01 Arch : x64 FullPath : \\share\drivers\E7470-win8.1-A01-DCD7V\E7470\win8.1\x64 Model : 9343 OS : Win8.1 Ver : A04 Arch : x64 FullPath : \\share\drivers\9343-Win8.1-A04-HXWH4\9343\Win8.1\x64 Model : E7470 OS : win10 Ver : A07 Arch : x64 FullPath : \\share\drivers\E7470-win10-A07-WXGDV\E7470\win10\x64  The count is 15 with all architectures Now I need to filter them. I am then comparing them with other arrays (set as constants: #Specify which type of folders to look for based on Operating System. #Supported Values: Win7, Win8, Win8.1, Win10$OSCheck = @('Win10')

#Specify which type of folders to look for based on architecture.
#Supported Values: x86,x64
$archCheck = @('x64') #Break it down even further based on model.$FilterByModel = $true$DellModels = @('E7470','E7450','E6530','E6540')

#search driver types
$FilterbyDriverCategory =$true
$DriverCategory = @('audio','chipset','communication','input','network','security','storage')  Based on theses filters I should get: 5 models with x86 drivers 2 unsupported drivers: E6500, M6700 3 unsupported OS: E6500(Win7), 9343(Win8.1), E7470(Win8.1) 3 drivers in conflict: E7470(A01), E7470(A07), E7470(A09)  With filters in place, it should leave me with: \\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x64 \\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x86 \\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x64 \\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x86 \\share\drivers\E7470-win10-A05-6K6HR\E7470\win10\x64 \\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x64 \\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x86 \\share\drivers\M6700-win10-A02-T08R2\M6700\win10\x64 \\share\drivers\M6700-win10-A02-T08R2\M6700\win10\x86 \\share\drivers\E7470-win10-A09-PY2N2\E7470\win10\x64 \\share\drivers\E6500-win7-A05-JJ15G\E6500\win7\x64 \\share\drivers\E6500-win7-A05-JJ15G\E6500\win7\x86 \\share\drivers\E7470-win8.1-A01-DCD7V\E7470\win8.1\x64 \\share\drivers\9343-Win8.1-A04-HXWH4\9343\Win8.1\x64 \\share\drivers\E7470-win10-A07-WXGDV\E7470\win10\x64  I am able to filter OS, Arch and Model: #Create new hashtable for temporary use$CabCollection_oschk = @()
Foreach ($driverSet in$CabCollection){
#filter by Operating System
$OSFound = Compare-Object$driverSet.OS $OSCheck -IncludeEqual | Where-Object {$_.SideIndicator -eq "=="}
If($OSFound){ #write-host$driverSet.FullPath
$CabTable_oschk = New-Object -TypeName PSObject -Property ([ordered]@{ Model =$driverSet.Model
OS       = $driverSet.OS Ver =$driverSet.Ver
Arch     = $driverSet.Arch FullPath =$driverSet.FullPath
})

$CabCollection_oschk +=$CabTable_oschk
}

}
#Rebuild original collection
$CabCollection =$CabCollection_oschk
Write-host "$($CabCollection.Count) drivers filtered for specified operating systems" -ForegroundColor Cyan

#Create new hashtable for temporary use
$CabCollection_archchk = @() Foreach ($driverSet in $CabCollection){ #filter by architecture$ArchFound = Compare-Object $driverSet.Arch$archCheck -IncludeEqual | Where-Object {$_.SideIndicator -eq "=="} If($ArchFound){
#write-host $driverSet.FullPath$CabTable_archchk = New-Object -TypeName PSObject -Property ([ordered]@{
Model    = $driverSet.Model OS =$driverSet.OS
Ver      = $driverSet.Ver Arch =$driverSet.Arch
FullPath = $driverSet.FullPath })$CabCollection_archchk += $CabTable_archchk } } #Rebuild original collection$CabCollection = $CabCollection_archchk Write-host "$($CabCollection.Count) drivers filtered for specified architecture" -ForegroundColor Cyan If ($FilterByModel){
#Create new hashtable for temporary use
$CabCollection_modelchk = @() Foreach ($driverSet in $CabCollection){ #filter by model$ModelFound = Compare-Object $driverSet.Model$DellModels -IncludeEqual | Where-Object {$_.SideIndicator -eq "=="} If($ModelFound){
#write-host $driverSet.FullPath$CabTable_modelchk = New-Object -TypeName PSObject -Property ([ordered]@{
Model    = $driverSet.Model OS =$driverSet.OS
Ver      = $driverSet.Ver Arch =$driverSet.Arch
FullPath = $driverSet.FullPath })$CabCollection_modelchk += $CabTable_modelchk } } #Rebuild original collection$CabCollection = $CabCollection_modelchk Write-host "$($CabCollection.Count) drivers filtered for specified models" -ForegroundColor Cyan }  This leaves me with 6 models, 1 of them having multiple versions of drivers. Model : E6530 OS : win10 Ver : A01 Arch : x64 FullPath : \\share\drivers\E6530-win10-A01-PXT6R\E6530\win10\x64 Model : E7450 OS : win10 Ver : A04 Arch : x64 FullPath : \\share\drivers\E7450-win10-A04-DNY52\E7450\win10\x64 Model : E7470 OS : win10 Ver : A05 Arch : x64 FullPath : \\share\drivers\E7470-win10-A05-6K6HR\E7470\win10\x64 Model : E6540 OS : win10 Ver : A03 Arch : x64 FullPath : \\share\drivers\E6540-win10-A03-FHWDF\E6540\win10\x64 Model : E7470 OS : win10 Ver : A09 Arch : x64 FullPath : \\share\drivers\E7470-win10-A09-PY2N2\E7470\win10\x64 Model : E7470 OS : win10 Ver : A07 Arch : x64 FullPath : \\share\drivers\E7470-win10-A07-WXGDV\E7470\win10\x64  After many of hours trying to figure out how to filter the cab versions, i have figured it out, but felt there could be an easier way. here is my code to filter them: #Create new hashtable for temporary use$CabCollection_verchk = @()

Foreach ($driverSet in ($CabCollection | Group-object Model | Where-Object {$_.Count -eq 1}) ){$CabTable_verchk = New-Object -TypeName PSObject -Property ([ordered]@{
Model    = $driverSet.Group.Model OS =$driverSet.Group.OS
Ver      = $driverSet.Group.Ver Arch =$driverSet.Group.Arch
FullPath = $driverSet.Group.FullPath })$CabCollection_verchk += $CabTable_verchk } Foreach ($driverSet in ($CabCollection | Group-object Model | Where-Object {$_.Count -gt 1}) ){
$SimilarModels =$driverSet | Foreach {$_.Group}$LatestVersion = ($SimilarModels.ver | measure -Maximum | Select -First 1).Maximum Foreach ($Model in ($SimilarModels | Where-Object {$_.Ver -eq $LatestVersion}) ){$CabCollection_verchk += $Model } } #Rebuild original collection$CabCollection = $CabCollection_verchk Write-host "$($CabCollection.Count) drivers filtered for latest version" -ForegroundColor Cyan Not I only see 4 drivers in my collection. The only next thing to do is grab those drivers and copy them to another folder. This should drop the size down dramatically, eepecially if you don't include video drivers (which you should exclude becuse you should download jsut the three catalyst drivers from (ati,intel,nvidia) mine went down from 13gb to 3gb. You can find the code here: DriverConsolidator Now the next thing to do is filter the drivers inf even further to grab only the latest....coming soon ## Wednesday, September 20, 2017 ### Installing PowerCLI on a disconnected network It is a constant battle working on multiple secured disconnected networks when everything is going to the cloud. What's worse its now XAAS (Everything-as-a-Service) is the new norm and I guess this means Powershell modules as well...specifically the most important one for our environment, PowerCLI. We upgrade out vCenter environment to 6.5.2 and I figured I wanted the same PowerCLI version I guess starting with 6.5.1 it's now a module you can get only from Microsoft PowerShell Gallery. But I want to use 6.5.2... HINT: You can still use the 6.5.0 installer if you like, but I like using the latest greatest and starting with There is an article that states how to do this, but I found this does not work entirely. https://blogs.vmware.com/PowerCLI/2017/08/new-release-powercli-652.html I have downloaded the PowerCLI using the command Save-Module -Name VMware.PowerCLI -Path <path\to\folder> Copied it an external drive, moved it over and copied it into my profile path (C:\Users\Username\Documents\WindowsPowerShell\Modules\). Opened a new instance of powershell and its not loaded nor is it recognized as a module.$env:PSModulePath does state my path is one of the locations. Hmmm...

I first try to import the module manually, but I kept getting the error when loading its first dependency, VMWare.VimAutomation.Sdk:

The log4net assembly is explicitly loaded by the PowerShell because it is in the RequiredAssemblies list of the VMware.VimAutomation.Sdk.psd1 module manifest (see VMware.VimAutomation.Sdk.psd1).

Huh?

After troubleshooting this over and over and reading online forums about it and getting nowhere, for shits and giggles, I tried running this command on my disconnected system, thinking it would find the modules on my profile or at lease an error I could follow:

Install-Module -Name VMware.PowerCLI

Instead I get an message saying I need to get that latest nuget. What?

I was curious, I decided to click Yes knowingly it will not work, but thought it would give me an error code I could work with:

No file information but it did give me a link....

I go to my internet connected PC type in that link. It takes me down the rabbit hole of the azure cloud

I get redirected to: https://az818661.vo.msecnd.net/providers/providers.masterList.feed.swidtag

Which then I find the link for Nuget: https://oneget.org/nuget-2.8.5.208.package.swidtag

That link takes me to the actual dll: https://oneget.org/Microsoft.PackageManagement.NuGetProvider-2.8.5.208.dll

Down the rabbit hole I go....

Based on this I search where this dll's get installed at on my connected system:
C:\Program Files\PackageManagement\ProviderAssemblies\nuget\2.8.5.208\Microsoft.PackageManagement.NuGetProvider.dll

Cool. I copied the dll over to my disconnect system (using the same folder structure). Then I re-ran just to see if I get prompted again:

Install-Module -Name VMware.PowerCLI -Verbose

No nuget message but now all I get is it can't find the repository. Great....not

Obviously I'm not connected to the internet so the repository its looking for is not available. What now?

Lets install PowerCLI manually.  After trying to manually importing the VMware.PowerCLI.psd1;

Install-Module $home\Documents\WindowsPowershell\Modules\VMware.PowerCLI\6.5.2.6268016\VMware.PowerCLI.psd1 It came back with dependencies that weren't install. I import the module VMWare.VimAutomation.Sdk, success! Run the import again...another dependencies....there are 17 more to go.... The PowerCLI does have 18 other modules that are required to be loaded first. But which one first? If you try to import the each dependencies one by one (alphabetically it will not work), they too have dependency errors. If you open the VMware.PowerCLI.psd1 file in notepad (or ISE) you will see the dependencies with their version numbers: I thought that by running this it would auto install the modules for me...Nope Install-Module$home\Documents\WindowsPowerShell\Modules\VMware.PowerCLI\6.5.2.6268016\VMware.PowerCLI.psd1

If I run through each module in the order it specifies, they all install just fine calling each psd1 file. However Vmware.VIMAutomation.PSCloud dependency is Vmware.VIMAutomation.Cloud and Vmware.VIMAutomation.Storage requires Vmware.VIMAutomation.SotrageUtility, yet they are not in that order. I could change the order in the psd1 file, but I didn't want to mess with what VMware release.

Instead I wrote my own installer ps1 file. I wrote it to parse the required module in VMware.PowerCLI.psd1, then add it to a hashtable with its version, then find those folders and look in their psd1 file for sub dependency, then install in the appropriate order.

These are the features added to the script:
• Find the latest downloaded PowerCLI version folder, and copy the files to the users profile Powershell directory
• Include a progress bar for coping
• Copy Nuget folder (located in PowerCLI version folder) to C:\Program Files\PackageManagement\ProviderAssemblies
• Disable CEIP
• Copy a modified version of Initialize-PowerCLIEnvironment.ps1 to the users profile PowerCLI directory
• Copy a icon to the users profile PowerCLI directory
• Create PowerCLI desktop shortcuts, x86 and x64 (like the installer did, pointing to Initialize-PowerCLIEnvironment.ps1  and using the icon)
The difference between old installer, it used to copy the modules to the C:\Program Files (x86)\VMware\Infrastructure\PowerCLI\Modules, add Initialize-PowerCLIEnvironment.ps1 to theC:\Program Files (x86)\VMware\Infrastructure\PowerCLI\Scripts folder, a a startmenu and desktop shortcuts to that scripts for 32-bit and 64-bit Powershell and add an entry into the PSModulePath system environment variable.

You will also need to have a copy of nuget with the saved version of PowerCLI. The folder structure should look like this:

If there is a later version that comes out, the script does detect that folder or you can update the variable (line 4)

$LatestModuleVersion = '6.5.2.6268016' You can get the PowerShell script on github (updated 2/8/2019): PowerCLIInstaller Coming soon...version 10 ## Monday, September 11, 2017 ### OSD Computer Name Prompt I work with a lot of Microsoft products, one of my favorite is Microsoft Deployment Toolkit and System Center Configuration Manager, otherwise known as MDT and SCCM (Sick-em boy). My favorite part is customizing the Windows Operating System. In my company, I work with the latest. Windows 10/SCCM 2012 R2 (1511)...yes there is a later one. What I enjoy is customizing Task Sequences. Writing PowerShell GUI's to control variables. Yes I know SCCM with MDT integrated and using its built in UDI wizard does all this for you, but what fun is that? Here is a PowerShell I wrote to prompt for a computer name. I have tested this against most of our Dell Systems and it does come back with the correct information. The cool thing is I loaded all the images as binary so it will load the proper image when prompted. Obviously as newer models come out; they too would need to be added. Here are some things it checks • Chassis types • Check current name if MININT (prompt) • Name Validation check To get SCCM to prompt the computer name correctly, you will need a few prerequisites. • If your using the SCCM (1511) and its latest ADK, be sure to provision a new Boot image so that the WinPE is matched and apply the hotfix: 3143760 • To allow this script to be interactive, copy the ServiceUI.exe and TSProgressUI.exe from the MDT's <DeploymentShare>\tools\x64 folder (can also be found under the MDT installation folder in Templates). Add it as part of the script package. • Add Run Command line in Task sequence. Add the package to is and run the command like this: ServiceUI.exe -process:TSProgressUI.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File Set-OSDComputerName.ps1 The script can be found here: Set-OSDComputerName.ps1 This is very basic script but it has potential to be more... ## Friday, September 8, 2017 ### PowerCLI Datastore Uploader GUI Since VMware is forcing the webgui for their vSphere client; you will require the vSphere plugin to be able to upload files to the datastore. however the plugin doesn't work on every browser; Chrome and IE are the only ones I found that works...sometimes. However, there are other ways to accomplish this: PowerCLI. The task isn't to hard; VMware has a KB on how to do it. Basically you need to connect to the vcenter server, get the datastore and folder (if needed), map a PSDrive to that datastore, then run the Copy-DatastoreItem command. Simple right? It is for an experienced administrator. But I like to make things even simpler; why not build a UI for it using XAML and PowerShell? Here we go again.... This simple form will check if PowerCLI is installed, if not, then either check a specified network directory for the module or get the latest from https://www.powershellgallery.com using NuGet Since I work on disconnected networks; the network share is useful for our environments It will also store the last used vCenter/IP in a file under your temp directory. I thought about making a dropdown list for it for multiple vCenter scenarios. The progress bar in the UI does not work yet. I am still working on a runspace for it so it doesn't lock up the menu; however if you will see the progess in the Powershell CLI or ISE This form can be found on https://github.com Oh the fun things you can do with powershell.... ## Thursday, November 17, 2016 ### Admin Run-As Menu I found that over the years accessing tools can be time consuming especially when multiple accounts are used for different tools. I developed a PowerShell driven menu (using the latest WPF technology and Mahapps theme) that is highly customizable. This tool isn't perfect and I'm sure there are many coding flaws with it, but I have tested and implemented it in my IT environment and everyone loves it especially the helpdesk. I designed this tool with one thing in mind: to make a simple push button menu that will launch the tools needed with the appropriate permissions. When launched you will be presented with 6 tabs (I originally had just one, but found the other shops liked it as well), each tab menu supports a different section. In this screenshot, I have the system admins, Enterprise Admins, SCCM / Automation Team (that's me), Exchange Team and Infrastructure Team. I've added the 6 menu as an Extra Tab for additional tools that are used almost daily. How it works is when the main PowerShell (AdminMenu.ps1) is called (link from a desktop shortcut), it loads 2 primary functions PowerShell scripts (AdminMenuExtensions.ps1 and ImageBase64Resources.ps1, then it loads 6 more PowerShell scripts for the Tabs (AdminMenu-Tab#.ps1). However I have added more functionality so in reality it loads a total of 14 ps1 files! I wrote the UI using Visual Studio 2015 Community Edition so as the Admin Menu launches it loads the XAML form with a XML configuration file. A new element I've added is, it loads a notification icon and a quick access (always on top) button in the bottom right corner that when clicked it will either hide or open the menu in front of any other window (works most of the time) Now each button is displayed using a configuration file written in XML. There are also options in the configure file I will get over later. The great thing is this menu is highly customizable because each tab (with exception of Tab 6) can hold 26 configurable buttons. Some of the main buttons on each tab (left column) launches a console specified in the AdminMenu-Tab#.ps1 file. The menu in the right column are scripts or other useful tools an admin uses (mostly scripts). Almost 100% of the scripts it uses are written in PowerShell and are all menu driven scripts. Most of them I got from https://gallery.technet.microsoft.com, others I have found on the net or I write myself. I was only interested in GUI driven menus. The real drive for this menu was because at work I use three different accounts to access different consoles. I needed a way to temporary store my credentials securely so I can launch any console on the fly. The Credential Management section on the far right does just that. It will store up to three credentials that are selectable. This only stores it for the time the menu is open, however if the menu is closed and reopened it does remember that username and domain entered, but the password has to be re-entered for it to be selectable again. How this credential system works: when you enter alternate credentials it stores them in a global variable and to an encrypted file. When selected and the user presses a button on a tab, it actually calls a function that launches the exe or bat or vbs or whatnot, with that credential variable using -Credential switch. ...hence the name Admin Run-As Menu I used FIPS compliance algorithms with encrypted cred file to ensure it was as secure as possible. Now to make this script easy to use and easy to configure, obviously a lot of complicated scripts must be written to do this, but ultimately there are only a few things to edit to make it customized; the configuration file along with the corresponding tab Like I mentioned before the Admin Run-As Menu, when launched, reads a configuration file to display the buttons color and name along with other settings: • Theme color • Accent color • Require Privilege Administrator access (UAC) • RSAT Check • Debug Mode • Hide all buttons not used (instead of a gray outline. • Hide app if not top window • Hide Credential Management feature • Load additional PowerShell modules • Load additional PowerShell Extension scripts • Use remote confit file Now to control what the button do after editing the xml file: The corresponding Tab PowerShell script has to be modified to match the process its calling like this: As you see I designated function section for each button name (eg: Call-btnTab1_01,Call-btnTab1_02, Call-btnTab1_03, etc.) In each of these function this is where you write the PowerShell code you want it to do. I made this simpler by just using the built-in function: Start-ButtonProcess. This function has many parameters. here is what is wrote as the guide: USE INTGRATED FUNCTION (EASIEST) - to log to output box in tab, use -OutputTab switch - to identify process alias, use -Alias switch, otherwise the button name will be used - to specify a custom run message use the -CustomRunMsg switch - to specify a custom error message use the -CustomErrMsg switch (this will only display if errors) - Auto use credentials feature if selected in menu, you can force it not to by adding -NeverRunAs switch EXAMPLE (EXE): Start-ButtonProcess -Alias "$ButtonClicked" -Path "$PSHOME\PowerShell.exe" -WorkingDirectory "$envWinDir\System32" -OutputTab tab1 -WindowStyle Normal

EXAMPLE (EXE) with Parameters:
Start-ButtonProcess -Alias "$ButtonClicked" -Path "$envWinDir\system32\mstsc.exe" -Parameters ("/v:" + $WPFtxtTab1Name1.Text) -OutputTab tab1 -WindowStyle Normal EXAMPLE (PS1): Start-ButtonProcess -ProcessCall ps1 -File "Start-PoshPAIG.ps1" -WorkingDirectory "$(\$scriptRoot + "\Scripts\PoshPAIG_2_1_5")" -CreateNoWindow

Nothing is flawless, there are parts of the code that could have written better. I thought about compiling this into an full executable, but I wanted it highly customizable and easy to update if needed, however I did compile an executable wrapper to call the AdminMenu.ps1 file (source code is below).

If you want to review the source, you can download it from here (GitHub):

The installer version is simply a compressed version of the source code that extracts and registers to a windows system that its installed. It will also place a shortcut on the desktop. There are two versions I have, one that used the exe wrapper (not signed) as the entry point, the other is just a shortcut to PowerShell calling a file.

(the installer is written with Inno Setup, its source is on GitHub as well).

EXE Source Code: EXE Wrapper

*I also have a full version (it contains 16mb of useful PowerShell driven GUI downloaded all over the internet that are added to the menu which I used to screenshot the above pics. I don't post the full installer due to the sources of the script and copyrights, if you'd like a download link send me a message or email.)

I want to thank all the people on Gallery TechNet for writing wonderful PowerShell GUI scripts. My inspiration comes from here:
https://gallery.technet.microsoft.com/
https://foxdeploy.com/2015/04/16/part-ii-deploying-powershell-guis-in-minutes-using-visual-studio/
https://psappdeploytoolkit.codeplex.com/

Features I would like to add are (and working on):