do we need PscxInputObjectCommandBase?

Topics: Developer Forum
Mar 16, 2007 at 12:16 AM
I find myself needing PscxInputObjectPathCommandBase without the Path bits -- how best to proceed?
Mar 16, 2007 at 12:47 AM
I'll do the refactoring we talked about the other day...
Mar 16, 2007 at 12:59 AM
Ah, I remember now. That looks like a good step forward.

In the long run it would be good to come up with a design that's less filesystem provider centric. It's quite hairy at the moment to derive from our base commands to create cmdlets to work on the registry (or directoryservices, or gac or whatever) paths. The -Path parameter should be provider agnostic, perhaps with some way to configure accepted providers, much like the InputObject is configured by RegisterInputObject<> calls.


Mar 16, 2007 at 1:19 AM
It's there, your command only needs to provide the parameter property and call ProcessInputObject from ProcessRecord.
Mar 16, 2007 at 1:47 AM
Edited Mar 16, 2007 at 2:01 AM
I agree, the PscxPathInputObjectBase class should be absolutely provider-agnostic. Could you guys look on my shelveset "Provider-agnostic PscxPathInputObjectCommandBase"?

The PscxCmdlet checks whether the input PSObject has a PSPath property and stores it in the CurrentInputObjectPath instance variable.
The PscxInputObjectPathCommandBase provides a RegisterPathInputType<T>, which registers a ProcessPath(CurrentInputObjectPath) call as the handler of the T objects.

Mar 19, 2007 at 3:28 PM
looks ok to me. Will this break much if you check this in?
Mar 19, 2007 at 10:34 PM
Edited Mar 19, 2007 at 10:35 PM
On a somewhat related topic, the one minor drag of these base classes is that the property attributes are fixed unless we provide multiple base classes with slightly differing attributes. For instance, I would like to be able to use Format-Xml like so:

"<a><b></b></a>" | fxml
but that doesn't work because the accept pipeline input attribute for the Path parameters specifies ByPropertyName and ByValue. Since the input is a string it gets routed to the Path parameter. I have to do this instead:

"<a><b></b></a>" | fxml -InputObject {$_}
In the case of this cmdlet (and probably Format-Hex) I would like to specify just ByPropertyName so that the original syntax would be allowed. However this would mean that this won't work:

'foo.xml' | fxml
but I think that is OK. Thoughts?
Mar 20, 2007 at 8:46 PM
I think I'm with you on this Keith -- {'foo.xml' | fxml} always looked a little weird to me anyway. In my head, that should be {gc foo.xml | fxml} -- so I guess I agree with you in principal. What breaks if we change this? I don't think there's anything wrong with creating a wider range of base classes if we need to fork one of them. We just need to name them well so there's no confusion. I think your first example is a great illustration of why usage patterns should drive our designs; that's the first thing I would try with {fxml} - it should accept a piped in string, no question about it.
Mar 21, 2007 at 6:38 AM
Well it would break if you used 'foo.xml' | fxml which I don't think is a common usage. The other way that I can think of would be if you did 'gci *.xml -name | fxml'. This also doesn't seem very likely. Is there any other thing that outputs filenames as pure strings instead of a FileInfo object that has a Path/PSPath parameter?
Mar 21, 2007 at 2:43 PM
Not that I can think of - if something is outputting strings as filenames, that's obviously not the "powershell way." The only strings that should ever come out of a cmdlet or provider are data. objects, objects, objects!
Apr 1, 2007 at 4:00 PM
hmmm - the changes that we did, while good, are not quite enough. The path resolving functionality as it stands is still filesystemprovider centric. The problem stems from the fact that the path that is pushed to ProcessPath is actually a provider-internal path, taken from Get(Un)resolvedProviderPathFromPSPath. You don't really notice this with the filesystem provider because the PSDrive names are the same as the Root, e.g. PSDrive C's root is C:\

Example (assume PscxPathCommandBase):

my-command -path c:\temp\file.ext

This results in "c:\temp\file.ext" being passed to ProcessPath. Yep, that looks fine, except try it again with a new psdrive called mydrive for example, also with a root to c:\

my-command -path mydrive:\temp\file.ext

ProcessPath receives "c:\temp\file.ext", not mydrive:\temp\file.ext. Now you can probably see where the problem is. This is especially obvious when we want to work with other providers on the path. Lets try this with the gac drive:

my-command -path gac:\system.web

ProcessPath receives "system.web" doh. Derived commands get no information about what sort of path that is. So, what's the solution? Pretty straightforward -- we should be passing down System.Management.Automation.PathInfo objects, not strings. We can get them by processing the path/literal path parameter with

Collection<PathInfo> pathInfos = SessionState.Path.GetResolvedPSPathFromPSPath(path);

instead of

Collection<string> rpaths = GetResolvedProviderPathFromPSPath(path, out provider);

PathInfo objects contain the drive, path, providerinfo and providerpath information: Everything we need.

I'm creating a work item for this, and since I've done the research, I'm probably in the best position for this bit, so I'll assign it to me and perform an impact assessment before committing anything.

Apr 1, 2007 at 4:24 PM
This discussion has been copied to Work Item 9298. You may wish to continue further discussion there.
Jun 12, 2007 at 8:15 PM

rkeithhill wrote:
"<a><b></b></a>" | fxml
but that doesn't work because the accept pipeline input attribute for the Path parameters specifies ByPropertyName and ByValue.

I know this is ancient and I'm not really contributing to the discussion, but just for the record, this works:

[xml]"<a><b></b></a>" | fxml