How to get Management Pack Bundle file information from SCOM? - c#

I am using OperationsManager module to work with SCOM, I need to find the somemanagementpack.mpb file information from SCOM which is already imported in SCOM an than need to delete the same somemanagementpack.mpb file locally based on the version
Below is the command I am using
Import-Module "OperationsManager"
New-SCOMManagementGroupConnection -ComputerName "DEVSCOM"
$mp = Get-SCManagementPack -BundleFile C:\Temp\somemanagementpack.mpb
$version = $mp.Version
$localVersion = "1.0.0.0"
if($version -gt $localVersion)
{
Remove-Item "C:\Temp\somemanagementpack.mpb" -Force
}
but when I am trying to remove it getting below error, I have also tried using Dispose method but nothing happens
The action can't be completed because the file is open

SCOM is locking the file. The only way to get it to stop is to kill the PowerShell process.
As a workaround I recommend making a copy of each file first to another directory. Have your script get the version from the copy. Then delete the original file that won't be locked if it matches your criteria. After you are done close the PowerShell window and delete the directory with all the copied files.
Import-Module "OperationsManager"
New-SCOMManagementGroupConnection -ComputerName "DEVSCOM"
Copy-Item C:\Temp\somemanagementpack.mpb C:\Temp\Copy\somemanagementpack.mpb
$mp = Get-SCManagementPack -BundleFile C:\Temp\Copy\somemanagementpack.mpb
$version = $mp.Version
$localVersion = "1.0.0.0"
if($version -gt $localVersion)
{
Remove-Item "C:\Temp\somemanagementpack.mpb" -Force
}
As you can see only the copy gets locked

Related

How to open SolidWorks sldprt files as read-only with PowerShell?

I built this open-file function in PowerShell for a GUI I wrote that lets you find and open various files on a server. I mainly use it for opening SolidWorks files as read-only, but also for PDF files and it should work for just about any other file if there is a file association for it.
The problem is that sometimes it doesn't work when opening the sldprt files. SolidWorks will either ignore the open file request or it wont open as read-only. I think this is mostly just a solidworks issue as sometimes it wont open files when double clicked on from windows explorer.
Anyway my solution is to set the file attribute to read-only. start a job that opens the file in SolidWorks, and then waits for the SolidWorks process to go idle before removing the read-only attribute. It does this through an event that watches for the job state to change. Since this is running through a GUI it has to be done in the background to prevent the GUI from locking up.
Is there a simpler way to open files as read-only with PowerShell?
I think it might be possible using the SolidWorks .dll files, but they are meant to be loaded in C# or VB-script and I have no idea what i'm doing in either of those languages.
function open-File{
param(
[parameter(Mandatory=$true)]$file,
[bool]$readOnly = $true,
$processName=$null
)
[scriptblock]$openFileScriptBlock = {
param(
$file,
$readOnly,
$processName=$null
)
#initiate variables
$loaded = $false
$file = get-item $file
$processLastCpu = 0
$timeout = 0
if ($readonly -and !$file.isReadOnly){
$file.isReadOnly = $true
#call file with default application
$attempts = 0
while ($true){
try{$startedProcess = start-process "$($file.fullname)" -PassThru; break}
catch{
$attempts++
if ($attempts -eq 3){return "cannot open file: $file, Error:$_"}
}
}
start-sleep -seconds 2
if ($processName){
$processName = $startedProcess.name
if ($processName -eq "SWSHEL~1"){$processName = "SLDWORKS"}
}
#wait until process shows up in the process manager
while ($loaded -eq $false -and $timeout -lt 25 ){
try {
$process = get-process -name $processName -erroraction 'stop'
if ($?){$loaded = $true; $timeout = 0} else {throw}
}catch{start-sleep -milliseconds 200; $timeout++}
}
start-sleep -seconds 2
#wait for process to go idle
while ($process.cpu -ne $processLastCpu -and $timeout -lt 10){
$processLastCpu = $process.cpu
start-sleep -milliseconds 500
$timeout++
}
$file.isreadonly = $false
} else {start-process "$($file.fullname)"}
return ,$file
}
if (!(test-path -path $file)){update-message "File not found: $file"; return}
$openFileJob = start-job -name 'openfile' -scriptblock $openFileScriptBlock -argumentlist $file, $readOnly, $processName
Register-ObjectEvent $OpenFileJob StateChanged -Action {
$jobResult = $sender | receive-job
$sender | remove-job -Force
unregister-event -sourceIdentifier $event.sourceIdentifier
remove-job -name $event.sourceIdentifier -force
try{update-message "opened file $($jobResult.name)"}
catch{update-message $jobResult}
} | out-null
}
I know its a old question, but i was wondering if you ever managed to get a solution?
If not, there is a few things you could try: first off, if your code is opening any other file just fine, it does not seem to be there the problem is.
File association with all SLD-files are working most of the time; but we do see it going bad from time to time (often related to updates), in that case, double-check that all SLD-file types are set to open with 'Solidworks-Launcher' (and not Solidworks directly).
Using the launcher, will ensure Solidworks does not try to open a file, into an already running instance of Solidworks.
Also, try to check the following: Solidworks Options -> Collaboration ->
'Enable Multi-user environments'... is this set?
whatever state it is in; try changing is to the opposite.
That checkmark is allowing multiple Solidworks-users to open the same file at the same time, and it does so by changing the read-state of the file, back and fourth.
(it could be it is interfering with your code)
Both of these things will be PC-specific, so if you change them on one machine, they might also need to be changed on other machines.

PowerShell Set Drive Labels Persisting And Unchangeable Until Reboot

Our software needs to map a network drive depending on which database the User logs in to.
The software first checks that the drive isn't already mapped, if it is then it skips the mapping step.
If the drive isn't mapped, or it is mapped to a different share (i.e. the User was previously logged in to a different database), then it clears any existing drive mapping, and maps the required drive.
It does this by generating and then running a PowerShell script.
Remove-SmbMapping -LocalPath "R:" -Force -UpdateProfile;
Remove-PSDrive -Name "R" -Force;
net use "R" /delete /y;
$password = ConvertTo-SecureString -String "Password" -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList "Username", $password;
New-PSDrive -Name "R" -PSProvider "FileSystem" -Root "\\server\share" -Credential $credential -Persist;
$a = New-Object -ComObject shell.application;
$a.NameSpace( "R:" ).self.name = "FriendlyName";
The first three lines remove any existing mapping on that drive letter. They all theoretically do the same thing, however thanks to Microsoft it's entirely random which line will actually work. It only consistently works if all three lines are run.
The middle three lines map the new drive.
The last two lines change the drive label of the new drive to something more user-friendly than the default \\server\share label
The first time someone logs in after a reboot the above script works perfectly. The new drive is mapped, and the label is changed.
However, if the User then logs out and logs into a different database, the label will not change.
For example, the User first logs in to 'Database A', and the drive is mapped with the label 'DatabaseAFiles'. All well and good.
But if the User then logs out, and logs in to 'Database B', the drive is correctly mapped and points to the correct share, but the label still says 'DatabaseAFiles' and not 'DatabaseBFiles'.
If the User reboots their PC, however, and logs in to 'Database B', then the label will correctly say 'DatabaseBFiles', but any subsequent log ins to other databases again won't change the label.
Reboot
Log in to Database A, label is DatabaseAFiles
Log out and into Database B, label is still DatabaseAFiles
Reboot
Log in to Database B, label is now DatabaseBFiles
This is not dependent on the last two script lines being present (the two that set the label), I actually added those to try to fix this issue. If those two lines are removed, the label is the default \\server\share label, and still doesn't change correctly, i.e.
Reboot
Log in to Database A, label is \\servera\sharea
Log out and into Database B, label is still \\servera\sharea
Reboot
Log in to Database B, label is now \\serverb\shareb
Regardless of the label, the drive is always correctly mapped to the correct share, and using it has all the correct directories and files.
Everything works correctly, it's just the label that is incorrect after the first login per reboot.
The script is run from within a C# program in a created PowerShell instance
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript(script);
IAsyncResult result = PowerShellInstance.BeginInvoke();
while (result.IsCompleted == false)
{
Thread.Sleep(1000);
}
}
As it maps a drive, it cannot be run in Adminstrator mode (the drive won't be mapped for the actual User), it has to be run in normal mode, so there is a check earlier up for that.
If I take a copy of the script and run it in a PowerShell session outside the C# program, I get exactly the same results (everything works but the label is wrong after the first login), so it's not that it's being run from within the C# program.
It's entirely possible that the issue is with either File Explorer or with Windows, either caching the label somewhere and reusing it could be the problem, of course.
Anyone have any suggestions of things I can try please?
A time ago, I have had to rename file shares and therefor I wrote this function. Maybe this is helpful for you.
#--------------------------------------
function Rename-NetworkShare {
#--------------------------------------
param(
[string]$sharePattern,
[string]$value
)
$regPath = Get-ChildItem 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2'
$propertyName = '_LabelFromReg'
foreach( $child in $regPath ) {
if( $child.PSChildName -like ('*' + $sharePattern + '*') ) {
if( !$child.Property.Contains( $propertyName ) ) {
New-ItemProperty $child.PSPath -Name $propertyName -PropertyType String | Out-Null
}
Set-ItemProperty -Path $child.PSPath -Name $propertyName -Value $value | Out-Null
}
}
}
Rename-NetworkShare -sharePattern 'patternOldName' -value 'NewFriendlyName'
It's not ideal, there's one bit I'm not happy about, but this is the best I've been able to come up with so far. If I come up with something better I'll post that instead.
Firstly, I check if there is already a drive mapped to the letter I want to use:-
// Test if mapping already exists for this database
var wrongMapping = false;
var drives = DriveInfo.GetDrives();
foreach (var drive in drives)
{
var driveLetter = drive.RootDirectory.ToString().Substring(0, 1);
if (driveLetter == mappingDetails.DriveLetter && Directory.Exists(drive.Name))
{
wrongMapping = true; // Assume this is the wrong drive, if not we'll return from the method before it's used anyway
var unc = "Unknown";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Network\\" + driveLetter))
{
if (key != null)
{
unc = key.GetValue("RemotePath").ToString();
}
}
if (unc == mappingDetails.Root)
{
View.Status = #"Drive already mapped to " + mappingDetails.DriveLetter + ":";
ASyncDelay(2000, () => View.Close());
return; // Already mapped, carry on with login
}
}
}
If we already have the correct path mapped to the correct drive letter, then we return and skip the rest of the mapping code.
If not, we'll have the variable wrongMapping, which will be true if we have a different path mapped to the drive letter we want. This means that we'll need to unmap that drive first.
This is done via a Powershell script run the by C# program, and contains the bit I'm not happy about:-
Remove-PSDrive mappingDetails.DriveLetter;
Remove-SmbMapping -LocalPath "mappingDetails.DriveLetter:" -Force -UpdateProfile;
Remove-PSDrive -Name "mappingDetails.DriveLetter" -Force;
net use mappingDetails.DriveLetter /delete /y;
Stop-Process -ProcessName explorer;
The first four lines are different ways to unmap a drive, and at least one of them will work. Which one does work seems to be random, but between all four the drives (so far) always get unmapped.
Then we get this bit:
Stop-Process -ProcessName explorer;
This will close and restart the Explorer process, thus forcing Windows to admit that the drive we just unmapped is really gone. Without this, Windows won't fully release the drive, and most annoyingly it will remember the drive label and apply it to the next drive mapped (thus making a mapping to CompanyBShare still say CompanyAShare).
However, in so doing it will close any open File Explorer windows, and also briefly blank the taskbar, which is not good.
But, given that currently no Company sites have more than one share, and it's only the Developers and Support that need to remove existing drives and map new ones, for now we'll put up with it.
Once any old drive is unmapped, we then carry on and map the new drive, which again is done via a PowerShell script run from the C# code.
$password = ConvertTo-SecureString -String "mappingDetails.Password" -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList "mappingDetails.Username", $password;
New-PSDrive -Name "mappingDetails.DriveLetter" -PSProvider "FileSystem" -Root "mappingDetails.Root" -Credential $credential -Persist;
$sh=New_Object -com Shell.Application;
$sh.NameSpace('mappingDetails.DriveLetter:').Self.Name = 'friendlyName';
New-Item –Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\" –Name "foldername";
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg";
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg" -Value "friendlyName" -PropertyType "String\";
The first part maps the drive:
$password = ConvertTo-SecureString -String "mappingDetails.Password" -AsPlainText -Force;
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList "mappingDetails.Username", $password;
New-PSDrive -Name "mappingDetails.DriveLetter" -PSProvider "FileSystem" -Root "mappingDetails.Root" -Credential $credential -Persist;
The middle part changes the name directly:
$sh=New_Object -com Shell.Application;
$sh.NameSpace('mappingDetails.DriveLetter:').Self.Name = 'friendlyName';
And the end part changes the name in the Registry:
New-Item –Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\" –Name "foldername";
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg";
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2\foldername" -Name "_LabelFromReg" -Value "friendlyName" -PropertyType "String\";
Firstly, it creates a key for this path (it the key already exists it'll fail but the script will carry on)
Then it removes the existing property _LabelFromReg (if it doesn't exist it'll fail but the script will carry on)
Then it (re)creates the property _LabelFromReg with the new friendlyname.
So, again doing the same thing two ways, but between the two it works.
I'd like to find some alternative to having to kill and restart the Explorer process, it's really tacky, but it seems to be the only way to get Windows to acknowledge the changes.
And at least I now get the correct labels on the drives when mapped.

How can I get the `Suggestion` of PowerShell's Get-Command in C#?

If I create a file called "dir.exe" and run PowerShell command Get-Command dir -Type Application, I get and error because dir is not an application (although that file exists):
gcm : The term 'dir' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:2
+ (gcm dir -Type Application)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (dir:String) [Get-Command], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand
Suggestion [3,General]: The command dir was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type: ".\dir". See "get-help about_Command_Precedence" for more details.
Notice the Suggestion at the bottom: Suggestion [3,General]: The command dir was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type: ".\dir". See "get-help about_Command_Precedence" for more details.
I'm trying to catch that suggestion in my C# code:
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management.Automation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Helpers.Tests {
[TestClass]
public class PowerShellRunner_Tests {
[TestMethod]
public void GetCommand_Test() {
// create file called "dir.exe" to see how PowerShell handles
// "Get-Command dir -Type Application":
File.Create("dir.exe").Dispose();
using (PowerShell powerShell = PowerShell.Create()) {
powerShell.AddCommand("get-command")
.AddArgument("dir")
.AddParameter("Type", CommandTypes.Application.ToString());
// run "Get-Command dir -Type Application":
CommandInfo commandInfo = powerShell.Invoke<CommandInfo>().FirstOrDefault();
// get the error:
ErrorRecord error = powerShell.Streams.Error.FirstOrDefault();
// emit the "Suggestion":
Trace.WriteLine(error.ErrorDetails.RecommendedAction);
}
}
}
}
However error.ErrorDetails is null. How can I get that Suggestion?
(I'm trying to get the behavior of where.exe but without the hassle of running a whole process for that).
Given that the end goal is to emulate where.exe's behavior, try the following:
(Get-Command -Type Application .\dir, dir -ErrorAction Ignore).Path
Note the use of -Type Application to limit results to executables and exclude PowerShell-internal commands such as function and aliases.
This will look in the current directory first, as where.exe does.
Give a mere name such as dir, Get-Command doesn't look in the current directory, because PowerShell does not permit invoking executables located in the current directory by name only - for security reasons; using relative path .\, however, makes Get-Command find such an executable.
From cmd.exe, however - whose behavior where.exe assumes - invoking a current-directory-only dir.exe with just dir (by name only) works fine.
If the output is just one path, and that path is a file in the current directory, you can infer that the dir executable exists only in the current directory, which is the condition under which PowerShell emits the suggestion to use an explicit path on invocation.
$fullPaths = (Get-Command -Type Application .\dir, dir -ErrorAction Ignore).Path
$emitSuggestion = $fullPaths.Count -eq 1 -and
(Test-Path ('.\' + (Split-Path -Leaf $fullPaths[0]))
Note: Strictly speaking, you'd also to have rule out the case where the current directory just so happens be one that is listed in $env:PATH:
$env:PATH -split ';' -ne '' -notcontains (Split-Path -Parent $fullPaths[0])
You can report that to your C# code by writing a custom version of the suggestion to the error stream via Write-Error, or, preferably, to the warning stream, with Write-Warning.
To use the above commands via the PowerShell SDK, it's simplest to use the .AddScript() method; e.g.:
powerShell.AddScript("(Get-Command -Type Application .\dir, dir -ErrorAction Ignore).Path");
As for capturing or silencing PowerShell's suggestions:
Unfortunately, you cannot gain access to suggestions programmatically (written as of Windows PowerShell v5.1 / PowerShell Core 6.1.0):
Using the PowerShell SDK, as you do, involves the PowerShell default host, which fundamentally doesn't emit suggestions.
It is only the console host, as used in console (terminal) windows that emits suggestions, but even there suggestions are printed directly to the screen, bypassing PowerShell's system of output streams.
In short: Suggestions only show in console windows (terminals), and can only be viewed, not captured there.
A quick demonstration of the behavior of suggestions in a console window (assumes Windows, with a file named dir.exe in the current dir and not also in $env:PATH):
PS> & { try { Get-Command dir.exe } catch {} } *>$null
Suggestion [3,General]: The command dir.exe was not found, but does exist in the current location. Windows PowerShell does not load commands from the current location by default. If you trust this command, instead type: ".\dir.exe". See "get-help about_Command_Precedence" for more details.
As you can see, despite the attempt to suppress all output (*>$null), the suggestion still printed to the screen, which also implies that you cannot capture suggestions.
However, there is a way to silence suggestions, namely with -ErrorAction Ignore (PSv3+); by contrast, with -ErrorAction SilentlyContinue the suggestion still prints(!):
PS> & { try { Get-Command dir.exe -ErrorAction Ignore } catch {} } *>$null
# no output

Programatically Pin\UnPin the folder from quick access menu in windows 10

I have a desktop application written in c#, and this application enables users to create the folder on their machine Hard drive . on windows 7 and 8, The App creates a shortcut for this folder under Favorit menu on the left side of windows Explorer window.
In windows 10 there is no Favorite menu, it was replaced by Quick access menu, and if you right click on the folder you can choose to Pin folder for quick access.
To do this programmatically from inside c# code, I found a .exe that can execute the Pin action as if the user clicked on the menu item to pin the folder
I got it from here http://www.maddogsw.com/cmdutils/
The problem is this exe does not contain an option for Unpin the folder from quick access so i will not be able to remove the shortcut from the quick access menu unless if I deleted it and I don't want to do that.
I tried to find the shortcut file and I found it in this path
%AppData%\Windows\Recent\AutomaticDestinations
but there is no mapping between this file shortcut and the file itself. and at the same time when I delete the files from this path, all the Pinned folders shortcut delete from the quick access not only my shortcut.
anyone can help in this ??
Do I need to know if there is any command that I can use it to Pin\Unpin folders to quick access from the command prompt?
I know it's a bit late, but I've found a way to do it and thought maybe someone could still use this.
So as was mentioned by Bradley Uffner, there is no API for this to avoid the constant abuse of such APIs. But there is still a (rather ugly) way to do it!
I'm no expert in PowerShell, but I found a way to do it using PowerShell:
# To add 'C:\path\to\folder' to quick access:
$qa = New-Object -ComObject shell.application
$qa.NameSpace('C:\path\to\folder').Self.InvokeVerb("pintohome")
# To remove 'C:\path\to\folder' from quick access:
($qa.Namespace("shell:::{679F85CB-0220-4080-B29B-5540CC05AAB6}").Items() | Where-Object { $_.Path -EQ 'C:\path\to\folder' }).InvokeVerb("unpinfromhome")
Which finally led me to the solution using C#:
using System.Management.Automation;
using System.Management.Automation.Runspaces
private static void AddFolderToQuickAccess(string pathToFolder)
{
using (var runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
var ps = PowerShell.Create();
var shellApplication =
ps.AddCommand("New-Object").AddParameter("ComObject", "shell.application").Invoke();
dynamic nameSpace = shellApplication.FirstOrDefault()?.Methods["NameSpace"].Invoke(pathToFolder);
nameSpace?.Self.InvokeVerb("pintohome");
}
}
private static void RemoveFolderFromQuickAccess(string pathToFolder)
{
using (var runspace = RunspaceFactory.CreateRunspace())
{
runspace.Open();
var ps = PowerShell.Create();
var removeScript =
$"((New-Object -ComObject shell.application).Namespace(\"shell:::{{679f85cb-0220-4080-b29b-5540cc05aab6}}\").Items() | Where-Object {{ $_.Path -EQ \"{pathToFolder}\" }}).InvokeVerb(\"unpinfromhome\")";
ps.AddScript(removeScript);
ps.Invoke();
}
}
NOTE: For this to work, you need to add a reference to System.Management.Automation which can easily be obtained as a nuget.

Loading a Powershell Module from the C# code of a custom Provider

I've been working on a VERY specific functionality "need" to tie into a custom Provider I'm writing in C#.
Basically I set out to find a way to replicate the
A:
B:
etc functions defined when PowerShell loads so instead of having to type
CD A:
You can just do the aforementioned
A:
I tried first to have my provider inject the functions into the runspace but it seems I'm completely missing the timing of how to get that to work so I went another route.
Basically I have a VERY simple PSM1 file UseColons.psm1
function Use-ColonsForPSDrives
{
[CmdletBinding()] Param()
Write-Verbose "Looping Through Installed PowerShell Providers"
Get-PSProvider | % `
{
Write-Verbose "Found $($_.Name) checking its drives"
$_.Drives | ? { (Get-Command | ? Name -eq "$($_.Name):") -eq $null } | `
{
Write-Verbose "Setting up: `"function $($_.Name):() {Set-Location $($_.Name):}`""
if ($Verbose)
{
. Invoke-Expression -Command "function $($_.Name):() {Set-Location $($_.Name):}"
}
else
{
. Invoke-Expression -Command "function $($_.Name):() {Set-Location $($_.Name):}" -ErrorAction SilentlyContinue
}
Write-Verbose "Finished with drive $($_.Name)"
}
}
# Cert and WSMan do not show up as providers until you try to naviagte to their drives
# As a result we will add their functions manually but we will check if they are already set anyways
if ((Get-Command | ? Name -eq "Cert:") -eq $null) { . Invoke-Expression -Command "function Cert:() {Set-Location Cert:}" }
if ((Get-Command | ? Name -eq "WSMan:") -eq $null) { . Invoke-Expression -Command "function WSMan:() {Set-Location WSMan:}" }
}
. Use-ColonsForPSDrives
In simple terms it loops through all loaded providers, then through all the drives of each provider, then it checks if the Function: drive contains a function matching the {DriveName}: format and if one is not found it creates one.
The psd1 file is nothing more than export all functions
This is stored in the %ProgramFiles%\WindowsPowerShell\Modules path under its own folder
And finally I have profile.ps1 under the %windir%\system32\windowspowershell\v1.0 directory that just does
Remove-Module UseColons -ErrorAction SilentlyContinue
Import-Module UseColons
So when I load PowerShell or the ISE if I want to get to say dir through the variables I can just call
Variable:
Or if I need to switch back to the registry
HKLM:
HKCU:
Which when you are working with multiple providers typing that CD over and over as you switch is just annoying.
Now to the problem I'm still working on developing the actual PowerShell provider this was originally intended for. But when I debug it the UseColons module loads BEFORE visual studio turns around and loads the new provider so if I manually remove and import the module again it does its thing and I have all my drive functions for my provider.
I wanted to know after that LONG explanation how can I either:
Setup my UseColons module to load LAST
Find a way to have my Custom Provider (technically a module since it has the provider AND custom Cmdlets) load the UseColons module when it initializes
I don't want to remove it from my standard profile because it is very helpful when I'm not working on the new provider and just tooling around using powershell for administrative stuff.
Hopefully someone can give me some ideas or point me in the direction of some good deeper dive powershell provider documentations and how-tos.
In your module manifest (.psd1), you have a DLL as the RootModule?
This is a horrible hack, and does not help for drives that get created in the future, but...
In your module manifest, instead of YourProvider.dll as the RootModule, use Dummy.psm1 instead (can be an empty file). Then, for NestedModules, use #( 'YourProvider.dll', 'UseColons' ). This allows the UseColons module to be loaded after YourProvider.dll. (Dummy will be last.)

Categories